-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #76 from IBM/keycloak
PoC: Enable Keycloak for Identity Managment
- Loading branch information
Showing
25 changed files
with
3,814 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
#!/bin/bash | ||
|
||
JWTFILE="/jwt/token" | ||
IDSREQFILE="/pod-metadata/tsi-identities" | ||
|
||
# set the initial wait to 10 seconds | ||
# once the vault secret is retrieved successfully, switch to | ||
# provided parameter | ||
WAIT_SEC=10 | ||
|
||
# when script is running in init initContainer, attempt obtaining secrets only few times | ||
MAX_EXEC=5 | ||
COUNTER=0 | ||
|
||
while true | ||
do | ||
# first we should wait for the token to be available | ||
if [ ! -s "$JWTFILE" ]; then | ||
echo "$JWTFILE does not exist yet. Let's wait for it. Please make sure the JSS in initalized." | ||
while [ ! -s "$JWTFILE" ]; do | ||
sleep 5 | ||
done | ||
fi | ||
|
||
# get the identity definitions | ||
if [ ! -s "$IDSREQFILE" ]; then | ||
echo "$IDSREQFILE does not exist or empty." | ||
|
||
if $IS_SIDECAR; then | ||
echo "Nothing to do. Waiting..." | ||
while [ ! -s "$IDSREQFILE" ]; do | ||
sleep 5 | ||
done | ||
else | ||
# if the script is running in initContainer, there is no need to block | ||
# when no secrets are needed | ||
echo "Nothing to do. Exiting ..." | ||
exit 0 | ||
fi | ||
|
||
fi | ||
|
||
/usr/local/bin/get-keycloak-identities.sh | ||
RT=$? | ||
# When script is running as sidecar, run it forever | ||
if $IS_SIDECAR; then | ||
if [ "$RT" == "0" ]; then | ||
# introduce the random wait value from 1 to 30 seconds | ||
RAND_WAIT=$((1 + RANDOM % 30)) | ||
WAIT_SEC=$((${IDENTITY_REFRESH_SEC} + RAND_WAIT)) | ||
echo "Waiting $WAIT_SEC seconds ..." | ||
fi | ||
else | ||
# when it's running as initContainer, exit after successful transaction | ||
if [ "$RT" == "0" ]; then | ||
echo "Keycloak identities successfully executed!" | ||
exit 0 | ||
fi | ||
if [[ "$COUNTER" -gt "$MAX_EXEC" ]]; then | ||
echo "$COUNTER unsuccessful attempts to get Keycloak identities. Exiting..." | ||
exit 1 | ||
fi | ||
((COUNTER++)) | ||
fi | ||
sleep "${WAIT_SEC}" | ||
done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
#!/bin/bash | ||
|
||
IDSOUTDIR="/usr/share/secrets" | ||
JWTFILE="/jwt/token" | ||
# IDSREQFILE - Identities request file from Pod Annotation | ||
IDSREQFILE="/pod-metadata/tsi-identities" | ||
|
||
# when we decide to pass the Keycloak address on cluster level: | ||
# validate if KEYCLOAK_ADDR env. variable is set | ||
# if [ "$KEYCLOAK_ADDR" == "" ]; then | ||
# echo "KEYCLOAK_ADDR must be set" | ||
# exit 1 | ||
# fi | ||
|
||
# make sure that JWT file exists | ||
if [ ! -s "$JWTFILE" ]; then | ||
echo "$JWTFILE does not exist. Make sure Trusted Identity is setup correctly" | ||
exit 1 | ||
fi | ||
|
||
# since annotations are provided in YAML format, | ||
# convert YAML to JSON for easier manipulations | ||
if [ ! -s "$IDSREQFILE" ]; then | ||
echo "$IDSREQFILE contains no data. Nothing to do" | ||
exit 1 | ||
fi | ||
JSON=$(yq r -j "$IDSREQFILE") | ||
if [ "$?" != "0" ]; then | ||
echo "Error parsing $IDSREQFILE file. Incorrect format" | ||
exit 1 | ||
fi | ||
|
||
# the return values from this function are ignored | ||
# we only use the echoed values | ||
run() | ||
{ | ||
# example of the realm token URL: | ||
# "${KEYCLOAK_ADDR}/auth/realms/hello-world-authz/protocol/openid-connect/token" | ||
local KEYCLOAK_TOKEN_URL=$1 | ||
local K_LOCAL=$2 | ||
local LOCPATH=${K_LOCAL:-"tsi-secrets/identities"} | ||
local AUD=$3 | ||
local JWTFILE="/jwt/token" | ||
local TOKEN_RESP=$(mktemp /tmp/token-resp.XXX) | ||
local FILENAME="access_token.$3.$COUNT" | ||
|
||
# local-path must start with "tsi-secrets" | ||
if [[ ${LOCPATH} != "tsi-secrets" ]] && [[ ${LOCPATH} != "/tsi-secrets" ]] && [[ ${LOCPATH} != /tsi-secrets/* ]] && [[ ${LOCPATH} != tsi-secrets/* ]]; then | ||
echo "ERROR: invalid local-path requested: $LOCPATH" | ||
echo "Local path must start with /tsi-secrets" | ||
return 1 | ||
fi | ||
local IDSOUTDIR=${IDSOUTDIR}/${LOCPATH} | ||
|
||
# Sample format for requesting the access token: | ||
# curl --location --request POST 'http://<keycloak-server>/auth/realms/tsi-realm/protocol/openid-connect/token' \ | ||
# --header 'Content-Type: application/x-www-form-urlencoded' \ | ||
# --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:uma-ticket' \ | ||
# --data-urlencode 'audience=tsi-client' \ | ||
# --data-urlencode 'client_id=tsi-client' \ | ||
# --data-urlencode "tsi_token=$(cat /jwt/token)" | ||
|
||
# Sample format for requesting the public key from Keycloak: | ||
# curl --location --request GET 'http://<keycloak-server>/auth/realms/tsi-realm/protocol/openid-connect/certs' \ | ||
# --header 'Content-Type: application/x-www-form-urlencoded' \ | ||
# --data-urlencode --data-urlencode "tsi_token=$(cat /jwt/token)" | ||
|
||
SC=$(curl --max-time 10 -s -w "%{http_code}" -o $TOKEN_RESP --location --request POST \ | ||
${KEYCLOAK_TOKEN_URL} --header 'Content-Type: application/x-www-form-urlencoded' \ | ||
--data-urlencode 'client_id=tsi-client' --data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:uma-ticket' \ | ||
--data-urlencode "tsi_token=$(cat $JWTFILE)" --data-urlencode "audience=$AUD" 2> /dev/null) | ||
local RT=$? | ||
|
||
# return value for curl timeout is 28 | ||
if [[ "$RT" == "28" ]]; then | ||
echo "Timout while getting Keycloak token" | ||
rm $TOKEN_RESP | ||
return 1 | ||
fi | ||
|
||
if [[ "$RT" != "0" ]]; then | ||
echo "Unknown error getting Keycloak token" | ||
cat $TOKEN_RESP | ||
rm $TOKEN_RESP | ||
return 1 | ||
fi | ||
|
||
if [ "$SC" != "200" ]; then | ||
echo "Error getting Keycloak token" | ||
cat $TOKEN_RESP | ||
rm $TOKEN_RESP | ||
return 1 | ||
fi | ||
|
||
RESP=$(cat $TOKEN_RESP) | ||
# rm -f $TOKEN_RESP | ||
mkdir -p ${IDSOUTDIR} | ||
mv $TOKEN_RESP ${IDSOUTDIR}/${FILENAME} | ||
# REF_TOK=$(echo $RESP | jq -r '.refresh_token') | ||
# ACCESS_TOK=$(echo $RESP | jq -r '.access_token') | ||
# echo $ACCESS_TOK | cut -d"." -f2 | sed 's/\./\n/g' | base64 --decode | jq | ||
echo $RESP | jq -r '.access_token' | cut -d"." -f2 | base64 --decode | jq '.' > ${IDSOUTDIR}/${FILENAME}.txt | ||
} | ||
|
||
## create help menu: | ||
helpme() | ||
{ | ||
cat <<HELPMEHELPME | ||
Syntax: $0 | ||
HELPMEHELPME | ||
} | ||
|
||
ERR=0 | ||
COUNT=0 | ||
for row in $(echo "${JSON}" | jq -c '.[]' ); do | ||
# for each requested identities parse its attributes | ||
KEYCLOAK_ADDR=$(echo "$row" | jq -r '."tsi.keycloak/token-url"') | ||
KEYCLOAK_PATH=$(echo "$row" | jq -r '."tsi.keycloak/local-path"') | ||
KEYCLOAK_AUDS=$(echo "$row" | jq -r '."tsi.keycloak/audiences"') | ||
if [ "$KEYCLOAK_PATH" == "null" ]; then | ||
KEYCLOAK_PATH="" | ||
fi | ||
if [ "$KEYCLOAK_AUDS" == "null" ]; then | ||
KEYCLOAK_AUDS="tsi-client" | ||
fi | ||
|
||
# audiences can be separated with comma | ||
auds=$(echo $KEYCLOAK_AUDS | tr "," "\n") | ||
for aud in $auds; do | ||
|
||
# then run identity retrieval from Keycloak | ||
run $KEYCLOAK_ADDR $KEYCLOAK_PATH $aud | ||
RT=$? | ||
if [ "$RT" != "0" ]; then | ||
echo "Error processing identities token-url=${KEYCLOAK_ADDR}, audiance=$aud, local-path=$KEYCLOAK_PATH" | ||
# if we want to end the init process in case of the failed attempt, | ||
# uncomment all the way to the end | ||
# ERR=1 | ||
fi | ||
# increase the counter | ||
COUNT=$((COUNT+1)) | ||
done | ||
# if [ "$ERR" -ne 0 ]; then | ||
# exit 1 | ||
# fi | ||
done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,24 @@ | ||
#!/usr/bin/env bash | ||
|
||
/usr/local/bin/execute-get-token.sh & | ||
|
||
/usr/local/bin/execute-get-vault-secrets.sh | ||
RT=$? | ||
|
||
if ! $IS_SIDECAR; then | ||
if [ "$RT" == "0" ]; then | ||
echo "All good!" | ||
exit 0 | ||
echo "All good with secrets" | ||
else | ||
echo "Unsuccessful Vault retrieve" | ||
exit 1 | ||
fi | ||
fi | ||
/usr/local/bin/execute-get-keycloak-identities.sh | ||
RT=$? | ||
if ! $IS_SIDECAR; then | ||
if [ "$RT" == "0" ]; then | ||
echo "All good with identities" | ||
else | ||
echo "Unsuccessful retrieve" | ||
echo "Unsuccessful Keycloak retrieve" | ||
exit 1 | ||
fi | ||
fi |
Oops, something went wrong.