Skip to content

Commit

Permalink
Merge branch 'release-1.0' into DBP-1066-helm-charts-improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
M-Schiborr authored Nov 29, 2024
2 parents c38b4fb + d2c7660 commit bee1b91
Show file tree
Hide file tree
Showing 123 changed files with 5,746 additions and 2,121 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
with:
node_version: '18'
deploy_stage: 'dev'
timeout_minutes: 15
timeout_minutes: 20
permissions:
contents: read
secrets: inherit
Expand Down
6 changes: 3 additions & 3 deletions charts/dbildungs-iam-server/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: dBildungs-IAM-server
type: application
appVersion: ""
dependencies:
- name: redis-cluster
- name: redis
repository: https://charts.bitnami.com/bitnami
version: 11.0.6
condition: redis-cluster.enabled
version: 20.3.0
condition: redis.enabled
14 changes: 9 additions & 5 deletions charts/dbildungs-iam-server/config/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@
"SERVICE_CLIENT_ID": "spsh-service"
},
"REDIS": {
"HOST": "dbildungs-iam-server-redis-cluster",
"HOST": "dbildungs-iam-server-redis",
"PORT": 6379,
"USERNAME": "default",
"PASSWORD": "",
"USE_TLS": false,
"CLUSTERED": true
"USE_TLS": false
},
"LDAP": {
"URL": "ldap://spsh-xxx.svc.cluster.local",
Expand All @@ -52,7 +51,7 @@
"BACKEND_FOR_FRONTEND_MODULE_LOG_LEVEL": "debug"
},
"ITSLEARNING": {
"ENABLED": "false",
"ENABLED": false,
"ENDPOINT": "https://itslearning.example.com",
"USERNAME": "username",
"PASSWORD": "password",
Expand All @@ -61,7 +60,7 @@
"ROOT_ERSATZ": "ersatz"
},
"OX": {
"ENABLED": "false",
"ENABLED": false,
"ENDPOINT": "https://ox_ip:ox_port/webservices/OXUserService",
"CONTEXT_ID": "1337",
"CONTEXT_NAME": "contextname",
Expand All @@ -77,5 +76,10 @@
},
"IMPORT": {
"IMPORT_FILE_MAXGROESSE_IN_MB": 10
},
"SYSTEM": {
"RENAME_WAITING_TIME_IN_SECONDS": 3,
"STEP_UP_TIMEOUT_ENABLED": "true",
"STEP_UP_TIMEOUT_IN_SECONDS": 10
}
}
23 changes: 23 additions & 0 deletions charts/dbildungs-iam-server/cron/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM alpine:3.19

# Install necessary packages
RUN apk update && \
apk add --no-cache bash cronie jq openssl vim wget

# Create a new user and group
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# Copy scripts into the image
COPY scripts/ /scripts/

