What would you like to be added?
A new namespace-scoped CRD OIDCIssuer that lives in the project namespace (project-<name>). A project admin can create one or more OIDCIssuer resources to register custom OIDC issuers with the onboarding API without platform operator involvement.
The system generates a globally unique, human-readable prefix for each registered issuer and exposes it in status.prefix. Once registered, the issuer is trusted globally by the onboarding API (not just within the owning project). Members from this issuer can be referenced in any Project.spec.members or Workspace.spec.members by prepending the prefix to the username or group name. The prefix includes the trailing colon so that the full member name is simply status.prefix + username. A team can register an issuer in their own project and a different project admin can grant those identities access to their project by using the same prefix.
API design
The spec is modelled after the Gardener OpenIDConnect CRD, with usernamePrefix and groupsPrefix omitted from spec because they are system-generated and exposed in status instead.
apiVersion: core.openmcp.cloud/v1alpha1
kind: OIDCIssuer
metadata:
name: github-actions
namespace: project-my-team
spec:
# Required: URL the provider signs ID tokens as (the "iss" claim).
issuerURL: https://token.actions.githubusercontent.com
# Required: acceptable values for the "aud" claim in ID tokens.
audiences:
- https://github.com/my-org
# Required: JWT claim to use as the username.
usernameClaim: sub
# Optional: JWT claim to use for group membership. Omit if the provider does not issue groups.
groupsClaim: groups
# Optional: PEM-encoded CA bundle for validating the provider's TLS certificate.
# caBundle: |
# -----BEGIN CERTIFICATE-----
# ...
# Optional: key-value pairs that must be present in the ID token.
requiredClaims:
# repository: my-org/my-repo
# Optional: static JWKS for offline validation (base64-encoded JSON Web Key Set).
# jwks:
# keys: <base64>
status:
# Derived as "project:<project>:issuer:<name>:". Includes the trailing colon.
# Members from this issuer are referenced as "<prefix><username>".
prefix: "project:my-team:issuer:github-actions:"
conditions:
- type: Ready
status: "True"
The prefix is derived deterministically as project:<project-name>:issuer:<oidcissuer-name>: and written to status.prefix. Global uniqueness is guaranteed structurally: Project names are cluster-scoped and unique, and OIDCIssuer names are unique within their namespace, so no two resources can produce the same prefix.
Usage example
After creating the OIDCIssuer in project-my-team, a project admin adds members using the generated prefix:
apiVersion: core.openmcp.cloud/v1alpha1
kind: Project
metadata:
name: my-team
spec:
members:
- kind: User
name: openmcp:alice@example.com # system IDP, unchanged
roles: [admin]
- kind: User
name: project:my-team:issuer:github-actions:repo:my-org/my-repo:ref:refs/heads/main
roles: [view] # GitHub Actions workflow identity
- kind: Group
name: project:my-team:issuer:github-actions:my-org # GitHub org as group
roles: [view]
Because the registered issuer is trusted globally, a different project admin can reference the same identities in their own project without registering the issuer again:
apiVersion: core.openmcp.cloud/v1alpha1
kind: Project
metadata:
name: other-team
spec:
members:
- kind: User
name: project:my-team:issuer:github-actions:repo:my-org/my-repo:ref:refs/heads/main
roles: [view]
Constraints
OIDCIssuer is namespace-scoped, living in the project namespace. Only project admins can create and delete it.
- The registered issuer is trusted globally by the onboarding API. Any principal from this issuer can be granted access to any Project or Workspace by any admin with edit access to that resource, using the generated prefix.
- The registered issuer is not automatically trusted by ControlPlanes. Those continue to configure their own
spec.iam.oidc.extraProviders independently. This feature only concerns authentication to the onboarding API (managing Projects, Workspaces, ControlPlanes).
OIDCIssuer cannot be created outside a project namespace.
Acceptance criteria
Open question: implementation location
The controller reconciling OIDCIssuer must register the issuer with the onboarding cluster's kube-apiserver. The mechanism depends on the cluster flavor:
| Onboarding cluster flavor |
Mechanism |
| Gardener shoot |
Create an OpenIDConnect resource (authentication.gardener.cloud/v1alpha1) via gardener-extension-shoot-oidc-service |
| Vanilla Kubernetes (>= 1.30) |
Patch the AuthenticationConfiguration file (apiserver.config.k8s.io/v1) directly |
| Other managed Kubernetes |
Provider-specific (may not be feasible at all) |
Implementing in platform-service-project-workspace is the most direct option, but would introduce a conditional dependency on gardener-extension-shoot-oidc-service when the onboarding cluster is a Gardener shoot, coupling a generic onboarding service to a specific infrastructure provider. An alternative is to introduce a separate, platform-specific adapter component: platform-service-project-workspace manages only the OIDCIssuer CRD lifecycle (prefix generation, status), while the adapter handles the actual trust registration on the underlying cluster.
Why is this needed?
Today, OIDC issuers trusted by the onboarding API are configured solely by platform operators. This blocks two common use cases:
-
Access management: Teams that use their own OIDC issuer (a corporate SSO, a GitHub Actions issuer, a Kubernetes cluster's ServiceAccount issuer) cannot reference their own users or groups in Project.spec.members or Workspace.spec.members. Every identity must come from the system IDP.
-
Automation bootstrap: Automated actors (CI pipelines, orchestrators) can only authenticate to the onboarding API if their issuer is trusted at platform level. There is no self-service path for a project owner to grant their own automation access. The available workaround is to create a Kubernetes ServiceAccount inside the project and generate short-lived tokens for it, but this requires manual token rotation and adds significant maintenance overhead for any team running continuous automation.
What would you like to be added?
A new namespace-scoped CRD
OIDCIssuerthat lives in the project namespace (project-<name>). A project admin can create one or moreOIDCIssuerresources to register custom OIDC issuers with the onboarding API without platform operator involvement.The system generates a globally unique, human-readable prefix for each registered issuer and exposes it in
status.prefix. Once registered, the issuer is trusted globally by the onboarding API (not just within the owning project). Members from this issuer can be referenced in anyProject.spec.membersorWorkspace.spec.membersby prepending the prefix to the username or group name. The prefix includes the trailing colon so that the full member name is simplystatus.prefix + username. A team can register an issuer in their own project and a different project admin can grant those identities access to their project by using the same prefix.API design
The spec is modelled after the Gardener
OpenIDConnectCRD, withusernamePrefixandgroupsPrefixomitted from spec because they are system-generated and exposed in status instead.The prefix is derived deterministically as
project:<project-name>:issuer:<oidcissuer-name>:and written tostatus.prefix. Global uniqueness is guaranteed structurally: Project names are cluster-scoped and unique, and OIDCIssuer names are unique within their namespace, so no two resources can produce the same prefix.Usage example
After creating the
OIDCIssuerinproject-my-team, a project admin adds members using the generated prefix:Because the registered issuer is trusted globally, a different project admin can reference the same identities in their own project without registering the issuer again:
Constraints
OIDCIssueris namespace-scoped, living in the project namespace. Only project admins can create and delete it.spec.iam.oidc.extraProvidersindependently. This feature only concerns authentication to the onboarding API (managing Projects, Workspaces, ControlPlanes).OIDCIssuercannot be created outside a project namespace.Acceptance criteria
OIDCIssuerin their project namespace without platform operator involvement.status.prefixof the formproject:<project>:issuer:<name>:for eachOIDCIssuer.Project.spec.membersandWorkspace.spec.membersin any project using<prefix><name>.Open question: implementation location
The controller reconciling
OIDCIssuermust register the issuer with the onboarding cluster's kube-apiserver. The mechanism depends on the cluster flavor:OpenIDConnectresource (authentication.gardener.cloud/v1alpha1) viagardener-extension-shoot-oidc-serviceAuthenticationConfigurationfile (apiserver.config.k8s.io/v1) directlyImplementing in
platform-service-project-workspaceis the most direct option, but would introduce a conditional dependency ongardener-extension-shoot-oidc-servicewhen the onboarding cluster is a Gardener shoot, coupling a generic onboarding service to a specific infrastructure provider. An alternative is to introduce a separate, platform-specific adapter component:platform-service-project-workspacemanages only theOIDCIssuerCRD lifecycle (prefix generation, status), while the adapter handles the actual trust registration on the underlying cluster.Why is this needed?
Today, OIDC issuers trusted by the onboarding API are configured solely by platform operators. This blocks two common use cases:
Access management: Teams that use their own OIDC issuer (a corporate SSO, a GitHub Actions issuer, a Kubernetes cluster's ServiceAccount issuer) cannot reference their own users or groups in
Project.spec.membersorWorkspace.spec.members. Every identity must come from the system IDP.Automation bootstrap: Automated actors (CI pipelines, orchestrators) can only authenticate to the onboarding API if their issuer is trusted at platform level. There is no self-service path for a project owner to grant their own automation access. The available workaround is to create a Kubernetes
ServiceAccountinside the project and generate short-lived tokens for it, but this requires manual token rotation and adds significant maintenance overhead for any team running continuous automation.