forked from baron/baron-sso
production 푸시 초안
This commit is contained in:
243
scripts/backup/refresh_works_drive_token.sh
Executable file
243
scripts/backup/refresh_works_drive_token.sh
Executable file
@@ -0,0 +1,243 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
source "$script_dir/lib/common.sh"
|
||||
|
||||
repo_root="$(backup_repo_root)"
|
||||
env_file="${WORKS_DRIVE_ENV_FILE:-$repo_root/.env}"
|
||||
|
||||
if [[ -f "$env_file" ]]; then
|
||||
set -a
|
||||
# shellcheck source=/dev/null
|
||||
source "$env_file"
|
||||
set +a
|
||||
fi
|
||||
|
||||
token_grant="${WORKS_DRIVE_TOKEN_GRANT:-refresh-token}"
|
||||
token_url="${WORKS_ADMIN_OAUTH_TOKEN_URL:-https://auth.worksmobile.com/oauth2/v2.0/token}"
|
||||
authorize_url="${WORKS_DRIVE_OAUTH_AUTHORIZE_URL:-https://auth.worksmobile.com/oauth2/v2.0/authorize}"
|
||||
client_id="${WORKS_DRIVE_OAUTH_CLIENT_ID:-}"
|
||||
client_secret="${WORKS_DRIVE_OAUTH_CLIENT_SECRET:-}"
|
||||
redirect_uri="${WORKS_DRIVE_OAUTH_REDIRECT_URI:-}"
|
||||
scope="${WORKS_DRIVE_OAUTH_SCOPE:-file}"
|
||||
curl_bin="${WORKS_DRIVE_CURL_BIN:-curl}"
|
||||
set_auth_mode="${WORKS_DRIVE_TOKEN_SET_AUTH_MODE:-true}"
|
||||
|
||||
backup_require_command jq
|
||||
|
||||
urlencode() {
|
||||
jq -nr --arg value "$1" '$value|@uri'
|
||||
}
|
||||
|
||||
redact_for_log() {
|
||||
sed -E 's/("(access_token|refresh_token|client_secret)"[[:space:]]*:[[:space:]]*)"[^"]*"/\1"REDACTED"/Ig'
|
||||
}
|
||||
|
||||
split_curl_response() {
|
||||
local response="$1"
|
||||
local __body_var="$2"
|
||||
local __status_var="$3"
|
||||
local status
|
||||
local body
|
||||
|
||||
status="$(tail -n 1 <<<"$response")"
|
||||
if [[ "$status" =~ ^[0-9][0-9][0-9]$ ]]; then
|
||||
body="$(sed '$d' <<<"$response")"
|
||||
else
|
||||
status="200"
|
||||
body="$response"
|
||||
fi
|
||||
|
||||
printf -v "$__body_var" '%s' "$body"
|
||||
printf -v "$__status_var" '%s' "$status"
|
||||
}
|
||||
|
||||
require_oauth_client() {
|
||||
[[ -n "$client_id" ]] || backup_die "WORKS_DRIVE_OAUTH_CLIENT_ID is required."
|
||||
[[ -n "$client_secret" ]] || backup_die "WORKS_DRIVE_OAUTH_CLIENT_SECRET is required."
|
||||
}
|
||||
|
||||
extract_code_from_callback_url() {
|
||||
local raw_url="$1"
|
||||
local query
|
||||
local param
|
||||
local code=""
|
||||
local decoded
|
||||
|
||||
query="${raw_url#*\?}"
|
||||
query="${query%%#*}"
|
||||
|
||||
IFS='&' read -r -a params <<<"$query"
|
||||
for param in "${params[@]}"; do
|
||||
if [[ "$param" == code=* ]]; then
|
||||
code="${param#code=}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
decoded="${code//+/ }"
|
||||
printf '%b' "${decoded//%/\\x}"
|
||||
}
|
||||
|
||||
write_env_value() {
|
||||
local key="$1"
|
||||
local value="$2"
|
||||
local tmp_file
|
||||
local env_uid=""
|
||||
local env_gid=""
|
||||
local env_mode=""
|
||||
|
||||
[[ -n "$key" ]] || backup_die "env key is required."
|
||||
[[ "$value" != *$'\n'* ]] || backup_die "env value for $key must not contain a newline."
|
||||
|
||||
mkdir -p "$(dirname "$env_file")"
|
||||
tmp_file="$(mktemp "$env_file.tmp.XXXXXX")"
|
||||
|
||||
if [[ -f "$env_file" ]]; then
|
||||
env_uid="$(stat -c '%u' "$env_file")"
|
||||
env_gid="$(stat -c '%g' "$env_file")"
|
||||
env_mode="$(stat -c '%a' "$env_file")"
|
||||
awk -v key="$key" -v value="$value" '
|
||||
BEGIN { written = 0 }
|
||||
$0 ~ "^[[:space:]]*" key "=" {
|
||||
print key "=" value
|
||||
written = 1
|
||||
next
|
||||
}
|
||||
{ print }
|
||||
END {
|
||||
if (!written) {
|
||||
print key "=" value
|
||||
}
|
||||
}
|
||||
' "$env_file" >"$tmp_file"
|
||||
else
|
||||
printf '%s=%s\n' "$key" "$value" >"$tmp_file"
|
||||
fi
|
||||
|
||||
if [[ -n "$env_mode" ]]; then
|
||||
chmod "$env_mode" "$tmp_file"
|
||||
else
|
||||
chmod 600 "$tmp_file"
|
||||
fi
|
||||
|
||||
if [[ -n "$env_uid" && -n "$env_gid" ]]; then
|
||||
chown "$env_uid:$env_gid" "$tmp_file" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
mv "$tmp_file" "$env_file"
|
||||
}
|
||||
|
||||
print_authorize_url() {
|
||||
[[ -n "$client_id" ]] || backup_die "WORKS_DRIVE_OAUTH_CLIENT_ID is required."
|
||||
[[ -n "$redirect_uri" ]] || backup_die "WORKS_DRIVE_OAUTH_REDIRECT_URI is required."
|
||||
|
||||
printf '%s?client_id=%s&redirect_uri=%s&scope=%s&response_type=code&state=%s\n' \
|
||||
"$authorize_url" \
|
||||
"$(urlencode "$client_id")" \
|
||||
"$(urlencode "$redirect_uri")" \
|
||||
"$(urlencode "$scope")" \
|
||||
"$(urlencode "${WORKS_DRIVE_OAUTH_STATE:-baron-sso-backup}")"
|
||||
}
|
||||
|
||||
request_refresh_token_grant() {
|
||||
require_oauth_client
|
||||
|
||||
local refresh_token="${WORKS_DRIVE_OAUTH_REFRESH_TOKEN:-}"
|
||||
local response
|
||||
local response_body
|
||||
local http_status
|
||||
|
||||
[[ -n "$refresh_token" ]] || backup_die "WORKS_DRIVE_OAUTH_REFRESH_TOKEN is required for refresh-token grant."
|
||||
backup_require_command "$curl_bin"
|
||||
|
||||
response="$("$curl_bin" -sS -w $'\n%{http_code}' -X POST \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
--data-urlencode "grant_type=refresh_token" \
|
||||
--data-urlencode "refresh_token=$refresh_token" \
|
||||
--data-urlencode "client_id=$client_id" \
|
||||
--data-urlencode "client_secret=$client_secret" \
|
||||
"$token_url")"
|
||||
split_curl_response "$response" response_body http_status
|
||||
|
||||
if [[ "$http_status" -lt 200 || "$http_status" -ge 300 ]]; then
|
||||
backup_die "WORKS refresh token request failed (HTTP $http_status): $(printf '%s' "$response_body" | redact_for_log)"
|
||||
fi
|
||||
|
||||
printf '%s\n' "$response_body"
|
||||
}
|
||||
|
||||
request_authorization_code_grant() {
|
||||
require_oauth_client
|
||||
|
||||
local code="${WORKS_DRIVE_AUTH_CODE:-}"
|
||||
local response
|
||||
local response_body
|
||||
local http_status
|
||||
|
||||
if [[ -z "$code" && -n "${WORKS_DRIVE_AUTH_CALLBACK_URL:-}" ]]; then
|
||||
code="$(extract_code_from_callback_url "$WORKS_DRIVE_AUTH_CALLBACK_URL")"
|
||||
fi
|
||||
|
||||
[[ -n "$code" ]] || backup_die "WORKS_DRIVE_AUTH_CODE or WORKS_DRIVE_AUTH_CALLBACK_URL is required for authorization-code grant."
|
||||
[[ -n "$redirect_uri" ]] || backup_die "WORKS_DRIVE_OAUTH_REDIRECT_URI is required for authorization-code grant."
|
||||
backup_require_command "$curl_bin"
|
||||
|
||||
response="$("$curl_bin" -sS -w $'\n%{http_code}' -X POST \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
--data-urlencode "grant_type=authorization_code" \
|
||||
--data-urlencode "code=$code" \
|
||||
--data-urlencode "client_id=$client_id" \
|
||||
--data-urlencode "client_secret=$client_secret" \
|
||||
--data-urlencode "redirect_uri=$redirect_uri" \
|
||||
"$token_url")"
|
||||
split_curl_response "$response" response_body http_status
|
||||
|
||||
if [[ "$http_status" -lt 200 || "$http_status" -ge 300 ]]; then
|
||||
backup_die "WORKS authorization code token request failed (HTTP $http_status): $(printf '%s' "$response_body" | redact_for_log)"
|
||||
fi
|
||||
|
||||
printf '%s\n' "$response_body"
|
||||
}
|
||||
|
||||
persist_token_response() {
|
||||
local response_body="$1"
|
||||
local refresh_token
|
||||
local expires_in
|
||||
|
||||
expires_in="$(jq -r '.expires_in // empty' <<<"$response_body")"
|
||||
refresh_token="$(jq -r '.refresh_token // empty' <<<"$response_body")"
|
||||
|
||||
if [[ -n "$refresh_token" ]]; then
|
||||
write_env_value WORKS_DRIVE_OAUTH_REFRESH_TOKEN "$refresh_token"
|
||||
backup_log "WORKS Drive refresh token updated: $env_file"
|
||||
else
|
||||
backup_log "WORKS token refresh succeeded without a rotated refresh token."
|
||||
fi
|
||||
|
||||
if [[ "$set_auth_mode" == "true" ]]; then
|
||||
write_env_value WORKS_DRIVE_AUTH_MODE refresh-token
|
||||
fi
|
||||
|
||||
if [[ -n "$expires_in" ]]; then
|
||||
backup_log "WORKS Drive access token issued. expires_in=$expires_in"
|
||||
else
|
||||
backup_log "WORKS Drive access token issued."
|
||||
fi
|
||||
}
|
||||
|
||||
case "$token_grant" in
|
||||
print-authorize-url)
|
||||
print_authorize_url
|
||||
;;
|
||||
refresh-token)
|
||||
persist_token_response "$(request_refresh_token_grant)"
|
||||
;;
|
||||
authorization-code)
|
||||
persist_token_response "$(request_authorization_code_grant)"
|
||||
;;
|
||||
*)
|
||||
backup_die "unknown WORKS_DRIVE_TOKEN_GRANT: $token_grant. Expected refresh-token, authorization-code, or print-authorize-url."
|
||||
;;
|
||||
esac
|
||||
@@ -17,6 +17,7 @@ if [[ -f "$repo_root/.env" ]]; then
|
||||
WORKS_DRIVE_ACCESS_TOKEN
|
||||
WORKS_DRIVE_ACCESS_TOKEN_FILE
|
||||
WORKS_DRIVE_ACCESS_TOKEN_CMD
|
||||
WORKS_DRIVE_AUTH_MODE
|
||||
WORKS_DRIVE_OAUTH_SCOPE
|
||||
WORKS_DRIVE_SPLIT_SIZE
|
||||
WORKS_DRIVE_MAX_SINGLE_FILE_BYTES
|
||||
@@ -43,7 +44,7 @@ if [[ -f "$repo_root/.env" ]]; then
|
||||
declare -A env_override_values=()
|
||||
env_override_set=()
|
||||
for env_key in "${env_override_keys[@]}"; do
|
||||
if [[ -v "$env_key" ]]; then
|
||||
if [[ -n "${!env_key:-}" ]]; then
|
||||
env_override_set+=("$env_key")
|
||||
env_override_values["$env_key"]="${!env_key}"
|
||||
fi
|
||||
@@ -69,6 +70,7 @@ WORKS_DRIVE_PARENT_FILE_ID="${WORKS_DRIVE_PARENT_FILE_ID:-${WORKS_DRIVE_SHAREDRI
|
||||
|
||||
dry_run="${WORKS_DRIVE_DRY_RUN:-false}"
|
||||
target="${WORKS_DRIVE_TARGET:-sharedrive}"
|
||||
auth_mode="${WORKS_DRIVE_AUTH_MODE:-auto}"
|
||||
api_base_url="${WORKS_ADMIN_API_BASE_URL:-https://www.worksapis.com}"
|
||||
curl_bin="${WORKS_DRIVE_CURL_BIN:-curl}"
|
||||
archive_dir="${WORKS_DRIVE_ARCHIVE_DIR:-/tmp/baron-sso-backup-upload}"
|
||||
@@ -81,6 +83,11 @@ upload_reports="${WORKS_DRIVE_UPLOAD_REPORTS:-true}"
|
||||
report_folder_name="${WORKS_DRIVE_REPORT_FOLDER_NAME:-reports}"
|
||||
report_dir="$backup_path/reports"
|
||||
|
||||
case "$auth_mode" in
|
||||
auto | service-account | refresh-token) ;;
|
||||
*) backup_die "unknown WORKS_DRIVE_AUTH_MODE: $auth_mode. Expected auto, service-account, or refresh-token." ;;
|
||||
esac
|
||||
|
||||
if [[ -f "$backup_path" ]]; then
|
||||
report_dir="$(dirname "$backup_path")"
|
||||
fi
|
||||
@@ -330,6 +337,13 @@ request_refresh_access_token() {
|
||||
jq -er '.access_token' <<<"$response_body"
|
||||
}
|
||||
|
||||
service_account_credentials_configured() {
|
||||
[[ -n "${WORKS_DRIVE_OAUTH_CLIENT_ID:-}" ]] \
|
||||
&& [[ -n "${WORKS_DRIVE_OAUTH_CLIENT_SECRET:-}" ]] \
|
||||
&& [[ -n "${WORKS_DRIVE_OAUTH_CLIENT_SERVICE_ACCOUNT:-}" ]] \
|
||||
&& { [[ -n "${WORKS_DRIVE_OAUTH_CLIENT_PRIVATE_KEY:-}" ]] || [[ -n "${WORKS_DRIVE_OAUTH_CLIENT_PRIVATE_KEY_FILE:-}" ]]; }
|
||||
}
|
||||
|
||||
resolve_access_token() {
|
||||
if [[ -n "${WORKS_DRIVE_ACCESS_TOKEN:-}" ]]; then
|
||||
printf '%s\n' "$WORKS_DRIVE_ACCESS_TOKEN"
|
||||
@@ -347,12 +361,27 @@ resolve_access_token() {
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -n "${WORKS_DRIVE_OAUTH_REFRESH_TOKEN:-}" ]]; then
|
||||
request_refresh_access_token
|
||||
return
|
||||
fi
|
||||
case "$auth_mode" in
|
||||
service-account)
|
||||
request_service_account_token
|
||||
;;
|
||||
refresh-token)
|
||||
request_refresh_access_token
|
||||
;;
|
||||
auto)
|
||||
if service_account_credentials_configured; then
|
||||
request_service_account_token
|
||||
return
|
||||
fi
|
||||
|
||||
request_service_account_token
|
||||
if [[ -n "${WORKS_DRIVE_OAUTH_REFRESH_TOKEN:-}" ]]; then
|
||||
request_refresh_access_token
|
||||
return
|
||||
fi
|
||||
|
||||
request_service_account_token
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
package_backup_path() {
|
||||
|
||||
Reference in New Issue
Block a user