Files
2nd/10_Wiki/Topics/Coding/DevOps_Secrets_Rotation_Automation.md
T
Antigravity Agent f8b21af4be Wiki cleanup: error-doc removal, dedup merge, link normalization
10_Wiki/Topics 대규모 정리:
- 오류 캡처/미완성 stub 문서 227개 제거
- 교차폴더 중복 43클러스터 병합 (63파일 → redirect)
- 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건
- 카테고리 MOC 6개 신규 생성
- Graph 섹션 미해결 related-keyword 링크 10,058건 제거

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 23:52:15 +09:00

5.0 KiB

id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
id title category status source_trust_level verification_status created_at updated_at tags tech_stack applied_in aliases
devops-secrets-rotation-automation Secrets Rotation — 자동 회전 / 무중단 Coding draft B conceptual 2026-05-09 2026-05-09
devops
secrets
rotation
security
vibe-coding
language applicable_to
TS / AWS / Vault
DevOps
secret rotation
AWS Secrets Manager
HashiCorp Vault
KMS
key rotation

Secrets Rotation

Secret 영원히 같으면 leak 시 영원히 노출. 자동 회전 + 무중단 (dual-secret window). AWS Secrets Manager / HashiCorp Vault / Kubernetes External Secrets.

📖 핵심 개념

  • Static secret: 수동 회전 — 잊혀짐.
  • Dynamic secret: 매 요청마다 발급 (Vault dynamic creds).
  • Dual-secret window: 새 secret 활성, 기존도 N분 유효.
  • Lease: 짧은 시간만 유효, 갱신 필요.

💻 코드 패턴

AWS Secrets Manager rotation

// Lambda rotation function (4-step)
export const handler = async (event: RotationEvent) => {
  const { Step, SecretId, ClientRequestToken } = event;
  switch (Step) {
    case 'createSecret':  return createSecret(SecretId, ClientRequestToken);
    case 'setSecret':     return setSecret(SecretId, ClientRequestToken);  // DB 에 새 password 적용
    case 'testSecret':    return testSecret(SecretId, ClientRequestToken); // 새 password 로 연결 확인
    case 'finishSecret':  return finishSecret(SecretId, ClientRequestToken); // AWSCURRENT 로 promote
  }
};
# Terraform
resource "aws_secretsmanager_secret_rotation" "db" {
  secret_id = aws_secretsmanager_secret.db.id
  rotation_lambda_arn = aws_lambda_function.rotate.arn
  rotation_rules { automatically_after_days = 30 }
}

App 측 — refresh 주기

class SecretCache {
  private cached: { value: string; fetchedAt: number } | null = null;
  private ttlMs = 60_000;

  async get(): Promise<string> {
    if (!this.cached || Date.now() - this.cached.fetchedAt > this.ttlMs) {
      const v = await fetchFromSecretsManager(this.secretId);
      this.cached = { value: v, fetchedAt: Date.now() };
    }
    return this.cached.value;
  }
}

Dual-credential window

-- DB 에 user app_v1, app_v2 둘 다 존재
-- v1 active 동안 v2 만들고 → v2 로 새 deploy → v1 비활성
CREATE USER app_v2 WITH PASSWORD 'new';
GRANT ALL ON DATABASE app TO app_v2;
-- 새 pod 들 v2 사용 시작
-- 1시간 후
DROP USER app_v1;

Vault dynamic creds

// app 이 매번 짧은 lease 의 creds 받음
const r = await vault.read('database/creds/readonly');
const { username, password, lease_id, lease_duration } = r.data;

setTimeout(() => vault.renew(lease_id), lease_duration * 0.7 * 1000);

Kubernetes External Secrets

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata: { name: db-secret }
spec:
  refreshInterval: 1h
  secretStoreRef: { name: aws-secrets, kind: ClusterSecretStore }
  target: { name: db, creationPolicy: Owner }
  data:
  - secretKey: url
    remoteRef: { key: app/db, property: url }

ESO 가 Secret 자동 sync — 회전되면 1h 안에 pod 에 반영. Pod restart 또는 reloader 로 새 값 로드.

App restart on secret change

# stakater/reloader 추가
metadata:
  annotations:
    reloader.stakater.com/auto: "true"

KMS key rotation

resource "aws_kms_key" "main" {
  description             = "App data"
  deletion_window_in_days = 30
  enable_key_rotation     = true # 매년 자동 회전
}

API key 회전 패턴

// 사용자 API key — 새거 발급 시 24h 둘 다 활성
async function rotateApiKey(userId: string): Promise<string> {
  const old = await db.apiKeys.find(userId);
  const newKey = generate();
  await db.apiKeys.insert({ userId, key: newKey, status: 'active' });
  await db.apiKeys.update(old.id, { status: 'sunset', expiresAt: now() + 24 * H });
  return newKey;
}

🤔 의사결정 기준

종류 솔루션
Cloud (AWS) Secrets Manager + 자동 rotation lambda
Cloud (GCP) Secret Manager + Cloud Functions
K8s External Secrets Operator
Self-hosted HashiCorp Vault
Static creds 만 Doppler / 1Password Connect
Dynamic / short-lived Vault dynamic secrets
Key encryption KMS / Cloud KMS / Vault Transit

안티패턴

  • Rotation 수동: 잊혀짐. 자동.
  • 새 secret 즉시 강제 — old 비활성: 아직 transition 중인 pod 다운.
  • Secret env var 만 — restart 필요: ESO + Reloader.
  • Repo 에 commit (.env.prod): leak. .gitignore + secret scan.
  • Logging 시 secret 출력: 마스킹.
  • 단일 user 모든 service 공유: 한 leak = 전체.
  • 회전 불가능한 client (mobile app): refresh token 쓰고 짧은 access.
  • Terraform state 안 secret 평문: state encrypt + 권한 제한.

🤖 LLM 활용 힌트

  • Secrets Manager / Vault + 자동 rotation lambda.
  • App = 짧은 cache + 회전 가능 구조.
  • ESO + Reloader = K8s 표준.

🔗 관련 문서