Skip to content

docs: add ADRs for Dex as OIDC issuer and Keycloak migration path - #3542

Open
CasLubbers wants to merge 19 commits into
mainfrom
APL-2049-adrs
Open

docs: add ADRs for Dex as OIDC issuer and Keycloak migration path#3542
CasLubbers wants to merge 19 commits into
mainfrom
APL-2049-adrs

Conversation

@CasLubbers

@CasLubbers CasLubbers commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Copilot AI lite review requested due to automatic review settings August 14, 2026 11:20

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 two new ADRs documenting the planned move from Keycloak to Dex as the OIDC issuer and the decision to keep migration for existing clusters manual, and updates the ADR index accordingly.

Changes:

  • Added ADR describing why/how Dex replaces Keycloak as the OIDC issuer.
  • Added ADR describing the manual migration path for existing clusters.
  • Updated adr/index.md to include the new ADRs (and reformatted the index list).

Reviewed changes

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

File Description
adr/index.md Reformats the ADR index list and adds entries for the two new ADRs.
adr/2026-08-06-dex-as-issuer.md New ADR capturing the decision and constraints for using Dex as issuer.
adr/2026-08-06-keycloak-to-dex-migration-path.md New ADR capturing the decision to keep migration manual for existing clusters.
Suppressed comments (1)

adr/index.md:23

  • This index entry uses "favor" while the ADR title uses British spelling ("favour") in the ADR itself (adr/2026-06-25-drop-sops-for-sealedsecrets.md:1). Keeping the index text consistent makes it easier to find the ADR by title search.
* [ADR-2026-06-25](2026-06-25-drop-sops-for-sealedsecrets.md) - Drop SOPS in favor of SealedSecrets

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread adr/index.md
* [ADR-2022-04-22](2022-04-22-values-migration.md) - Values migration
* [ADR-2022-04-23](2022-04-23-pre-upgrade.md) - A new otomi pre-upgrade command
* [ADR-2022-05-17](2022-05-17-destroy-upon-uninstall.md) - Extra flags to accommodate destroy upon uninstall
* [ADR-2022-06-07](2022-06-07-ingress-classes.md) - Ingress classes
Comment thread adr/index.md
* [ADR-2020-11-06](2020-11-06-konstraint-policy-library.md) - Konstraint library to support Common Rego Language definitions
* [ADR-2021-10-18](2021-10-18-defaults-and-derived.md) - Derived values
* [ADR-2021-10-28](2021-10-28-internal-values.md) - Internal values
* [ADR-2022-03-24](2022-03-24-custom-ca.md) - urice:
Comment thread adr/2026-08-06-keycloak-to-dex-migration-path.md Outdated

### How users reach the configuration

Users are created through the API and stored as SealedSecrets in the `apl-users` namespace. Under Keycloak they reach the issuer at runtime, because the Keycloak operator watches those Secrets. Dex has no operator, so the records must be in hand when the configuration is rendered.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

In Keycloak, various problems arose from this approach, too. The operator was both watching Secrets and a common ConfigMap, and had several issues synchronizing data correctly. We eventually decided for a plan to abandon the operator and instead have the API act as a direct proxy into Keycloak, but due to the perspective of deprecating Keycloak this was never followed up on.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The problem now is that we cannot fully use the Dex API for users as it is missing the Group attribute. That one only works in the configuration file. So the our apl-api cannot suffice as an proxy for Dex.
But it is good to keep in mind for future reference that we do not want to create a dex-operator.

Bringing an external identity provider remains supported, and the two populations stay mutually exclusive, as they are under Keycloak:

- **Users created in APL** originate in the values repository and are rendered into Dex's `staticPasswords` from their materialised form on the cluster, as described above. The values repository remains their system of record.
- **Federated users** arrive through a Dex `oidc` connector configured from the existing `oidc.*` settings. They are never written to the values repository, and their team membership comes from group claims.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Will this also be the migration path for Keycloak? Adding Keycloak as an OIDC connector but excluding it from direct APL management would leave an option for legacy installations to keep the user base, and migrate at their own choice (if ever). This would require them to exclusively create and update users through the Keycloak UI from that point on, but that would be acceptable.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I read the options below, what I meant is a fourth option, somewhat a mix of option 2 and 3: Making Dex the OIDC provider on all installations, but on migrated ones leave Keycloak behind it. Cut off apl-keycloak-operator, creating new users through API exclusively in Dex.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes that sounds as a good option. The only problem I have seen so far is that if we switch a Keycloak cluster to Dex as issuer. The users will lose their Harbor and Gitea account.
The subject that Dex returns is different. Gitea and Harbor will therefore create new accounts automatically. Maybe further down the line we can fix this or have a better solution for it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Especially in Harbor I doubt individual users have significant amounts of data attached to their personal account. But in that case there is indeed little use in adding Dex as a layer on migrated installations.


Bringing an external identity provider remains supported, and the two populations stay mutually exclusive, as they are under Keycloak:

- **Users created in APL** originate in the values repository and are rendered into Dex's `staticPasswords` from their materialised form on the cluster, as described above. The values repository remains their system of record.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why is the only considered approach to render the configuration?

There were ideas before to not use apl-operator for purposes anymore, where it has to deal with mixes of resources and states of the cluster. Teams are somewhere on the border of this, but too many templates need the information which teams exist. With users however, reading resources, processing them, and writing them back to another resource seems quite complicated.
What if API were to read and write the configuration file resource directly? It would require a separate backup. Are there other reasons this was not considered?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

TBH I did not think of it. Could be a valid option. The apl-operator seemed the easiest one to me because it has the values structure and needs the configuration file on start up. So with some extra templating it can create users.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What I am aiming at is that I would rather avoid adding more complexity to the operator. Considering our discussions of possibly migrating code, actually simplifying would help in the long run.

I do see the advantage of keeping everything in the values repository however. One similar idea: The API could write out the users as SealedSecret resources, and External Secrets Operator could select the resulting Secrets to produce the configuration file. That is all components we already have.

- **Runs a pre-release Dex.** Auth sessions and RP-initiated logout are merged on Dex's master branch but unreleased (dexidp/dex#4560). Without sessions there is no single sign-on across applications that run their own OIDC flow, and no logout endpoint. The image is therefore pinned to a master digest with `DEX_SESSIONS_ENABLED=true`. **APL must not be released while this pin stands.**
- **Single sign-on needs explicit configuration.** `sessions.ssoSharedWithDefault` defaults to `none`, which gives no SSO at all. It is set to `all`.
- **Every claim must be requested.** Keycloak attached `groups` through a protocol mapper regardless of scope; Dex only emits a claim when its scope is requested (`server/tokens/issuer.go`). Consumers that previously asked for `openid` alone now need the full scope list, or they authenticate successfully with no authorization.
- **Logout requires the ID token.** Dex refuses `post_logout_redirect_uri` without `id_token_hint`, and a browser redirect cannot carry one. Logout is therefore driven from oauth2-proxy's `backend_logout_url`, which substitutes `{id_token}`.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is that a problem, or the solution (i.e. OAuth2-Proxy)? To be fair this parameter is also recommended in Keycloak, but optional.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

A solution, did not test the logout option in the PoC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants