From 029fc3e76e583518529819cf11d28e931fe91174 Mon Sep 17 00:00:00 2001 From: dbildungs-iam-server-gha Date: Wed, 18 Dec 2024 12:57:43 +0000 Subject: [PATCH] dbildungs-iam-server --- automation/dbildungs-iam-server/Chart.yaml | 4 +- .../dbildungs-iam-server/config/config.json | 30 +-- .../dbildungs-iam-server/cron/Dockerfile | 2 + .../cron/scripts/get_access_token.sh | 20 +- .../templates/_dbildungs-iam-server-envs.tpl | 189 +++++++++--------- .../templates/backend-deployment.yaml | 6 +- .../templates/configmap.yaml | 8 + .../templates/cronjob.yaml | 22 +- .../templates/secret.yaml | 9 + automation/dbildungs-iam-server/values.yaml | 26 ++- 10 files changed, 183 insertions(+), 133 deletions(-) diff --git a/automation/dbildungs-iam-server/Chart.yaml b/automation/dbildungs-iam-server/Chart.yaml index 083ff74a3..0d6f3ab88 100644 --- a/automation/dbildungs-iam-server/Chart.yaml +++ b/automation/dbildungs-iam-server/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 -appVersion: SPSH-1655 +appVersion: SPSH-1176 description: dBildungs-IAM-server name: dbildungs-iam-server type: application -version: 0.0.0-spsh-1655-20241218-1247 +version: 0.0.0-spsh-1176-20241218-1257 diff --git a/automation/dbildungs-iam-server/config/config.json b/automation/dbildungs-iam-server/config/config.json index 5fd3be1f9..99745ae08 100644 --- a/automation/dbildungs-iam-server/config/config.json +++ b/automation/dbildungs-iam-server/config/config.json @@ -30,11 +30,14 @@ "PASSWORD": "", "USE_TLS": false }, + "LDAP": { "URL": "ldap://spsh-xxx.svc.cluster.local", "BIND_DN": "cn=admin,dc=schule-sh,dc=de", - "ADMIN_PASSWORD": "password" + "ADMIN_PASSWORD": "password", + "BASE_DN": "dc=schule-sh,dc=de" }, + "DATA": { "ROOT_ORGANISATION_ID": "d39cb7cf-2f9b-45f1-849f-973661f2f057" }, @@ -51,22 +54,10 @@ "BACKEND_FOR_FRONTEND_MODULE_LOG_LEVEL": "debug" }, "ITSLEARNING": { - "ENABLED": false, - "ENDPOINT": "https://itslearning.example.com", - "USERNAME": "username", - "PASSWORD": "password", "ROOT": "sh", "ROOT_OEFFENTLICH": "oeffentlich", "ROOT_ERSATZ": "ersatz" }, - "OX": { - "ENABLED": false, - "ENDPOINT": "https://ox_ip:ox_port/webservices/OXUserService", - "CONTEXT_ID": "1337", - "CONTEXT_NAME": "contextname", - "USERNAME": "username", - "PASSWORD": "password" - }, "PRIVACYIDEA": { "ENDPOINT": "http://localhost:5000", "USERNAME": "admin", @@ -75,11 +66,22 @@ "REALM": "defrealm" }, "IMPORT": { - "IMPORT_FILE_MAXGROESSE_IN_MB": 10 + "CSV_FILE_MAX_SIZE_IN_MB": 10, + "CSV_MAX_NUMBER_OF_USERS": 2000, + "PASSPHRASE_SECRET": "44abDqJk2qgwRbpGfO0VZx7DpXeFsm7R", + "PASSPHRASE_SALT": "YDp6fYkbUcj4ZkyAOnbAHGQ9O72htc5M" }, "SYSTEM": { "RENAME_WAITING_TIME_IN_SECONDS": 3, "STEP_UP_TIMEOUT_ENABLED": "true", "STEP_UP_TIMEOUT_IN_SECONDS": 10 + }, + "VIDIS": { + "BASE_URL": "https://service-stage.vidis.schule", + "USERNAME": "", + "PASSWORD": "", + "REGION_NAME": "test-region", + "KEYCLOAK_GROUP": "VIDIS-service", + "KEYCLOAK_ROLE": "VIDIS-user" } } diff --git a/automation/dbildungs-iam-server/cron/Dockerfile b/automation/dbildungs-iam-server/cron/Dockerfile index a05b37677..6d3099a88 100644 --- a/automation/dbildungs-iam-server/cron/Dockerfile +++ b/automation/dbildungs-iam-server/cron/Dockerfile @@ -1,5 +1,7 @@ FROM alpine:3.19 +ENV LOG_FILE_PATH=/var/log/cron.log + # Install necessary packages RUN apk update && \ apk add --no-cache bash cronie jq openssl vim wget diff --git a/automation/dbildungs-iam-server/cron/scripts/get_access_token.sh b/automation/dbildungs-iam-server/cron/scripts/get_access_token.sh index 52be637af..878999566 100644 --- a/automation/dbildungs-iam-server/cron/scripts/get_access_token.sh +++ b/automation/dbildungs-iam-server/cron/scripts/get_access_token.sh @@ -53,13 +53,13 @@ elif [ -n "$JWKS_FILE_PATH" ] && [ -f "$JWKS_FILE_PATH" ]; then # JWKS_FILE_PATH is set, use the file jwks=$(cat "$JWKS_FILE_PATH") else - echo "Error: No JWKS environment variable or JWKS file found." >> /var/log/cron.log + echo "Error: No JWKS environment variable or JWKS file found." >> "${LOG_FILE_PATH}" exit 1 fi # Check if environment variables are set if [[ -z "$clientId" || -z "$kc_token_url" || -z "$jwks" ]]; then - echo "Error: CLIENT_ID, TOKEN_URL, and JWKS environment variables must be set." >> /var/log/cron.log + echo "Error: CLIENT_ID, TOKEN_URL, and JWKS environment variables must be set." >> "${LOG_FILE_PATH}" exit 1 fi @@ -68,7 +68,7 @@ key_json=$(echo "$jwks" | jq -c '.keys[0]') # Check if key_json is empty if [[ -z "$key_json" ]]; then - echo "Error: No keys found in JWKS." >> /var/log/cron.log + echo "Error: No keys found in JWKS." >> "${LOG_FILE_PATH}" exit 1 fi @@ -110,14 +110,14 @@ dq=INTEGER:0x$dq_dec qi=INTEGER:0x$qi_dec EOF -echo "Starting to generate PEM-formatted private key" >> /var/log/cron.log +echo "Starting to generate PEM-formatted private key" >> "${LOG_FILE_PATH}" # Generate the PEM-formatted private key temp_key_file=$(mktemp) openssl asn1parse -genconf "$asn1_structure" -out "$temp_key_file" > /dev/null 2>&1 openssl rsa -in "$temp_key_file" -inform DER -outform PEM -out "$temp_key_file.pem" > /dev/null 2>&1 -echo "Ending to generate PEM-formatted private key" >> /var/log/cron.log +echo "Ending to generate PEM-formatted private key" >> "${LOG_FILE_PATH}" # Remove temporary files rm "$asn1_structure" "$temp_key_file" @@ -146,14 +146,14 @@ payload_base64=$(base64url_encode "$payload") # Combine header and payload header_payload="$header_base64.$payload_base64" -echo "Payload created" >> /var/log/cron.log +echo "Payload created" >> "${LOG_FILE_PATH}" # Sign the JWT signature=$(echo -n "$header_payload" | \ openssl dgst -sha256 -sign "$temp_key_file.pem" | \ openssl enc -base64 -A | tr '+/' '-_' | tr -d '=') -echo "Signed the JWT" >> /var/log/cron.log +echo "Signed the JWT" >> "${LOG_FILE_PATH}" # Remove the temporary PEM key file rm "$temp_key_file.pem" @@ -166,7 +166,7 @@ response=$(wget -qO- --post-data "grant_type=client_credentials&client_id=$clien --header "Content-Type: application/x-www-form-urlencoded" \ "$kc_token_url") -echo "Access token requested" >> /var/log/cron.log +echo "Access token requested" >> "${LOG_FILE_PATH}" # Check if the response contains an access token if echo "$response" | grep -q '"access_token"'; then @@ -174,7 +174,7 @@ if echo "$response" | grep -q '"access_token"'; then access_token=$(echo "$response" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p') echo "$access_token" else - echo "Failed to retrieve access token. Response:" >> /var/log/cron.log - echo "$response" >> /var/log/cron.log + echo "Failed to retrieve access token. Response:" >> "${LOG_FILE_PATH}" + echo "$response" >> "${LOG_FILE_PATH}" exit 1 fi diff --git a/automation/dbildungs-iam-server/templates/_dbildungs-iam-server-envs.tpl b/automation/dbildungs-iam-server/templates/_dbildungs-iam-server-envs.tpl index ab47c9675..677d80464 100644 --- a/automation/dbildungs-iam-server/templates/_dbildungs-iam-server-envs.tpl +++ b/automation/dbildungs-iam-server/templates/_dbildungs-iam-server-envs.tpl @@ -1,94 +1,99 @@ {{- define "dbildungs-iam-server-backend-envs" }} - - name: DB_SECRET - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: db-password - - name: DB_USERNAME - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: db-username - - name: DB_HOST - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: db-host - - name: KC_ADMIN_SECRET - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: keycloak-adminSecret - - name: DB_CLIENT_URL - value: "postgres://$(DB_HOST)/" - - name: KC_CLIENT_SECRET - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: keycloak-clientSecret - - name: KC_SERVICE_CLIENT_PRIVATE_JWKS - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: service-account-private-jwks - - name: FRONTEND_SESSION_SECRET - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: frontend-sessionSecret - - name: ITSLEARNING_ENABLED - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: itslearning-enabled - - name: ITSLEARNING_ENDPOINT - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: itslearning-endpoint - - name: ITSLEARNING_USERNAME - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: itslearning-username - - name: ITSLEARNING_PASSWORD - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: itslearning-password - - name: LDAP_ADMIN_PASSWORD - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: ldap-admin-password - - name: PI_BASE_URL - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: pi-base-url - - name: PI_ADMIN_USER - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: pi-admin-user - - name: PI_ADMIN_PASSWORD - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: pi-admin-password - - name: PI_USER_RESOLVER - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: pi-user-resolver - - name: PI_REALM - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: pi-user-realm - - name: REDIS_PASSWORD - valueFrom: - secretKeyRef: - name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} - key: redis-password +- name: DB_SECRET + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: db-password +- name: DB_USERNAME + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: db-username +- name: DB_HOST + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: db-host +- name: KC_ADMIN_SECRET + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: keycloak-adminSecret +- name: DB_CLIENT_URL + value: "postgres://$(DB_HOST)/" +- name: KC_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: keycloak-clientSecret +- name: KC_SERVICE_CLIENT_PRIVATE_JWKS + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: service-account-private-jwks +- name: FRONTEND_SESSION_SECRET + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: frontend-sessionSecret +- name: ITSLEARNING_ENABLED + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: itslearning-enabled +- name: ITSLEARNING_ENDPOINT + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: itslearning-endpoint +- name: ITSLEARNING_USERNAME + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: itslearning-username +- name: ITSLEARNING_PASSWORD + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: itslearning-password +- name: LDAP_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: ldap-admin-password +- name: PI_BASE_URL + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: pi-base-url +- name: PI_ADMIN_USER + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: pi-admin-user +- name: PI_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: pi-admin-password +- name: PI_USER_RESOLVER + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: pi-user-resolver +- name: PI_REALM + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: pi-user-realm +- name: REDIS_PASSWORD + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: redis-password +- name: OX_PASSWORD + valueFrom: + secretKeyRef: + name: {{ default .Values.auth.existingSecret .Values.auth.secretName }} + key: ox-password {{- end}} diff --git a/automation/dbildungs-iam-server/templates/backend-deployment.yaml b/automation/dbildungs-iam-server/templates/backend-deployment.yaml index 0c5b14b06..56a8aae53 100644 --- a/automation/dbildungs-iam-server/templates/backend-deployment.yaml +++ b/automation/dbildungs-iam-server/templates/backend-deployment.yaml @@ -45,9 +45,9 @@ spec: command: [ "node", "dist/src/console/main.js", "keycloak", "update-clients", "dev" ] env: {{- include "dbildungs-iam-server-backend-envs" . | indent 12 }} - {{- if .Values.backend.extraEnvVars }} - {{ toYaml .Values.backend.extraEnvVars | nindent 12 }} - {{- end }} + {{- if .Values.backend.extraEnvVars }} + {{ toYaml .Values.backend.extraEnvVars | nindent 12 }} + {{- end }} envFrom: - configMapRef: name: {{ template "common.names.name" . }} diff --git a/automation/dbildungs-iam-server/templates/configmap.yaml b/automation/dbildungs-iam-server/templates/configmap.yaml index 6603a8e9f..4ddcd1b46 100644 --- a/automation/dbildungs-iam-server/templates/configmap.yaml +++ b/automation/dbildungs-iam-server/templates/configmap.yaml @@ -22,9 +22,17 @@ data: LDAP_OEFFENTLICHE_SCHULEN_DOMAIN: "{{ .Values.ldap.oeffentlicheSchulenDomain }}" LDAP_ERSATZSCHULEN_DOMAIN: "{{ .Values.ldap.ersatzschulenDomain }}" STATUS_REDIRECT_URL: "{{ .Values.status.url }}" + OX_ENABLED: "{{ .Values.ox.enabled }}" + OX_USERNAME: "{{ .Values.ox.username }}" + OX_ENDPOINT: "{{ .Values.ox.endpoint }}" + OX_CONTEXT_ID: "{{ .Values.ox.contextId }}" + OX_CONTEXT_NAME: "{{ .Values.ox.contextName }}" SYSTEM_RENAME_WAITING_TIME_IN_SECONDS: "{{ .Values.backend.env.renameWaitingTimeInSeconds }}" SYSTEM_STEP_UP_TIMEOUT_ENABLED: "{{ .Values.backend.env.stepUpTimeoutEnabled }}" SYSTEM_STEP_UP_TIMEOUT_IN_SECONDS: "{{ .Values.backend.env.stepUpTimeoutInSeconds }}" ITSLEARNING_ROOT: '{{ .Values.itslearning.root }}' ITSLEARNING_ROOT_OEFFENTLICH: '{{ .Values.itslearning.rootOeffentlich }}' ITSLEARNING_ROOT_ERSATZ: '{{ .Values.itslearning.rootErsatz }}' + NODE_OPTIONS: "--max-old-space-size={{ .Values.backend.env.maxOldSpaceSize }}" + IMPORT_CSV_FILE_MAX_SIZE_IN_MB: '{{ .Values.import.csvFileMaxSizeInMB }}' + IMPORT_CSV_MAX_NUMBER_OF_USERS: '{{ .Values.import.csvMaxNumberOfUsers }}' diff --git a/automation/dbildungs-iam-server/templates/cronjob.yaml b/automation/dbildungs-iam-server/templates/cronjob.yaml index b2b72b23f..629512553 100644 --- a/automation/dbildungs-iam-server/templates/cronjob.yaml +++ b/automation/dbildungs-iam-server/templates/cronjob.yaml @@ -8,6 +8,8 @@ metadata: spec: schedule: {{ $job_options.schedule }} startingDeadlineSeconds: 300 + successfulJobsHistoryLimit: 1 + failedJobsHistoryLimit: 1 jobTemplate: spec: backoffLimit: 0 @@ -22,10 +24,9 @@ spec: image: "{{ $.Values.cronjobs.image.repository }}:{{ $.Values.cronjobs.image.tag }}" imagePullPolicy: {{ $.Values.cronjobs.image.pullPolicy | default "Always"}} securityContext: - # not yet possible since we need to install some tools - # privileged: false - # runAsUser: 1000 - # runAsNonRoot: true + privileged: false + runAsUser: 1000 + runAsNonRoot: true capabilities: drop: - ALL @@ -41,6 +42,8 @@ spec: value: "https://{{ $.Values.backendHostname }}{{ $job_options.endpoint }}" - name: HTTP_METHOD value: "{{ $job_options.httpMethod }}" + - name: LOG_FILE_PATH + value: "/tmp/log/cron.log" resources: limits: memory: "128Mi" @@ -52,11 +55,9 @@ spec: - "sh" - "-c" - | - mkdir /scripts && - cp /scripts_tmp/*.sh /scripts/ && - chmod +x /scripts/*.sh && - touch /var/log/cron.log && - chmod 644 /var/log/cron.log && + mkdir /tmp/log/ && + touch /tmp/log/cron.log && + chmod 644 /tmp/log/cron.log && cd {{ $.Values.cronjobs.scriptDir }} && bash {{ $job_options.script }} volumeMounts: @@ -65,7 +66,7 @@ spec: subPath: jwks.json readOnly: true - name: script-volume - mountPath: /scripts_tmp + mountPath: /scripts readOnly: false ports: - containerPort: {{ $.Values.cronjobs.port }} @@ -74,6 +75,7 @@ spec: - name: script-volume configMap: name: {{ template "common.names.name" $ }}-cronjob-scripts-configmap + defaultMode: 0555 - name: secret-volume-jwks secret: secretName: dbildungs-iam-server diff --git a/automation/dbildungs-iam-server/templates/secret.yaml b/automation/dbildungs-iam-server/templates/secret.yaml index 10e959f4e..a28314969 100644 --- a/automation/dbildungs-iam-server/templates/secret.yaml +++ b/automation/dbildungs-iam-server/templates/secret.yaml @@ -24,4 +24,13 @@ data: pi-user-realm: {{ .Values.auth.pi_user_realm }} secrets-json: {{ .Values.auth.secrets_json }} redis-password: {{ .Values.auth.redis_password }} + vidis-base-url: {{ .Values.auth.vidis_base_url }} + vidis-username: {{ .Values.auth.vidis_username }} + vidis-password: {{ .Values.auth.vidis_password }} + vidis-region-name: {{ .Values.auth.vidis_region_name }} + vidis-keycloak-group: {{ .Values.auth.vidis_keycloak_group }} + vidis-keycloak-role: {{ .Values.auth.vidis_keycloak_role }} + import-passphrase-secret: {{ .Values.auth.import_passphrase_secret }} + import-passphrase-salt: {{ .Values.auth.import_passphrase_salt }} + ox-password: {{ .Values.auth.ox_password }} {{- end }} diff --git a/automation/dbildungs-iam-server/values.yaml b/automation/dbildungs-iam-server/values.yaml index 5050e647e..4daf0f153 100644 --- a/automation/dbildungs-iam-server/values.yaml +++ b/automation/dbildungs-iam-server/values.yaml @@ -33,6 +33,7 @@ ldap: bindDN: cn=admin,dc=schule-sh,dc=de oeffentlicheSchulenDomain: schule-sh.de ersatzschulenDomain: ersatzschule-sh.de + base_dn: dc=schule-sh,dc=de itslearning: root: sh @@ -58,6 +59,22 @@ auth: pi_user_resolver: '' pi_user_realm: '' redis_password: '' + vidis_base_url: '' + vidis_username: '' + vidis_password: '' + vidis_region_name: '' + vidis_keycloak_group: '' + vidis_keycloak_role: '' + import_passphrase_secret: '' + import_passphrase_salt: '' + ox_password: '' + +ox: + enabled: false + username: 'oxadmin' + endpoint: 'https://webmail.example.com' + contextId: '10' + contextName: '10' backend: replicaCount: 1 @@ -139,6 +156,7 @@ backend: renameWaitingTimeInSeconds: 3 stepUpTimeoutInSeconds: 900 stepUpTimeoutEnabled: 'false' + maxOldSpaceSize: 3584 autoscaling: enabled: false @@ -156,8 +174,8 @@ status: cronjobs: enabled: true image: - tag: DBP-1083-latest - repository: ghcr.io/hpi-schul-cloud/cron-tools + tag: '1.1.0' + repository: docker.io/schulcloud/cron-tools pullPolicy: IfNotPresent port: 5656 keycloakTokenUrl: '/realms/SPSH/protocol/openid-connect/token' @@ -186,3 +204,7 @@ cronjobs: endpoint: '/api/cron/unlock' httpMethod: 'PUT' script: 'cron_trigger.sh' + +import: + csvFileMaxSizeInMB: 10 + csvMaxNumberOfUsers: 2000