diff options
author | Andreas Geissler <andreas-geissler@telekom.de> | 2024-07-17 15:07:55 +0200 |
---|---|---|
committer | Andreas Geissler <andreas-geissler@telekom.de> | 2024-08-08 10:26:38 +0200 |
commit | 4881740b6385d11a53969aae7bf2050c8a5c8843 (patch) | |
tree | 072bd3e43ec21b2c06fc88c8cc233a05e12516b4 | |
parent | 004ebce85d8214df87689db574efd7f16c87524d (diff) |
[AUTHENTICATION] Fixes for REALM generation
- Some fixes for the client creation within the REALM.
- Addition function for SMTP server configuration
- README additions
- Kyverno policy violation fixes
Issue-ID: OOM-3306
Change-Id: I6df34be566257f40795e454a6a81b4743cb8edb1
Signed-off-by: Andreas Geissler <andreas-geissler@telekom.de>
-rw-r--r-- | kubernetes/authentication/Chart.yaml | 2 | ||||
-rw-r--r-- | kubernetes/authentication/README.md | 299 | ||||
-rw-r--r-- | kubernetes/authentication/templates/_utils.tpl | 122 | ||||
-rw-r--r-- | kubernetes/authentication/templates/authorizationpolicy.yaml | 2 | ||||
-rw-r--r-- | kubernetes/authentication/templates/requestauthentication.yaml | 2 | ||||
-rw-r--r-- | kubernetes/authentication/values.yaml | 63 |
6 files changed, 401 insertions, 89 deletions
diff --git a/kubernetes/authentication/Chart.yaml b/kubernetes/authentication/Chart.yaml index a3ac43c4e7..e8400aeb81 100644 --- a/kubernetes/authentication/Chart.yaml +++ b/kubernetes/authentication/Chart.yaml @@ -16,7 +16,7 @@ # limitations under the License. # ============LICENSE_END========================================================= apiVersion: v2 -version: 14.0.0 +version: 14.0.1 description: ONAP Realm creation, Oauth2Proxy installation and configuration name: authentication sources: diff --git a/kubernetes/authentication/README.md b/kubernetes/authentication/README.md index 75d8f05ebd..4907a1d9f1 100644 --- a/kubernetes/authentication/README.md +++ b/kubernetes/authentication/README.md @@ -1,7 +1,29 @@ -TBD: Description about settings... +# Helm Chart for Authentication Application +This component delivers: -``` +- Keycloak Realm creation and import +- (Optionally) creation of AuthenticationPolicies for Ingress to enable + OAuth Authentication and RoleBased access to Ingress APIs and UIs + +## REALM Configuration settings + +- In the configuration section "realmSettings" multiple REALMs can be configured +- Each REALM configuration has the following sections: + - [General REALM settings](#general-realm-settings) + - [CLIENT definitions](#client-definitions) + - (optional) [CLIENT SCOPE definitions](#client-scope-definitions) + - (optional) [Access control definitions](#access-control-definitions) + - (optional) [GROUP definitions](#group-definitions) + - (optional) [USER definitions](#user-definitions) + - (optional) [IDENTITY PROVIDER definitions](#identity-provider-and-mapper-definitions) + - (optional) [SMTP server definitions](#smtp-server-definitions) + +### General REALM settings + +This sections sets the realm general attributes shown in Keycloak + +```yaml realmSettings: - name: <Realm ID> - unique ID for a realm (e.g. "ONAP") displayName: <Display Name> - (optional) Keycloak Display Name (e.g. "ONAP Realm") @@ -10,45 +32,274 @@ realmSettings: admin: <admin theme> - (optional) Keycloak Theme for Admin UI (e.g. "base") account: <account theme> - (optional) Keycloak Theme for Account UI (e.g. "base") email: <email theme> - (optional) Keycloak Theme for Email UI (e.g. "base") - groups: - (optional) Group definitions - - name: <group name> - Group name - path: /path> - Group URL path - realmRoles: [ <role>,... ] - (optional) List of Realm roles - initialUsers: - (optional) List of initial users - - username: <user name> - Name of the User - password: <password> - Initial Password - email: <email> - Email Address - firstName: <first name> - (optional) First Name - lastName: <last name> - (optional) Last Name - groups: - (optional) group membership - - <group name> + attributes: + frontendUrl: "<Keycloak URL>" - External Url for Keycloak access (e.g. "https://keycloak-$PARAM_BASE_URL/") ``` -``` +### CLIENT definitions + +In this section each realm authentication client is defined e.g. portal-bff, oauth2-proxy, grafana + +possible "attribute" settings (maybe more): + - id.token.as.detached.signature: "false" + - exclude.session.state.from.auth.response: "false" + - tls.client.certificate.bound.access.tokens: "false" + - saml.allow.ecp.flow: "false" + - saml.assertion.signature: "false" + - saml.force.post.binding: "false" + - saml.multivalued.roles: "false" + - saml.encrypt: "false" + - saml.server.signature: "false" + - saml.server.signature.keyinfo.ext: "false" + - saml.artifact.binding: "false" + - saml_force_name_id_format: "false" + - saml.client.signature: "false" + - saml.authnstatement: "false" + - saml.onetimeuse.condition: "false" + - oidc.ciba.grant.enabled: "false" + - frontchannel.logout.session.required: "true" + - backchannel.logout.session.required: "true" + - backchannel.logout.revoke.offline.tokens: "false" + - client_credentials.use_refresh_token: "false" + - acr.loa.map: "{}" + - require.pushed.authorization.requests: "false" + - oauth2.device.authorization.grant.enabled: "false" + - display.on.consent.screen: "false" + - token.response.type.bearer.lower-case: "false" + - use.refresh.tokens: "true" + - post.logout.redirect.uris: '<url>' + +```yaml clients: oauth2_proxy: - clientId: "oauth2-proxy-onap" - name: "Oauth2 Proxy" - secret: 5YSOkJz99WHv8enDZPknzJuGqVSerELp - protocol: openid-connect - portal_app: - clientId: "portal-app" + clientId: "<client ID>" - client ID + name: "<client name>" - (optional) client name + secret: <client secret> - (optional) client secret + clientAuthenticatorType: <type> - (optional) auth type (default: client-secret) + protocol: <protocol> - (optional) auth protocol (default: openid-connect) + description: "<description>" - (optional) client description + baseUrl: "<base path>" - (optional) url subpath (e.g. /application) + rootUrl: "<root URL>" - (optional) root url + adminUrl: "<admin URL>" - (optional) admin url + bearerOnly: "<false|true>" - (optional) bearerOnly (default: false) + consentRequired: "<false|true>" - (optional) consentRequired (default: false) + standardFlowEnabled: "<false|true>" - (optional) standardFlowEnabled (default: true) + implicitFlowEnabled: "<false|true>" - (optional) implicitFlowEnabled (default: false) + directAccessGrantsEnabled: "<false|true>" - (optional) directAccessGrantsEnabled (default: true) + serviceAccountsEnabled: "<false|true>" - (optional) serviceAccountsEnabled (default: false) + frontchannelLogout: "<false|true>" - (optional) frontend channel logout (default: true) + surrogateAuthRequired: "<false|true>" - (optional) surrogate Auth Required (default: false) + publicClient: "<false|true>" - (optional) public Client (default: false) + attributes: - (optional) attributes settings (see code) + post.logout.redirect.uris: '<url>' - example + protocolMappers: - (optional) protocol mappers + - name: "Audience for Oauth2Proxy" - examples + protocolMapper: "oidc-audience-mapper" + config: + included.client.audience: "oauth2-proxy-onap" + id.token.claim: "false" + access.token.claim: "true" + included.custom.audience: "oauth2-proxy-onap" + - name: "SDC-User" + protocolMapper: "oidc-usermodel-attribute-mapper" + config: + multivalued: "false" + userinfo.token.claim: "true" + user.attribute: "sdc_user" + id.token.claim: "true" + access.token.claim: "true" + claim.name: "sdc_user" + jsonType.label: "String" + additionalDefaultScopes: + - "onap_roles" redirectUris: - "https://portal-$PARAM_BASE_URL/*" - "http://localhost/*" - protocol: openid-connect + webOrigins: + - "https://argocd-$PARAM_BASE_URL" + defaultClientScopes: + - "web-origins" + - "profile" + - "acr" + - "email" + - "roles" + - "groups" ``` +### CLIENT SCOPE definitions + +Here additional scopes besides the default scopes can be defined and set as default client scope + +default scopes: + + - roles + - groups + - acr + - profile + - address + - web-origin + - phone + - email + - offline_access + - role_list + - microprofile-jwt + +```yaml + defaultClientScopes: + - "onap_roles" + additionalClientScopes: + - name: onap_roles + description: OpenID Connect scope for add user onap roles to the access token + protocolMappers: + - name: aud + protocol: openid-connect + protocolMapper: oidc-audience-mapper + consentRequired: false + config: + included.client.audience: oauth2-proxy + id.token.claim: 'false' + access.token.claim: 'true' + - name: client roles + protocol: openid-connect + protocolMapper: oidc-usermodel-client-role-mapper + consentRequired: false + config: + multivalued: 'true' + userinfo.token.claim: 'false' + id.token.claim: 'true' + access.token.claim: 'true' + claim.name: onap_roles + jsonType.label: String + usermodel.clientRoleMapping.clientId: oauth2-proxy ``` + +### Access control definitions + +In this section additional roles (assignableRoles) besides the default roles can be set. + +default roles: + - user + - admin + - offline_access + - uma_authorization + - default-roles-<realm> + +(optional) accessRoles can be defined. +These access roles are used in the Ingress "Auhorization Policy" to restrict the access to certain services +The access role is assigned to a realm client (e.g. oauth2_proxy) + +```yaml accessControl: assignableRoles: - name: onap-operator-read description: "Allows to perform GET operations for all ONAP components" - associatedAccessRoles: [ "dmaap-bc-api-read", "dmaap-dr-node-api-read", "dmaap-dr-prov-api-read", "dmaap-mr-api-read", "msb-consul-api-read", "msb-discovery-api-read", "msb-eag-ui-read", "msb-iag-ui-read", "nbi-api-read", "aai-api-read", "aai-babel-api-read", "aai-sparkybe-api-read", "cds-blueprintsprocessor-api-read", "cds-ui-read", "cps-core-api-read", "cps-ncmp-dmi-plugin-api-read", "cps-temporal-api-read", "reaper-dc1-read", "sdc-be-api-read", "sdc-fe-ui-read", "sdc-wfd-be-api-read", "sdc-wfd-fe-ui-read", "so-admin-cockpit-ui-read", "so-api-read", "usecase-ui-read", "uui-server-read" ] - + associatedAccessRoles: [ "dmaap-bc-api-read", ... ] accessRoles: "oauth2_proxy": - name: dmaap-bc-api-read methodsAllowed: ["GET"] servicePrefix: dmaap-bc-api +``` + +### GROUP definitions + +```yaml + groups: - (optional) Group definitions + - name: <group name> - Group name + path: /path> - Group URL path + roles: [ <role>,... ] - (optional) List of Realm roles +``` + +### USER definitions + +```yaml + initialUsers: - (optional) List of initial users + - username: <user name> - Name of the User + firstName: <first name> - (optional) First Name + lastName: <last name> - (optional) Last Name + email: <email> - (optional) Email Address + emailVerified : <true|false>- (optional)Email verified + credentials: - (optional) credentials + - type: password - (optional) initial password (<pwd>: encrypted password, <salt>: used salt) + secretData: "{\"value\":\"<pwd>\",\"salt\":\"<salt>\"}" + credentialData: "{\"hashIterations\":27500,\"algorithm\":\"pbkdf2-sha256\"}" + attributes: - (optional) additional attributes + sdc_user: - example attribute + - "cs0008" + realmRoles: - (optional) assigned realm roles + - <role name> + groups: - (optional) group membership + - <group name> +``` + +### Identity Provider and Mapper definitions + +```yaml + identityProviders: + - name: "gitlab" + displayName: "gitlab" + config: + userInfoUrl: "https://gitlab.devops.telekom.de/oauth/userinfo" + validateSignature: "true" + clientId: "ee4e0db734157e9cdad16733656ba285f2f813354aa7c590a8693e48ed156860" + tokenUrl: "https://gitlab.devops.telekom.de/oauth/token" + jwksUrl: "https://gitlab.devops.telekom.de/oauth/discovery/keys" + issuer: "https://gitlab.devops.telekom.de" + useJwksUrl: "true" + authorizationUrl: "https://gitlab.devops.telekom.de/oauth/authorize" + clientAuthMethod: "client_secret_post" + syncMode: "IMPORT" + clientSecret: "gloas-35267790bf6fb7c4b507aea11db46d80174cb8ef4192e77424803b595eef735e" + defaultScope: "openid read_user email" + identityProviderMappers: + - name: "argo-admins" + identityProviderAlias: "gitlab" + identityProviderMapper: "oidc-advanced-group-idp-mapper" + config: + claims: "[{\"key\":\"groups_direct\",\"value\":\"dt-rc\"}]" + syncMode: "FORCE" + group: "/ArgoCDAdmins" + - name: "ArgoCDRestricted" + identityProviderAlias: "gitlab" + identityProviderMapper: "oidc-advanced-group-idp-mapper" + config: + claims: "[{\"key\":\"groups_direct\",\"value\":\"\"}]" + syncMode: "FORCE" + group: "/ArgoCDRestricted" + - name: "lastName " + identityProviderAlias: "gitlab" + identityProviderMapper: "oidc-user-attribute-idp-mapper" + config: + claim: "nickname" + syncMode: "FORCE" + user.attribute: "lastName" +``` + +### SMTP Server definitions + +```yaml + smtpServer: + password: "EYcQE44+AEYcQE44A!" + starttls: "true" + auth: "true" + port: "587" + host: "mailauth.telekom.de" + from: "dl_t-nap_support@telekom.de" + fromDisplayName: "tnapsupport" + ssl: "false" + user: "tnapsupport" +``` + +## Ingress Authentication settings + +Activating the Ingress Authentication (enabled: true) will create AuthorizationPolicy resources for each defined "accessControl.accessRoles" in a REALM definition. + +``` +ingressAuthentication: + enabled: false + exceptions: + - '{{ include "ingress.config.host" (dict "dot" . "baseaddr" "keycloak-ui") }}' + - '{{ include "ingress.config.host" (dict "dot" . "baseaddr" "portal-ui") }}' + - '{{ include "ingress.config.host" (dict "dot" . "baseaddr" "minio-console") }}' + - '{{ include "ingress.config.host" (dict "dot" . "baseaddr" "uui-server") }}' ```
\ No newline at end of file diff --git a/kubernetes/authentication/templates/_utils.tpl b/kubernetes/authentication/templates/_utils.tpl index 0cdcd7955a..806f96164a 100644 --- a/kubernetes/authentication/templates/_utils.tpl +++ b/kubernetes/authentication/templates/_utils.tpl @@ -45,6 +45,7 @@ enabled: true {{ include "auth._users" $realm }} {{ include "auth._identity" $realm }} {{ include "auth._identityMapper" $realm }} +{{ include "auth._smtpServer" $realm }} {{ include "auth._attributes" (dict "dot" $dot "realm" $realm) }} {{- end -}} @@ -142,84 +143,60 @@ Usage: clients: {{- range $index, $client := $realm.clients }} - clientId: "{{ $client.clientId }}" + {{- if $client.name }} name: "{{ $client.name }}" - description: "{{ default "" $client.description }}" + {{- end }} + {{- if $client.description }} + description: "{{ $client.description }}" + {{- end }} {{- if $client.rootUrl }} rootUrl: {{ tpl $client.rootUrl $dot }} - {{- else }} - rootUrl: "" {{- end }} {{- if $client.adminUrl }} adminUrl: {{ tpl $client.adminUrl $dot }} - {{- else }} - adminUrl: "" {{- end }} {{- if $client.baseUrl }} baseUrl: {{ tpl $client.baseUrl $dot }} - {{- else }} - baseUrl: "" {{- end }} - surrogateAuthRequired: false + surrogateAuthRequired: {{ default false $client.surrogateAuthRequired }} enabled: true alwaysDisplayInConsole: false - clientAuthenticatorType: "client-secret" - secret: "{{ default "" $client.secret }}" + clientAuthenticatorType: {{ default "client-secret" $client.clientAuthenticatorType }} + {{- if $client.secret }} + secret: "{{ $client.secret }}" + {{- end }} + {{- if $client.redirectUris }} redirectUris: - {{- if $client.redirectUris }} {{- range $index2, $url := $client.redirectUris }} - {{ tpl $url $dot }} {{- end }} - {{- else }} - - "*" - {{- end }} - {{- if $client.webOrigins }} + {{- else }} + redirectUris: [] + {{- end }} + {{- if $client.webOrigins }} webOrigins: {{- range $index3, $web := $client.webOrigins }} - - {{ $web }} + - {{ $web | quote }} {{- end }} - {{- else }} + {{- else }} webOrigins: [] - {{- end }} + {{- end }} notBefore: 0 - bearerOnly: false - consentRequired: false - standardFlowEnabled: true - implicitFlowEnabled: false - directAccessGrantsEnabled: true - serviceAccountsEnabled: false - publicClient: false - frontchannelLogout: true - protocol: "{{ $client.protocol }}" + bearerOnly: {{ default false $client.bearerOnly }} + consentRequired: {{ default false $client.consentRequired }} + standardFlowEnabled: {{ default true $client.standardFlowEnabled }} + implicitFlowEnabled: {{ default false $client.implicitFlowEnabled }} + directAccessGrantsEnabled: {{ default true $client.directAccessGrantsEnabled }} + serviceAccountsEnabled: {{ default false $client.serviceAccountsEnabled }} + publicClient: {{ default false $client.publicClient }} + frontchannelLogout: {{ default false $client.frontchannelLogout }} + protocol: "{{ default "openid-connect" $client.protocol }}" + {{- if $client.attributes }} attributes: - id.token.as.detached.signature: "false" - saml.assertion.signature: "false" - saml.force.post.binding: "false" - saml.multivalued.roles: "false" - saml.encrypt: "false" - saml.server.signature: "false" - saml.server.signature.keyinfo.ext: "false" - exclude.session.state.from.auth.response: "false" - saml.artifact.binding: "false" - saml_force_name_id_format: "false" - saml.client.signature: "false" - saml.authnstatement: "false" - saml.onetimeuse.condition: "false" - tls-client-certificate-bound-access-tokens: "false" - oidc.ciba.grant.enabled: "false" - backchannel.logout.session.required: "true" - client_credentials.use_refresh_token: "false" - acr.loa.map: "{}" - require.pushed.authorization.requests: "false" - oauth2.device.authorization.grant.enabled: "false" - display.on.consent.screen: "false" - backchannel.logout.revoke.offline.tokens: "false" - token.response.type.bearer.lower-case: "false" - use.refresh.tokens: "true" - {{- if $client.additionalAttributes }} - {{- range $key,$value := $client.additionalAttributes }} + {{- range $key,$value := $client.attributes }} {{ $key }}: {{ tpl $value $dot }} {{- end }} - {{- end }} + {{- end }} authenticationFlowBindingOverrides: {} fullScopeAllowed: true nodeReRegistrationTimeout: -1 @@ -235,21 +212,27 @@ clients: {{- end }} {{- end }} defaultClientScopes: + {{- if $client.defaultClientScopes }} + {{- range $index2, $scope := $client.defaultClientScopes }} + - {{ $scope }} + {{- end }} + {{- else }} - web-origins - - acr - profile + - acr - email - {{- if $client.additionalDefaultScopes }} - {{- range $index2, $scope := $client.additionalDefaultScopes }} - - {{ $scope }} - {{- end }} {{- end }} optionalClientScopes: + {{- if $client.optionalClientScopes }} + {{- range $index2, $scope := $client.optionalClientScopes }} + - {{ $scope }} + {{- end }} + {{- else }} - address - phone - offline_access - - groups - microprofile-jwt + {{- end }} {{- end }} {{- end }} @@ -716,7 +699,9 @@ users: enabled: true totp: false email: "{{ default "" $user.email }}" - emailVerified: true + emailVerified: "{{ default true $user.emailVerified }}" + firstName: "{{ default "" $user.firstName }}" + lastName: "{{ default "" $user.lastName }}" {{- if $user.attributes }} attributes: {{ toYaml $user.attributes | nindent 6 }} @@ -800,6 +785,19 @@ identityProviderMappers: {{- end }} {{/* +Renders the smtpServer section in a realm. +Usage: +{{ include "auth._smtpServer" ( dict "dot" .Values) }} +*/}} +{{- define "auth._smtpServer" -}} +{{- $dot := default . .dot -}} +{{- if $dot.smtpServer }} +smtpServer: + {{ toYaml $dot.smtpServer | nindent 2 }} +{{- end }} +{{- end }} + +{{/* Renders the attributes section in a realm. Usage: {{ include "auth._attributes" ( dict "dot" . "realm" $realm ) }} @@ -808,6 +806,6 @@ Usage: {{- $dot := default . .dot -}} {{- $realm := (required "'realm' param, set to the specific service, is required." .realm) -}} attributes: - frontentUrl: {{ tpl $realm.attributes.frontendUrl $dot }} + frontendUrl: {{ tpl $realm.attributes.frontendUrl $dot }} acr.loa.map: "{\"ABC\":\"5\"}" {{- end }} diff --git a/kubernetes/authentication/templates/authorizationpolicy.yaml b/kubernetes/authentication/templates/authorizationpolicy.yaml index f4857bdbac..abd40725da 100644 --- a/kubernetes/authentication/templates/authorizationpolicy.yaml +++ b/kubernetes/authentication/templates/authorizationpolicy.yaml @@ -87,4 +87,4 @@ spec: selector: matchLabels: istio: ingress -{{- end }}
\ No newline at end of file +{{- end }} diff --git a/kubernetes/authentication/templates/requestauthentication.yaml b/kubernetes/authentication/templates/requestauthentication.yaml index 036680d7cb..92bea9f48e 100644 --- a/kubernetes/authentication/templates/requestauthentication.yaml +++ b/kubernetes/authentication/templates/requestauthentication.yaml @@ -33,4 +33,4 @@ spec: - issuer: "https://{{ include "ingress.config.host" (dict "dot" $dot "baseaddr" "keycloak-ui") }}/{{ .Values.keycloak.relativePath }}realms/master" jwksUri: {{ .Values.keycloak.intURL }}realms/master/protocol/openid-connect/certs forwardOriginalToken: true -{{- end }}
\ No newline at end of file +{{- end }} diff --git a/kubernetes/authentication/values.yaml b/kubernetes/authentication/values.yaml index 94e9f7031c..ba99879e87 100644 --- a/kubernetes/authentication/values.yaml +++ b/kubernetes/authentication/values.yaml @@ -49,8 +49,60 @@ onap-keycloak-config-cli: secrets: KEYCLOAK_PASSWORD: secret existingConfigSecret: "keycloak-config-cli-config-realms" + securityContext: + runAsGroup: 65534 + runAsNonRoot: true + runAsUser: 65534 + seccompProfile: + type: RuntimeDefault + containerSecurityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + - CAP_NET_RAW + readOnlyRootFilesystem: true + resources: + limits: + cpu: "1" + memory: 500Mi + requests: + cpu: 100m + memory: 10Mi onap-oauth2-proxy: + securityContext: + capabilities: + drop: + - ALL + - CAP_NET_RAW + + resources: + limits: + cpu: 500m + memory: 500Mi + requests: + cpu: 500m + memory: 500Mi + + initContainers: + waitForRedis: + #image: + # repository: "dockerhub.devops.telekom.de/alpine" + # tag: "3.20" + securityContext: + capabilities: + drop: + - ALL + - CAP_NET_RAW + resources: + limits: + cpu: 100m + memory: 300Mi + requests: + cpu: 100m + memory: 300Mi + # Oauth client configuration specifics config: # Create a new secret with the following command @@ -99,8 +151,19 @@ onap-oauth2-proxy: redis: # provision an instance of the redis sub-chart enabled: true + master: + containerSecurityContext: + capabilities: + drop: ["ALL", "CAP_NET_RAW"] + replica: + containerSecurityContext: + capabilities: + drop: ["ALL", "CAP_NET_RAW"] sentinel: enabled: true + containerSecurityContext: + capabilities: + drop: ["ALL", "CAP_NET_RAW"] serviceAccount: nameOverride: keycloak-init |