From 2f332cd3af88d4cd3bcda60f36cf53c0afba063f Mon Sep 17 00:00:00 2001 From: wooyoung85 Date: Tue, 25 Feb 2025 16:30:08 +0900 Subject: [PATCH] docs: Add guide for Dex and Keycloak (#3012) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add guide for Dex and Keycloak Signed-off-by: WOOYOUNG SEO Signed-off-by: wooyoung85 * Update README.md Signed-off-by: Julius von Kohout <45896133+juliusvonkohout@users.noreply.github.com> Signed-off-by: WOOYOUNG SEO Signed-off-by: wooyoung85 * Rename common/README.md to common/dex/README.md Signed-off-by: Julius von Kohout <45896133+juliusvonkohout@users.noreply.github.com> Signed-off-by: 서우영 책임 Architect AI 아키텍처팀 (wy.seo@lgcns.com Signed-off-by: wooyoung85 * Update README.md Signed-off-by: Julius von Kohout <45896133+juliusvonkohout@users.noreply.github.com> Signed-off-by: 서우영 책임 Architect AI 아키텍처팀 (wy.seo@lgcns.com Signed-off-by: wooyoung85 --------- Signed-off-by: WOOYOUNG SEO Signed-off-by: wooyoung85 Signed-off-by: Julius von Kohout <45896133+juliusvonkohout@users.noreply.github.com> Signed-off-by: wooyoung85 Signed-off-by: 서우영 책임 Architect AI 아키텍처팀 (wy.seo@lgcns.com Co-authored-by: Julius von Kohout <45896133+juliusvonkohout@users.noreply.github.com> --- README.md | 2 + common/dex/README.md | 191 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 common/dex/README.md diff --git a/README.md b/README.md index 04ce26e77..0ff5856d5 100644 --- a/README.md +++ b/README.md @@ -339,6 +339,8 @@ data: #- groups # groups might be used in the future ``` +For Keycloak we have rough guidelines in . + #### Knative Knative is used by the KServe official Kubeflow component. diff --git a/common/dex/README.md b/common/dex/README.md new file mode 100644 index 000000000..4155e9790 --- /dev/null +++ b/common/dex/README.md @@ -0,0 +1,191 @@ +# Kubeflow Dex & Keycloak Integration Guide + +In addition to the guidelines for GitHub, Google, Microsoft and other OIDC providers in https://github.com/kubeflow/manifests#dex and direct oauth2-proxy connection without DEX to typical OIDC IDP providers such as Azure in https://github.com/kubeflow/manifests/blob/master/common/oauth2-proxy/README.md#change-the-default-authentication-from-dex--oauth2-proxy-to-oauth2-proxy-only we try to roughly explain here how to configure Dex to use Keycloak as an external OpenID Connect provider for Kubeflow. + +> [Note] +> ✅ Replace the domains of Keycloak and Kubeflow containing `example.com` with ones that are appropriately tailored to the actual situation. +> ✅ If a realm already exists, there's no need to create one. +> ✅ As you know, If the first attempt fails, you can just run it again. + +## Configure Keycloak + +### Create a Realm + +- Realm Name: `` + +### Create a Client +- Client Type: `OpenID Connect` +- Client ID: `kubeflow-oidc-authservice` (⚠️ Never use a different value) +- Client Authentication: `On` +- Authentication Flow: Check `Standard flow` and `Direct access grants` +- Root URL: `https://kubeflow.example.com` +- Home URL: `https://kubeflow.example.com` +- Valid Redirect URIs: `https://kubeflow.example.com/dex/callback` +- Valid Post Logout Redirect URIs: `https://kubeflow.example.com/oauth2/sign_out` +- Web Origins: `*` + +After creating the realm and client, note down the **Client Secret**(`YOUR_KEYCLOAK_CLIENT_SECRET`) which will be used in later steps. + +## Update Dex Configuration + +Modify the Dex ConfigMap to connect to Keycloak. + +```bash +KEYCLOAK_ISSUER="https://keycloak.example.com/realms/" +CLIENT_ID="kubeflow-oidc-authservice" +CLIENT_SECRET="" +REDIRECT_URI="https://kubeflow.example.com/dex/callback" +DEX_ISSUER="https://kubeflow.example.com/dex" + + +tee common/dex/overlays/oauth2-proxy/config-map.yaml <<- DEX_CONFIG +apiVersion: v1 +kind: ConfigMap +metadata: + name: dex +data: + config.yaml: | + issuer: $DEX_ISSUER + storage: + type: kubernetes + config: + inCluster: true + web: + http: 0.0.0.0:5556 + logger: + level: "debug" + format: text + oauth2: + skipApprovalScreen: true + enablePasswordDB: false + # staticPasswords: + # - email: user@example.com + # hashFromEnv: DEX_USER_PASSWORD + # username: user + # userID: "15841185641784" + staticClients: + - idEnv: OIDC_CLIENT_ID + redirectURIs: ["/oauth2/callback"] + name: 'Dex Login Application' + secretEnv: OIDC_CLIENT_SECRET + connectors: + - type: oidc + id: keycloak + name: keycloak + config: + issuer: $KEYCLOAK_ISSUER + clientID: $CLIENT_ID + clientSecret: $CLIENT_SECRET + redirectURI: $REDIRECT_URI + insecure: false + insecureSkipEmailVerified: true + userNameKey: email + scopes: + - openid + - profile + - email + - offline_access +DEX_CONFIG + + +kustomize build common/dex/overlays/oauth2-proxy | kubectl delete -f - +kustomize build common/dex/overlays/oauth2-proxy | kubectl apply -f - +``` + +## Update OAuth2 Proxy Configuration +Configure the OAuth2 Proxy to use the newly configured Dex issuer. + +```bash +DEX_ISSUER="https://kubeflow.example.com/dex" + +tee common/oauth2-proxy/base/oauth2_proxy.cfg <<- OAUTH2_PROXY_CONFIG +provider = "oidc" +oidc_issuer_url = "$DEX_ISSUER" +scope = "profile email offline_access openid" +email_domains = "*" +insecure_oidc_allow_unverified_email = "true" + +upstreams = [ "static://200" ] + +skip_auth_routes = [ + "^/dex/", +] + +api_routes = [ + "/api/", + "/apis/", + "^/ml_metadata", +] + +skip_oidc_discovery = true +login_url = "/dex/auth" +redeem_url = "http://dex.auth.svc.cluster.local:5556/dex/token" +oidc_jwks_url = "http://dex.auth.svc.cluster.local:5556/dex/keys" + +skip_provider_button = false + +provider_display_name = "Dex" +custom_sign_in_logo = "/custom-theme/kubeflow-logo.svg" +banner = "-" +footer = "-" + +prompt = "none" + +set_authorization_header = true +set_xauthrequest = true + +cookie_name = "oauth2_proxy_kubeflow" +cookie_expire = "24h" +cookie_refresh = 0 + +code_challenge_method = "S256" + +redirect_url = "/oauth2/callback" +relative_redirect_url = true +OAUTH2_PROXY_CONFIG + + +kustomize build common/oauth2-proxy/overlays/m2m-dex-only/ | kubectl delete -f - +kustomize build common/oauth2-proxy/overlays/m2m-dex-only/ | kubectl apply -f - +``` + +## Update Istio Request Authentication +Adjust the Istio Request Authentication configuration to pass the correct JWT claims. + +```bash +DEX_ISSUER="https://kubeflow.example.com/dex" + +tee common/oauth2-proxy/components/istio-external-auth/requestauthentication.dex-jwt.yaml <<- ISTIO_REQUEST_AUTH_CONFIG +apiVersion: security.istio.io/v1beta1 +kind: RequestAuthentication +metadata: + name: dex-jwt + namespace: istio-system +spec: + selector: + matchLabels: + app: istio-ingressgateway + jwtRules: + - issuer: $DEX_ISSUER + forwardOriginalToken: true + outputClaimToHeaders: + - header: kubeflow-userid + claim: email + - header: kubeflow-groups + claim: groups + fromHeaders: + - name: Authorization + prefix: "Bearer " +ISTIO_REQUEST_AUTH_CONFIG + + +# For Kubeflow 1.91, change istio-1-24 to istio-1-22 +kustomize build common/istio-1-24/istio-install/overlays/oauth2-proxy | kubectl delete -f - +kustomize build common/istio-1-24/istio-install/overlays/oauth2-proxy | kubectl apply -f - +kustomize build common/oauth2-proxy/overlays/m2m-dex-only/ | kubectl delete -f - +kustomize build common/oauth2-proxy/overlays/m2m-dex-only/ | kubectl apply -f - +``` + +## Final Checks +- **Review Logs**: Make sure to tail the logs of the Dex, OAuth2 Proxy, and Istio ingress gateway deployments to verify that the configurations are working as expected. +- **Test Authentication**: Try accessing your Kubeflow endpoint (ex. https://kubeflow.example.com) and verify that you’re redirected to Keycloak for authentication and that after login you are correctly returned to Kubeflow.