Skip to content

dex: configure connectors through values - #3568

Open
danish9039 wants to merge 1 commit into
kubeflow:masterfrom
danish9039:gsoc/dex-connectors
Open

dex: configure connectors through values#3568
danish9039 wants to merge 1 commit into
kubeflow:masterfrom
danish9039:gsoc/dex-connectors

Conversation

@danish9039

@danish9039 danish9039 commented Aug 2, 2026

Copy link
Copy Markdown
Member

Pull Request Template for Kubeflow Manifests

✏️ Summary of Changes

Makes replacing the Dex login flow a values change.

Out of the box Dex authenticates against a static password database holding a
single demonstration account. Every real installation has to replace that with a
company identity provider. Until now the chart hardcoded the shape of
config.yaml and exposed no way to add a connector, so the only route was
rewriting the ConfigMap by hand, as common/dex/README.md describes.

Connectors

config:
  enablePasswordDB: false
  connectors:
  - type: oidc
    id: keycloak
    name: Keycloak
    config:
      issuer: https://keycloak.example.com/realms/kubeflow
      clientID: $KEYCLOAK_CLIENT_ID
      clientSecret: $KEYCLOAK_CLIENT_SECRET
      redirectURI: https://kubeflow.example.com/dex/callback
      userNameKey: email

extraEnvironmentSecrets:
- keycloak-oidc-credentials

Each entry is passed to Dex exactly as written, so any connector the
Dex documentation describes works — OIDC,
LDAP, GitHub, Microsoft, SAML — without the chart needing to know about it. Only
type, id and name are required by the chart; everything under config
belongs to Dex.

Credentials stay out of values.yaml

Dex resolves $VARIABLE references from its environment. extraEnvironmentSecrets
names existing Secrets in the auth namespace, which the chart appends to the
container's envFrom:

envFrom:
- secretRef: {name: dex-oidc-client}
- secretRef: {name: dex-passwords}
- secretRef: {name: keycloak-oidc-credentials}

The chart does not create those Secrets. They must exist before the release is
installed.

Providers behind a private certificate authority

Dex reads connector certificate authorities from filesrootCAs is a list
of paths, read with os.ReadFile — so a Secret alone is not enough. The chart
mounted only its own ConfigMap, which left an operator whose identity provider
uses a private authority with no option except insecureSkipVerify: true,
disabling certificate verification altogether.

connectorCertificateAuthoritySecret: corporate-certificate-authority
config:
  connectors:
  - type: oidc
    id: keycloak
    name: Keycloak
    config:
      issuer: https://keycloak.example.com/realms/kubeflow
      rootCAs:
      - /etc/dex/certificate-authorities/ca.crt

The Secret is mounted read-only at /etc/dex/certificate-authorities. The LDAP
connector takes the certificate inline through rootCAData and is unaffected.

Guards

  • config.enablePasswordDB: false with no connector is rejected. Otherwise
    Dex starts with no way to authenticate anyone, which locks every user out.
  • config.connectors must be a list, and each connector must declare type,
    id and name. Both fail before anything renders.
  • A rootCAs path under /etc/dex/certificate-authorities with no
    connectorCertificateAuthoritySecret is rejected, rather than starting Dex
    with a certificate it cannot read.

Two related fixes

staticPasswords was rendered unconditionally, so disabling the password
database left a dangling entry. Dex ignored it, but it read as sloppy. It is now
rendered only when the password database is enabled.

Changing a connector changes the configuration checksum on the Deployment, so
helm upgrade restarts the pods and the new configuration takes effect. There is
a test for this, because a configuration change that does not restart the
workload silently does nothing.

Parity is unaffected

config.connectors defaults to empty and extraEnvironmentSecrets to an empty
list, so the rendered output is unchanged and the Kustomize comparison still
passes for every component. Connector configurations have no Kustomize
counterpart to compare against, so they are covered by unit tests instead.

📦 Dependencies

None. Applies to the merged Dex chart and is independent of every open pull
request.

🐛 Related Issues

Raised during review of #3524: "How can i disable for example the default login
flow? what are the things i can easily configure?"
The login flow belongs to
this chart rather than the Dashboard chart, and it was not configurable. Now it
is.

Validation

python3 tests/test_dex_helm_connectors.py          # 9 tests
python3 tests/test_dex_helm_rollout_checksums.py   # 3 tests
./tests/helm_kustomize_compare_all.sh dex
./tests/helm_kustomize_compare_all.sh              # every component
helm lint common/dex/helm --namespace auth
black --check tests/
git diff --check

Verified locally against Helm 4.1.0 and Kustomize v5.8.1.

✅ Contributor Checklist

  • I have tested these changes with kustomize. See Installation Prerequisites.
  • All commits are signed-off to satisfy the DCO check.
  • I have considered adding my company to the adopters page to support Kubeflow and help the community, since I expect help from the community for my issue (see 1. and 2.).

You can join the CNCF Slack and access our meetings at the Kubeflow Community website. Our channel on the CNCF Slack is here #kubeflow-community-distribution.

@google-oss-prow

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign juliusvonkohout for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds configurable Dex identity-provider connectors, external credential Secrets, and private certificate authority support.

Changes:

  • Adds connector configuration and validation safeguards.
  • Mounts credential and certificate authority Secrets.
  • Adds documentation and automated Helm tests.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
