--- /dev/null
+#!/bin/bash
+
+# ============LICENSE_START===============================================
+# Copyright (C) 2023 Nordix Foundation. 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.
+# ============LICENSE_END=================================================
+#
+
+# Script intended to be sourced by other script to add functions to the keycloak rest API
+
+KC_URL=http://localhost:8462
+echo "Keycloak url: "$KC_URL
+
+__get_admin_token() {
+ echo "Get admin token"
+ ADMIN_TOKEN=""
+ while [ "${#ADMIN_TOKEN}" -lt 20 ]; do
+ ADMIN_TOKEN=$(curl -s -X POST --max-time 2 "$KC_URL/realms/master/protocol/openid-connect/token" -H "Content-Type: application/x-www-form-urlencoded" -d "username=admin" -d "password=admin" -d 'grant_type=password' -d "client_id=admin-cli" | jq -r '.access_token')
+ if [ "${#ADMIN_TOKEN}" -lt 20 ]; then
+ echo "Could not get admin token, retrying..."
+ echo "Retrieved token: $ADMIN_TOKEN"
+ fi
+ done
+ echo "Admin token: ${ADMIN_TOKEN:0:10}..."
+ echo $ADMIN_TOKEN > .admin_token
+ __ADM_TOKEN_TS=$SECONDS
+}
+
+__check_admin_token() {
+ __diff=$(($SECONDS-$__ADM_TOKEN_TS))
+ if [ $__diff -gt 15 ]; then
+ __get_admin_token
+ fi
+}
+
+__get_admin_token
+
+indent1() { sed 's/^/ /'; }
+indent2() { sed 's/^/ /'; }
+
+decode_token() {
+ echo "Decoding access_token"
+ echo $1 | jq -R 'split(".") | .[0,1] | @base64d | fromjson'
+}
+
+decode_jwt() {
+ echo "Decoding jwt"
+ echo $1 | jq -r .access_token | jq -R 'split(".") | .[0,1] | @base64d | fromjson'
+}
+
+list_realms() {
+ echo "Listing all realms"
+ __check_admin_token
+ curl -s \
+ -X GET \
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
+ "$KC_URL/admin/realms" | jq -r '.[].id' | indent2
+}
+delete_realms() {
+ echo "$@"
+ for realm in "$@"; do
+ echo "Attempt to delete realm: $realm"
+ __check_admin_token
+ curl -s \
+ -X DELETE \
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
+ "$KC_URL/admin/realms/$realm" | indent1
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+ echo " OK"
+ done
+}
+
+create_realms() {
+ echo "Creating realms: $@"
+ while [ $# -gt 0 ]; do
+ echo " Attempt to create realm: $1"
+ __check_admin_token
+cat > .jsonfile1 <<- "EOF"
+{
+"realm":"$__realm_name",
+"enabled":true
+}
+EOF
+ export __realm_name=$1
+ envsubst < .jsonfile1 > .jsonfile2
+ curl -s \
+ -X POST \
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
+ -H "Content-Type: application/json" \
+ -d @".jsonfile2" \
+ "$KC_URL/admin/realms" | indent2
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+ echo " OK"
+ shift
+ done
+}
+
+create_clients() {
+ __realm=$1
+ shift
+ echo "Attempt to create clients $@ for realm: $__realm"
+
+cat > .jsonfile1 <<- "EOF"
+{
+ "clientId":"$__client_name",
+ "publicClient": false,
+ "serviceAccountsEnabled": true,
+ "rootUrl":"https://example.com/example/",
+ "adminUrl":"https://example.com/example/"
+}
+EOF
+ while [ $# -gt 0 ]; do
+ echo " Creating client: $1"
+ __check_admin_token
+ export __client_name=$1
+ envsubst < .jsonfile1 > .jsonfile2
+ curl -s \
+ -X POST \
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
+ -H "Content-Type: application/json" \
+ -d @".jsonfile2" \
+ "$KC_URL/admin/realms/$__realm/clients" | indent1
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+ echo " OK"
+ shift
+ done
+}
+
+__get_client_id() {
+ __client_data=$(curl -s \
+ -X GET \
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
+ "$KC_URL/admin/realms/$1/clients?clientId=$2")
+ if [ $? -ne 0 ]; then
+ return 1
+ fi
+ __client_id=$(echo $__client_data | jq -r '.[0].id')
+ echo $__client_id
+ return 0
+}
+
+generate_client_secrets() {
+ __realm=$1
+ shift
+ echo "Attempt to generate secret for clients $@ in realm $__realm"
+ while [ $# -gt 0 ]; do
+ __check_admin_token
+ __client_id=$(__get_client_id $__realm $1)
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+ echo " Client id for client $1 in realm $__realm: "$__client_id | indent1
+ echo " Creating secret"
+ __client_secret=$(curl -s \
+ -X POST \
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
+ "$KC_URL/admin/realms/$__realm/clients/$__client_id/client-secret")
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+ __client_secret=$(curl -s \
+ -X GET \
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
+ "$KC_URL/admin/realms/$__realm/clients/$__client_id/client-secret")
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+ __client_secret=$(echo $__client_secret | jq -r .value)
+ echo " Client secret for client $1 in realm $__realm: "$__client_secret | indent1
+ echo $__client_secret > ".sec_$__realm""_$1"
+ echo " OK"
+ shift
+ done
+}
+
+create_client_roles() {
+ # <realm-name> <client-name> [<role-name>]+
+ __check_admin_token
+ __client_id=$(__get_client_id $1 $2)
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+ __realm=$1
+ shift; shift;
+ while [ $# -gt 0 ]; do
+
+cat > .jsonfile1 <<- "EOF"
+{
+ "name":"$__role"
+}
+EOF
+ export __role=$1
+ envsubst < .jsonfile1 > .jsonfile2
+ curl -s \
+ -X POST \
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
+ -H "Content-Type: application/json" \
+ -d @".jsonfile2" \
+ "$KC_URL/admin/realms/$__realm/clients/$__client_id/roles" | indent1
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+ shift
+ done
+}
+
+__get_service_account_id() {
+ # <realm-name> <client-id>
+ __service_account_data=$(curl -s \
+ -X GET \
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
+ "$KC_URL/admin/realms/$1/clients/$2/service-account-user")
+ if [ $? -ne 0 ]; then
+ return 1
+ fi
+ __service_account_id=$(echo $__service_account_data | jq -r '.id')
+ echo $__service_account_id
+ return 0
+}
+
+__get_client_available_role_id() {
+ # <realm-name> <service-account-id> <client-id> <client-role-name>
+ __client_role_data=$(curl -s \
+ -X GET \
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
+ "$KC_URL/admin/realms/$1/users/$2/role-mappings/clients/$3/available")
+ if [ $? -ne 0 ]; then
+ return 1
+ fi
+ #__client_role_id=$(echo $__client_role_data | jq -r '.id')
+ __client_role_id=$(echo $__client_role_data | jq -r '.[] | select(.name=="'$4'") | .id ')
+ echo $__client_role_id
+ return 0
+}
+
+__get_client_mapped_role_id() {
+ # <realm-name> <service-account-id> <client-id> <client-role-name>
+ __client_role_data=$(curl -s \
+ -X GET \
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
+ "$KC_URL/admin/realms/$1/users/$2/role-mappings/clients/$3")
+ if [ $? -ne 0 ]; then
+ return 1
+ fi
+ #__client_role_id=$(echo $__client_role_data | jq -r '.id')
+ __client_role_id=$(echo $__client_role_data | jq -r '.[] | select(.name=="'$4'") | .id ')
+ echo $__client_role_id
+ return 0
+}
+
+add_client_roles_mapping() {
+ # <realm-name> <client-name> [<role-name>]+
+ echo "Attempt to add roles ${@:3} to client $2 in realm $1"
+ __check_admin_token
+ __realm=$1
+ __client=$2
+ __client_id=$(__get_client_id $__realm $__client)
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+ echo " Client id for client $__client in realm $__realm: "$__client_id | indent1
+ __service_account_id=$(__get_service_account_id $__realm $__client_id)
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+ echo " Service account id for client $__client in realm $__realm: "$__service_account_id | indent1
+ shift; shift
+ __cntr=0
+ __all_roles=$@
+ while [ $# -gt 0 ]; do
+ if [ $__cntr -eq 0 ]; then
+ echo "[" > .jsonfile2
+ fi
+ __client_role_id=$(__get_client_available_role_id $__realm $__service_account_id $__client_id $1)
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+
+ __role='{"name":"'$1'","id":"'$__client_role_id'","composite": false,"clientRole": true}'
+ if [ $__cntr -gt 0 ]; then
+ echo "," >> .jsonfile2
+ fi
+ echo $__role >> .jsonfile2
+ let __cntr=__cntr+1
+ shift
+ done
+ echo "]" >> .jsonfile2
+ echo " Adding roles $__all_roles to client $__client in realm $__realm"
+
+ curl -s \
+ -X POST \
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
+ -H "Content-Type: application/json" \
+ -d @".jsonfile2" \
+ "$KC_URL/admin/realms/$__realm/users/$__service_account_id/role-mappings/clients/$__client_id" | indent2
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+ echo " OK"
+}
+
+
+
+remove_client_roles_mapping() {
+ # <realm-name> <client-name> [<role-name>]+
+ echo "Attempt to removed roles ${@:3} from client $2 in realm $1"
+ __check_admin_token
+ __realm=$1
+ __client=$2
+ __client_id=$(__get_client_id $__realm $__client)
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+ echo " Client id for client $__client in realm $__realm: "$__client_id | indent1
+ __service_account_id=$(__get_service_account_id $__realm $__client_id)
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+ echo " Service account id for client $__client in realm $__realm: "$__service_account_id | indent1
+ shift; shift
+ __cntr=0
+ __all_roles=$@
+ while [ $# -gt 0 ]; do
+ if [ $__cntr -eq 0 ]; then
+ echo "[" > .jsonfile2
+ fi
+ __client_role_id=$(__get_client_mapped_role_id $__realm $__service_account_id $__client_id $1)
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+
+ __role='{"name":"'$1'","id":"'$__client_role_id'","composite": false,"clientRole": true}'
+ if [ $__cntr -gt 0 ]; then
+ echo "," >> .jsonfile2
+ fi
+ echo $__role >> .jsonfile2
+ let __cntr=__cntr+1
+ shift
+ done
+ echo "]" >> .jsonfile2
+ echo " Removing roles $__all_roles from client $__client in realm $__realm"
+
+ curl -s \
+ -X DELETE \
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
+ -H "Content-Type: application/json" \
+ -d @".jsonfile2" \
+ "$KC_URL/admin/realms/$__realm/users/$__service_account_id/role-mappings/clients/$__client_id" | indent2
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+ echo " OK"
+}
+
+add_client_hardcoded-claim-mapper() {
+# <realm-name> <client-name> <mapper-name> <claim-name> <claim-value>
+ __check_admin_token
+ __realm=$1
+ __client=$2
+ export __mapper_name=$3
+ export __claim_name=$4
+ export __claim_value=$5
+
+ __client_id=$(__get_client_id $__realm $__client)
+ if [ $? -ne 0 ]; then
+ echo " Fatal error when getting client id, response: "$?
+ exit 1
+ fi
+ cat > .jsonfile1 <<- "EOF"
+{
+ "name": "$__mapper_name",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-hardcoded-claim-mapper",
+ "consentRequired": false,
+ "config": {
+ "claim.value": "$__claim_value",
+ "userinfo.token.claim": "true",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "$__claim_name",
+ "access.tokenResponse.claim": "false"
+ }
+}
+EOF
+ envsubst < .jsonfile1 > .jsonfile2
+ curl -s \
+ -X POST \
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
+ -H "Content-Type: application/json" \
+ -d @".jsonfile2" \
+ "$KC_URL/admin/realms/nonrtric-realm/clients/"$__client_id"/protocol-mappers/models" | indent2
+ if [ $? -ne 0 ]; then
+ echo "Command failed"
+ exit 1
+ fi
+ set +x
+ cat .jsonfile2
+ echo " OK"
+}
+
+# Get a client token
+# args: <realm-name> <client-name>
+get_client_token() {
+ __check_admin_token
+ __realm=$1
+ __client=$2
+ __client_id=$(__get_client_id $__realm $__client)
+ if [ $? -ne 0 ]; then
+ echo " Fatal error when getting client id, response: "$?
+ exit 1
+ fi
+
+ __client_secret=$(curl -s -f \
+ -X GET \
+ -H "Authorization: Bearer ${ADMIN_TOKEN}" \
+ "$KC_URL/admin/realms/$__realm/clients/$__client_id/client-secret")
+ if [ $? -ne 0 ]; then
+ echo " Fatal error when getting client secret, response: "$?
+ exit 1
+ fi
+
+ __client_secret=$(echo $__client_secret | jq -r .value)
+
+ __TMP_TOKEN=$(curl -s -f -X POST $KC_URL/realms/$__realm/protocol/openid-connect/token \
+ -H Content-Type:application/x-www-form-urlencoded \
+ -d client_id="$__client" -d client_secret="$__client_secret" -d grant_type=client_credentials)
+ if [ $? -ne 0 ]; then
+ echo " Fatal error when getting client token, response: "$?
+ exit 1
+ fi
+
+ echo $__TMP_TOKEN| jq -r .access_token
+ return 0
+}