# Set execute permissions for all .sh scripts in /scripts/ and create a log file
RUN chmod +x /scripts/*.sh \
&& touch /var/log/cron.log \
&& chmod 644 /var/log/cron.log \
&& chown -R appuser:appgroup /scripts /var/log/cron.log

# Switch to the new user
USER appuser

# Start the cron service in foreground
CMD ["/usr/sbin/crond", "-f"]
15 changes: 15 additions & 0 deletions charts/dbildungs-iam-server/cron/keys/dummy_jwks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"keys": [
{
"kty": "RSA",
"n": "23mzd3v4YjgWMzO7XYYwD92NqCm436ErU1-NPTVok9aaVXx5mjZKfh_Xoyp5BEgjQU042MKOhl1Ri17HfOOf6k4cpBpvBQhENp0yfNPv_-kSy4OgdA3qk9-kZyvuRX1-0LKvJMwlrCLCLEfiv_yn8YQLpQeqgdIj1AlX37fcnSxxL3qukM_-Hm8dCB2mbUzANT_uRkSCHFQWVDxcbocKAmhr0808CmpiINWEIVv7AhS_HVSliaeB-iteAKN3W9Am3tCtGZaWKUlioKueQux7OTKxHm5fM-jZ9ZPnb7_RQlOGV9vu-TTMO8pKYkqn15LcnYuBKKHmFEBO8vRxI9_8Lw",
"e": "AQAB",
"d": "CdcSByhlbC9BkjgejW89FmkDjJJE-gR63HkV7F70T7SOejNjga4vdtTXUTclR94yyR8SORMNWtQyRMJnb_UGBXZNGG_K9yR2EntyeQrzjBDCHqJ0fjTlheMVYZQkUbSdC_RcSpUQl1V-STKhOvmz-e3Gq-Evxt70wPFOTEyCYAA5zTSgF7vwoxtKChfOb3NvkLUmD4JrBEb0vzapTgVvoyB158glUGEibpHBaVvVnA98qEI5hqJE2jhhtaoGyvErIkWDOummb1WPN2D0Nqsvr-sfwH3mxKFLDogHIfjMLxDaP9Y3I7Wwie9pbpsg6zK66s6EB27hkZnbRLlwaK4ImQ",
"p": "_KCzohdV8BpnvfDxyL-Zjj8paJB5RBLkewf7xl-sqLHykjn-_nR1OGfEr8Gc0zwYD6FtTAJ9JN-h730vBacUVZDrgnKOW0NbQPIwNXCSisyChhbkSVXLBi94r_-t92ieJ8wPbchynF6Z1UyH0m4rieKnAPcxuio9iLuXdQrRNEs",
"q": "3me1bHQ_GO5mPKwUf-kSZDguninq98ERMOAYdr__yUM1fc8QJ_3FSkZsSFr91Fi5kPvP9gthPRYhlfKeix61ibypLnLpyx6A298VIdG8VFjPrXzlme5CGSPYN9-YRSQq31e-xSdkn3lKiJlqPZzlRARyHveJlSWu07LuS91AgS0",
"dp": "--U1GEOSchWyKaeNPrElaLu8C0I7WFBKOA7u0o9ldtPwXjOr-Yaftz1o1iMEv29lQnigpbC5ncHLEyRMdaNyWBtnaSvWnFNeMzUKMs7rn7Bp2VAMEr-T77f36-3SRiavxFjpbXr4JMkDNLbZm0405Yj1IrZYhBtIPgVm8NJ3ZV8",
"dq": "ofqgbKvBZLQEq_2cNIiYh3tPoIvhAK6Riao8xwgREBEt_UH4f1fY_76IkK4MnkI8bHapwIYLPQVIUsBQbfxgtT89bIHu-qttqDUyW944Lqo8HxuO0WxwoYS0rgTgDsNHokByxX5qT6dz_EbX1KXXaJFgWGNqxcCbMr3nxkMO_sU",
"qi": "r8ZslmjXzZJUv6IoN6nUT12UpzmhbriRXxjTcLNSwZBuSXz8QV_7F8ViNyEcot20aDo35t8IssLnDD9nxDAGTCL68FkXTJaAsUE2beGfkX9Sz5r_Gzlcer_Gjhl5aNHeZYgIMsYciPhM4laBzKD3d51xQuDFMMX1RQUvyDHDIog"
}
]
}
57 changes: 57 additions & 0 deletions charts/dbildungs-iam-server/cron/scripts/cron_trigger.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/bin/bash

# Check if BACKEND_ENDPOINT_URL is set
if [ -z "$BACKEND_ENDPOINT_URL" ]; then
echo "Error: BACKEND_ENDPOINT_URL is not set."
exit 1
fi

# Check if HTTP_METHOD is set
if [ -z "$HTTP_METHOD" ]; then
echo "Error: HTTP_METHOD is not set."
exit 1
fi

endpoint_url="${BACKEND_ENDPOINT_URL}"

echo "Triggering $endpoint_url with $HTTP_METHOD at $(date)"

# Call get_access_token.sh and capture the access token
access_token=$(./get_access_token.sh)

# Create temporary files for headers and body
header_file=$(mktemp)
body_file=$(mktemp)

# Function to clean up temporary files on exit
cleanup() {
rm -f "$header_file" "$body_file"
}
trap cleanup EXIT

# Make the request with JWT authorization
wget --quiet \
--method="$HTTP_METHOD" \
--header="Authorization: Bearer $access_token" \
--header="Content-Type: application/json" \
--output-document="$body_file" \
--server-response \
"$endpoint_url" \
2> "$header_file"

# Extract the HTTP status code from the headers
http_status=$(awk '/^ HTTP\// {print $2; exit}' "$header_file")

# Extract the response body
response_body=$(cat "$body_file")

# Output the response details
echo "Finished triggering $endpoint_url with $HTTP_METHOD at $(date)"
echo "HTTP Status: $http_status"
echo "Response Body: $response_body"

# Exit with status 1 if the HTTP status code is not 200
if [ "$http_status" -ne 200 ]; then
echo "Error: HTTP request failed with status code $http_status"
exit 1
fi
180 changes: 180 additions & 0 deletions charts/dbildungs-iam-server/cron/scripts/get_access_token.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
#!/bin/bash

# Ensure the script exits on any error
set -e

# Function to perform base64 URL encoding
base64url_encode() {
# Base64 encode the input, replace '+' with '-', '/' with '_', and remove padding '='
echo -n "$1" | openssl enc -base64 -A | tr '+/' '-_' | tr -d '='
}

base64url_decode() {
local input="$1"

# Replace URL-specific characters with Base64 standard characters
local base64_str="${input//-/+}"
base64_str="${base64_str//_/\/}"

# Calculate the required padding
local padding=$((4 - ${#base64_str} % 4))
if (( padding != 4 )); then
base64_str+=$(printf '=%.0s' $(seq 1 $padding))
fi

# Decode the Base64 string
# The -w0 option ensures no line wrapping (GNU base64)
if base64 --help 2>&1 | grep -q -- '-w'; then
echo "$base64_str" | base64 -d -w0
else
echo "$base64_str" | base64 -d
fi
}

# Function to decode base64url and convert to hex, preserving leading zeros
decode_to_hex() {
base64url_decode "$1" | hexdump -v -e '/1 "%02x"'
}

# Generate a random string for 'jti' claim
generate_jti() {
head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13
}

# Load environment variables
clientId="${KC_CLIENT_ID}"
kc_token_url="${KC_TOKEN_URL}"

# Load JWKS from environment variable or file
if [ -n "$JWKS" ]; then
# JWKS is set in the environment, use it directly
jwks="$JWKS"
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
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
exit 1
fi

# Extract the first key from the JWKS
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
exit 1
fi

# Extract RSA components from JWK
n=$(echo "$key_json" | jq -r '.n')
e=$(echo "$key_json" | jq -r '.e')
d=$(echo "$key_json" | jq -r '.d')
p=$(echo "$key_json" | jq -r '.p')
q=$(echo "$key_json" | jq -r '.q')
dp=$(echo "$key_json" | jq -r '.dp')
dq=$(echo "$key_json" | jq -r '.dq')
qi=$(echo "$key_json" | jq -r '.qi')

# Decode the base64url-encoded components and convert to hex
n_dec=$(decode_to_hex "$n")
e_dec=$(decode_to_hex "$e")
d_dec=$(decode_to_hex "$d")
p_dec=$(decode_to_hex "$p")
q_dec=$(decode_to_hex "$q")
dp_dec=$(decode_to_hex "$dp")
dq_dec=$(decode_to_hex "$dq")
qi_dec=$(decode_to_hex "$qi")

# Create an ASN.1 structure for the RSA private key
asn1_structure=$(mktemp)

cat > "$asn1_structure" <<EOF
asn1=SEQUENCE:private_key
[private_key]
version=INTEGER:0
n=INTEGER:0x$n_dec
e=INTEGER:0x$e_dec
d=INTEGER:0x$d_dec
p=INTEGER:0x$p_dec
q=INTEGER:0x$q_dec
dp=INTEGER:0x$dp_dec
dq=INTEGER:0x$dq_dec
qi=INTEGER:0x$qi_dec
EOF

echo "Starting to generate PEM-formatted private key" >> /var/log/cron.log

# 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

# Remove temporary files
rm "$asn1_structure" "$temp_key_file"

# Create JWT header
header='{"alg":"RS256","typ":"JWT"}'
header_base64=$(base64url_encode "$header")

# Create JWT payload
current_time=$(date +%s)
exp_time=$((current_time + 300)) # Token valid for 5 minutes
jti=$(generate_jti)

payload=$(cat <<EOF
{
"iss": "$clientId",
"sub": "$clientId",
"aud": "$kc_token_url",
"jti": "$jti",
"exp": $exp_time
}
EOF
)
payload_base64=$(base64url_encode "$payload")

# Combine header and payload
header_payload="$header_base64.$payload_base64"

echo "Payload created" >> /var/log/cron.log

# 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

# Remove the temporary PEM key file
rm "$temp_key_file.pem"

# Create the JWT assertion
jwt_assertion="$header_payload.$signature"

# Make the POST request to Keycloak to get the access token
response=$(wget -qO- --post-data "grant_type=client_credentials&client_id=$clientId&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=$jwt_assertion" \
--header "Content-Type: application/x-www-form-urlencoded" \
"$kc_token_url")

echo "Access token requested" >> /var/log/cron.log

# Check if the response contains an access token
if echo "$response" | grep -q '"access_token"'; then
# Extract the access token from the response
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
exit 1
fi
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,21 @@
secretKeyRef:
name: {{ default .Values.auth.existingSecret .Values.auth.secretName }}
key: pi-admin-password
- name: SYSTEM_RENAME_WAITING_TIME_IN_SECONDS # TODO
valueFrom:
secretKeyRef:
name: {{ default .Values.auth.existingSecret .Values.auth.secretName }}
key: system-rename-waiting-time-in-seconds
- name: SYSTEM_STEP_UP_TIMEOUT_IN_SECONDS # TODO
valueFrom:
secretKeyRef:
name: {{ default .Values.auth.existingSecret .Values.auth.secretName }}
key: system-step-up-timeout-in-seconds
- name: SYSTEM_STEP_UP_TIMEOUT_ENABLED # TODO
valueFrom:
secretKeyRef:
name: {{ default .Values.auth.existingSecret .Values.auth.secretName }}
key: system-step-up-timeout-enabled
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
Expand Down
4 changes: 4 additions & 0 deletions charts/dbildungs-iam-server/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ data:
PI_RENAME_WAITING_TIME: "{{ .Values.privacyidea.renameWaitingTime }}"
PI_REALM: "{{ .Values.privacyidea.realm }}"
PI_USER_RESOLVER: "{{ .Values.privacyidea.userResolver }}"
STATUS_REDIRECT_URL: "{{ .Values.status.url }}"
ITSLEARNING_ROOT: '{{ .Values.itslearning.root }}'
ITSLEARNING_ROOT_OEFFENTLICH: '{{ .Values.itslearning.rootOeffentlich }}'
ITSLEARNING_ROOT_ERSATZ: '{{ .Values.itslearning.rootErsatz }}'
11 changes: 11 additions & 0 deletions charts/dbildungs-iam-server/templates/cronjob-envs-configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "common.names.name" . }}-cronjob-envs-configmap
namespace: {{ template "common.names.namespace" . }}
labels:
{{- include "common.labels" . | nindent 4 }}
data:
KC_TOKEN_URL: "https://{{ $.Values.keycloakHostname }}{{ $.Values.cronjobs.keycloakTokenUrl }}"
JWKS_FILE_PATH: "{{ $.Values.cronjobs.jwksFilePath }}"
KC_CLIENT_ID: "{{ $.Values.cronjobs.keycloakClientId }}"
Loading

0 comments on commit bee1b91

Please sign in to comment.