#!/usr/bin/env bash function error_handler() { >&2 echo "Exited with BAD EXIT CODE '${2}' in ${0} script at line: ${1}." exit "$2" } trap 'error_handler ${LINENO} $?' ERR set -o errtrace -o errexit -o nounset -o pipefail # you can get a list of users from the keycloak realm file like: # grep '"email" :' keycloak/realm_exports/spiffworkflow-realm.json | awk -F : '{print $2}' | sed -E 's/ "//g' | sed -E 's/",//g' > s # we keep some of these in keycloak/test_user_lists # spiffworkflow-realm.json is a mashup of the status and sartography user lists. user_file_with_one_email_per_line="${1:-}" keycloak_realm="${2:-spiffworkflow}" if [[ -z "${1:-}" ]]; then >&2 echo "usage: $(basename "$0") [user_file_with_one_email_per_line]" exit 1 fi if [[ -z "${KEYCLOAK_BASE_URL:-}" ]]; then KEYCLOAK_BASE_URL=http://localhost:7002 fi if [[ -z "${ADMIN_USERNAME:-}" ]]; then ADMIN_USERNAME="admin" fi if [[ -z "${ADMIN_PASSWORD:-}" ]]; then ADMIN_PASSWORD="admin" fi REALM_NAME="$keycloak_realm" SECURE=false KEYCLOAK_URL=$KEYCLOAK_BASE_URL/realms/$REALM_NAME/protocol/openid-connect/token if [[ $SECURE = 'y' ]]; then INSECURE= else INSECURE=--insecure fi # https://www.appsdeveloperblog.com/keycloak-rest-api-create-a-new-user/ result=$(curl --fail -s -X POST "$KEYCLOAK_URL" "$INSECURE" \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data-urlencode "username=${ADMIN_USERNAME}" \ --data-urlencode "password=${ADMIN_PASSWORD}" \ --data-urlencode 'grant_type=password' \ --data-urlencode 'client_id=admin-cli' ) backend_token=$(jq -r '.access_token' <<< "$result") function add_user() { local user_email=$1 local username=$2 local user_attribute_one=$3 local credentials='{"type":"password","value":"'"${username}"'","temporary":false}' local data='{"email":"'"${user_email}"'", "enabled":"true", "username":"'"${username}"'", "credentials":['"${credentials}"']' if [[ -n "$user_attribute_one" ]]; then data=''${data}', "attributes": {"'${custom_attribute_one}'": [ "'$user_attribute_one'" ]}' fi data="${data}}" local http_code http_code=$(curl --silent -o /dev/null -w '%{http_code}' --location --request POST "${KEYCLOAK_BASE_URL}/admin/realms/${keycloak_realm}/users" \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $backend_token" \ --data-raw "$data") echo "$http_code" } first_line_processed="false" custom_attribute_one='' while read -r input_line; do if ! grep -qE '^#' <<<"$input_line" ; then if [[ "$first_line_processed" == "false" ]]; then email_header=$(awk -F ',' '{print $1}' <<<"$input_line") if [[ "$email_header" != "email" ]]; then >&2 echo "ERROR: the first column in the first row must be email." exit 1 fi custom_attribute_one=$(awk -F ',' '{print $2}' <<<"$input_line") first_line_processed="true" elif [[ -n "$input_line" ]]; then user_email=$(awk -F ',' '{print $1}' <<<"$input_line") username=$(awk -F '@' '{print $1}' <<<"$user_email") user_attribute_one=$(awk -F ',' '{print $2}' <<<"$input_line") http_code=$(add_user "$user_email" "$username" "$user_attribute_one") if [[ "$http_code" == "409" ]]; then user_info=$(curl --fail --silent --location --request GET "${KEYCLOAK_BASE_URL}/admin/realms/${keycloak_realm}/users?username=${username}&exact=true" \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $backend_token") user_id=$(jq -r '.[0] | .id' <<<"$user_info") if [[ -z "$user_id" ]]; then >&2 echo "ERROR: Could not find user_id for user: ${user_email}" exit 1 fi curl --fail --location --silent --request DELETE "${KEYCLOAK_BASE_URL}/admin/realms/${keycloak_realm}/users/${user_id}" \ -H 'Content-Type: application/json' \ -H "Authorization: Bearer $backend_token" http_code=$(add_user "$user_email" "$username" "$user_attribute_one") fi if [[ "$http_code" != "201" ]]; then >&2 echo "ERROR: Failed to create user: ${user_email} with http_code: ${http_code}" exit 1 fi fi fi done <"$user_file_with_one_email_per_line"