如何让keycloak导出领域用户然后退出
how to get keycloak to export realm users and then exit
我们 运行 Keycloak docker AWS ECS 中的映像,我们需要一种方法来使用 ansible 导出领域和所有用户以实现自动化目的。我们可以 运行 使用 ansible 命令 运行 导出
docker exec -i 702f2fd7858d \
/bin/bash -c "export JDBC_PARAMS=?currentSchema=keycloak_service &&
/opt/jboss/keycloak/bin/standalone.sh \
-Djboss.socket.binding.port-offset=100 \
-Dkeycloak.migration.action=export \
-Dkeycloak.migration.provider=singleFile \
-Dkeycloak.migration.realmName=API \
-Dkeycloak.migration.usersExportStrategy=REALM_FILE \
-Dkeycloak.migration.file=/tmp/my_realm.json"
但 docker 容器在导出后继续 运行。我们无法 grep 日志以查找导出过程完成,因为我们使用 Docker 的 AWS 日志驱动程序来阻止访问任何日志。遗憾的是,Keycloak REST API 不支持将用户包含在现有的部分导出端点中,或者至少不支持触发将包含用户的领域导出到已安装的文件系统中的端点。
几天前我遇到了同样的问题并实施了一个可行的解决方案:
#!/usr/bin/env bash
#
# backup-keycloak.sh
# Copy the export bash script to the (already running) keycloak container
# to perform an export
docker cp docker-exec-cmd.sh keycloak:/tmp/docker-exec-cmd.sh
# Execute the script inside of the container
docker exec -it keycloak /tmp/docker-exec-cmd.sh
# Grab the finished export from the container
docker cp keycloak:/tmp/realms-export-single-file.json .
在容器内执行导出的Bash脚本如下:
#!/usr/bin/env bash
#
# docker-exec-cmd.sh
set -o errexit
set -o errtrace
set -o nounset
set -o pipefail
# If something goes wrong, this script does not run forever, but times out
TIMEOUT_SECONDS=300
# Logfile for the keycloak export instance
LOGFILE=/tmp/standalone.sh.log
# destionation export file
JSON_EXPORT_FILE=/tmp/realms-export-single-file.json
# Remove files from old backups inside the container
# You could also move the files or change the name with timestamp prefix
rm -f ${LOGFILE} ${JSON_EXPORT_FILE}
# Start a new keycloak instance with exporting options enabled.
# Use the port offset argument to prevent port conflicts
# with the "real" keycloak instance.
timeout ${TIMEOUT_SECONDS}s \
/opt/jboss/keycloak/bin/standalone.sh \
-Dkeycloak.migration.action=export \
-Dkeycloak.migration.provider=singleFile \
-Dkeycloak.migration.file=${JSON_EXPORT_FILE} \
-Djboss.socket.binding.port-offset=99 \
> ${LOGFILE} &
# Grab the keycloak export instance process id
PID="${!}"
# Wait for the export to finish
# It will wait till it sees the string, which indicates
# a successful finished backup.
# If it will take too long (>TIMEOUT_SECONDS), it will be stopped.
timeout ${TIMEOUT_SECONDS}s \
grep -m 1 "Export finished successfully" <(tail -f ${LOGFILE})
# Stop the keycloak export instance
kill ${PID}
我想到了这个单行:
sh -c 'echo $$; exec /opt/jboss/keycloak/bin/standalone.sh -Djboss.socket.binding.port-offset=98 -Dkeycloak.migration.action=export -Dkeycloak.migration.provider=dir -Dkeycloak.migration.dir=/tmp/realms/' | { read pid; while read -r line; do echo "$line"; test "$line" = "${line% Export finished successfully}" || kill $pid; done; }
它没有任何超时逻辑,它只是等待导出成功完成。
它应该 posix 兼容。
我们 运行 Keycloak docker AWS ECS 中的映像,我们需要一种方法来使用 ansible 导出领域和所有用户以实现自动化目的。我们可以 运行 使用 ansible 命令 运行 导出
docker exec -i 702f2fd7858d \
/bin/bash -c "export JDBC_PARAMS=?currentSchema=keycloak_service &&
/opt/jboss/keycloak/bin/standalone.sh \
-Djboss.socket.binding.port-offset=100 \
-Dkeycloak.migration.action=export \
-Dkeycloak.migration.provider=singleFile \
-Dkeycloak.migration.realmName=API \
-Dkeycloak.migration.usersExportStrategy=REALM_FILE \
-Dkeycloak.migration.file=/tmp/my_realm.json"
但 docker 容器在导出后继续 运行。我们无法 grep 日志以查找导出过程完成,因为我们使用 Docker 的 AWS 日志驱动程序来阻止访问任何日志。遗憾的是,Keycloak REST API 不支持将用户包含在现有的部分导出端点中,或者至少不支持触发将包含用户的领域导出到已安装的文件系统中的端点。
几天前我遇到了同样的问题并实施了一个可行的解决方案:
#!/usr/bin/env bash
#
# backup-keycloak.sh
# Copy the export bash script to the (already running) keycloak container
# to perform an export
docker cp docker-exec-cmd.sh keycloak:/tmp/docker-exec-cmd.sh
# Execute the script inside of the container
docker exec -it keycloak /tmp/docker-exec-cmd.sh
# Grab the finished export from the container
docker cp keycloak:/tmp/realms-export-single-file.json .
在容器内执行导出的Bash脚本如下:
#!/usr/bin/env bash
#
# docker-exec-cmd.sh
set -o errexit
set -o errtrace
set -o nounset
set -o pipefail
# If something goes wrong, this script does not run forever, but times out
TIMEOUT_SECONDS=300
# Logfile for the keycloak export instance
LOGFILE=/tmp/standalone.sh.log
# destionation export file
JSON_EXPORT_FILE=/tmp/realms-export-single-file.json
# Remove files from old backups inside the container
# You could also move the files or change the name with timestamp prefix
rm -f ${LOGFILE} ${JSON_EXPORT_FILE}
# Start a new keycloak instance with exporting options enabled.
# Use the port offset argument to prevent port conflicts
# with the "real" keycloak instance.
timeout ${TIMEOUT_SECONDS}s \
/opt/jboss/keycloak/bin/standalone.sh \
-Dkeycloak.migration.action=export \
-Dkeycloak.migration.provider=singleFile \
-Dkeycloak.migration.file=${JSON_EXPORT_FILE} \
-Djboss.socket.binding.port-offset=99 \
> ${LOGFILE} &
# Grab the keycloak export instance process id
PID="${!}"
# Wait for the export to finish
# It will wait till it sees the string, which indicates
# a successful finished backup.
# If it will take too long (>TIMEOUT_SECONDS), it will be stopped.
timeout ${TIMEOUT_SECONDS}s \
grep -m 1 "Export finished successfully" <(tail -f ${LOGFILE})
# Stop the keycloak export instance
kill ${PID}
我想到了这个单行:
sh -c 'echo $$; exec /opt/jboss/keycloak/bin/standalone.sh -Djboss.socket.binding.port-offset=98 -Dkeycloak.migration.action=export -Dkeycloak.migration.provider=dir -Dkeycloak.migration.dir=/tmp/realms/' | { read pid; while read -r line; do echo "$line"; test "$line" = "${line% Export finished successfully}" || kill $pid; done; }
它没有任何超时逻辑,它只是等待导出成功完成。 它应该 posix 兼容。