Skip to content

feat(CORE-27): allow opt-in public clients#2598

Merged
mjnagel merged 7 commits intomainfrom
sebastianlaskawiec/core-27
Apr 27, 2026
Merged

feat(CORE-27): allow opt-in public clients#2598
mjnagel merged 7 commits intomainfrom
sebastianlaskawiec/core-27

Conversation

@slaskawi
Copy link
Copy Markdown
Contributor

@slaskawi slaskawi commented Apr 20, 2026

Description

This Pull Request adds a new ADR as well as the implementation for Public Keycloak Clients.

Related Issue

Relates to https://linear.app/defense-unicorns/issue/CORE-27/consider-allowing-public-clients

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Other (security config, docs update, etc)

Steps to Validate

Tested automatically:

  • The negative case is tested in this repo
  • The positive case is tested in UDS Identity Config

Checklist before merging

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces an opt-in security hardening flag that allows non-device-flow Keycloak SSO clients configured as publicClient: true, while keeping stricter defaults and adding validation, tests, chart plumbing, and documentation.

Changes:

  • Add SECURITY_HARDENING_PUBLIC_CLIENTS_ENABLED (default "false") to Keycloak realmInitEnv, propagate it into the realm env Secret, and validate its schema.
  • Update the UDS Operator Package admission validator to (1) always reject inherently-incompatible public client options and (2) gate non-device-flow public clients behind the new flag.
  • Add unit/integration tests, helm-unittest coverage, docs updates, and an ADR describing the decision.

Reviewed changes

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

Show a summary per file
File Description
test/vitest/keycloak-public-clients.spec.ts Adds an integration test asserting standard-flow public clients are denied by default.
src/pepr/operator/index.ts Watches keycloak-realm-env Secret updates to refresh the in-memory public-clients flag.
src/pepr/operator/crd/validators/package-validator.ts Splits public-client validation into always-enforced guards plus a flag-gated non-device-flow check.
src/pepr/operator/crd/validators/package-validator.spec.ts Adds unit test coverage for always-enforced and flag-gated public-client behaviors.
src/pepr/operator/controllers/config/types.ts Extends operator config shape with securityHardeningPublicClientsEnabled.
src/pepr/operator/controllers/config/config.ts Loads the flag from keycloak-realm-env at startup and updates it on Secret changes.
src/keycloak/chart/values.yaml Introduces realmInitEnv.SECURITY_HARDENING_PUBLIC_CLIENTS_ENABLED default.
src/keycloak/chart/values.schema.json Adds schema validation for the new realmInitEnv value.
src/keycloak/chart/tests/kc_public_clients_test.yaml Adds helm-unittest assertions for Secret propagation of the new realm env key.
docs/reference/configuration/identity-and-authorization.md Documents the new flag and the risks/constraints of public clients.
docs/how-to-guides/identity-and-authorization/register-and-customize-sso-clients.mdx Mentions the new flag in the context of client customization guidance.
docs/how-to-guides/identity-and-authorization/configure-user-account-settings.mdx Adds an optional procedure step and verification notes for enabling public clients.
docs/how-to-guides/identity-and-authorization/configure-device-flow.mdx Updates device-flow guidance to reflect the new default/opt-in behavior.
adrs/0010-allow-opt-in-public-clients.md Records the rationale and decision for a default-off opt-in flag.

