Secret Rotation
AI 요청 프롬프트
https://docs.axelabs.ai/ops/runbook/secret-rotation 따라 [secret name] 회전 진행해줘.
진행:
1. 회전 대상 secret + provider 식별 (Azure / Meta / Naver / GitHub / Anthropic / 기타)
2. Azure 면 az cli 6 단계 분기, 그 외면 `axe secret rotate <ENV_NAME>` interactive 분기
3. 페이지의 각 step 명령 실행 + 검증, 매 step 결과 받고 다음. 특히 OLD secret revoke 직전 사용자 확인 (NEW secret 무중단 swap + production 검증 통과 후)
4. 함정 발생 시 페이지 본문 따라 우회 (App Owner 부재 / external portal 수동 / `unset NEW` shell history 정리 / merge-mode pull 누락)
5. 회전 완료 + production health 검증 + (선택) /ops/updates Ship Log 한 줄본인 AI session = Claude Code / Cursor / ChatGPT 데스크탑 / Claude.app / 기타.
페이지 본문 = 사람이 직접 read 도 가능, AI 도 참고. AI 가 본 페이지 fetch 후 위 진행 순서대로 사용자와 step-by-step interactive 풀어나감.
D-ops-17 + D-ops-19 (2026-05-21) 이후 표준: Azure 의 client_secret 은 az cli 6 단계 로 portal UI 0회. 다른 provider (Meta/Naver/GitHub/Anthropic) 는
axe secret rotate의 interactive 경로 + 외부 portal 수동.
Azure 회전 — az cli 6 단계 (권장)
APP_ID=137fc0ef-eb9f-4903-acbc-1a748add349c # frame_mcp (예시)
OLD_KEY_ID=$(az ad app credential list --id $APP_ID \
--query "[?starts_with(hint,'<old prefix>')].keyId | [0]" -o tsv)
# 1. Azure 새 secret 추가 — --append 가 OLD 유지 = overlap window
NEW=$(az ad app credential reset --id $APP_ID \
--display-name "auto-rotated 2026-MM-DD" --years 2 --append \
--query password -o tsv)
# 2. vault PUT
axe secret push AZURE_FRAME_MCP_CLIENT_SECRET --service frame --value "$NEW"
# 3. pull (merge-mode — config 보존)
axe secret pull frame
# 4. 무중단 swap
axe deploy frame axe --apply # frame / hive
axe blueprint upgrade axe --apply # blueprint
# 5. 검증
docker exec $(active container) env | grep AZURE_FRAME_MCP_CLIENT_SECRET
/usr/bin/curl -sI https://axe.axelabs.ai/frame/health # 200
# 6. OLD revoke (검증 후)
az ad app credential delete --id $APP_ID --key-id $OLD_KEY_ID
unset NEW # shell history 에서 제거전제조건 — App Owner 확인
az ad app credential reset 은 app 의 owner 만 가능. portal-등록 app 은 default 로 owner 없음:
az ad app owner list --id $APP_ID --query "[].userPrincipalName" -o tsv
# 비어 있으면 → portal 에서 owner 추가 후 재시도:
# open "https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/Owners/appId/$APP_ID"본 플랫폼의 모든 AXE app 은 [email protected] owner 박혀 있음 (2026-05-21 audit). 신규 az cli 등록 app 은 호출자가 owner 자동 박힘.
다른 provider 회전 — axe secret rotate interactive
Anthropic / GitHub / Meta / Naver / Slack 등 az 안 통하는 provider:
axe secret rotate <ENV_NAME> --service <svc>진행:
- 매니페스트의
rotation_external확인 → provider portal URL 출력 - 운영자가 portal 에서 새 값 발급 → 복사 → 프롬프트에 붙여넣기 (
getpass, 화면 안 보임) - vault PUT
axe secret pull SVC(merge-mode)axe ship SVC트리거 (working tree dirty 면 abort —axe deploy ... --apply로 수동 보완)- 운영자가 provider 에서 OLD 수동 revoke
상세 데이터 흐름: /architecture/secrets.
회전 주기 — 정기 점검
Microsoft Entra ID app 의 client_secret 회전 주기 = 24개월 (Frame MCP), 180일 (Blueprint, Vaultwarden).
만료 30일 전 자동 알림. 미루지 말 것 — 만료 = OAuth 전체 마비.
사전 알림
현재 상태: com.axe.secret-check launchd 자동 알림 + axe secret status --customer X CLI 는 향후 추가 예정 (TODO). 현재는 수동 확인:
# 운영자 콘솔 (admin.axelabs.ai) 에 secret 만료일 표시 — `axe console rebuild` 가 매시 갱신
# 또는 Vault 에 보관된 메타에서 직접 확인:
bw get item "Frame MCP — claude.ai connector secret" # 만료일 필드 확인출력 예:
axe customer:
blueprint: expires 2026-08-15 (89 days)
vaultwarden: expires 2026-09-01 (106 days)
frame_mcp: expires 2028-05-19 (730 days)90일 이내면 운영자 콘솔 dashboard 에 빨간 배너.
회전 절차 (180일 secret, ~30분)
예: customer axe 의 frame_mcp secret 회전 (24개월 만료).
1. 새 secret 발급 (customer IT 측)
customer IT 에게 메일:
제목: [AXE Labs] Frame MCP client_secret 갱신 요청 (만료 30일 전)
안녕하세요,
귀사 Microsoft Entra ID 의 'Frame MCP' app 의 client_secret 이
30일 후 만료됩니다 (2028-05-19).
다음 절차로 새 secret 발급 + 안전 채널로 전달 부탁드립니다:
1. Azure portal → Microsoft Entra ID → App registrations → 'Frame MCP'
2. Certificates & secrets → + New client secret
3. Description: frame-mcp-axe-2028-05
4. Expires: 24 months
5. Add → VALUE 즉시 복사
6. Bitwarden Send (view-once, `-a 1 -d 1`) 또는 안전 채널로 운영자에게 전달 — 절차: [/architecture/secrets § 사람에게 전달](/architecture/secrets#사람에게-전달--bitwarden-send)
운영자 측 swap 완료 후 기존 secret 은 안전하게 폐기됩니다.
감사합니다.
액스코퍼레이션 주식회사 (운영 주체, [email protected])2. 새 secret 받으면
# Keychain push (replace 기존)
security add-generic-password -a axe -s "axe.axe.frame.client_secret" -w '<new_value>' -U
# Verify
security find-generic-password -s "axe.axe.frame.client_secret" -w
# → <new_value> 출력되면 OK3. 컨테이너 재기동 (env reload)
cd /Users/axe/frame
set -a && source .env.local && set +a
docker compose up -d --force-recreate frame-mcp-blue frame-mcp-green
sleep 5
# Verify env 적용
docker exec frame-mcp-blue env | grep AZURE_FRAME_MCP_CLIENT_SECRET | head -c 30
# → 새 값의 prefix 보이면 OK⚠️ 다운타임 ~3초 —
--force-recreate가 blue+green 동시 재기동. 향후 blue→green→blue 순차 재기동으로 0초 만들 예정 (D-ops-16 후보).
4. claude.ai connector 측 영향
frame_mcp secret 의 경우 직원 측 영향 있음:
- claude.ai 의 Custom Connector 에 입력한 secret 도 갱신 필요
- 운영자 → 직원들에게 새 secret 전달 (안전 채널)
- 직원 각자 claude.ai 의 connector 편집 → Advanced 의 OAuth Client Secret 교체 → Save
⚠️ 이게 secret 회전의 가장 큰 운영 부담. 직원이 많을수록 painful. 향후 OAuth proxy 패턴 (D-ops-15) 으로 secret 분배 제거 검토.
5. 기존 secret 폐기 (24시간 후)
새 secret 활성 확인 + 직원 전원 swap 완료 후:
# customer IT 에게:
"기존 client_secret (<처음 4글자만 hint, 예: XX.X~ 처럼 식별 가능한 prefix>)
Azure portal 에서 삭제 부탁드립니다.
새 secret 으로 swap 완료 + 24시간 검증 완료했습니다."⚠️ secret VALUE 평문을 docs/메일/채팅 어디에도 적지 마세요. 식별 hint 는 Azure portal 의 secret 표에서 보이는 hint prefix (보통 처음 3-4자 + ”…”) 만 사용. 운영자 본인이 회전 시점에는 Keychain
find-generic-password로 prefix 확인.
customer IT 측에서 Azure portal → Certificates & secrets → 기존 secret 옆 휴지통 클릭.
6. 검증
# customers.yaml 메타 업데이트 (선택)
# sso.apps.frame_mcp.client_secret_env 의 만료일 주석 갱신
# Audit (TODO: `axe secret status` 추가 후)
# 현재는 Vault item 의 만료 메타 갱신 + 운영자 콘솔 dashboard 확인함정
| 함정 | 결과 | 회피 |
|---|---|---|
| 만료일 잊고 24시간 후 마비 | OAuth 전체 다운 | 매일 자동 알림 + 30일 전 작업 |
| 새 secret swap 전 기존 삭제 | OAuth 즉시 다운 | 24시간 grace period |
| Keychain replace 안 하고 새로 add | duplicate, 어떤 게 active 인지 모름 | -U 플래그로 update |
| 컨테이너 restart 만 (—force-recreate X) | env file 재로드 안 됨 | up -d --force-recreate |
| 직원에게 secret 일괄 push 잊음 | 직원들 connector 실패 | swap 전에 communication |
응급: secret 노출 의심
평문이 어딘가 노출된 의심이 있을 경우 (메일 전송 사고, 노트북 분실 등):
- customer IT 에게 즉시 새 secret 발급 요청 (정상 절차 X, 비상)
- 받자마자 Keychain push + 컨테이너 재기동
- 기존 secret 즉시 삭제 (24시간 grace X)
- audit_log 검사 — 의심 시간대에 비정상 access 있는지
- 직원 전원에게 알림 + claude.ai connector 즉시 update 요청
상세: Runbook · Secret 노출 대응 (예정).