Security
OIDC (Dex)
Sign in to the hub with GitHub, Google, LDAP, or any OIDC provider via Dex.
For teams or anywhere you want real per-user identities, use OIDC. The hub itself doesn’t care which OIDC provider you use, but the easiest path is Dex — it sits in front of GitHub / Google / LDAP / SAML / OIDC backends and presents one OIDC endpoint to the hub.
Browser ──▶ Hub ──▶ Dex ──▶ Identity backend (GitHub, Google, LDAP, …)
│ │
└────────── OIDC redirect ────────────────────┘
Prerequisites
- A publicly reachable URL for Dex (or in-cluster access if you don’t expose it)
- An identity backend (GitHub OAuth app, Google credentials, LDAP server, etc.)
- The hub already deployed somewhere — we’ll switch it from static-token to OIDC
1. Deploy Dex
helm repo add dex https://charts.dexidp.io
helm repo update
kubectl create namespace dex
A small PVC for the SQLite database:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: dex-data
namespace: dex
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 1Gi
Dex values (dex-values.yaml):
config:
issuer: https://idp.example.com
storage:
type: sqlite3
config:
file: /var/dex/dex.db
web:
http: 0.0.0.0:5556
staticClients:
- id: kedge
name: Kedge
secret: "<generate-a-secret>"
redirectURIs:
- https://hub.example.com/auth/callback
connectors:
- type: github
id: github
name: GitHub
config:
clientID: <github-client-id>
clientSecret: <github-client-secret>
redirectURI: https://idp.example.com/callback
# Optional — restrict to an org
# org: your-org
volumes:
- name: dex-data
persistentVolumeClaim:
claimName: dex-data
volumeMounts:
- name: dex-data
mountPath: /var/dex
service:
type: ClusterIP
ingress:
enabled: true
className: "nginx" # or cloudflare-tunnel, etc.
hosts:
- host: idp.example.com
paths:
- path: /
pathType: Prefix
Install Dex:
helm upgrade --install dex dex/dex \
--namespace dex \
-f dex-values.yaml
Verify:
curl -s https://idp.example.com/.well-known/openid-configuration | head -5
2. Configure the hub for OIDC
Update your hub values — remove staticAuthToken, add the idp section:
hub:
hubExternalURL: "https://hub.example.com"
devMode: false # Real OIDC needs real TLS verification
idp:
issuerURL: "https://idp.example.com"
clientID: "kedge"
clientSecret: "<same-secret-as-in-dex-staticClients>"
Roll out:
helm upgrade --install kedge oci://ghcr.io/faroshq/charts/kedge-hub \
-f values.yaml \
--namespace kedge-system
3. Log in
kubectl kedge login --hub-url https://hub.example.com
The browser opens to the hub’s /auth endpoint, which redirects to Dex, which redirects to your identity backend (GitHub, Google, …). After you authorize, the CLI receives the resulting OIDC token and writes it to your kubeconfig.
Identity connectors
Dex supports many backends. The most common configurations:
GitHub
- GitHub → Settings → Developer settings → OAuth Apps → New OAuth App.
- Authorization callback URL:
https://idp.example.com/callback - Add to Dex
connectors:
- type: github
id: github
name: GitHub
config:
clientID: <github-client-id>
clientSecret: <github-client-secret>
redirectURI: https://idp.example.com/callback
# Optional — restrict to organization members
org: your-org
- Create OAuth credentials in the Google Cloud Console.
- Add to Dex
connectors:
- type: google
id: google
name: Google
config:
clientID: <google-client-id>
clientSecret: <google-client-secret>
redirectURI: https://idp.example.com/callback
# Optional — restrict to a Workspace domain
hostedDomains:
- example.com
LDAP
- type: ldap
id: ldap
name: LDAP
config:
host: ldap.example.com:636
insecureNoSSL: false
bindDN: cn=admin,dc=example,dc=com
bindPW: admin-password
userSearch:
baseDN: ou=users,dc=example,dc=com
filter: "(objectClass=person)"
username: uid
idAttr: uid
emailAttr: mail
nameAttr: cn
Troubleshooting
invalid issuer from the hub — config.issuer in Dex must match idp.issuerURL in the hub byte-for-byte. Same scheme, no trailing slash.
Callback URL mismatch — redirectURIs in Dex’s staticClients must be exactly <hubExternalURL>/auth/callback. Mismatched scheme or path is the usual culprit.
TLS errors on the issuer — If Dex is using a self-signed cert (don’t, in prod), set hub.devMode: true to skip TLS verification of the OIDC issuer. Don’t ship that to production.
Dex logs:
kubectl -n dex logs -l app.kubernetes.io/name=dex
Discovery sanity check:
curl -s https://idp.example.com/.well-known/openid-configuration | jq .