diff --git a/docs/configuration/uds-operator.md b/docs/configuration/uds-operator.md index c5e9f5053..0fc42f551 100644 --- a/docs/configuration/uds-operator.md +++ b/docs/configuration/uds-operator.md @@ -21,6 +21,7 @@ The UDS Operator plays a pivotal role in managing the lifecycle of UDS Package C - **SSO Group Authentication:** - Group authentication determines who can access the application based on keycloak group membership. - At this time `anyOf` allows defining a list of groups, a user must belong to at least one of them. + - Custom client `protocolMapper`'s that will be created alongside the client and added to the client's dedicated scope. - **Authservice Protection:** - Authservice authentication provides application agnostic SSO for applications that opt-in. {{% alert-caution %}} @@ -61,7 +62,7 @@ spec: port: 9411 description: "Tempo" - # SSO allows for the creation of Keycloak clients and with automatic secret generation + # SSO allows for the creation of Keycloak clients and with automatic secret generation and protocolMappers sso: - name: Grafana Dashboard clientId: uds-core-admin-grafana @@ -70,6 +71,22 @@ spec: groups: anyOf: - /UDS Core/Admin + # Define protocolMappers to be created as dedicated scopes for the client + protocolMappers: + - name: username + protocol: "openid-connect" + protocolMapper: "oidc-usermodel-property-mapper" + config: + user.attribute: "username" + claim.name: "username" + userinfo.token.claim: "true" + - name: email + protocol: "openid-connect" + protocolMapper: "oidc-usermodel-property-mapper" + config: + user.attribute: "email" + claim.name: "email" + userinfo.token.claim: "true" ``` ### Example UDS Package CR with SSO Templating diff --git a/src/pepr/operator/controllers/keycloak/types.ts b/src/pepr/operator/controllers/keycloak/types.ts index 028fcad0b..bd20fe20d 100644 --- a/src/pepr/operator/controllers/keycloak/types.ts +++ b/src/pepr/operator/controllers/keycloak/types.ts @@ -1,3 +1,5 @@ +import { ProtocolMapper } from "../../crd/generated/package-v1alpha1"; + export interface Client { alwaysDisplayInConsole: boolean; attributes: Record; @@ -17,6 +19,7 @@ export interface Client { notBefore: number; optionalClientScopes: string[]; protocol: string; + protocolMappers?: ProtocolMapper[]; publicClient: boolean; redirectUris: string[]; registrationAccessToken?: string; @@ -48,6 +51,7 @@ export const clientKeys = [ "notBefore", "optionalClientScopes", "protocol", + "protocolMappers", "publicClient", "redirectUris", "registrationAccessToken", diff --git a/src/pepr/operator/crd/generated/package-v1alpha1.ts b/src/pepr/operator/crd/generated/package-v1alpha1.ts index cd0f7330c..69d17692d 100644 --- a/src/pepr/operator/crd/generated/package-v1alpha1.ts +++ b/src/pepr/operator/crd/generated/package-v1alpha1.ts @@ -538,7 +538,7 @@ export interface Sso { */ enabled?: boolean; /** - * The client sso group type + * The client SSO group type */ groups?: Groups; /** @@ -549,6 +549,10 @@ export interface Sso { * Specifies the protocol of the client, either 'openid-connect' or 'saml' */ protocol?: Protocol; + /** + * Protocol Mappers to configure on the client + */ + protocolMappers?: ProtocolMapper[]; /** * Defines whether the client requires a client secret for authentication */ @@ -594,23 +598,48 @@ export enum ClientAuthenticatorType { } /** - * The client sso group type + * The client SSO group type */ export interface Groups { /** - * List of groups allowed to access to client + * List of groups allowed to access the client */ anyOf?: string[]; } /** * Specifies the protocol of the client, either 'openid-connect' or 'saml' + * + * Protocol of the mapper */ export enum Protocol { OpenidConnect = "openid-connect", Saml = "saml", } +export interface ProtocolMapper { + /** + * Configuration options for the mapper. + */ + config?: { [key: string]: string }; + /** + * Whether user consent is required for this mapper + */ + consentRequired?: boolean; + /** + * Name of the mapper + */ + name: string; + /** + * Protocol of the mapper + */ + protocol: Protocol; + /** + * Protocol Mapper type of the mapper + */ + protocolMapper: string; +} + export interface Status { authserviceClients?: string[]; endpoints?: string[]; diff --git a/src/pepr/operator/crd/sources/package/v1alpha1.ts b/src/pepr/operator/crd/sources/package/v1alpha1.ts index d228a0c6b..33d288bc8 100644 --- a/src/pepr/operator/crd/sources/package/v1alpha1.ts +++ b/src/pepr/operator/crd/sources/package/v1alpha1.ts @@ -303,6 +303,42 @@ const sso = { type: "string", }, }, + protocolMappers: { + description: "Protocol Mappers to configure on the client", + type: "array", + default: [], + items: { + type: "object", + required: ["name", "protocol", "protocolMapper"], + properties: { + name: { + description: "Name of the mapper", + type: "string", + }, + protocol: { + description: "Protocol of the mapper", + type: "string", + enum: ["openid-connect", "saml"], + }, + protocolMapper: { + description: "Protocol Mapper type of the mapper", + type: "string", + }, + consentRequired: { + description: "Whether user consent is required for this mapper", + type: "boolean", + default: false, + }, + config: { + description: "Configuration options for the mapper.", + type: "object", + additionalProperties: { + type: "string", + }, + }, + }, + }, + }, rootUrl: { description: "Root URL appended to relative URLs", type: "string", @@ -359,11 +395,11 @@ const sso = { }, }, groups: { - description: "The client sso group type", + description: "The client SSO group type", type: "object", properties: { anyOf: { - description: "List of groups allowed to access to client", + description: "List of groups allowed to access the client", type: "array", items: { type: "string",