Automation/Terraform

[Terraform 6장] Managing Secrets with Terraform

[앙금빵] 2025. 1. 19.

본 글은 Terraform Up& Running 책에 대하여 6장에 대한 내용 정리 글이다.


개요

소프트웨어를 개발하고 배포하는 과정에서, 우리는 종종 데이터베이스 비밀번호, API 키, TLS 인증서, SSH 키, GPG 키와 같은 중요한 비밀 정보를 다루게 된다. 이러한 정보가 외부에 유출되면, 악의적인 사용자가 회사 시스템에 무단으로 접근하거나 고객 정보를 불법적으로 열람하고 조작할 수 있어 막대한 피해를 초래할 수 있다.

 

이 단원은 비밀 관리(Secrets Management)라고 하며, 해당 장에서는 비밀 정보를 안전하게 보관할 수 있는 기본 원리부터 다양한 도구를 활용하는 방법, 그리고 Terraform과 연동하여 안전하게 인프라 구성을 자동화하는 과정을 다룬다.

 

6-1. Secret 관리

Secret은 종류마다 적절한 암호화 및 저장 전략이 달라야 하며, 안전하고 효율적인 관리 방식을 택하기 위해서는 각 유형 및 사용 사례에 맞춰 올바른 도구를 선택하고 운영해야 한다.

비밀 유형은 크게 개인 비밀, 고객 비밀, 인프라 비밀 세 가지로 분류되어진다.

  • 개인 비밀: 개인 계정 정보나 SSH 키처럼 개인에게 속한다.
  • 고객 비밀: 서비스 사용자인 고객의 인증 정보나 개인 식별 정보(PII), 건강 정보(PHI) 등이 포함된다.
  • 인프라 비밀: 데이터베이스 비밀번호, API 키, TLS 인증서처럼 시스템 운영에 필요한 자격 증명이다.

 

각 비밀 유형에 따라 저장 방식이 달라야 한다. 예를 들어, 인프라 비밀번호는 복호화가 가능해야 하므로 대칭키 암호화(AES 등)를 주로 사용하지만, 고객 비밀번호는 복호화가 불필요하므로 해시 함수(bcrypt 등)를 통해 원래 비밀번호를 복원 불가능하게 만든다.

 

비밀을 저장하는 대표적인 방식은 (1)파일 기반 비밀 저장소와 (2) 중앙 집중형 비밀 저장소다.

  • 파일 기반 비밀 저장소: 암호화된 파일을 버전 관리 시스템에 저장하는 형태다.
    • 이 파일을 암호화하기 위해서는 별도의 암호화 키가 필요하며, 이 키를 다시 안전하게 보관해야 하는 어려움이 있다.
    • 일반적으로 클라우드 제공사의 KMS(AWS KMS, GCP KMS, Azure Key Vault 등)를 이용하거나, PGP 키를 사용해 각 개발자의 공개 키로 비밀을 암호화하고 개인 키는 개발자별로 안전하게 관리한다.

 

  • 중앙 집중형 비밀 저장소: 웹 서비스 형태로 네트워크를 통해 접근하는 형태다.
    • 내부적으로 데이터베이스(MySQL, PostgreSQL, DynamoDB 등)에 암호화된 상태로 비밀을 저장한다. 이때 필요한 암호화 키는 서비스 자체 혹은 AWS KMS를 통해 관리한다.

 

Secret에 접근하기 위한 인터페이스 종류

  • API(예: REST API)를 통해 애플리케이션이 부팅 시 자동으로 비밀번호를 가져올 수 있으며, Terraform 같은 IaC(Infrastructure as Code) 도구에서도 활용된다.
  • CLI는 파일 기반 혹은 중앙 집중형 저장소를 명령줄에서 간편히 다룰 수 있게 해주며, 스크립팅에도 유용하다.
  • UI는 웹, 데스크톱, 모바일 등에서 직관적인 접근을 제공하여 팀 전체가 쉽게 비밀을 검색·관리할 수 있다.

 

6-2. Providers

Terraform로 AWS 등 클라우드 프로바이더에 연결하려면 액세스 키 같은 비밀이 필요하다. 가장 안 좋은 방법은 소스 코드에 비밀을 평문(plain text)으로 직접 넣는 것이며, 이는 보안 위험뿐 아니라 여러 사용자와 환경에서 사용하기가 비효율적이다.

 