tests/test_dex_helm_connectors.py Tests connector rendering and validation.
common/dex/helm/values.yaml Defines new connector and Secret values.
common/dex/helm/templates/validate-config.yaml Validates connector configuration.
common/dex/helm/templates/dex.yaml Mounts and exposes external Secrets.
common/dex/helm/templates/config-map.yaml Renders connectors conditionally.
common/dex/helm/templates/_helpers.tpl Defines the certificate authority mount path.
common/dex/helm/README.md Documents connector configuration and credentials.
.github/workflows/helm-kustomize-comparison.yml Executes the new tests.
Suppressed comments (2)

tests/test_dex_helm_connectors.py:224

  • The single-letter v hides that the comprehension iterates over volumes and violates the expressive-naming requirement in AGENTS.md:7. Use volume here.
        volumes = [v["name"] for v in deployment["spec"]["template"]["spec"]["volumes"]]

tests/test_dex_helm_connectors.py:329

  • ca abbreviates certificate authority even though AGENTS.md:7 requires explicitly long, expressive names. Spell out certificate_authority in this test name.
    def test_a_non_normalized_root_ca_path_is_rejected(self):

Comment on lines +26 to +28
{{- if and (not .Values.config.enablePasswordDB) (not .Values.config.connectors) }}
{{- fail "config.enablePasswordDB is false and config.connectors is empty, so Dex would have no way to authenticate anyone; configure a connector or keep the password database enabled" }}
{{- end }}
Comment thread common/dex/helm/README.md
kubectl create secret generic keycloak-oidc-credentials \
--namespace auth \
--from-literal=KEYCLOAK_CLIENT_ID=kubeflow \
--from-literal=KEYCLOAK_CLIENT_SECRET=<client secret>
Comment on lines +56 to +57
{{- if or (contains "/./" $certificate) (contains "/../" $certificate) }}
{{- fail (printf "config.connectors[%d] rootCAs entry %s is not a normalized path; write it without . or .. segments" $index $certificate) }}
Comment thread common/dex/helm/README.md
Comment on lines +72 to +73
The chart does not create these Secrets. They must exist before the release is
installed.
configuration = self.dex_configuration(result.stdout)
self.assertNotIn("staticPasswords", configuration)
self.assertFalse(configuration["enablePasswordDB"])
self.assertEqual([c["id"] for c in configuration["connectors"]], ["keycloak"])
Comment on lines +200 to +205
mount = next(
m
for m in pod["containers"][0]["volumeMounts"]
if m["mountPath"] == "/etc/dex/certificate-authorities"
)
self.assertTrue(mount["readOnly"])
Comment on lines +207 to +209
v
for v in pod["volumes"]
if v["name"] == "connector-certificate-authorities"
volumes = [v["name"] for v in deployment["spec"]["template"]["spec"]["volumes"]]
self.assertEqual(volumes, ["config"])

def test_root_ca_path_without_the_secret_fails(self):
@danish9039
danish9039 force-pushed the gsoc/dex-connectors branch from aeda73e to caf552e Compare August 31, 2026 17:39
Signed-off-by: danish9039 <danishsiddiqui040@gmail.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Boolean and path validation accept inputs that produce unusable Dex configurations, and the documented Secret command is invalid Bash syntax.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Suppressed comments (2)

tests/dex_helm_connectors_test.py:209

  • The one-letter name v hides that this expression selects a volume. Use the explicit volume name required by the repository naming standard.
            v
            for v in pod["volumes"]
            if v["name"] == "connector-certificate-authorities"

tests/dex_helm_connectors_test.py:224

  • The one-letter name v obscures that this comprehension iterates volumes. Use the explicit volume name required by the repository naming standard.
        volumes = [v["name"] for v in deployment["spec"]["template"]["spec"]["volumes"]]
  • Files reviewed: 8/8 changed files
  • Comments generated: 6
  • Review effort level: Balanced

Comment on lines +26 to +28
{{- if and (not .Values.config.enablePasswordDB) (not .Values.config.connectors) }}
{{- fail "config.enablePasswordDB is false and config.connectors is empty, so Dex would have no way to authenticate anyone; configure a connector or keep the password database enabled" }}
{{- end }}
Comment on lines +6 to +8
{{- if not (or (kindIs "slice" .Values.config.connectors) (kindIs "invalid" .Values.config.connectors)) }}
{{- fail (printf "config.connectors must be a list of Dex connectors; got %s" (kindOf .Values.config.connectors)) }}
{{- end }}
Comment on lines +56 to +58
{{- if or (contains "/./" $certificate) (contains "/../" $certificate) }}
{{- fail (printf "config.connectors[%d] rootCAs entry %s is not a normalized path; write it without . or .. segments" $index $certificate) }}
{{- end }}
Comment thread common/dex/helm/README.md
kubectl create secret generic keycloak-oidc-credentials \
--namespace auth \
--from-literal=KEYCLOAK_CLIENT_ID=kubeflow \
--from-literal=KEYCLOAK_CLIENT_SECRET=<client secret>
configuration = self.dex_configuration(result.stdout)
self.assertNotIn("staticPasswords", configuration)
self.assertFalse(configuration["enablePasswordDB"])
self.assertEqual([c["id"] for c in configuration["connectors"]], ["keycloak"])
Comment on lines +200 to +204
mount = next(
m
for m in pod["containers"][0]["volumeMounts"]
if m["mountPath"] == "/etc/dex/certificate-authorities"
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants