Merge "[POLICY] Fix Kyverno Policy violations"
diff --git a/kubernetes/authentication/Chart.yaml b/kubernetes/authentication/Chart.yaml
index a3ac43c..e8400ae 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 75d8f05..4907a1d 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 @@
       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 0cdcd79..806f961 100644
--- a/kubernetes/authentication/templates/_utils.tpl
+++ b/kubernetes/authentication/templates/_utils.tpl
@@ -45,6 +45,7 @@
 {{ 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 @@
 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 @@
       {{- end }}
       {{- end }}
     defaultClientScopes:
-      - web-origins
-      - acr
-      - profile
-      - email
-      {{- if $client.additionalDefaultScopes }}
-      {{-   range $index2, $scope := $client.additionalDefaultScopes }}
+      {{- if $client.defaultClientScopes }}
+      {{-   range $index2, $scope := $client.defaultClientScopes }}
       - {{ $scope }}
       {{-   end }}
+      {{- else }}
+      - web-origins
+      - profile
+      - acr
+      - email
       {{- 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 @@
     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 @@
 {{- 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 @@
 {{- $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 f4857bd..abd4072 100644
--- a/kubernetes/authentication/templates/authorizationpolicy.yaml
+++ b/kubernetes/authentication/templates/authorizationpolicy.yaml
@@ -87,4 +87,4 @@
   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 036680d..92bea9f 100644
--- a/kubernetes/authentication/templates/requestauthentication.yaml
+++ b/kubernetes/authentication/templates/requestauthentication.yaml
@@ -33,4 +33,4 @@
   - 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 94e9f70..ba99879 100644
--- a/kubernetes/authentication/values.yaml
+++ b/kubernetes/authentication/values.yaml
@@ -49,8 +49,60 @@
   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 @@
   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
diff --git a/kubernetes/uui/Chart.yaml b/kubernetes/uui/Chart.yaml
index 7c4a5b7..900a6c9 100644
--- a/kubernetes/uui/Chart.yaml
+++ b/kubernetes/uui/Chart.yaml
@@ -18,7 +18,7 @@
 apiVersion: v2
 description: ONAP uui
 name: uui
-version: 13.0.0
+version: 13.1.0
 
 dependencies:
   - name: common
@@ -39,3 +39,6 @@
   - name: uui-intent-analysis
     version: ~13.x-0
     repository: 'file://components/uui-intent-analysis'
+  - name: uui-llm-adaptation
+    version: ~13.x-0
+    repository: 'file://components/uui-llm-adaptation'
diff --git a/kubernetes/uui/components/uui-llm-adaptation/.helmignore b/kubernetes/uui/components/uui-llm-adaptation/.helmignore
new file mode 100644
index 0000000..f0c1319
--- /dev/null
+++ b/kubernetes/uui/components/uui-llm-adaptation/.helmignore
@@ -0,0 +1,21 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
diff --git a/kubernetes/uui/components/uui-llm-adaptation/Chart.yaml b/kubernetes/uui/components/uui-llm-adaptation/Chart.yaml
new file mode 100644
index 0000000..1c36c23
--- /dev/null
+++ b/kubernetes/uui/components/uui-llm-adaptation/Chart.yaml
@@ -0,0 +1,35 @@
+# Copyright © 2022 Huawei Technologies Co., Ltd. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: v2
+description: ONAP uui llm adaptation
+name: uui-llm-adaptation
+version: 13.0.0
+
+dependencies:
+  - name: common
+    version: ~13.x-0
+    repository: '@local'
+  - name: repositoryGenerator
+    version: ~13.x-0
+    repository: '@local'
+  - name: postgres
+    version: ~13.x-0
+    repository: '@local'
+  - name: serviceAccount
+    version: ~13.x-0
+    repository: '@local'
+  - name: readinessCheck
+    version: ~13.x-0
+    repository: '@local'
diff --git a/kubernetes/uui/components/uui-llm-adaptation/resources/config/llm-adaptation-init.sql b/kubernetes/uui/components/uui-llm-adaptation/resources/config/llm-adaptation-init.sql
new file mode 100644
index 0000000..5379c73
--- /dev/null
+++ b/kubernetes/uui/components/uui-llm-adaptation/resources/config/llm-adaptation-init.sql
@@ -0,0 +1,23 @@
+--
+-- Copyright (C) 2024 CMCC, Inc. and others. All rights reserved.
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+
+CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
+
+create table if not exists intent(
+    intent_id varchar(255) primary key,
+    intent_name varchar(255),
+    intent_generateType VARCHAR (225)
+);
\ No newline at end of file
diff --git a/kubernetes/uui/components/uui-llm-adaptation/resources/entrypoint/run.sh b/kubernetes/uui/components/uui-llm-adaptation/resources/entrypoint/run.sh
new file mode 100644
index 0000000..f1dcefa
--- /dev/null
+++ b/kubernetes/uui/components/uui-llm-adaptation/resources/entrypoint/run.sh
@@ -0,0 +1,31 @@
+{{/*
+#
+# Copyright (C) 2022 Huawei Technologies Co., Ltd. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+*/}}
+
+main_path="/home/uui"
+echo @main_path@ $main_path
+
+JAVA_PATH="$JAVA_HOME/bin/java"
+JAVA_OPTS="-Xms50m -Xmx128m"
+echo @JAVA_PATH@ $JAVA_PATH
+echo @JAVA_OPTS@ $JAVA_OPTS
+
+jar_path="$main_path/usecase-ui-llm-adaptation.jar"
+echo @jar_path@ $jar_path
+
+echo "Starting usecase-ui-llm-adaptation..."
+$JAVA_PATH $JAVA_OPTS -classpath $jar_path -jar $jar_path $SPRING_OPTS
diff --git a/kubernetes/uui/components/uui-llm-adaptation/templates/configmap.yaml b/kubernetes/uui/components/uui-llm-adaptation/templates/configmap.yaml
new file mode 100644
index 0000000..3583c41
--- /dev/null
+++ b/kubernetes/uui/components/uui-llm-adaptation/templates/configmap.yaml
@@ -0,0 +1,31 @@
+{{/*
+# Copyright © 2022 Huawei Technologies Co., Ltd. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+*/}}
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ include "common.fullname" . }}
+  namespace: {{ include "common.namespace" . }}
+data:
+{{ tpl (.Files.Glob "resources/config/*").AsConfig . | indent 2 }}
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ include "common.fullname" . }}-entrypoint
+  namespace: {{ include "common.namespace" . }}
+data:
+{{ tpl (.Files.Glob "resources/entrypoint/*").AsConfig . | indent 2 }}
diff --git a/kubernetes/uui/components/uui-llm-adaptation/templates/deployment.yaml b/kubernetes/uui/components/uui-llm-adaptation/templates/deployment.yaml
new file mode 100644
index 0000000..d2824d1
--- /dev/null
+++ b/kubernetes/uui/components/uui-llm-adaptation/templates/deployment.yaml
@@ -0,0 +1,74 @@
+{{/*
+# Copyright © 2022 Huawei Technologies Co., Ltd. All rights reserved.
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+*/}}
+
+apiVersion: apps/v1
+kind: Deployment
+metadata: {{- include "common.resourceMetadata" . | nindent 2 }}
+spec:
+  selector: {{- include "common.selectors" . | nindent 4 }}
+  replicas: {{ .Values.replicaCount }}
+  template:
+    metadata: {{- include "common.templateMetadata" . | nindent 6 }}
+    spec:
+      initContainers: {{ include "common.readinessCheck.waitFor" . | nindent 6 }}
+      containers:
+      - name: {{ include "common.name" . }}
+        image: {{ include "repositoryGenerator.repository" . }}/{{ .Values.image }}
+        imagePullPolicy: {{ .Values.pullPolicy }}
+        command: ["sh", "-c"]
+        args:
+        - ". /uui/run.sh"
+        ports: {{ include "common.containerPorts" . | nindent 10 }}
+        env:
+        - name: POSTGRES_IP
+          value: {{ .Values.postgres.service.name2 }}
+        - name: POSTGRES_PORT
+          value: "{{ .Values.postgres.service.externalPort }}"
+        - name: POSTGRES_DB_NAME
+          value: {{ .Values.postgres.config.pgDatabase }}
+        - name: POSTGRES_USERNAME
+          {{- include "common.secret.envFromSecretFast" (dict "global" . "uid" "pg-user-creds" "key" "login") | indent 10 }}
+        - name: POSTGRES_PASSWORD
+          {{- include "common.secret.envFromSecretFast" (dict "global" . "uid" "pg-user-creds" "key" "password") | indent 10 }}
+{{- if eq .Values.liveness.enabled true }}
+        livenessProbe:
+          tcpSocket:
+            port: {{ .Values.liveness.port }}
+          initialDelaySeconds: {{ .Values.liveness.initialDelaySeconds }}
+          periodSeconds: {{ .Values.liveness.periodSeconds }}
+{{- end }}
+        readinessProbe:
+          tcpSocket:
+            port: {{ .Values.readiness.port }}
+          initialDelaySeconds: {{ .Values.readiness.initialDelaySeconds }}
+          periodSeconds: {{ .Values.readiness.periodSeconds }}
+        resources: {{ include "common.resources" . | nindent 10 }}
+{{- if .Values.nodeSelector }}
+        nodeSelector: {{ toYaml .Values.nodeSelector | nindent 10 }}
+{{- end }}
+{{- if .Values.affinity }}
+        affinity: {{ toYaml .Values.affinity | nindent 10 }}
+{{- end }}
+        volumeMounts:
+        - mountPath: /uui/run.sh
+          name: entrypoint
+          subPath: run.sh
+      serviceAccountName: {{ include "common.fullname" (dict "suffix" "read" "dot" . )}}
+      volumes:
+      - name: entrypoint
+        configMap:
+          name: {{ include "common.fullname" . }}-entrypoint
+          defaultMode: 0755
+      {{- include "common.imagePullSecrets" . | nindent 6 }}
diff --git a/kubernetes/uui/components/uui-llm-adaptation/templates/job.yaml b/kubernetes/uui/components/uui-llm-adaptation/templates/job.yaml
new file mode 100644
index 0000000..90d6d63
--- /dev/null
+++ b/kubernetes/uui/components/uui-llm-adaptation/templates/job.yaml
@@ -0,0 +1,82 @@
+{{/*
+# Copyright © 2022 Huawei Technologies Co., Ltd. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+*/}}
+
+apiVersion: batch/v1
+kind: Job
+metadata:
+  name: {{ include "common.fullname" . }}-init-postgres
+  namespace: {{ include "common.namespace" . }}
+  labels:
+    app: {{ include "common.name" . }}-job
+    chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
+    release: {{ include "common.release" . }}
+    heritage: {{ .Release.Service }}
+spec:
+  backoffLimit: 20
+  template:
+    metadata:
+      labels:
+        app: {{ include "common.name" . }}-job
+        release: {{ include "common.release" . }}
+    spec:
+      restartPolicy: Never
+      initContainers:
+      - command:
+        - /app/ready.py
+        args:
+        - --service-name
+        - "{{ .Values.postgres.service.name2 }}"
+        env:
+        - name: NAMESPACE
+          valueFrom:
+            fieldRef:
+              apiVersion: v1
+              fieldPath: metadata.namespace
+        image: {{ include "repositoryGenerator.image.readiness" . }}
+        imagePullPolicy: {{ .Values.pullPolicy }}
+        name: {{ include "common.name" . }}-readiness
+        resources:
+          limits:
+            cpu: "100m"
+            memory: "500Mi"
+          requests:
+            cpu: "3m"
+            memory: "20Mi"
+      containers:
+      - name: {{ include "common.name" . }}-job
+        image: {{ include "repositoryGenerator.image.postgres" . }}
+        imagePullPolicy: {{ .Values.pullPolicy }}
+        env:
+        - name: PGUSER
+          {{- include "common.secret.envFromSecretFast" (dict "global" . "uid" "pg-user-creds" "key" "login") | indent 10 }}
+        - name: PGPASSWORD
+          {{- include "common.secret.envFromSecretFast" (dict "global" . "uid" "pg-user-creds" "key" "password") | indent 10 }}
+        command:
+        - /bin/sh
+        - -c
+        - |
+          psql -h $(UUI_ADAPTATION_PG_PRIMARY_SERVICE_HOST) -f /aaa/init/llm-adaptation-init.sql -d {{ .Values.postgres.config.pgDatabase }}
+        volumeMounts:
+        - name: init-data
+          mountPath: /aaa/init/llm-adaptation-init.sql
+          subPath: llm-adaptation-init.sql
+      {{ include "common.waitForJobContainer" . | indent 6 | trim }}
+      {{- include "common.imagePullSecrets" . | nindent 6 }}
+      serviceAccountName: {{ include "common.fullname" (dict "suffix" "read" "dot" . )}}
+      volumes:
+      - name: init-data
+        configMap:
+          name: {{ include "common.fullname" . }}
diff --git a/kubernetes/uui/components/uui-llm-adaptation/templates/secrets.yaml b/kubernetes/uui/components/uui-llm-adaptation/templates/secrets.yaml
new file mode 100644
index 0000000..638e02c
--- /dev/null
+++ b/kubernetes/uui/components/uui-llm-adaptation/templates/secrets.yaml
@@ -0,0 +1,17 @@
+{{/*
+# Copyright © 2022 Huawei Technologies Co., Ltd. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+*/}}
+
+{{ include "common.secretFast" . }}
diff --git a/kubernetes/uui/components/uui-llm-adaptation/templates/service.yaml b/kubernetes/uui/components/uui-llm-adaptation/templates/service.yaml
new file mode 100644
index 0000000..33e96ef
--- /dev/null
+++ b/kubernetes/uui/components/uui-llm-adaptation/templates/service.yaml
@@ -0,0 +1,17 @@
+{{/*
+# Copyright © 2022 Huawei Technologies Co., Ltd. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+*/}}
+
+{{ include "common.service" . }}
diff --git a/kubernetes/uui/components/uui-llm-adaptation/values.yaml b/kubernetes/uui/components/uui-llm-adaptation/values.yaml
new file mode 100644
index 0000000..9010bca
--- /dev/null
+++ b/kubernetes/uui/components/uui-llm-adaptation/values.yaml
@@ -0,0 +1,126 @@
+# Copyright © 2022 Huawei Technologies Co., Ltd. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Default values for uui llm adaptation.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+global:
+  passwordStrength: long
+
+#Pods Service Account
+serviceAccount:
+  nameOverride: uui-llm-adaptation
+  roles:
+    - read
+
+secrets:
+  - uid: pg-root-pass
+    name: &pgRootPassSecretName '{{ include "common.release" . }}-uui-adaptation-pg-root-pass'
+    type: password
+    externalSecret: '{{ ternary "" (tpl (default "" .Values.postgres.config.pgRootPasswordExternalSecret) .) (hasSuffix "uui-adaptation-pg-root-pass" .Values.postgres.config.pgRootPasswordExternalSecret) }}'
+    password: '{{ .Values.postgres.config.pgRootpassword }}'
+    policy: generate
+  - uid: pg-user-creds
+    name: &pgUserCredsSecretName '{{ include "common.release" . }}-uui-adaptation-pg-user-creds'
+    type: basicAuth
+    externalSecret: '{{ ternary "" (tpl (default "" .Values.postgres.config.pgUserExternalSecret) .) (hasSuffix "uui-adaptation-pg-user-creds" .Values.postgres.config.pgUserExternalSecret) }}'
+    login: '{{ .Values.postgres.config.pgUserName }}'
+    password: '{{ .Values.postgres.config.pgUserPassword }}'
+    passwordPolicy: generate
+
+image: onap/usecase-ui-llm-adaptation:14.0.0
+pullPolicy: Always
+
+# flag to enable debugging - application support required
+debugEnabled: false
+flavor: small
+replicaCount: 1
+nodeSelector: {}
+affinity: {}
+
+service:
+  type: ClusterIP
+  name: uui-llm-adaptation
+  ports:
+  - name: http-rest
+    port: &svc_port 8083
+
+liveness:
+  initialDelaySeconds: 120
+  port: *svc_port
+  periodSeconds: 10
+  enabled: true
+
+readiness:
+  initialDelaySeconds: 60
+  port: *svc_port
+  periodSeconds: 10
+
+# application configuration override for postgres
+postgres:
+  nameOverride: &postgresName uui-adaptation-postgres
+  service:
+    name: *postgresName
+    name2: uui-adaptation-pg-primary
+    name3: uui-adaptation-pg-replica
+  container:
+    name:
+      primary: uui-adaptation-pg-primary
+      replica: uui-adaptation-pg-replica
+  config:
+    pgUserName: uui
+    pgDatabase: uuiadaptation
+    pgUserExternalSecret: *pgUserCredsSecretName
+    pgRootPasswordExternalSecret: *pgRootPassSecretName
+  persistence:
+    mountSubPath: uui/uuiadaptation/data
+    mountInitPath: uui
+
+readinessCheck:
+  wait_for:
+    services:
+      - '{{ .Values.postgres.service.name2 }}'
+
+wait_for_job_container:
+  containers:
+    - '{{ include "common.name" . }}-job'
+
+# We usually recommend not to specify default resources and to leave this as a conscious
+# choice for the user. This also increases chances charts run on environments with little
+# resources, such as Minikube. If you do want to specify resources, uncomment the following
+# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
+#
+# Example:
+# Configure resource requests and limits
+# ref: http://kubernetes.io/docs/user-guide/compute-resources/
+# Minimum memory for development is 2 CPU cores and 4GB memory
+# Minimum memory for production is 4 CPU cores and 8GB memory
+resources:
+  small:
+    limits:
+      cpu: "2"
+      memory: "1Gi"
+    requests:
+      cpu: "1"
+      memory: "200Mi"
+  large:
+    limits:
+      cpu: "4"
+      memory: "2Gi"
+    requests:
+      cpu: "2"
+      memory: "1Gi"
+  unlimited: {}
+