Runbook: Rotacja klucza IAM pinbox24-bms1-s3
Cel: Zaktualizować s3Bucket_api_accessKeyId w v42-prod, aby getSignedUrl mogło generować presigned URLs dla bucketu pinbox24.
Kontekst: IAM user pinbox24-bms1-s3 ma dwa klucze: WKRQ**** (nowy) i LGQ2**** (stary). Kasujemy LGQ2****, tworzymy nowy, aktualizujemy backend-environment.env i SOPS.
Czas: ~10 minut. Nie ma downtime (PM2 reload zamiast restart).
Wykonaj lokalnie (Windows PowerShell)
# 0. Ustaw SOPS key
$env:SOPS_AGE_KEY_FILE = "C:\Users\konar\.age\p24-infra-keys.txt"
# 1. Rotacja IAM — uruchom skrypt Python
# Skrypt: C:\Users\konar\AppData\Local\Temp\claude\...\iam_rotate.py
# Skrypt kasuje LGQ2, tworzy nowy klucz, zapisuje do CREDS_OUTFILE
$CREDS = "C:\Users\konar\AppData\Local\Temp\p24creds-rotation.tmp"
$env:CREDS_OUTFILE = $CREDS
$decrypted = sops --decrypt --input-type dotenv --output-type dotenv C:\code_2026\p24-infra\secrets\administration.env.sops
$env:WA_AK = ($decrypted | Select-String "^WASABI_ADMIN_ACCESS_KEY=").Line.Split("=",2)[1].Trim()
$env:WA_SK = ($decrypted | Select-String "^WASABI_ADMIN_SECRET_KEY=").Line.Split("=",2)[1].Trim()
python "C:\Users\konar\AppData\Local\Temp\claude\C--code-2026-p24-infra\50c947c8-06cb-4a88-b7c7-95ed654152ae\scratchpad\iam_rotate.py"
$env:WA_AK = ""; $env:WA_SK = ""
# Powinno wypisać: "IAM_OK" i "Keys after: [...]"
# 2. Załaduj nowe credentials z temp pliku
$credsContent = Get-Content $CREDS
$env:NEW_ACC = ($credsContent | Select-String "^NEW_ACCESS=").Line.Split("=",2)[1]
$env:NEW_SEC = ($credsContent | Select-String "^NEW_SECRET=").Line.Split("=",2)[1]
Remove-Item $CREDS -Force # usuń temp plik natychmiast
Write-Host "New key len=$($env:NEW_ACC.Length) secret len=$($env:NEW_SEC.Length)"
# 3. Aktualizuj SOPS
$SOPS_FILE = "C:\code_2026\p24-infra\secrets\pinbox24-w4.env.sops"
$plain = sops --decrypt --input-type dotenv --output-type dotenv $SOPS_FILE
$updated = $plain | ForEach-Object {
if ($_ -match "^V42_s3Bucket_api_accessKeyId=") { "V42_s3Bucket_api_accessKeyId=$($env:NEW_ACC)" }
elseif ($_ -match "^V42_s3Bucket_api_secretAccessKey=") { "V42_s3Bucket_api_secretAccessKey=$($env:NEW_SEC)" }
else { $_ }
}
$content = $updated -join "`n"
[System.IO.File]::WriteAllText($SOPS_FILE, $content, [System.Text.UTF8Encoding]::new($false))
sops --encrypt --in-place $SOPS_FILE
sops --decrypt --input-type dotenv --output-type dotenv $SOPS_FILE | Out-Null
if ($LASTEXITCODE -ne 0) { throw "SOPS canary FAILED — do NOT commit" }
Write-Host "SOPS updated OK"
# 4. Aktualizuj bms-1 backend-environment.env
$updateScript = "C:\Users\konar\AppData\Local\Temp\claude\C--code-2026-p24-infra\50c947c8-06cb-4a88-b7c7-95ed654152ae\scratchpad\update_bms1_env.sh"
scp -o BatchMode=yes "$updateScript" "root@94.23.26.113:/tmp/update_bms1_env.sh"
ssh -o BatchMode=yes root@94.23.26.113 "NEW_ACC='$($env:NEW_ACC)' NEW_SEC='$($env:NEW_SEC)' bash /tmp/update_bms1_env.sh"
# 5. Wyczyść env vars
$env:NEW_ACC = ""; $env:NEW_SEC = ""
# 6. Commit SOPS
cd C:\code_2026\p24-infra
git add secrets/pinbox24-w4.env.sops
git commit -m "secret: rotate pinbox24-bms1-s3 IAM key (V42_s3Bucket_api_accessKeyId)"Weryfikacja
# Test getSignedUrl endpoint (zastąp TOKEN i FILE_ID prawdziwymi wartościami)
# $TOKEN = jwt z zalogowanego sesji w4.pinbox24.com
# Invoke-RestMethod -Uri "https://w4.pinbox24.com/api/offices/files/$FILE_ID/getSignedUrl" -Headers @{Authorization = "Bearer $TOKEN"}
# → Powinno zwrócić { url: "https://s3.eu-central-1.wasabisys.com/..." }# Na bms-1: sprawdź że nowy klucz ma dostęp do bucketu pinbox24
# (uruchom po update env)
ssh root@94.23.26.113 "bash /tmp/test_s3.sh"
# → OK: status 200Rollback
Jeśli nowy klucz nie działa:
# bms-1: przywróć z backupu
ls /home/p24-server-scripts/v4/v42/backend-environment.env.bak.s3rotation-*
cp /home/p24-server-scripts/v4/v42/backend-environment.env.bak.s3rotation-YYYYMMDDHHMMSS \
/home/p24-server-scripts/v4/v42/backend-environment.env
docker exec v42-prod pm2 reload all --update-envUwaga: rollback przywróci stary (AJ00) klucz, który też nie działa dla bucketu pinbox24. Konieczne będzie ręczne wpisanie poprawnego klucza.