이번 포스팅에서는 terraform에서의 key 암호화에 대해 알아보겠다.
terraform을 통해 AWS RDB를 만든다고 가정했을 때, terraform 코드에 계정과 패스워드가 평문으로 들어갈 수 있다.
rdb.tf
resource "aws_db_instance" "example" {
identifier_prefix = "terraform-up-and-running"
engine = "mysql"
allocated_storage = 10
instance_class = "db.t2.micro"
skip_final_snapshot = true
db_name = var.db_name
# How to set these parameters securely?
username = "???"
password = "???"
}
이런 민감정보들이 소스코드 관리 툴이나 버전관리 시스템에 노출되었을 때 끼치는 영향은 치명적일 것이다. 이러한 보안위협을 방지하기 위해서 terraform에서는 AWS KMS, GCP KMS 등과 연계하여 보안기능을 제공한다.
바로 실습을 통해 알아보자.
AWS Key Management Service(AWS KMS)를 통해 민감데이터를 암호화 하여 AWS의 각종 서비스들과 연계할 수 있다.
# 키 생성(기본값)
# aws kms create-key --description "my text encrypt descript demo"
CREATE_KEY_JSON=$(aws kms create-key --description "my text encrypt descript demo")
echo $CREATE_KEY_JSON | jq
# 키 ID확인
KEY_ID=$(echo $CREATE_KEY_JSON | jq -r ".KeyMetadata.KeyId")
echo $KEY_ID
# 키 alias 생성
export ALIAS_SUFFIX=kimchigood
aws kms create-alias --alias-name alias/$ALIAS_SUFFIX --target-key-id $KEY_ID
# 생성한 별칭 확인
aws kms list-aliases
kms 키를 생성하고, 생성된 KEY_ID값으로 Key alias를 생성해준다.
이제 terraform 코드에서 관리되는 평문의 민감데이터를 AWS KMS와 연동해보자. 실습순서는 민감데이터를 AWS KMS를 통해 암호화하고, terraform 코드를 통해 암호화된 데이터에 접근하여 리소스를 생성하는 순서로 한다.
db-creds.yaml
cat <<EOT > db-creds.yml
username: admin
password: password
EOT
AWS KMS 암호화
aws kms encrypt --key-id alias/$ALIAS_SUFFIX --cli-binary-format raw-in-base64-out --plaintext file://db-creds.yml --output text --query CiphertextBlob | tee db-creds.yml.encrypted
# 암호문 확인
cat db-creds.yml.encrypted
$ AQICAHg8IvteQXbfnvbAi0mI9EZbzfkFa7fyZdPjYrOmNfVFPwEONo1NMIe6nekkVfoJpOyIAAAAgTB/BgkqhkiG9w0BBwagcjBwAgEAMGsGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMwnhGRVbCvjdpRb+vAgEQgD7dCm1uBTHdzVnZ2d7vxA65OMMeyeqK7j7/PlF+yG5j3x9jvTP3bBGhpm3STAEzriYFXbvg7mXs93woRS1WHw==
terraform 코드 연동
rds.tf
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_prefix = "terraform-up-and-running"
engine = "mysql"
allocated_storage = 10
instance_class = "db.t2.micro"
skip_final_snapshot = true
db_name = var.db_name
# Pass the secrets to the resource
username = local.db_creds.username
password = local.db_creds.password
}
variables.tf
variable "db_name" {
description = "The name to use for the database"
type = string
default = "example"
}
outputs.tf
output "address" {
value = aws_db_instance.example.address
description = "Connect to the database at this endpoint"
}
output "port" {
value = aws_db_instance.example.port
description = "The port the database is listening on"
}
terraform 실행
terraform init & terraform plan
rds.tf 코드를 보면 db-creds.yml.encrypted의 값을 읽어와서 RDS를 생성하게 되는데, 현재 세팅되어있는 AWS KMS를 통해 암호화된 db-creds.yml.encrypted 를 복호화 하고, 그 변수를 가져와서 ID/PASSWORD를 적용하여 리소스를 생성하게 된다.
AWS KMS 키는 아래와 같은 방법으로 삭제하도록 하자.
terraform destroy -auto-approve
# 생성한 키 ID 변수 지정
KEY_ID=$(echo $CREATE_KEY_JSON | jq -r ".KeyMetadata.KeyId")
# 키 비활성화
aws kms disable-key --key-id $KEY_ID
# 키 삭제 예약 : 대기 기간(7일)
aws kms schedule-key-deletion --key-id $KEY_ID --pending-window-in-days 7