Initial commit: git-hangman-lab and keycloak-hangman-lab skills
This commit is contained in:
140
git-hangman-lab/scripts/git/link-keycloak
Executable file
140
git-hangman-lab/scripts/git/link-keycloak
Executable file
@@ -0,0 +1,140 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Get the directory where this script is located
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
|
||||
USERNAME=$(pass_mgr get-username --key git)
|
||||
KC_PASS=$(pass_mgr get-secret --key keycloak)
|
||||
GITEA_PASS=$(pass_mgr get-secret --key git)
|
||||
|
||||
if [[ -z "$USERNAME" || -z "$KC_PASS" || -z "$GITEA_PASS" ]]; then
|
||||
echo "[ERROR] Missing required credentials in pass_mgr" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sql_escape() {
|
||||
printf '%s' "$1" | sed "s/'/''/g"
|
||||
}
|
||||
|
||||
WORKDIR="/tmp"
|
||||
COOKIES_FILE="$WORKDIR/${USERNAME}_oidc_cookies.txt"
|
||||
KC_LOGIN_HTML="$WORKDIR/${USERNAME}_kc_login.html"
|
||||
KC_POST_LOGIN_HTML="$WORKDIR/${USERNAME}_kc_post_login.html"
|
||||
KC_POST_LOGIN_LOG="$WORKDIR/${USERNAME}_kc_post_login.log"
|
||||
GITEA_CALLBACK_HTML="$WORKDIR/${USERNAME}_gitea_after_callback.html"
|
||||
GITEA_LINK_HTML="$WORKDIR/${USERNAME}_gitea_link_account.html"
|
||||
GITEA_LINK_RESP_HTML="$WORKDIR/${USERNAME}_gitea_link_signin.html"
|
||||
GITEA_LINK_RESP_LOG="$WORKDIR/${USERNAME}_gitea_link_signin.log"
|
||||
|
||||
OIDC_URL="https://git.hangman-lab.top/user/oauth2/hangman-lab"
|
||||
ESCAPED_USERNAME=$(sql_escape "$USERNAME")
|
||||
|
||||
cleanup() {
|
||||
"$SCRIPT_DIR/external-login-ctrl" --disable >/dev/null 2>&1 || true
|
||||
if [[ -n "${ORIG_LOGIN_TYPE:-}" && -n "${ORIG_LOGIN_SOURCE:-}" ]]; then
|
||||
ssh root@vps.git "
|
||||
set -euo pipefail
|
||||
. /root/git-kc/.env
|
||||
docker exec -i git-kc-mysql mysql -uroot -p\"\$MYSQL_ROOT_PASSWORD\" giteadb -e \"UPDATE user SET login_type=${ORIG_LOGIN_TYPE}, login_source=${ORIG_LOGIN_SOURCE}, login_name=${ORIG_LOGIN_NAME_SQL:-NULL} WHERE name='${ESCAPED_USERNAME}';\"
|
||||
" >/dev/null 2>&1 || true
|
||||
fi
|
||||
rm -f "$COOKIES_FILE" "$KC_LOGIN_HTML" "$KC_POST_LOGIN_HTML" "$KC_POST_LOGIN_LOG" \
|
||||
"$GITEA_CALLBACK_HTML" "$GITEA_LINK_HTML" "$GITEA_LINK_RESP_HTML" "$GITEA_LINK_RESP_LOG"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
rm -f "$COOKIES_FILE" "$KC_LOGIN_HTML" "$KC_POST_LOGIN_HTML" "$KC_POST_LOGIN_LOG" \
|
||||
"$GITEA_CALLBACK_HTML" "$GITEA_LINK_HTML" "$GITEA_LINK_RESP_HTML" "$GITEA_LINK_RESP_LOG"
|
||||
|
||||
# Capture original login fields so we can restore them exactly.
|
||||
ORIG_STATE=$(ssh root@vps.git "
|
||||
set -euo pipefail
|
||||
. /root/git-kc/.env
|
||||
docker exec -i git-kc-mysql mysql -N -B -uroot -p\"\$MYSQL_ROOT_PASSWORD\" giteadb -e \"SELECT login_type, login_source, COALESCE(login_name, '__NULL__') FROM user WHERE name='${ESCAPED_USERNAME}' LIMIT 1;\"
|
||||
")
|
||||
|
||||
if [[ -z "$ORIG_STATE" ]]; then
|
||||
echo "[ERROR] User not found in Gitea DB: $USERNAME" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
IFS=$'\t' read -r ORIG_LOGIN_TYPE ORIG_LOGIN_SOURCE ORIG_LOGIN_NAME <<< "$ORIG_STATE"
|
||||
if [[ "$ORIG_LOGIN_NAME" == "__NULL__" ]]; then
|
||||
ORIG_LOGIN_NAME_SQL="NULL"
|
||||
else
|
||||
ORIG_LOGIN_NAME_SQL="'$(sql_escape "$ORIG_LOGIN_NAME")'"
|
||||
fi
|
||||
|
||||
"$SCRIPT_DIR/external-login-ctrl" --enable
|
||||
|
||||
echo "[INFO] 通过 OIDC 入口触发跳转,获取 Keycloak 登录页..."
|
||||
curl -s -L -c "$COOKIES_FILE" "$OIDC_URL" -o "$KC_LOGIN_HTML"
|
||||
|
||||
KC_LOGIN_URL=$(perl -ne '
|
||||
if(/<form id="kc-form-login"/ .. /<\/form>/){
|
||||
if(/action="([^"]+)"/){
|
||||
my $u=$1; $u=~s/&/&/g; print $u; exit
|
||||
}
|
||||
}
|
||||
' "$KC_LOGIN_HTML")
|
||||
|
||||
if [[ -z "${KC_LOGIN_URL:-}" ]]; then
|
||||
echo "[ERROR] 未找到 kc-form-login 表单的 action URL" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[INFO] 登录 Keycloak..."
|
||||
curl -v "$KC_LOGIN_URL" \
|
||||
-b "$COOKIES_FILE" -c "$COOKIES_FILE" \
|
||||
--data-urlencode "username=$USERNAME" \
|
||||
--data-urlencode "password=$KC_PASS" \
|
||||
-d "credentialId=" \
|
||||
-o "$KC_POST_LOGIN_HTML" \
|
||||
2>"$KC_POST_LOGIN_LOG" || true
|
||||
|
||||
GITEA_CALLBACK_URL=$(grep -i "location: https://git.hangman-lab.top" "$KC_POST_LOGIN_LOG" | sed -E 's/.*location: (https:[^\r]+).*/\1/i' | tail -n1)
|
||||
|
||||
if [[ -z "${GITEA_CALLBACK_URL:-}" ]]; then
|
||||
echo "[ERROR] 登录后未发现返回 Gitea 的 callback URL" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[INFO] 调用 Gitea 回调..."
|
||||
curl -s -L -b "$COOKIES_FILE" -c "$COOKIES_FILE" "$GITEA_CALLBACK_URL" -o "$GITEA_CALLBACK_HTML"
|
||||
|
||||
echo "[INFO] 访问 Gitea Link Account 页面..."
|
||||
curl -s -b "$COOKIES_FILE" "https://git.hangman-lab.top/user/link_account" -o "$GITEA_LINK_HTML"
|
||||
|
||||
CSRF_TOKEN=$(perl -ne 'if(/name="_csrf" value="([^"]+)"/){print $1; exit}' "$GITEA_LINK_HTML" || true)
|
||||
|
||||
if [[ -z "${CSRF_TOKEN:-}" ]]; then
|
||||
echo "[ERROR] 未能从 Link Account 页面解析出 _csrf" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[INFO] 临时将 login_type 改为本地登录..."
|
||||
ssh root@vps.git "
|
||||
set -euo pipefail
|
||||
. /root/git-kc/.env
|
||||
docker exec -i git-kc-mysql mysql -uroot -p\"\$MYSQL_ROOT_PASSWORD\" giteadb -e \"UPDATE user SET login_type=0, login_source=0, login_name=NULL WHERE name='${ESCAPED_USERNAME}';\"
|
||||
"
|
||||
|
||||
echo "[INFO] 提交 link_account_signin..."
|
||||
curl -v "https://git.hangman-lab.top/user/link_account_signin" \
|
||||
-b "$COOKIES_FILE" -c "$COOKIES_FILE" \
|
||||
--data-urlencode "_csrf=$CSRF_TOKEN" \
|
||||
--data-urlencode "user_name=$USERNAME" \
|
||||
--data-urlencode "password=$GITEA_PASS" \
|
||||
-o "$GITEA_LINK_RESP_HTML" \
|
||||
2>"$GITEA_LINK_RESP_LOG" || true
|
||||
|
||||
echo "[INFO] 恢复原始登录方式..."
|
||||
ssh root@vps.git "
|
||||
set -euo pipefail
|
||||
. /root/git-kc/.env
|
||||
docker exec -i git-kc-mysql mysql -uroot -p\"\$MYSQL_ROOT_PASSWORD\" giteadb -e \"UPDATE user SET login_type=${ORIG_LOGIN_TYPE}, login_source=${ORIG_LOGIN_SOURCE}, login_name=${ORIG_LOGIN_NAME_SQL} WHERE name='${ESCAPED_USERNAME}';\"
|
||||
"
|
||||
unset ORIG_LOGIN_TYPE ORIG_LOGIN_SOURCE ORIG_LOGIN_NAME ORIG_LOGIN_NAME_SQL
|
||||
|
||||
echo "[DONE] Keycloak 账号关联完成"
|
||||
Reference in New Issue
Block a user