Secrets Manager 비밀 관리
"DB 비밀번호를 .env 파일이 아닌 안전한 금고에 보관하자"
학습 목표
- Secrets Manager에 DB 자격 증명을 저장할 수 있다
- IAM 역할에 Secrets Manager 접근 권한을 부여할 수 있다
- EC2에서 AWS CLI로 비밀 값을 조회할 수 있다
- 비밀번호 자동 교체(로테이션)의 개념과 필요성을 이해할 수 있다
IAM Role: ShopEasy-EC2-Role
DB 자격 증명 암호화 저장
ap-northeast-2
왜 Secrets Manager가 필요한가?
현재 ShopEasy API 서버는 DB 접속 정보를 .env 파일에 평문으로 저장하고 있습니다.
# .env 파일 (현재 상태 - 위험!)
DB_TYPE=mysql
DB_HOST=shopeasy-db.xxxx.ap-northeast-2.rds.amazonaws.com
DB_PORT=3306
DB_USER=admin
DB_PASSWORD=ShopEasy2024!
DB_NAME=ecommerce
이 방식의 문제점
- Git 커밋 유출: 실수로
.env파일을 Git에 커밋하면 비밀번호가 공개 저장소에 노출됩니다 - 서버 침해: EC2 서버가 해킹되면
.env파일을 읽어 DB에 직접 접근할 수 있습니다 - 비밀번호 변경 어려움: 비밀번호를 바꾸려면 모든 서버의
.env파일을 수동으로 수정해야 합니다 - 감사 불가: 누가 언제 비밀번호를 조회했는지 추적할 수 없습니다
.env 파일에 비밀번호를 저장하는 것은 포스트잇에 비밀번호를 적어 모니터에 붙여두는 것과 같습니다.
누구나 지나가면서 볼 수 있고, 복사할 수 있으며, 누가 봤는지 알 수 없습니다.
반면 Secrets Manager는 잠금장치가 달린 금고와 같습니다. 열쇠(IAM 권한)가 있는 사람만 열 수 있고, 금고를 열 때마다 CCTV(CloudTrail)에 기록이 남습니다. 게다가 금고 안의 비밀번호를 자동으로 주기적으로 교체해주는 기능까지 있습니다.
Secrets Manager 동작 원리
기존 방식: 앱 시작 → .env 파일에서 비밀번호 읽기 → DB 접속
Secrets Manager 방식: 앱 시작 → Secrets Manager API 호출 → 비밀번호 받기 → DB 접속
코드나 파일에 비밀번호가 존재하지 않으므로, 서버가 침해되어도 비밀번호가 바로 노출되지 않습니다. API 호출에는 IAM 권한이 필요하기 때문입니다.
핵심 특징
| 특징 | 설명 |
|---|---|
| 암호화 저장 | 비밀 값은 KMS 키로 암호화되어 저장됩니다. 평문으로 디스크에 저장되지 않습니다 |
| 접근 제어 | IAM 정책으로 누가 어떤 비밀에 접근할 수 있는지 세밀하게 제어합니다 |
| 감사 추적 | CloudTrail을 통해 모든 비밀 조회/변경 기록이 남습니다 |
| 자동 교체 | Lambda 함수를 연결하면 비밀번호를 자동으로 주기적으로 변경합니다 |
| 버전 관리 | 비밀 값이 변경될 때 이전 버전을 유지하여, 교체 중에도 서비스가 중단되지 않습니다 |
비용 구조
| 항목 | 비용 | 설명 |
|---|---|---|
| 비밀 저장 | $0.40 / 비밀 / 월 | 저장된 비밀 1개당 월 $0.40 |
| API 호출 | $0.05 / 10,000건 | GetSecretValue 등 API 호출 건수 기준 |
비밀 1개를 저장하고 하루 100번 조회한다면, 월 비용은 약 $0.42입니다 ($0.40 + 3,000건 × $0.05/10,000). DB 자격 증명 유출로 인한 피해 비용에 비하면 매우 저렴한 보험입니다.
실습: Secrets Manager 구성
- Chapter 04에서 만든 IAM Role (ShopEasy-EC2-Role)이 EC2에 연결되어 있어야 합니다
- Chapter 03에서 만든 RDS MySQL 인스턴스가 실행 중이어야 합니다
- EC2에 SSH 접속이 가능해야 합니다
-
Secrets Manager에 DB 비밀번호 저장
RDS MySQL 접속에 필요한 자격 증명을 Secrets Manager에 저장합니다.
- 비밀 이름:
ShopEasy/DB - 비밀 유형: 다른 유형의 보안 암호 (키/값 쌍)
- 저장할 키/값:
host: RDS 엔드포인트port:3306username:adminpassword:ShopEasy2024!dbname:ecommerce
- 암호화 키:
aws/secretsmanager(기본 KMS 키)
비밀 이름 규칙ShopEasy/DB처럼 슬래시(/)로 계층 구조를 만들면 관리가 편합니다. 나중에ShopEasy/API-Key,ShopEasy/Redis등으로 확장할 수 있습니다.AWS 콘솔 → Secrets Manager → 새 보안 암호 저장 → 보안 암호 유형: "다른 유형의 보안 암호" 선택 → 키/값 쌍에 host, port, username, password, dbname을 각각 입력 → 다음 → 보안 암호 이름:
ShopEasy/DB입력 → 다음 → 교체 구성은 건너뛰기 → 저장 - 비밀 이름:
-
IAM 역할에 Secrets Manager 권한 추가
EC2가 Secrets Manager에서 비밀 값을 조회할 수 있도록
ShopEasy-EC2-Role에 권한을 추가합니다.- 정책 이름:
ShopEasy-SecretsManager-Access - 허용 액션:
secretsmanager:GetSecretValue - 리소스:
ShopEasy/DB비밀의 ARN (특정 비밀만 허용)
최소 권한 원칙secretsmanager:*로 모든 권한을 주지 마세요. GetSecretValue 액션만, ShopEasy/DB 비밀에만 허용하는 것이 보안 모범 사례입니다. 다른 비밀이나 비밀 삭제/수정 권한은 EC2에 필요하지 않습니다.IAM 콘솔 → 역할 →
ShopEasy-EC2-Role→ 권한 추가 → 인라인 정책 생성 → JSON 편집기에서 정책 작성 → 정책 이름:ShopEasy-SecretsManager-Access→ 정책 생성. Resource에는 Secrets Manager 콘솔에서 확인한 비밀 ARN을 넣되, 끝에*를 붙입니다 (Secrets Manager가 자동으로 랜덤 접미사를 추가하기 때문). - 정책 이름:
-
EC2에서 비밀 값 조회 테스트
EC2에 SSH로 접속한 후, AWS CLI를 사용하여 Secrets Manager에서 비밀 값을 정상적으로 조회할 수 있는지 테스트합니다.
bash# EC2 접속 ssh -i your-key.pem ec2-user@{EC2_PUBLIC_IP} # Secrets Manager에서 비밀 값 조회 aws secretsmanager get-secret-value \ --secret-id ShopEasy/DB \ --region ap-northeast-2응답의
SecretString필드에 JSON 형식의 DB 자격 증명이 포함되어 있으면 성공입니다.보기 좋게 출력하기--query SecretString --output text | python3 -m json.tool을 추가하면 비밀 값만 깔끔한 JSON 형식으로 볼 수 있습니다.AccessDeniedException이 발생하면 Step 2의 IAM 정책이 올바르게 설정되었는지 확인하세요. 정책의 Resource ARN이 실제 비밀 ARN과 일치하는지, 그리고 EC2에 IAM Role이 연결되어 있는지 확인합니다.
-
비밀번호 교체(로테이션) 개념 이해
Secrets Manager의 가장 강력한 기능 중 하나인 자동 비밀번호 교체(Auto Rotation)의 개념을 이해합니다.
자동 교체(Auto Rotation)란?비밀번호를 주기적으로 자동 변경하는 기능입니다. Secrets Manager가 Lambda 함수를 호출하여 다음 작업을 자동으로 수행합니다:
- 새 비밀번호 생성: 강력한 랜덤 비밀번호를 만듭니다
- DB 비밀번호 변경: RDS에 접속하여 비밀번호를 새 값으로 변경합니다
- 비밀 값 업데이트: Secrets Manager에 저장된 비밀번호를 새 값으로 교체합니다
- 테스트: 새 비밀번호로 DB 접속이 되는지 확인합니다
왜 비밀번호 교체가 중요한가?
- 유출 시 피해 최소화: 비밀번호가 유출되더라도, 자동 교체로 인해 유효 기간이 제한됩니다 (예: 30일마다 교체)
- 컴플라이언스 준수: PCI-DSS, HIPAA 등 보안 규정은 정기적인 비밀번호 변경을 요구합니다
- 수동 작업 제거: 관리자가 비밀번호를 직접 변경하고 모든 서버에 반영하는 번거로움이 없습니다
자동 교체 흐름Secrets Manager교체 일정 트리거
(예: 30일마다)↓ Lambda 호출Lambda (교체 함수)1. 새 비밀번호 생성
2. RDS 비밀번호 변경
3. Secrets Manager 업데이트
4. 접속 테스트↓ 비밀번호 변경RDS MySQL새 비밀번호 적용이번 실습에서는 교체를 구현하지 않습니다자동 교체에는 Lambda 함수 설정, VPC 네트워크 구성 등 추가 작업이 필요합니다. 이번 실습에서는 개념을 이해하는 것이 목표이며, 실제 구현은 하지 않습니다. 프로덕션 환경에서는 반드시 자동 교체를 활성화하는 것을 권장합니다.
확인 사항
아래 항목을 모두 완료했는지 체크하세요:
- Secrets Manager에
ShopEasy/DB비밀이 생성되었다 - 비밀에 host, port, username, password, dbname 키/값 쌍이 포함되어 있다
ShopEasy-EC2-Role에ShopEasy-SecretsManager-Access정책이 추가되었다- 정책에
secretsmanager:GetSecretValue액션만 허용되어 있다 - 정책의 Resource가
ShopEasy/DB비밀 ARN으로 제한되어 있다 - EC2에서
aws secretsmanager get-secret-value명령이 정상 동작한다 - 응답의 SecretString에 올바른 DB 자격 증명이 포함되어 있다
- 자동 교체(로테이션) 개념을 이해했다