6-2-1. Human user

(a) 환경 변수 사용

  • 일반적으로 Terraform는 코드를 직접 수정하지 않고, 환경 변수를 통해 비밀 정보를 주입받을수 있도록 구성을 권장한다.
$ export AWS_ACCESS_KEY_ID=(YOUR_ACCESS_KEY_ID)
$ export AWS_SECRET_ACCESS_KEY=(YOUR_SECRET_ACCESS_KEY)

(b) 개인용 비밀 관리 도구 사용

개인용 비밀 관리 도구(예: 1Password, LastPass)에 자격 증명을 저장해두고, 복사·붙여넣기 또는 CLI를 이용해 환경 변수로 설정하는 방식을 권장한다.

$ eval $(op signin my)
$ export AWS_ACCESS_KEY_ID=$(op get item 'aws-dev' --fields 'id')
$ export AWS_SECRET_ACCESS_KEY=$(op get item 'aws-dev' --fields 'secret')

(c) aws-vault 사용

  • AWS에 특화된 CLI 도구인 aws-vault는 자격 증명을 OS의 안전한 저장소(예: macOS Keychain)에 보관하고, terraform apply 같은 명령을 임시 세션 토큰과 함께 실행하도록 지원한다.
  • 영구 키 대신 임시 세션 자격 증명을 발급받아 사용하므로 비밀번호 유출 위험이 줄어든다.
$ aws-vault add dev
$ aws-vault exec dev -- terraform apply

 

6-2-2. Machine user

머신 사용자는 GitHub Actions나 CircleCI, Jenkins 같은 자동화된 서버를 지칭한다. 여기서는 사람이 일일이 서버에 접속해 명령어를 입력하지 않으며, 코드가 커밋되거나 빌드가 트리거될 때마다 서버가 알아서 Terraform를 실행하는 구조이다.

정리하면, 자동화된 서버는 사람처럼 직접 명령어를 입력하지 않기 때문에, 더 안전하고 자동화된 방식으로 환경 변수를 제공하거나 IAM Role 같은 매커니즘을 통해 필요한 권한을 부여하는 것이 중요하다.

  • CircleCi 등 외부 CI 플랫폼
  • Jenkins를 EC2 인스턴스에서 구동 (IAM Roles)
  • Github Actions (OIDC)

6-3. Resources and Data Sources

리소스/데이터 소스 정의 시 DB 자격 증명처럼 중요한 비밀 정보를 코드에 직접 넣지 말고 (1) 환경변수 (2) 암호화된 파일(KMS, PGP, sops 등) (3) 중앙 집중형 비밀 저장소(AWS Secrets Manager 등) 중을 활용하여 안전하게 전달해야 한다.

 

각 방법은 보안 요구 사항, 개발/운영 방식, 비용, 팀 규모에 따라 선택하면 되며, 공통적으로 “평문 비밀을 Terraform 코드와 버전 관리 시스템에서 분리”하고 “제대로 된 키 및 접근 정책(rotate, revoke, audit 등)”을 유지하는 것이 핵심이다.

 

6-3-1. 환경변수 (Environment Variables)

환경변수를 이용함으로써 얻을 수 있는 장점과 단점은 다음과 같다.

  • 장점: 코드에 평문 비밀이 없어지며, 다양한 비밀 관리 도구(예: 1Password, HashiCorp Vault 등)와 쉽게 연동 가능. 테스트 시 환경 변수만 설정하면 되므로 편리. 비용 없음.
  • 단점: Terraform 코드에만 의존하지 않으므로, 사용자별 환경 변수 설정을 별도로 관리해야 함. 일관된 비밀 관리 정책 강제 어려움.

 

변수 정의

  • sensitive = true를 통해 Terraform이 로그 등에 비밀값을 표시하지 않도록 한다.
variable "db_username" {
  description = "The username for the database"
  type        = string
  sensitive   = true
}
variable "db_password" {
  description = "The password for the database"
  type        = string
  sensitive   = true
}

 

환경 변수로 값 주입

  • Terraform는 TF_VAR_접두어가 붙은 환경 변수를 자동으로 해당 입력 변수에 매핑한다.
$ export TF_VAR_db_username=(DB_USERNAME)
$ export TF_VAR_db_password=(DB_PASSWORD)

 

