CloudNet@ 팀의 가시다님께서 Leading 하시는 Terraform T101 Study 내용 요약
해당 Terraform Study 는 Terraform Up and Running 책을 기반으로 진행 중입니다.
이번 포스팅에서는 테라폼을 사용하면서 다루게 되는 DB Password 등의 리소스 민감정보 관리에 대해서 알아보겠습니다.
1. Resource 민감정보
Database 등의 접속 관련 정보
RDS 리소스를 생성할 때 다음과 같이 코드를 작성할 수 있습니다.
resource "aws_db_instance" "example" {
identifier = "rds-example"
engine = "mysql"
allocated_storage = 10
instance_class = "db.t2.micro"
skip_final_snapshot = true
username = "AWS-RDS-Username"
password = "AWS-RDS-Password"
}
앞서 Provider 에 인증정보 입력을 하지 않았던 것과 마찬가지로 해당 코드가 유출된다면 심각한 보안사고로 이어질 수 있습니다.
때문에 DB 관련 민감정보를 암호화해서 저장하는 등의 관리가 필요합니다.
이러한 민감정보를 평문으로 작성하지 않고 관리할 수 있는 3가지 방법에 대해서 알아봅시다.
1.1. 환경변수 활용
첫 번째 방법은 직접 환경변수로 인증정보를 설정해주는 것입니다.
이 방법은 이전 포스팅에서 설명했던 Provider 의 환경변수 활용법과 동일합니다.
대신 아래와 같이 username , password 부분을 변수 처리해줍니다.
resource "aws_db_instance" "example" {
identifier = "rds-example"
engine = "mysql"
allocated_storage = 10
instance_class = "db.t2.micro"
skip_final_snapshot = true
db_name = "rdsexamplename"
username = var.db_username
password = var.db_password
}
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
}
이후 터미널에서 아래와 같은 커맨드를 입력해 변수를 전달해줍니다.
$ export TF_VAR_db_username=(DB_USERNAME)
$ export TF_VAR_db_password=(DB_PASSWORD)
1.2. AWS KMS 활용
두 번째 방법은 KMS 를 활용하여 DB 접속 정보를 암호화해서 저장하는 것입니다.
KMS 는 평문 파일을 암호화할 수 있습니다.
이를 이용하여 DB 접속 정보가 들어있는 파일을 암호화한 후 테라폼 코드로 전달해보도록 하겠습니다.
KMS Key 는 존재한다는 가정하에 다음과 같이 DB 접근 정보가 입력된 파일을 생성합니다.
# db-creds.yml
username: admin
password: password
이후 다음의 커맨드를 입력하여 파일을 암호화된 파일로 새로 생성합니다.
aws kms encrypt --key-id alias/{KMS-ALIAS} --cli-binary-format raw-in-base64-out --plaintext file://db-creds.yml --output text --query CiphertextBlob | tee db-creds.yml.encrypted
마지막으로 다음과 같이 테라폼에서 KMS Key 를 가져와 해당 파일을 복호화할 수 있도록 코드를 작성해줍니다.
provider "aws" {
region = "ap-northeast-2"
}
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" {
identifier = "rds-example"
engine = "mysql"
allocated_storage = 10
instance_class = "db.t2.micro"
skip_final_snapshot = true
db_name = "rdsexamplename"
username = local.db_creds.username
password = local.db_creds.password
}
1.3. 중앙 집중식 저장소 사용 (AWS Secrets Manager)
세 번째 방법은 중앙 집중식 비밀 저장소를 사용하는 것입니다.
중앙 집중식 저장소는 관리자가 민감정보를 안전하게 저장해놓으면 사용자는 저장소에 접근해서 민감정보를 조회하는 방식입니다.
AWS 에서는 AWS Secrets Manager 라는 저장소 서비스를 제공해주고 있습니다.
RDS 에서 사용할 민감 정보를 AWS Secrets Manager 에 생성해줍시다.
data "aws_kms_key" "my_key" {
key_id = "alias/kimalarm-key"
}
resource "aws_secretsmanager_secret" "my_secret" {
name = "rds-creds"
kms_key_id = data.aws_kms_key.my_key.id
recovery_window_in_days = 0
}
variable "secrets" {
type = map(string)
default = {
username = "testadmin"
password = "testpassword1!"
}
}
resource "aws_secretsmanager_secret_version" "rds_creds" {
secret_id = aws_secretsmanager_secret.kimalarm.id
secret_string = jsonencode(var.secrets)
}
Secret Key 가 생성된 것을 확인할 수 있습니다.
해당 키를 사용하는 테라폼 코드를 작성해봅니다.
data "aws_secretsmanager_secret_version" "creds" {
secret_id = "rds-creds"
}
locals {
db_creds = jsondecode(
data.aws_secretsmanager_secret_version.creds.secret_string
)
}
resource "aws_db_instance" "example" {
identifier = "rds-example"
engine = "mysql"
allocated_storage = 10
instance_class = "db.t2.micro"
skip_final_snapshot = true
db_name = "rdsexamplename"
username = local.db_creds.username
password = local.db_creds.password
}
RDS 가 Secret Manager 에 있는 정보를 가져온 것을 확인할 수 있습니다.
Secret Manager 의 정보는 콘솔에서 직접 생성할 수 있기 때문에 꼭 테라폼으로 생성할 필요는 없습니다.