diff --git a/docs/source/getting-started/configuration/authentication.md b/docs/source/getting-started/configuration/authentication.md index 182e20bb1..519ad2a1f 100644 --- a/docs/source/getting-started/configuration/authentication.md +++ b/docs/source/getting-started/configuration/authentication.md @@ -112,7 +112,298 @@ $ jmp login --exporter \ --issuer https:///realms/ ``` -### Dex +### Dex with GitHub + +Follow these steps to set up Dex with GitHub as the identity provider, +allowing members of specific GitHub organizations to authenticate with +Jumpstarter using their GitHub accounts. + +#### 1. Create a GitHub OAuth App + +1. Navigate to your GitHub organization's settings: + `https://github.com/organizations//settings/applications/new` + + :::{note} + You need admin access to the organization. The OAuth App only needs to be + created in one organization, even if you want to allow users from multiple + organizations. + ::: + +2. Fill in the application details: + + | Field | Value | + |-------|-------| + | **Application name** | `Jumpstarter` (or any descriptive name) | + | **Homepage URL** | `https://` | + | **Authorization callback URL** | `https:///callback` | + + Replace `` with the domain where Dex will be accessible + (e.g., `dex.apps.example.org`). + +3. Click **Register application**. + +4. On the application page: + - Copy the **Client ID** (displayed at the top) + - Click **Generate a new client secret** and copy the secret immediately + (it is only shown once) + +5. If you are restricting access to multiple GitHub organizations, each + organization may need to grant access to the OAuth App. Organization admins + can approve access at: + `https://github.com/organizations//settings/oauth_application_policy` + +#### 2. Create the GitHub credentials secret + +Create a namespace for Dex and a secret containing the OAuth App credentials: + +```console +$ kubectl create namespace dex +$ kubectl -n dex create secret generic dex-github \ + --from-literal=client-id='' \ + --from-literal=client-secret='' +``` + +:::{important} +Do not store the GitHub client secret in version control. Create the secret +directly on the cluster. +::: + +:::{note} +The command above passes the secret on the command line, which an +interactive shell may retain in history. If you prefer to avoid that, +write the secret to a permission-restricted file (`chmod 600`) and use +`--from-file=client-secret=/path/to/restricted/github-client-secret` +instead. +::: + +#### 3. Deploy Dex + +Deploy Dex with the GitHub connector. The example below uses Kubernetes +manifests. Adjust the `` placeholder and the list of GitHub +organizations to match your environment: + +```yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: dex-config + namespace: dex +data: + config.yaml: | + issuer: https:// + storage: + type: kubernetes + config: + inCluster: true + web: + http: 0.0.0.0:5556 + connectors: + - type: github + id: github + name: GitHub + config: + clientID: $GITHUB_CLIENT_ID + clientSecret: $GITHUB_CLIENT_SECRET + redirectURI: https:///callback + orgs: + - name: + - name: # optional + staticClients: + - id: jumpstarter-cli + name: Jumpstarter CLI + public: true + oauth2: + skipApprovalScreen: true +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dex + namespace: dex +spec: + replicas: 1 + selector: + matchLabels: + app: dex + template: + metadata: + labels: + app: dex + spec: + serviceAccountName: dex + containers: + - name: dex + image: ghcr.io/dexidp/dex:v2.41.1 + command: ["dex", "serve", "/etc/dex/config.yaml"] + ports: + - name: http + containerPort: 5556 + env: + - name: GITHUB_CLIENT_ID + valueFrom: + secretKeyRef: + name: dex-github + key: client-id + - name: GITHUB_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: dex-github + key: client-secret + volumeMounts: + - name: config + mountPath: /etc/dex + readOnly: true + readinessProbe: + httpGet: + path: /healthz + port: http + livenessProbe: + httpGet: + path: /healthz + port: http + volumes: + - name: config + configMap: + name: dex-config +``` + +Dex also needs RBAC permissions for its Kubernetes storage backend: + +```yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: dex + namespace: dex +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: dex +rules: + - apiGroups: ["dex.coreos.com"] + resources: ["*"] + verbs: ["*"] + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["create"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: dex +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: dex +subjects: + - kind: ServiceAccount + name: dex + namespace: dex +``` + +Expose Dex with a Service, then externally: + +```yaml +apiVersion: v1 +kind: Service +metadata: + name: dex + namespace: dex +spec: + selector: + app: dex + ports: + - name: http + port: 5556 + targetPort: http +``` + +On OpenShift, use a Route with edge TLS termination (the cluster's +wildcard certificate handles HTTPS automatically): + +```yaml +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + name: dex + namespace: dex +spec: + host: + port: + targetPort: http + tls: + termination: edge + insecureEdgeTerminationPolicy: Redirect + to: + kind: Service + name: dex +``` + +On vanilla Kubernetes, use an Ingress with cert-manager or your preferred TLS +solution instead. + +:::{note} +The `staticClients` entry for `jumpstarter-cli` must not include +`redirectURIs`. When a public client has no `redirectURIs` configured, Dex +automatically accepts any `http://localhost:/...` callback per +[RFC 8252](https://datatracker.ietf.org/doc/html/rfc8252), which is required +for CLI-based OAuth flows that listen on random ports. +::: + +#### 4. Configure Jumpstarter to trust Dex + +Add Dex as a JWT issuer on your `Jumpstarter` resource. Enable +`autoProvisioning` so that users are created automatically on first login: + +```yaml +spec: + authentication: + autoProvisioning: + enabled: true + jwt: + - issuer: + url: https:// + audiences: + - jumpstarter-cli + claimMappings: + username: + claim: "preferred_username" + prefix: "github:" +``` + +#### 5. Verify the deployment + +```console +$ curl -s https:///.well-known/openid-configuration | jq .issuer +"https://" +``` + +#### 6. Log in + +Users from the configured GitHub organizations can log in using the simplified +login format: + +```console +$ jmp login @ +``` + +For example: + +```console +$ jmp login myuser@jumpstarter-login.apps.example.org:443 +``` + +This opens a browser for GitHub OAuth authorization. After approval, the user +is authenticated as `github:` in Jumpstarter. + +With `autoProvisioning` enabled, no prior `jmp admin create client` step is +needed — the client resource is created automatically on first login. + +See the `jmp login` [man page](../../reference/man-pages/jmp.md) for the full +list of options. + +### Dex with Kubernetes Service Accounts Follow these steps to set up Dex for service account authentication: