With a client id / secret, to be secure you will have to go through a rotation. If you do a JWT signer, it's a little bit more complex, but you can still get the client going.
here is an example with grabbing the jwt from a signed aws kms so that you aren't responsible for getting the details.
#!/bin/bash
# Variables
KMS_KEY_ARN="arn_here"
ALGORITHM="RSASSA_PKCS1_V1_5_SHA_256"
CLIENT_ID="test"
AUTH_SERVER_TOKEN_ENDPOINT_URL="http://localhost:8080/realms/master/protocol/openid-connect/token"
# Helper functions
base64url_encode() {
openssl enc -base64 -A | tr '+/' '-_' | tr -d '='
}
generate_jti() {
# Generates a random string for jti using /dev/urandom
head -c 16 /dev/urandom | base64 | tr -d '/+=' | cut -c -22
}
# JWT Claims
ISSUER="$CLIENT_ID" # Issuer
SUBJECT="$CLIENT_ID" # Subject
AUDIENCE="$AUTH_SERVER_TOKEN_ENDPOINT_URL" # Audience
JTI=$(generate_jti) # JWT ID
CURRENT_TIME=$(date +%s)
EXPIRATION_TIME=$(($CURRENT_TIME + 3600)) # 1 hour from now
# Create JWT Header
HEADER=$(jq -n --arg alg "RS256" --arg typ "JWT" '{alg: $alg, typ: $typ}')
HEADER_BASE64=$(echo -n "$HEADER" | base64url_encode)
# Create JWT Payload
PAYLOAD=$(jq -n \
--arg iss "$ISSUER" \
--arg sub "$SUBJECT" \
--arg aud "$AUDIENCE" \
--arg jti "$JTI" \
--argjson iat $CURRENT_TIME \
--argjson exp $EXPIRATION_TIME \
'{iss: $iss, sub: $sub, aud: $aud, jti: $jti, iat: $iat, exp: $exp}')
PAYLOAD_BASE64=$(echo -n "$PAYLOAD" | base64url_encode)
# Prepare the message to be signed
MESSAGE="$HEADER_BASE64.$PAYLOAD_BASE64"
# Use AWS KMS to sign the message
SIGNATURE_JSON=$(echo -n "$MESSAGE" | aws kms sign \
--key-id "$KMS_KEY_ARN" \
--message-type RAW \
--signing-algorithm "$ALGORITHM" \
--message fileb:///dev/stdin \
--output json)
SIGNATURE=$(echo $SIGNATURE_JSON | jq -r '.Signature' | base64 -d | base64url_encode)
# Construct the JWT
JWT="$HEADER_BASE64.$PAYLOAD_BASE64.$SIGNATURE"
echo "jwt = \"$JWT\"" > terraform.tfvars
With a client id / secret, to be secure you will have to go through a rotation. If you do a JWT signer, it's a little bit more complex, but you can still get the client going.
here is an example with grabbing the jwt from a signed aws kms so that you aren't responsible for getting the details.
you can then use it like: