mirror of
https://github.com/dredx/prole.git
synced 2026-09-23 10:13:58 +00:00
fix(gitea): REST API bootstrap path bypasses broken admin CLI; fix DB namespace resolver
deploy.sh: resolve_knoe_db_namespace() now checks DATABASE_NAMESPACE from
config (k3s.cfg: knoe-db) before probing namespaces. Previously it fell back
to 'default' because only 'knoe' was probed, baking a wrong DB hostname into
app.ini. The running server was unaffected (uses GITEA__database__HOST env var)
but the gitea admin CLI, which reads app.ini directly, could not connect.
init_knoe_users.sh: add gitea_helm_admin_token() which reads the Helm
bootstrap admin password from the gitea-gitea k8s secret and exchanges it for
a REST API token — entirely avoiding the broken CLI. Add gitea_api_set_password()
which uses PATCH /api/v1/admin/users/{user} to set the password via the running
web server (which has the correct DB connection) instead of kubectl exec.
promote_gitea_admin() now prefers the REST-API-only path:
1. existing token (env / k8s secret)
2. Helm admin k8s secret → REST token; set KNOE_ADMIN_PRINCIPAL password via API
3. 1Password → CLI set-password → basic-auth token (fallback)
4. kubectl exec generate-access-token (last resort)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
abb38fc1e9
commit
dbe249ce9f
@ -897,6 +897,57 @@ gitea_api_token() {
|
||||
printf '%s' "$resp" | grep -o '"sha1":"[^"]*"' | cut -d'"' -f4
|
||||
}
|
||||
|
||||
# gitea_helm_admin_token [token_name]
|
||||
# Reads the Helm bootstrap admin password from the k8s secret created by the
|
||||
# Gitea Helm chart ({release}-gitea, key admin-password) and exchanges it for
|
||||
# a REST API token. This works even when the gitea admin CLI is broken (e.g.
|
||||
# wrong DB hostname in app.ini) because the request goes through the running
|
||||
# web server which has the correct GITEA__database__HOST env var.
|
||||
# Prints the token sha1 to stdout; returns 1 on failure.
|
||||
gitea_helm_admin_token() {
|
||||
local token_name="${1:-knoe-installer-helm}"
|
||||
local secret="${GITEA_HELM_RELEASE:-gitea}-gitea"
|
||||
local admin_user="${GITEA_HELM_ADMIN_USER:-gitea_admin}"
|
||||
|
||||
local admin_pw
|
||||
admin_pw=$(kubectl -n "$GITEA_NAMESPACE" get secret "$secret" \
|
||||
-o jsonpath='{.data.admin-password}' 2>/dev/null | b64_decode || true)
|
||||
if [[ -z "$admin_pw" ]]; then
|
||||
warn " Gitea: Helm admin secret '${secret}' not found or empty in namespace ${GITEA_NAMESPACE}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local tok
|
||||
tok=$(gitea_api_token "$admin_user" "$admin_pw" "$token_name")
|
||||
if [[ -z "$tok" ]]; then
|
||||
warn " Gitea: could not obtain API token for Helm admin '${admin_user}'"
|
||||
return 1
|
||||
fi
|
||||
log " Gitea: obtained bootstrap token from Helm admin '${admin_user}'"
|
||||
printf '%s' "$tok"
|
||||
}
|
||||
|
||||
# gitea_api_set_password <admin_token> <username> <new_password>
|
||||
# Changes a user's password via the Gitea admin REST API.
|
||||
# Uses the running web server (not the CLI), so it works even when app.ini
|
||||
# has a wrong database hostname (the server overrides via GITEA__ env vars).
|
||||
gitea_api_set_password() {
|
||||
local token="$1" username="$2" pw="$3"
|
||||
local http_code
|
||||
http_code=$(curl -s -o /dev/null -w '%{http_code}' \
|
||||
-X PATCH \
|
||||
-H "Authorization: token ${token}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"login_name\":\"${username}\",\"source_id\":0,\"password\":\"${pw}\"}" \
|
||||
"https://${GITEA_HOST}/api/v1/admin/users/${username}" 2>/dev/null) || true
|
||||
if [[ "$http_code" =~ ^2 ]]; then
|
||||
return 0
|
||||
else
|
||||
warn " Gitea: admin API set-password returned HTTP ${http_code} for '${username}'"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
promote_gitea_admin() {
|
||||
local token="$GITEA_ADMIN_TOKEN"
|
||||
|
||||
@ -906,27 +957,47 @@ promote_gitea_admin() {
|
||||
-o jsonpath='{.data.token}' 2>/dev/null | b64_decode || true)
|
||||
fi
|
||||
|
||||
# 2. Obtain token via 1Password-backed password for KNOE_ADMIN_PRINCIPAL.
|
||||
# gitea_ensure_password idempotently creates the 1Password item if needed,
|
||||
# then sets the password in Gitea and exchanges it for a short-lived token.
|
||||
# The plaintext password is held only in a local variable and cleared below.
|
||||
# 2. Bootstrap via the Helm admin account (k8s secret → REST API token).
|
||||
# This path works even when the gitea admin CLI is broken (app.ini has wrong
|
||||
# DB hostname) because REST calls go through the running server which has the
|
||||
# correct GITEA__database__HOST env var. Once we have a bootstrap token, use
|
||||
# it to also set KNOE_ADMIN_PRINCIPAL's password via API (from 1Password).
|
||||
local _helm_token=""
|
||||
if [[ -z "$token" ]]; then
|
||||
local _pw=""
|
||||
if _pw=$(gitea_ensure_password "${KNOE_ADMIN_PRINCIPAL}"); then
|
||||
log "Gitea: setting password for '${KNOE_ADMIN_PRINCIPAL}' from 1Password ..."
|
||||
if gitea_set_password "${KNOE_ADMIN_PRINCIPAL}" "$_pw"; then
|
||||
log "Gitea: password set; requesting API token ..."
|
||||
token=$(gitea_api_token "${KNOE_ADMIN_PRINCIPAL}" "$_pw" "knoe-installer")
|
||||
[[ -n "$token" ]] && log "Gitea: API token obtained for '${KNOE_ADMIN_PRINCIPAL}'"
|
||||
else
|
||||
warn "Gitea: failed to set password for '${KNOE_ADMIN_PRINCIPAL}'"
|
||||
if _helm_token=$(gitea_helm_admin_token "knoe-installer-helm"); then
|
||||
token="$_helm_token"
|
||||
# Opportunistically set KNOE_ADMIN_PRINCIPAL's 1Password-backed password
|
||||
# via REST so chrisfu can log in as fallback if SPNEGO is unavailable.
|
||||
if command -v op >/dev/null 2>&1; then
|
||||
local _pw=""
|
||||
if _pw=$(gitea_ensure_password "${KNOE_ADMIN_PRINCIPAL}"); then
|
||||
log "Gitea: setting password for '${KNOE_ADMIN_PRINCIPAL}' via admin REST API ..."
|
||||
gitea_api_set_password "$_helm_token" "${KNOE_ADMIN_PRINCIPAL}" "$_pw" \
|
||||
&& log "Gitea: password set for '${KNOE_ADMIN_PRINCIPAL}'" \
|
||||
|| true
|
||||
_pw=""
|
||||
fi
|
||||
fi
|
||||
_pw="" # clear plaintext from memory immediately
|
||||
fi
|
||||
fi
|
||||
|
||||
# 3. Fall back to Helm bootstrap admin via kubectl exec generate-access-token.
|
||||
# Useful when KNOE_ADMIN_PRINCIPAL has not yet logged in and op is unavailable.
|
||||
# 3. Try 1Password → set password via CLI → exchange for token.
|
||||
# Kept as fallback for when the Helm admin secret is absent (e.g. non-Helm deploy).
|
||||
if [[ -z "$token" ]]; then
|
||||
local _pw=""
|
||||
if _pw=$(gitea_ensure_password "${KNOE_ADMIN_PRINCIPAL}"); then
|
||||
log "Gitea: setting password for '${KNOE_ADMIN_PRINCIPAL}' via kubectl exec ..."
|
||||
if gitea_set_password "${KNOE_ADMIN_PRINCIPAL}" "$_pw"; then
|
||||
token=$(gitea_api_token "${KNOE_ADMIN_PRINCIPAL}" "$_pw" "knoe-installer")
|
||||
[[ -n "$token" ]] && log "Gitea: API token obtained for '${KNOE_ADMIN_PRINCIPAL}'"
|
||||
else
|
||||
warn "Gitea: CLI password change failed (DB host mismatch in app.ini?)"
|
||||
fi
|
||||
_pw=""
|
||||
fi
|
||||
fi
|
||||
|
||||
# 4. Last resort: kubectl exec generate-access-token (CLI path, may fail if DB broken).
|
||||
if [[ -z "$token" ]]; then
|
||||
local _gitea_pod
|
||||
_gitea_pod=$(kubectl -n "$GITEA_NAMESPACE" get pods \
|
||||
@ -934,12 +1005,12 @@ promote_gitea_admin() {
|
||||
--field-selector=status.phase=Running \
|
||||
-o jsonpath='{.items[0].metadata.name}' 2>/dev/null || true)
|
||||
if [[ -n "$_gitea_pod" ]]; then
|
||||
log "Gitea: attempting token generation via kubectl exec (Helm bootstrap admin) ..."
|
||||
log "Gitea: attempting token generation via kubectl exec (last resort) ..."
|
||||
local _u
|
||||
for _u in "gitea_admin" "${KNOE_ADMIN_PRINCIPAL}"; do
|
||||
token=$(kubectl -n "$GITEA_NAMESPACE" exec "$_gitea_pod" -c gitea -- \
|
||||
su git -s /bin/bash -c \
|
||||
"gitea admin user generate-access-token --username ${_u} --token-name knoe-installer --scopes 'write:admin,read:user' --raw 2>/dev/null" \
|
||||
"gitea admin user generate-access-token --username ${_u} --token-name knoe-installer --scopes write:admin,read:user --raw 2>/dev/null" \
|
||||
2>/dev/null | tail -1 || true)
|
||||
[[ -n "$token" ]] && { log "Gitea: token generated for user '${_u}'"; break; }
|
||||
done
|
||||
@ -948,7 +1019,7 @@ promote_gitea_admin() {
|
||||
|
||||
if [[ -z "$token" ]]; then
|
||||
warn "No Gitea admin token available — skipping admin promotion"
|
||||
warn " Ensure 'op signin' is active on this host, then re-run."
|
||||
warn " Ensure 'op signin' is active and the Helm admin secret exists, then re-run."
|
||||
warn " Or set GITEA_ADMIN_TOKEN and re-run."
|
||||
return 0
|
||||
fi
|
||||
|
||||
@ -623,16 +623,27 @@ resolve_knoe_db_namespace() {
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Prefer DATABASE_NAMESPACE from config (k3s.cfg sets this to knoe-db)
|
||||
if [[ -n "${DATABASE_NAMESPACE:-}" ]]; then
|
||||
KNOE_DB_NAMESPACE="$DATABASE_NAMESPACE"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ -n "${NAMESPACE:-}" ]]; then
|
||||
KNOE_DB_NAMESPACE="$NAMESPACE"
|
||||
return 0
|
||||
fi
|
||||
|
||||
if kubectl get namespace knoe >/dev/null 2>&1; then
|
||||
KNOE_DB_NAMESPACE="knoe"
|
||||
else
|
||||
KNOE_DB_NAMESPACE="default"
|
||||
fi
|
||||
# Probe known namespace patterns before falling back to 'default'
|
||||
local _ns
|
||||
for _ns in knoe-db knoe; do
|
||||
if kubectl get namespace "$_ns" >/dev/null 2>&1; then
|
||||
KNOE_DB_NAMESPACE="$_ns"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
KNOE_DB_NAMESPACE="default"
|
||||
}
|
||||
|
||||
setup_knoe_db_for_gitea() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user