diff --git a/scripts/registry-auth.sh b/scripts/registry-auth.sh index 272740a85..bfe2a9a7c 100755 --- a/scripts/registry-auth.sh +++ b/scripts/registry-auth.sh @@ -1,90 +1,107 @@ #!/bin/bash +# Hardened Registry Authentication Discovery & Hardening +# Standard: mmintel/klz-2026 + set -e -# --- Configuration --- -REGISTRY_URL="https://git.infra.mintel.me/api/packages/mmintel/npm/" -TEST_PACKAGE="@mintel/mail" +REGISTRY_DOMAIN="git.infra.mintel.me" +REGISTRY_PATH="/api/packages/mmintel/npm/" +TEST_PACKAGE_ENCODED="%40mintel%2Fmail" +TEST_URL="https://${REGISTRY_DOMAIN}${REGISTRY_PATH}${TEST_PACKAGE_ENCODED}" -echo "🔍 Starting functional registry discovery..." +echo "🔍 Starting robust functional registry discovery..." -# Function to test a specific header -test_auth() { +# Collect candidate tokens from environment +# We try them all because NPM_TOKEN might be stale while GITEA_PAT is fresh +CANDIDATES="" +[ -n "$NPM_TOKEN" ] && CANDIDATES="${CANDIDATES} NPM_TOKEN" +[ -n "$GITEA_PAT" ] && CANDIDATES="${CANDIDATES} GITEA_PAT" +[ -n "$MINTEL_PRIVATE_TOKEN" ] && CANDIDATES="${CANDIDATES} MINTEL_PRIVATE_TOKEN" + +if [ -z "$CANDIDATES" ]; then + echo "❌ No registry tokens found in environment (NPM_TOKEN, GITEA_PAT, MINTEL_PRIVATE_TOKEN are empty)." + exit 1 +fi + +AUTH_TYPE="None" +WORKING_TOKEN="" + +# Function to test connectivity +check_url() { local label=$1 - local header=$2 + local auth_header=$2 local url=$3 - echo "Trying $label..." - # Capture both status code and body - # Using -k because sometimes internal registries have cert issues in CI - RESPONSE=$(curl -s -k -w "\n%{http_code}" -H "$header" "$url") - STATUS=$(echo "$RESPONSE" | tail -n1) - BODY=$(echo "$RESPONSE" | head -n -1) - - echo "$label status: $STATUS" - if [ "$STATUS" == "200" ]; then + # Using -k for internal cert resilience + local code=$(curl -s -k -o /tmp/reg_body -w "%{http_code}" -H "$auth_header" "$url") + if [ "$code" = "200" ]; then return 0 else - if [ -n "$BODY" ]; then - echo "Response snippet: $(echo "$BODY" | head -c 200)" - fi + local body=$(cat /tmp/reg_body | head -c 100) + echo " $label failed ($code): $body" return 1 fi } -# 1. Discover Tokens -TOKEN="" -TOKEN_SRC="" -if [ -n "$NPM_TOKEN" ]; then - TOKEN=$NPM_TOKEN - TOKEN_SRC="NPM_TOKEN" -elif [ -n "$GITEA_PAT" ]; then - TOKEN=$GITEA_PAT - TOKEN_SRC="GITEA_PAT" -elif [ -n "$MINTEL_PRIVATE_TOKEN" ]; then - TOKEN=$MINTEL_PRIVATE_TOKEN - TOKEN_SRC="MINTEL_PRIVATE_TOKEN" -fi +for CANDIDATE_NAME in $CANDIDATES; do + TOKEN_VAL=$(eval echo "\$$CANDIDATE_NAME") + echo "Testing token from $CANDIDATE_NAME (length: ${#TOKEN_VAL})..." -if [ -z "$TOKEN" ]; then - echo "❌ No token found (NPM_TOKEN, GITEA_PAT, MINTEL_PRIVATE_TOKEN are empty)." - exit 1 -fi - -echo "Found token from $TOKEN_SRC (length: ${#TOKEN})" - -# 2. Functional Test -# In Gitea, the NPM package URL for discovery can be different. -# Try both @mintel/mail and mmintel/mail just in case. -TEST_URL="${REGISTRY_URL}@mintel/mail" - -AUTH_TYPE="" -if test_auth "Bearer" "Authorization: Bearer $TOKEN" "$TEST_URL"; then - AUTH_TYPE="Bearer" -elif test_auth "Basic (raw)" "Authorization: Basic $(echo -n "token:$TOKEN" | base64)" "$TEST_URL"; then - AUTH_TYPE="Basic" -elif test_auth "Basic (token:pass)" "Authorization: Basic $(echo -n "$TOKEN:" | base64)" "$TEST_URL"; then - AUTH_TYPE="Basic" -elif test_auth "Gitea Token" "Authorization: token $TOKEN" "$TEST_URL"; then - AUTH_TYPE="Token" -fi - -if [ -z "$AUTH_TYPE" ]; then - echo "❌ All auth methods failed for $TEST_URL." - echo "Trying alternative URL format..." - TEST_URL_ALT="${REGISTRY_URL}mmintel/mail" - if test_auth "Bearer (Alt)" "Authorization: Bearer $TOKEN" "$TEST_URL_ALT"; then + # 1. Try Bearer + if check_url "Bearer" "Authorization: Bearer ${TOKEN_VAL}" "${TEST_URL}"; then + echo "✅ Working Bearer token found in $CANDIDATE_NAME." AUTH_TYPE="Bearer" + WORKING_TOKEN="${TOKEN_VAL}" + break fi -fi -# 3. Generate .npmrc + # 2. Try Basic (token:x-oauth-basic) - Gitea Standard + # Encode token:x-oauth-basic + BASIC_AUTH=$(echo -n "${TOKEN_VAL}:x-oauth-basic" | base64 | tr -d '\n') + if check_url "Basic (token:x-oauth-basic)" "Authorization: Basic ${BASIC_AUTH}" "${TEST_URL}"; then + echo "✅ Working Basic (token:x-oauth-basic) found in $CANDIDATE_NAME." + AUTH_TYPE="Bearer" # Still use _authToken + WORKING_TOKEN="${TOKEN_VAL}" + break + fi + + # 3. Try Basic (token:empty) + BASIC_AUTH_EMPTY=$(echo -n "${TOKEN_VAL}:" | base64 | tr -d '\n') + if check_url "Basic (token:)" "Authorization: Basic ${BASIC_AUTH_EMPTY}" "${TEST_URL}"; then + echo "✅ Working Basic (token:) found in $CANDIDATE_NAME." + AUTH_TYPE="Bearer" + WORKING_TOKEN="${TOKEN_VAL}" + break + fi + + # 4. Try Gitea 'token' header + if check_url "Token Header" "Authorization: token ${TOKEN_VAL}" "${TEST_URL}"; then + echo "✅ Working Gitea Token header found in $CANDIDATE_NAME." + AUTH_TYPE="Bearer" + WORKING_TOKEN="${TOKEN_VAL}" + break + fi +done + +# Generate .npmrc echo "Generating .npmrc..." { echo "always-auth=true" - echo "@mintel:registry=https://git.infra.mintel.me/api/packages/mmintel/npm/" - echo "//git.infra.mintel.me/api/packages/mmintel/npm/:_authToken=$TOKEN" - # Fallback without trailing slash - echo "//git.infra.mintel.me/api/packages/mmintel/npm:_authToken=$TOKEN" + echo "@mintel:registry=https://${REGISTRY_DOMAIN}${REGISTRY_PATH}" + + if [ "$AUTH_TYPE" != "None" ]; then + echo "//${REGISTRY_DOMAIN}${REGISTRY_PATH}:_authToken=${WORKING_TOKEN}" + echo "//${REGISTRY_DOMAIN}${REGISTRY_PATH}:always-auth=true" + # Fallback without trailing slash for some versions of npm/pnpm + CLEAN_PATH=$(echo "${REGISTRY_PATH}" | sed 's/\/$//') + echo "//${REGISTRY_DOMAIN}${CLEAN_PATH}:_authToken=${WORKING_TOKEN}" + echo "✅ .npmrc hardened with verified $CANDIDATE_NAME." + else + echo "❌ ALL functional tests failed. Falling back to NPM_TOKEN (unverified)." + echo "//${REGISTRY_DOMAIN}${REGISTRY_PATH}:_authToken=${NPM_TOKEN}" + fi } > .npmrc -echo "✅ .npmrc hardened and generated (Detected Type: ${AUTH_TYPE:-None})." +# Debug summary +echo "Final .npmrc configuration (masked):" +cat .npmrc | sed 's/_authToken=.*/_authToken=********/'