Comment thread src/pepr/operator/controllers/config/config.ts Outdated
Comment thread src/pepr/operator/controllers/config/config.ts Outdated
Comment thread src/pepr/operator/controllers/config/types.ts Outdated
Comment thread docs/reference/configuration/identity-and-authorization.md Outdated
Comment thread docs/how-to-guides/identity-and-authorization/configure-device-flow.mdx Outdated
Comment thread src/pepr/operator/index.ts Outdated
Comment thread docs/how-to-guides/identity-and-authorization/configure-user-account-settings.mdx Outdated
Comment thread docs/how-to-guides/identity-and-authorization/configure-user-account-settings.mdx Outdated
Comment thread docs/how-to-guides/identity-and-authorization/configure-device-flow.mdx Outdated
slaskawi added a commit to defenseunicorns/uds-identity-config that referenced this pull request Apr 20, 2026
Adds an `allow-public-clients` toggle on the UDS Client Policy executor,
wired through `SECURITY_HARDENING_PUBLIC_CLIENTS_ENABLED` in realm.json5.
When the toggle is true, the executor permits `publicClient: true` only if
the client enforces PKCE with the S256 challenge method. When false (the
default), all public clients are rejected. Companion to defenseunicorns/uds-core#2598.
Comment thread adrs/0010-allow-opt-in-public-clients.md Outdated
Comment thread adrs/0010-allow-opt-in-public-clients.md Outdated
Comment thread adrs/0010-allow-opt-in-public-clients.md Outdated
Comment thread adrs/0010-allow-opt-in-public-clients.md Outdated
Comment thread adrs/0010-allow-opt-in-public-clients.md Outdated
Comment thread adrs/0010-allow-opt-in-public-clients.md Outdated
Comment thread docs/how-to-guides/identity-and-authorization/configure-user-account-settings.mdx Outdated
Comment thread src/keycloak/chart/values.yaml Outdated
Comment thread src/pepr/operator/crd/validators/package-validator.ts Outdated
@slaskawi slaskawi force-pushed the sebastianlaskawiec/core-27 branch 2 times, most recently from 8ca75b1 to 20ebeaa Compare April 21, 2026 08:29
@slaskawi slaskawi marked this pull request as ready for review April 21, 2026 08:29
@slaskawi slaskawi requested a review from a team as a code owner April 21, 2026 08:29
Comment thread src/pepr/operator/controllers/config/config.ts Outdated
Comment thread src/pepr/operator/crd/validators/package-validator.ts
Comment thread test/vitest/keycloak-public-clients.spec.ts
Comment thread adrs/0010-allow-opt-in-public-clients.md Outdated
Comment thread src/pepr/operator/crd/validators/package-validator.ts Outdated
Comment thread adrs/0010-allow-opt-in-public-clients.md Outdated
Comment thread src/pepr/operator/crd/validators/package-validator.ts
@slaskawi slaskawi force-pushed the sebastianlaskawiec/core-27 branch from fa9d4c2 to d99420e Compare April 23, 2026 06:46
@slaskawi slaskawi force-pushed the sebastianlaskawiec/core-27 branch from 7e45ba1 to 72e2138 Compare April 23, 2026 07:51
UDS bundle overrides coerce YAML scalars to their native type, so a bundle
passing ALLOW_PUBLIC_CLIENTS: "true" (string) arrives at the operator-config
chart as a boolean and fails the string-only schema. Widen the schema to
accept either form; Helm's quote filter in secret.yaml stringifies both to
the same Secret value, so the operator's === "true" check still works.
Comment thread src/pepr/uds-operator-config/values.schema.json Outdated
Copy link
Copy Markdown
Contributor

@mjnagel mjnagel left a comment

Choose a reason for hiding this comment

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

LGTM pending two open threads.

Comment thread src/pepr/operator/crd/validators/package-validator.spec.ts Outdated
@slaskawi slaskawi changed the title feat(CORE-27): allow opt-in public clients via SECURITY_HARDENING flag feat(CORE-27): allow opt-in public clients Apr 27, 2026
@mjnagel mjnagel merged commit 9af5ca7 into main Apr 27, 2026
39 checks passed
@mjnagel mjnagel deleted the sebastianlaskawiec/core-27 branch April 27, 2026 14:16
jasonwashburn pushed a commit that referenced this pull request Apr 28, 2026
🤖 I have created a release *beep* *boop*
---


##
[1.3.0](v1.2.0...v1.3.0)
(2026-04-28)


### Features

* **CORE-27:** allow opt-in public clients
([#2598](#2598))
([9af5ca7](9af5ca7))
* cycle gateways when istio gatewayTopology proxyProtocol changes
([#2595](#2595))
([5eceba7](5eceba7))


### Bug Fixes

* **ci:** run istio gen-crds in autogenerated-check
([#2605](#2605))
([40a1a97](40a1a97))
* handle apply properly for keycloak client secret
([#2627](#2627))
([c227289](c227289))
* re-add keycloak client registration authpol
([#2614](#2614))
([ebed871](ebed871))
* restore original loki write service account name
([#2599](#2599))
([a5386e2](a5386e2))
* updating prometheus to use endpointslice
([#2594](#2594))
([ba319c8](ba319c8))


### Miscellaneous

* add retry to multi-arch manifest check
([#2602](#2602))
([4e8ba23](4e8ba23))
* **deps-dev:** bump postcss from 8.5.8 to 8.5.12 in /scripts/renovate
([#2615](#2615))
([0922090](0922090))
* **deps:** update identity-config to 0.26.1
([#2616](#2616))
([fd105a2](fd105a2))
* **deps:** update istio to v1.29.2
([#2587](#2587))
([caddf35](caddf35))
* **deps:** update pepr to v1.1.6
([#2607](#2607))
([d9f2ae9](d9f2ae9))
* **deps:** update pepr to v1.1.7
([#2611](#2611))
([fd43cc3](fd43cc3))
* **deps:** update prometheus-stack
([#2546](#2546))
([6812697](6812697))
* **deps:** update velero chart to v12.0.1
([#2613](#2613))
([1048ae9](1048ae9))
* swap bundles google idp saml signing cert
([#2609](#2609))
([57795b9](57795b9))
* update istio CRDs to use v1 API
([#2606](#2606))
([079c361](079c361))


### Documentation

* add 1.3.0 release notes
([#2633](#2633))
([00468ab](00468ab))
* add keycloak admin handling doc
([#2597](#2597))
([328d19c](328d19c))
* add troubleshooting for too many open files
([#2612](#2612))
([0b64a05](0b64a05))
* update release notes for 1.2.1
([#2603](#2603))
([bfa8124](bfa8124))
* update release notes to include newest patches
([#2629](#2629))
([d59ca81](d59ca81))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.

5 participants