6-3-2. 암호화된 파일(Encrypted Files)

암호화된 파일을 관리함으로써 얻게되는 장단점은 다음과 같다.

  • 장점: 코드에 평문 비밀이 없고, 암호화된 상태로 버전 관리를 할 수 있어 환경 간 차이를 줄이고 테스트/버전 관리를 수월하게 함.
  • 단점: 파일 암호화·복호화 절차가 번거롭고, KMS나 PGP 키를 안전하게 관리해야 함. 키가 유출되면 이전 버전 비밀도 모두 복호화 가능.

 

키 관리 (KMS 등)

  • AWS KMS, GCP KMS, Azure Key Vault 같은 클라우드 키 관리 서비스 사용 또는 PGP 키 사용.
#AWS KMS 예시
resource "aws_kms_key" "cmk" { ... }
resource "aws_kms_alias" "cmk" {
  name          = "alias/kms-cmk-example"
  target_key_id = aws_kms_key.cmk.id
}

 

파일 암호화

  • db-creds.yml 파일에 DB 사용자명/비밀번호를 저장한 뒤 aws kms encrypt를 통해 db-creds.yml.encrypted 생성
  • 평문 파일을 삭제하고 암호화된 파일(.encrypted)만 버전 관리에 체크인

 

Terraform에서 복호화

data "aws_kms_secrets" "creds" {
  secret {
    name    = "db"
    payload = file("${path.module}/db-creds.yml.encrypted")
  }
}
locals {
  db_creds = yamldecode(data.aws_kms_secrets.creds.plaintext["db"])
}
resource "aws_db_instance" "example" {
  ...
  username = local.db_creds.username
  password = local.db_creds.password
}

 

6-3-3. 중앙 집중형 비밀 저장소(Secret Stores)

Secret 저장소를 통해 얻을 수 있는 장단점은 다음과 같다.

  • 장점:
    • 비밀이 코드나 버전 관리에 평문으로 남지 않음.
    • 회전(Rotation)·폐기(Revocation)·감사(Audit) 로그 등이 지원되어, 보안성과 관리성 향상.
    • 여러 환경에서 일관된 보안 규칙 적용 가능.
  • 단점:
    • 비밀이 코드와 함께 버전 관리되지 않으므로, 환경 설정 누락이나 불일치 가능성.
    • 사용량·건수에 따라 비용 발생.
    • 자체 구축형(예: Vault)은 운영·업데이트·모니터링에 추가 비용과 노력이 필요.
# AWS Secret 예제
data "aws_secretsmanager_secret_version" "creds" {
  secret_id = "db-creds"
}
locals {
  db_creds = jsondecode(data.aws_secretsmanager_secret_version.creds.secret_string)
}
resource "aws_db_instance" "example" {
  ...
  username = local.db_creds.username
  password = local.db_creds.password
}


6-4 State File & Plan File

State 파일

예를 들어, DB 사용자명/비밀번호를 Terraform 리소스(예: aws_db_instance)에 인자로 넘기면, 어떤 방식(환경 변수, 암호화 파일, 중앙 집중 비밀 저장소)으로 비밀을 읽어오든 최종적으로는 terraform.tfstate에 평문으로 기록된다.

 

이 문제는 2014년부터 이슈화되었지만, 아직 Terraform 자체적으로 완벽하게 해결된 기능은 없다. 타사가 만든 스크러빙(sanitizing) 도구도 지속적인 Terraform 버전 변화로 인해 안정성을 보장하기 어렵다.

 

이에 (1) State 파일을 암호화 가능한 백엔드에 저장 (2) State 백엔드 접근 권한을 철저히 제한해야 한다.

 

Plan 파일

terraform plan -out=example.plan 명령으로 결과(diff)를 파일에 저장하면, State 파일과 마찬가지로 비밀이 평문으로 들어간다.

그렇기에, DB 사용자명·비밀번호를 담은 리소스를 Plan 파일에 기록하면, 그 Plan 파일이 곧 잠재적 유출 위험이 된다. 만약 Plan 파일을 보관해야 한다면, 전송 및 저장 시 모두 암호화를 해야 한다. 예를 들어 S3 버킷에 example.plan 파일을 저장할 경우, TLS와 서버·클라이언트 암호화를 적용하고, 민감 버킷 접근을 제한해야 한다.

 

 

댓글