diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..80c8200 Binary files /dev/null and b/.DS_Store differ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c3518cb --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +FROM quay.io/ecosystem-appeng/keycloak-source:latest as keycloak + +FROM registry.access.redhat.com/ubi9/openjdk-11-runtime +WORKDIR /opt/keycloak/bin +ARG KEYCLOAK_VERSION=21.1.1 + +USER root +# COPY ca-bundle.crt /etc/pki/ca-trust/source/anchors +# RUN update-ca-trust extract +# RUN trust list --filter=ca-anchors | grep ingress -A3 + +RUN microdnf install -y jq +RUN mkdir -p /opt/keycloak/bin/client/lib/ + +COPY --from=keycloak /opt/keycloak/bin/client/keycloak-admin-cli-${KEYCLOAK_VERSION}.jar client +COPY --from=keycloak /opt/keycloak/bin/client/lib/ client/lib/ +COPY --from=keycloak /opt/keycloak/bin/kcadm.sh . + +COPY scripts/*.sh /opt/keycloak/bin/ + + +RUN chmod +x /opt/keycloak/bin/Entrypoint.sh && \ + chmod +x /opt/keycloak/bin/kcadm.sh && \ + chmod +x /opt/keycloak/bin/user-import.sh && \ + chmod +x /opt/keycloak/bin/user-export.sh && \ + chmod +x /opt/keycloak/bin/groups-ids-wrapper.sh + +USER 185 +ENTRYPOINT ["/opt/keycloak/bin/Entrypoint.sh"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bc489da --- /dev/null +++ b/Makefile @@ -0,0 +1,36 @@ + +help: ## Prints help for targets with comments + @grep -E '^[a-zA-Z0-9.\ _-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + +build: + docker build -t kc-exim:latest . + +export: ## run an export job, exports remote server users into local filesystem + + + docker run -it \ + -e EXPORT_KEYCLOAK_SERVER=$(EXPORT_KEYCLOAK_SERVER) \ + -e EXPORT_REALM=$(EXPORT_REALM) \ + -e EXPORT_TOKEN=$(token) \ + -v $(WORK_DIRECTORY):/home/default/EXPORT_DIR \ + kc-exim:latest export + +# export: ## run an export job, exports remote server users into local filesystem + + +# CONTAINER_ID=$$(docker run -d \ +# -e EXPORT_KEYCLOAK_SERVER=$(EXPORT_KEYCLOAK_SERVER) \ +# -e EXPORT_REALM=$(EXPORT_REALM) \ +# -e EXPORT_TOKEN=$(token) \ +# -v $(WORK_DIRECTORY):/home/default/EXPORT_DIR \ +# kc-exim:latest export); \ +# docker wait $${CONTAINER_ID} + +import: ## run an import job, imports local users/groups into a remote server + + docker run -it \ + -e IMPORT_KEYCLOAK_SERVER=$(IMPORT_KEYCLOAK_SERVER) \ + -e IMPORT_REALM=$(IMPORT_REALM) \ + -e IMPORT_TOKEN=$(token) \ + -v $(WORK_DIRECTORY):/home/default/IMPORT_DIR \ + kc-exim:latest import \ No newline at end of file diff --git a/README.md b/README.md index c07827e..c144aec 100644 --- a/README.md +++ b/README.md @@ -1,69 +1,50 @@ -# kcum -key cloak user migrationr shell scripts +# kc-exim +KeyCloak user Export/Import tool -## about -this app contains the kcadm.sh and its dependincies script provided with the latest Keycloak distibution. -in addition a customized scripts that uses the kcadm.sh to export/import keycloak users from a server/realm into a target server/realm -it does export relevant user infor including attributes -it does export group paths -during the import, the same groups expected to pre-exist in the target server, and the newly migrated users will join the target groups according to the target server group ids, (automatically) +## how to run **docker-needed** -## how to run +### build +``` +make build +``` -1. clone - - ``` +### EXPORT - git clone git@github.com:nemerna/kcum.git +1. prepare variables + ``` + # export the following env variables + EXPORT_KEYCLOAK_SERVER=http://localhost:2020 + EXPORT_REALM=kcm + EXPORT_TOKEN=xxxxx + WORK_DIRECTORY=$(pwd)/some-dir ``` -2. move to the project dir directory - +2. start the EXPORT job ``` - cd kcum + make export ``` -3. add the bin to your PATH +### IMPORT + +1. prepare variables ``` - export PATH=$PATH:$(pwd)/bin + # export the following env variables + IMPORT_KEYCLOAK_SERVER=http://localhost:1010 + IMPORT_REALM=kcm + IMPORT_TOKEN=xxxxx + WORK_DIRECTORY=$(pwd)/some-dir-that-contain-previous-export + ``` -4. export relevant env vars - +2. start the IMPORT job + ``` + make import ``` - #the work directory to proccess directory (always should be set) - export WORK_DIRECTORY=./USERMANAGER_EXPORT - - # the source server url (copy from) - export IMPORT_KEYCLOAK_SERVER=https://src-server.com - - # the realm of the source server (copy from) - export IMPORT_REALM=src-realm - - # the client-id of the source server (copy from) - export IMPORT_CLIENT=src-client - - # the client secret of the source server (copy from) - export IMPORT_SECRET=src-secret - - - # the target server url (create in) - export EXPORT_KEYCLOAK_SERVER=https://target-server.com - - # the realm of the target server (create in) - export EXPORT_REALM=target-realm - # the client-id of the target server (create in) - export EXPORT_CLIENT=target-client - # the client secret of the target server (create in) - export EXPORT_SECRET=target-secret +### obtaining a token - ``` -4. run the user manager - - ``` - user-manager.sh [export | import | migrate] - ``` -**NOTE: when you export, only export parameters needed, when import then only import parameters are needed, when igrate you need to specify both export and import related variables** +``` + export token=$(curl -X POST --location "https://your-keyclaok-server/realms/kcm/protocol/openid-connect/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=password&username=your-user-name&password=no-one-knows&client_id=your-client-id" | jq -r .access_token) +``` \ No newline at end of file diff --git a/bin/client/keycloak-admin-cli-21.1.2.jar b/bin/client/keycloak-admin-cli-21.1.2.jar deleted file mode 100644 index c8600c9..0000000 Binary files a/bin/client/keycloak-admin-cli-21.1.2.jar and /dev/null differ diff --git a/bin/client/keycloak-client-registration-cli-21.1.2.jar b/bin/client/keycloak-client-registration-cli-21.1.2.jar deleted file mode 100644 index a26776d..0000000 Binary files a/bin/client/keycloak-client-registration-cli-21.1.2.jar and /dev/null differ diff --git a/bin/client/lib/bcprov-jdk15on-1.70.jar b/bin/client/lib/bcprov-jdk15on-1.70.jar deleted file mode 100644 index 0e4198e..0000000 Binary files a/bin/client/lib/bcprov-jdk15on-1.70.jar and /dev/null differ diff --git a/bin/client/lib/keycloak-crypto-default-21.1.2.jar b/bin/client/lib/keycloak-crypto-default-21.1.2.jar deleted file mode 100644 index ba67ed9..0000000 Binary files a/bin/client/lib/keycloak-crypto-default-21.1.2.jar and /dev/null differ diff --git a/bin/client/lib/keycloak-crypto-fips1402-21.1.2.jar b/bin/client/lib/keycloak-crypto-fips1402-21.1.2.jar deleted file mode 100644 index 6e4bc99..0000000 Binary files a/bin/client/lib/keycloak-crypto-fips1402-21.1.2.jar and /dev/null differ diff --git a/bin/kc.bat b/bin/kc.bat deleted file mode 100755 index ddf4559..0000000 --- a/bin/kc.bat +++ /dev/null @@ -1,175 +0,0 @@ -@echo off -rem ------------------------------------------------------------------------- -rem Keycloak Startup Script -rem ------------------------------------------------------------------------- - -@if not "%ECHO%" == "" echo %ECHO% -setlocal - -rem Get the program name before using shift as the command modify the variable ~nx0 -if "%OS%" == "Windows_NT" ( - set PROGNAME=%~nx0% -) else ( - set PROGNAME=kc.bat -) - -if "%OS%" == "Windows_NT" ( - set DIRNAME=%~dp0% -) else ( - set DIRNAME=.\ -) - -set SERVER_OPTS=-Djava.util.logging.manager=org.jboss.logmanager.LogManager -Dquarkus-log-max-startup-records=10000 - -set DEBUG_MODE=false -set DEBUG_PORT_VAR=8787 -set DEBUG_SUSPEND_VAR=n -set CONFIG_ARGS= - -rem Read command-line args, the ~ removes the quotes from the parameter -:READ-ARGS -set KEY=%~1 -if "%KEY%" == "" ( - goto MAIN -) -if "%KEY%" == "--debug" ( - set DEBUG_MODE=true - set DEBUG_PORT_VAR=%2 - if "%DEBUG_PORT_VAR%" == "" ( - set DEBUG_PORT_VAR=8787 - ) - if "%DEBUG_SUSPEND_VAR%" == "" ( - set DEBUG_SUSPEND_VAR=n - ) - shift - shift - goto READ-ARGS -) -if "%KEY%" == "start-dev" ( - set CONFIG_ARGS=%CONFIG_ARGS% --profile=dev %KEY% - shift - goto READ-ARGS -) -if not "%KEY:~0,2%"=="--" if "%KEY:~0,2%"=="-D" ( - set SERVER_OPTS=%SERVER_OPTS% %KEY%=%2 - shift -) -if not "%KEY:~0,2%"=="--" if not "%KEY:~0,1%"=="-" ( - set CONFIG_ARGS=%CONFIG_ARGS% %KEY% -) -if not "%KEY:~0,2%"=="-D" ( - if "%KEY:~0,1%"=="-" ( - if "%~2"=="" ( - set CONFIG_ARGS=%CONFIG_ARGS% %KEY% - ) else ( - set CONFIG_ARGS=%CONFIG_ARGS% %KEY% %2% - ) - shift - ) -) -shift -goto READ-ARGS - -:MAIN -if not "x%JAVA_OPTS%" == "x" ( - echo "JAVA_OPTS already set in environment; overriding default settings with values: %JAVA_OPTS%" -) else ( - set "JAVA_OPTS=-Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.err.encoding=UTF-8 -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8" -) - -@REM See also https://github.com/wildfly/wildfly-core/blob/7e5624cf92ebe4b64a4793a8c0b2a340c0d6d363/core-feature-pack/common/src/main/resources/content/bin/common.sh#L57-L60 -if not "x%JAVA_ADD_OPENS%" == "x" ( - echo "JAVA_ADD_OPENS already set in environment; overriding default settings with values: %JAVA_ADD_OPENS%" -) else ( - set "JAVA_ADD_OPENS=--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED" -) -set "JAVA_OPTS=%JAVA_OPTS% %JAVA_ADD_OPENS%" - -if not "x%JAVA_OPTS_APPEND%" == "x" ( - echo "Appending additional Java properties to JAVA_OPTS: %JAVA_OPTS_APPEND%" - set JAVA_OPTS=%JAVA_OPTS% %JAVA_OPTS_APPEND% -) - -if NOT "x%DEBUG%" == "x" ( - set DEBUG_MODE=%DEBUG% -) - -if NOT "x%DEBUG_PORT%" == "x" ( - set DEBUG_PORT_VAR=%DEBUG_PORT% -) - -if NOT "x%DEBUG_SUSPEND%" == "x" ( - set DEBUG_SUSPEND_VAR=%DEBUG_SUSPEND% -) - -rem Set debug settings if not already set -if "%DEBUG_MODE%" == "true" ( - echo "%JAVA_OPTS%" | findstr /I "\-agentlib:jdwp" > nul - if errorlevel == 1 ( - set JAVA_OPTS=%JAVA_OPTS% -agentlib:jdwp=transport=dt_socket,address=%DEBUG_PORT_VAR%,server=y,suspend=%DEBUG_SUSPEND_VAR% - ) else ( - echo Debug already enabled in JAVA_OPTS, ignoring --debug argument - ) -) - -rem Setup Keycloak specific properties -set JAVA_OPTS=-Dprogram.name=%PROGNAME% %JAVA_OPTS% - -if "x%JAVA_HOME%" == "x" ( - set JAVA=java - echo JAVA_HOME is not set. Unexpected results may occur. - echo Set JAVA_HOME to the directory of your local JDK to avoid this message. -) else ( - if not exist "%JAVA_HOME%" ( - echo JAVA_HOME "%JAVA_HOME%" path doesn't exist - goto END - ) else ( - if not exist "%JAVA_HOME%\bin\java.exe" ( - echo "%JAVA_HOME%\bin\java.exe" does not exist - goto END - ) - set "JAVA=%JAVA_HOME%\bin\java" - ) -) - -set "CLASSPATH_OPTS=%DIRNAME%..\lib\quarkus-run.jar" - -set JAVA_RUN_OPTS=%JAVA_OPTS% -Dkc.home.dir=%DIRNAME%.. -Djboss.server.config.dir=%DIRNAME%..\conf -Dkeycloak.theme.dir=%DIRNAME%..\themes %SERVER_OPTS% -cp %CLASSPATH_OPTS% io.quarkus.bootstrap.runner.QuarkusEntryPoint %CONFIG_ARGS% - -SetLocal EnableDelayedExpansion - -set OPTIMIZED_OPTION=--optimized -set HELP_LONG_OPTION=--help -set BUILD_OPTION=build -set IS_HELP_SHORT=false - -echo %CONFIG_ARGS% | findstr /r "\<-h\>" > nul - -if not errorlevel == 1 ( - set IS_HELP_SHORT=true -) - -if "%PRINT_ENV%" == "true" ( - echo "Using JAVA_OPTS: %JAVA_OPTS%" - echo "Using JAVA_RUN_OPTS: %JAVA_RUN_OPTS%" -) - -set START_SERVER=true - -if "!CONFIG_ARGS:%OPTIMIZED_OPTION%=!"=="!CONFIG_ARGS!" if "!CONFIG_ARGS:%BUILD_OPTION%=!"=="!CONFIG_ARGS!" if "!CONFIG_ARGS:%HELP_LONG_OPTION%=!"=="!CONFIG_ARGS!" if "%IS_HELP_SHORT%" == "false" ( - setlocal enabledelayedexpansion - - "%JAVA%" -Dkc.config.build-and-exit=true %JAVA_RUN_OPTS% - - if not !errorlevel! == 0 ( - set START_SERVER=false - ) - - set JAVA_RUN_OPTS=-Dkc.config.built=true %JAVA_RUN_OPTS% -) - -if "%START_SERVER%" == "true" ( - "%JAVA%" %JAVA_RUN_OPTS% -) - -:END diff --git a/bin/kc.sh b/bin/kc.sh deleted file mode 100755 index 6b66014..0000000 --- a/bin/kc.sh +++ /dev/null @@ -1,132 +0,0 @@ -#!/bin/bash - -case "$(uname)" in - CYGWIN*) - IS_CYGWIN="true" - CFILE="$(cygpath "$0")" - RESOLVED_NAME="$(readlink -f "$CFILE")" - ;; - Darwin*) - RESOLVED_NAME="$(readlink "$0")" - ;; - FreeBSD) - RESOLVED_NAME="$(readlink -f "$0")" - ;; - Linux) - RESOLVED_NAME="$(readlink -f "$0")" - ;; -esac - -if [ "x$RESOLVED_NAME" = "x" ]; then - RESOLVED_NAME="$0" -fi - -GREP="grep" -DIRNAME="$(dirname "$RESOLVED_NAME")" - -abs_path () { - if [ -z $IS_CYGWIN ] ; then - echo "$DIRNAME/$1" - else - cygpath -w "$DIRNAME/$1" - fi -} - -SERVER_OPTS="-Dkc.home.dir='$(abs_path '..')'" -SERVER_OPTS="$SERVER_OPTS -Djboss.server.config.dir='$(abs_path '../conf')'" -SERVER_OPTS="$SERVER_OPTS -Djava.util.logging.manager=org.jboss.logmanager.LogManager" -SERVER_OPTS="$SERVER_OPTS -Dquarkus-log-max-startup-records=10000" -CLASSPATH_OPTS="'$(abs_path "../lib/quarkus-run.jar")'" - -DEBUG_MODE="${DEBUG:-false}" -DEBUG_PORT="${DEBUG_PORT:-8787}" -DEBUG_SUSPEND="${DEBUG_SUSPEND:-n}" - -CONFIG_ARGS=${CONFIG_ARGS:-""} - -while [ "$#" -gt 0 ] -do - case "$1" in - --debug) - DEBUG_MODE=true - if [ -n "$2" ] && [[ "$2" =~ ^[0-9]+$ ]]; then - DEBUG_PORT=$2 - shift - fi - ;; - --) - shift - break - ;; - *) - if [[ $1 = --* || ! $1 =~ ^-D.* ]]; then - if [[ "$1" = "start-dev" ]]; then - CONFIG_ARGS="$CONFIG_ARGS --profile=dev $1" - else - CONFIG_ARGS="$CONFIG_ARGS $1" - fi - else - SERVER_OPTS="$SERVER_OPTS $1" - fi - ;; - esac - shift -done - -if [ "x$JAVA" = "x" ]; then - if [ "x$JAVA_HOME" != "x" ]; then - JAVA="$JAVA_HOME/bin/java" - else - JAVA="java" - fi -fi - -# -# Specify options to pass to the Java VM. -# -if [ "x$JAVA_OPTS" = "x" ]; then - JAVA_OPTS="-Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.err.encoding=UTF-8 -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8" -else - echo "JAVA_OPTS already set in environment; overriding default settings with values: $JAVA_OPTS" -fi - -# See also https://github.com/wildfly/wildfly-core/blob/7e5624cf92ebe4b64a4793a8c0b2a340c0d6d363/core-feature-pack/common/src/main/resources/content/bin/common.sh#L57-L60 -if [ "x$JAVA_ADD_OPENS" = "x" ]; then - JAVA_ADD_OPENS="--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED" -else - echo "JAVA_ADD_OPENS already set in environment; overriding default settings with values: $JAVA_ADD_OPENS" -fi -JAVA_OPTS="$JAVA_OPTS $JAVA_ADD_OPENS" - -if [ "x$JAVA_OPTS_APPEND" != "x" ]; then - echo "Appending additional Java properties to JAVA_OPTS: $JAVA_OPTS_APPEND" - JAVA_OPTS="$JAVA_OPTS $JAVA_OPTS_APPEND" -fi - -# Set debug settings if not already set -if [ "$DEBUG_MODE" = "true" ]; then - DEBUG_OPT="$(echo "$JAVA_OPTS" | $GREP "\-agentlib:jdwp")" - if [ "x$DEBUG_OPT" = "x" ]; then - JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,address=$DEBUG_PORT,server=y,suspend=$DEBUG_SUSPEND" - else - echo "Debug already enabled in JAVA_OPTS, ignoring --debug argument" - fi -fi - -JAVA_RUN_OPTS="$JAVA_OPTS $SERVER_OPTS -cp $CLASSPATH_OPTS io.quarkus.bootstrap.runner.QuarkusEntryPoint ${CONFIG_ARGS#?}" - -if [ "$PRINT_ENV" = "true" ]; then - echo "Using JAVA_OPTS: $JAVA_OPTS" - echo "Using JAVA_RUN_OPTS: $JAVA_RUN_OPTS" -fi - -if [[ (! $CONFIG_ARGS = *"--optimized"*) ]] && [[ ! "$CONFIG_ARGS" == " build"* ]] && [[ ! "$CONFIG_ARGS" == *"-h" ]] && [[ ! "$CONFIG_ARGS" == *"--help"* ]]; then - eval "'$JAVA'" -Dkc.config.build-and-exit=true $JAVA_RUN_OPTS - EXIT_CODE=$? - JAVA_RUN_OPTS="-Dkc.config.built=true $JAVA_RUN_OPTS" - if [ $EXIT_CODE != 0 ]; then - exit $EXIT_CODE - fi -fi - -eval exec "'$JAVA'" $JAVA_RUN_OPTS diff --git a/bin/kcadm.bat b/bin/kcadm.bat deleted file mode 100644 index 9f69f85..0000000 --- a/bin/kcadm.bat +++ /dev/null @@ -1,8 +0,0 @@ -@echo off - -if "%OS%" == "Windows_NT" ( - set "DIRNAME=%~dp0%" -) else ( - set DIRNAME=.\ -) -java %KC_OPTS% -cp "%DIRNAME%\client\keycloak-admin-cli-21.1.2.jar" --add-opens=java.base/java.security=ALL-UNNAMED -Dkc.lib.dir="%DIRNAME%\client\lib" org.keycloak.client.admin.cli.KcAdmMain %* diff --git a/bin/kcadm.sh b/bin/kcadm.sh deleted file mode 100755 index 490c841..0000000 --- a/bin/kcadm.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/sh -case "`uname`" in - CYGWIN*) - CFILE = `cygpath "$0"` - RESOLVED_NAME=`readlink -f "$CFILE"` - ;; - Darwin*) - RESOLVED_NAME=`readlink "$0"` - ;; - FreeBSD) - RESOLVED_NAME=`readlink -f "$0"` - ;; - Linux) - RESOLVED_NAME=`readlink -f "$0"` - ;; -esac - -if [ "x$RESOLVED_NAME" = "x" ]; then - RESOLVED_NAME="$0" -fi - -DIRNAME=`dirname "$RESOLVED_NAME"` - -if [ "x$JAVA" = "x" ]; then - if [ "x$JAVA_HOME" != "x" ]; then - JAVA="$JAVA_HOME/bin/java" - else - JAVA="java" - fi -fi - -"$JAVA" $KC_OPTS -cp $DIRNAME/client/keycloak-admin-cli-21.1.2.jar --add-opens=java.base/java.security=ALL-UNNAMED -Dkc.lib.dir=$DIRNAME/client/lib org.keycloak.client.admin.cli.KcAdmMain "$@" diff --git a/bin/kcreg.bat b/bin/kcreg.bat deleted file mode 100644 index 46fc4e6..0000000 --- a/bin/kcreg.bat +++ /dev/null @@ -1,8 +0,0 @@ -@echo off - -if "%OS%" == "Windows_NT" ( - set "DIRNAME=%~dp0%" -) else ( - set DIRNAME=.\ -) -java %KC_OPTS% -cp "%DIRNAME%\client\keycloak-client-registration-cli-21.1.2.jar" --add-opens=java.base/java.security=ALL-UNNAMED -Dkc.lib.dir="%DIRNAME%\client\lib" org.keycloak.client.registration.cli.KcRegMain %* diff --git a/bin/kcreg.sh b/bin/kcreg.sh deleted file mode 100755 index c513eff..0000000 --- a/bin/kcreg.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/sh -case "`uname`" in - CYGWIN*) - CFILE = `cygpath "$0"` - RESOLVED_NAME=`readlink -f "$CFILE"` - ;; - Darwin*) - RESOLVED_NAME=`readlink "$0"` - ;; - FreeBSD) - RESOLVED_NAME=`readlink -f "$0"` - ;; - Linux) - RESOLVED_NAME=`readlink -f "$0"` - ;; -esac - -if [ "x$RESOLVED_NAME" = "x" ]; then - RESOLVED_NAME="$0" -fi - -if [ "x$JAVA" = "x" ]; then - if [ "x$JAVA_HOME" != "x" ]; then - JAVA="$JAVA_HOME/bin/java" - else - JAVA="java" - fi -fi - -DIRNAME=`dirname "$RESOLVED_NAME"` -"$JAVA" $KC_OPTS -cp $DIRNAME/client/keycloak-client-registration-cli-21.1.2.jar --add-opens=java.base/java.security=ALL-UNNAMED -Dkc.lib.dir=$DIRNAME/client/lib org.keycloak.client.registration.cli.KcRegMain "$@" diff --git a/bin/user-manager.sh b/bin/user-manager.sh deleted file mode 100755 index 825b450..0000000 --- a/bin/user-manager.sh +++ /dev/null @@ -1,124 +0,0 @@ -# #!/bin/bash - -action="$1" - -case "$action" in - "export") - - export ALL_USERS_FILE=${WORK_DIRECTORY}/EXPORT_SERVER_USERS.json - - # check for missing variables - variables=("EXPORT_KEYCLOAK_SERVER" "EXPORT_REALM" - "EXPORT_CLIENT" "EXPORT_SECRET" - "WORK_DIRECTORY" "ALL_USERS_FILE") - - for var in "${variables[@]}"; do - if [ -z "${!var}" ]; then - echo "Error: $var is not set" - exit 1 - fi - done - - echo "All variables are set" - - - - rm -rf $WORK_DIRECTORY - mkdir $WORK_DIRECTORY - - - # Login to Keycloak EXPORT SERVER - - echo $EXPORT_SECRET|kcadm.sh config credentials --server $EXPORT_KEYCLOAK_SERVER --realm $EXPORT_REALM --client $EXPORT_CLIENT - - - # run the exporter - user-exporter.sh - ;; - "import") - - export ALL_GROUPS_FILE=${WORK_DIRECTORY}/IMPORT_SERVER_GROUPS.json - - # check for missing variables - variables=("IMPORT_KEYCLOAK_SERVER" "IMPORT_REALM" - "IMPORT_CLIENT" "IMPORT_SECRET" - "WORK_DIRECTORY" "ALL_GROUPS_FILE") - - for var in "${variables[@]}"; do - if [ -z "${!var}" ]; then - echo "Error: $var is not set" - exit 1 - fi - done - - echo "All variables are set" - - # Login to Keycloak IMPORT SERVER - echo $IMPORT_SECRET|kcadm.sh config credentials --server $IMPORT_KEYCLOAK_SERVER --realm $IMPORT_REALM --client $IMPORT_CLIENT - - # get all groups of the target import server - kcadm.sh get groups > ${ALL_GROUPS_FILE} - - # run the groups wrapper - groups-ids-wrapper.sh - - # run the importer - user_importer.sh - - ;; - "migrate") - - export ALL_USERS_FILE=${WORK_DIRECTORY}/EXPORT_SERVER_USERS.json - export ALL_GROUPS_FILE=${WORK_DIRECTORY}/IMPORT_SERVER_GROUPS.json - - # check for missing variables - variables=("IMPORT_KEYCLOAK_SERVER" "EXPORT_KEYCLOAK_SERVER" "IMPORT_REALM" "EXPORT_REALM" - "IMPORT_CLIENT" "EXPORT_CLIENT" "IMPORT_SECRET" "EXPORT_SECRET" - "WORK_DIRECTORY" "WORK_DIRECTORY" "ALL_USERS_FILE" "ALL_GROUPS_FILE") - - for var in "${variables[@]}"; do - if [ -z "${!var}" ]; then - echo "Error: $var is not set" - exit 1 - fi - done - - echo "All variables are set" - - - - rm -rf $WORK_DIRECTORY - mkdir $WORK_DIRECTORY - rm -rf $WORK_DIRECTORY - mkdir $WORK_DIRECTORY - - - - - # Login to Keycloak EXPORT SERVER - - echo $EXPORT_SECRET|kcadm.sh config credentials --server $EXPORT_KEYCLOAK_SERVER --realm $EXPORT_REALM --client $EXPORT_CLIENT - - - # run the exporter - user-exporter.sh - - - # Login to Keycloak IMPORT SERVER - echo $IMPORT_SECRET|kcadm.sh config credentials --server $IMPORT_KEYCLOAK_SERVER --realm $IMPORT_REALM --client $IMPORT_CLIENT - - # get all groups of the target import server - kcadm.sh get groups > ${ALL_GROUPS_FILE} - - # run the groups wrapper - groups-ids-wrapper.sh - - # run the importer - user_importer.sh - ;; - *) - # Invalid action - echo "Invalid argument. Please provide 'export', 'import', or 'migrate' as the argument." - exit 1 - ;; -esac diff --git a/scripts/Entrypoint.sh b/scripts/Entrypoint.sh new file mode 100644 index 0000000..74a124e --- /dev/null +++ b/scripts/Entrypoint.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +export PATH=$PATH:/opt/keycloak/bin/ + +if [ "$1" = "import" ]; then + echo "Performing import..." + mkdir -p /home/default/TEMP_IMPORT_DIR + cp -r /home/default/IMPORT_DIR/* /home/default/TEMP_IMPORT_DIR + export WORK_DIRECTORY=/home/default/TEMP_IMPORT_DIR + user-import.sh +elif [ "$1" = "export" ]; then + echo "Performing export..." + export WORK_DIRECTORY=/home/default/EXPORT_DIR + user-export.sh +else + echo "Invalid argument provided." +fi \ No newline at end of file diff --git a/bin/groups-ids-wrapper.sh b/scripts/groups-ids-wrapper.sh similarity index 100% rename from bin/groups-ids-wrapper.sh rename to scripts/groups-ids-wrapper.sh diff --git a/bin/user-exporter.sh b/scripts/user-export.sh similarity index 61% rename from bin/user-exporter.sh rename to scripts/user-export.sh index dc1a0da..ae6123f 100755 --- a/bin/user-exporter.sh +++ b/scripts/user-export.sh @@ -1,10 +1,29 @@ #!/bin/bash -echo "starting exporter" +export ALL_USERS_FILE=${WORK_DIRECTORY}/EXPORT_SERVER_USERS.json + +# check for missing variables +variables=("EXPORT_KEYCLOAK_SERVER" "EXPORT_REALM" "EXPORT_TOKEN" + "WORK_DIRECTORY" "ALL_USERS_FILE") + +for var in "${variables[@]}"; do + if [ -z "${!var}" ]; then + echo "Error: $var is not set" + exit 1 + fi +done + +echo "All variables are set" + + +rm -rf $WORK_DIRECTORY +mkdir $WORK_DIRECTORY + +echo "starting exporter" ERROR_COUNT=0 # Get users as single json -kcadm.sh get users -r $EXPORT_REALM -F id,username > $ALL_USERS_FILE +kcadm.sh get users -r $EXPORT_REALM -F id,username --realm $EXPORT_REALM --server $EXPORT_KEYCLOAK_SERVER --token $EXPORT_TOKEN --no-config > $ALL_USERS_FILE # For each user, get role mappings, group memberships and user attributes and append it to the respective user entry users=$(cat $ALL_USERS_FILE | jq -c '.[]') @@ -25,7 +44,7 @@ do mkdir -p $WORK_DIRECTORY/$username # Get full user json excluding the id and timestamp - kcadm.sh get users/$user_id --fields '*(*(*(*(*(*))))),-id,-createdTimestamp' > $WORK_DIRECTORY/$username/user.json + kcadm.sh get users/$user_id --fields '*(*(*(*(*(*))))),-id,-createdTimestamp' --realm $EXPORT_REALM --server $EXPORT_KEYCLOAK_SERVER --token $EXPORT_TOKEN --no-config > $WORK_DIRECTORY/$username/USER.json # If failed to get user, skip the current iteration if [ $? -ne 0 ]; then @@ -35,7 +54,7 @@ do fi # Get the paths of all groups the current user is a member of and save into separate csv file (space separated) - kcadm.sh get users/$user_id/groups -F path --format CSV > $WORK_DIRECTORY/$username/group_paths.csv + kcadm.sh get users/$user_id/groups -F path --format CSV --realm $EXPORT_REALM --server $EXPORT_KEYCLOAK_SERVER --token $EXPORT_TOKEN --no-config > $WORK_DIRECTORY/$username/group_paths.csv # If failed, skip the rest, (for now there is no rest) if [ $? -ne 0 ]; then diff --git a/bin/user_importer.sh b/scripts/user-import.sh similarity index 61% rename from bin/user_importer.sh rename to scripts/user-import.sh index 894da23..927f31e 100755 --- a/bin/user_importer.sh +++ b/scripts/user-import.sh @@ -1,5 +1,24 @@ #!/bin/bash +export ALL_GROUPS_FILE=${WORK_DIRECTORY}/IMPORT_SERVER_GROUPS.json + +# check for missing variables +variables=("IMPORT_KEYCLOAK_SERVER" "IMPORT_TOKEN" "WORK_DIRECTORY" "ALL_GROUPS_FILE") + +for var in "${variables[@]}"; do + if [ -z "${!var}" ]; then + echo "Error: $var is not set" + exit 1 + fi +done + + +# get all groups of the target import server +kcadm.sh get groups --realm $IMPORT_REALM --server $IMPORT_KEYCLOAK_SERVER --token $IMPORT_TOKEN --no-config > ${ALL_GROUPS_FILE} + +# run the groups wrapper +groups-ids-wrapper.sh + for USER_DIR in $(find $WORK_DIRECTORY/* -type d) do USER_JSON_FILE="${USER_DIR}/USER.json" @@ -8,7 +27,7 @@ do if [[ -f $USER_JSON_FILE ]] then # Create user from user.json file - USER_ID=$(kcadm.sh create users -r $IMPORT_REALM -f $USER_JSON_FILE -i) + USER_ID=$(kcadm.sh create users -r $IMPORT_REALM -f $USER_JSON_FILE --realm $IMPORT_REALM --server $IMPORT_KEYCLOAK_SERVER --token $IMPORT_TOKEN --no-config -i) if [ $? -ne 0 ]; then #TO-DO handle when user exists, only join him to groups? echo "skipping the currently user as it exists , we talk about the dir $USER_JSON_FILE" @@ -21,7 +40,7 @@ do do if [[ ! -z "$GROUP_ID" ]] then - kcadm.sh update users/$USER_ID/groups/$GROUP_ID -r kcm -s realm=$IMPORT_REALM -s userId=$USER_ID -s groupId=$GROUP_ID -n + kcadm.sh update users/$USER_ID/groups/$GROUP_ID -r kcm -s realm=$IMPORT_REALM -s userId=$USER_ID -s groupId=$GROUP_ID --realm $IMPORT_REALM --server $IMPORT_KEYCLOAK_SERVER --token $IMPORT_TOKEN --no-config -n fi done < $GROUP_ID_FILE else