Ssoon
[6주차] 06 Terraform으로 Secret 관리 - Resources & Data Sources 본문
[6주차] 06 Terraform으로 Secret 관리 - Resources & Data Sources
구구달스 2022. 11. 27. 01:19CloudNet@ 팀의 가시다님이 진행하는 Terraform 101 Study 06주차 정리입니다.
✅ 환경 변수 - Environment variables
💠 전달하려는 secret 에 대한 변수를 선언합니다.
✔ sensitiev = true 👉 terrform 을 실행할 때 값을 기록하지 않습니다.
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
}
💠 해당 secret 가 필요한 Terraform 리소스에 변수를 전달합니다.
username = var.db_username
password = var.db_password
resource "aws_db_instance" "ssoon_ec2" {
identifier_prefix = "Ssoon"
engine = "mysql"
allocated_storage = 10
instance_class = "db.t2.micro"
skip_final_snapshot = true
db_name = var.db_name
#! secrets 를 리소스에 전달
username = var.db_username
password = var.db_password
tags = {
Name = "Ssoon-EC2"
}
}
💠 환경 변수 TF_VAR_foo를 설정하여 각 변수 foo에 대한 값을 전달합니다.
$ export TF_VAR_db_username=(DB_USERNAME)
$ export TF_VAR_db_password=(DB_PASSWORD)
🚩 Console 확인
📌 환경 변수를 통해 secrets 을 전달하면 코드에 일반 텍스트로 secrets 을 저장하는 것을 방지할 수 있지만 secrets 을 안전하게 저장하는 방법과 같은 중요한 질문에 대답하지는 않습니다.
환경 변수를 사용 장점
- 코드 및 버전 제어 시스템에서 일반 텍스트 secrets 을 유지합니다.
- 거의 모든 다른 secrets 관리 솔루션을 사용할 수 있으므로 secrets 을 저장하는 것이 쉽습니다
- 모든 언어에서 환경 변수 읽기가 간단하므로 secrets 검색이 쉽습니다.
- 환경 변수를 모의 값으로 쉽게 설정할 수 있으므로 자동화된 테스트와의 통합이 쉽습니다.
- 다른 비밀 관리 솔루션과 달리 환경 변수를 사용하면 비용이 들지 않습니다
환경 변수를 사용 단점
- 모든 것이 Terraform 코드 자체에 정의되어 있는 것은 아닙니다. 이것은 코드를 이해하고 유지하기 어렵게 만듭니다. 코드를 사용하는 모든 사용자는 이러한 환경 변수를 수동으로 설정하거나 wrapper scrip 를 실행하기 위해 추가 단계를 수행해야 함을 알아야 합니다
- secrets 관리 관행을 표준화하는 것은 더 어렵습니다. secrets 의 모든 관리는 Terraform 외부에서 발생하므로 코드는 보안 속성을 적용하지 않으며 누군가가 여전히 안전하지 않은 방식으로 비밀을 관리하고 있을 수 있습니다(예: 비밀을 일반 텍스트로 저장).
- secrets 는 코드와 함께 버전 지정, 패키징 및 테스트되지 않기 때문에 한 환경(예:스테이징)에 새 secrets 를 추가했지만 다른 환경(예: 프로덕션)에 추가하는 것을 잊는 것과 같은 구성 오류가 발생할 가능성이 큽니다.
✅ 암호화된 파일 - Encrypted files
파일의 일부 비밀과 같은 일부 데이터를 암호화하려면 암호화 키가 필요합니다. 암호화 키는 그 자체로 비밀이므로 안전하게 저장할 수 있는 방법이 필요합니다. 일반적인 솔루션은 클라우드 공급자의 KMS(예:AWS KMS, Google KMS, Azure Key Vault)를 사용하거나 팀에서 한 명 이상의 개
발자의 PGP 키를 사용하는 것입니다.
- AWS에서 관리하는 암호화 키인 KMS 고객 관리형 키(CMK)를 생성해야 합니다
- CMK를 생성하려면 먼저 IAM 정책인 키 정책을 정의해야 합니다.
- 해당 CMK를 사용할 수 있는 사람을 정의합니다.
- 현재사용자에게 CMK에 대한 관리자 권한을 부여하는 키 정책을 생성합니다.
💠 현재 사용자의 정보(사용자 이름, ARN 등)를 가져옵니다.
#! 현재 사용자의 세부 정보 조회
data "aws_caller_identity" "self" {}
💠 aws_iam_policy_document 을 사용하여 현재 사용자에게 CMK에 대한 관리 권한을 부여하는 정책을 생성합니다.
#! 현재 IAM 사용자를 CMK의 관리자로 만드는 정책
data "aws_iam_policy_document" "cmk_admin_policy" {
statement {
effect = "Allow"
resources = ["*"]
actions = ["kms:*"]
principals {
type = "AWS"
identifiers = [data.aws_caller_identity.self.arn]
}
}
}
💠 aws_kms_key 리소스를 사용하여 CMK를 생성합니다.
#! KMS Customer Managed Key (CMK) 생성
resource "aws_kms_key" "cmk" {
policy = data.aws_iam_policy_document.cmk_admin_policy.json
#! 테스트를 위해 짧은 삭제 기간을 설정
deletion_window_in_days = 7
}
💠 기본적으로 KMS CMK는 긴 숫자 식별자(예: b7670b0eed67-28e4-9b15-0d61e1485be3)로만 식별되므로 aws_kms_alias 리소스를 사용하여 CMK에 대해 alias 을 생성합니다.
#! CMK에 대한 alias 생성
resource "aws_kms_alias" "cmk" {
name = "alias/${kms-cmk-ssoon}"
target_key_id = aws_kms_key.cmk.id
}
❓ 위에 설정으로 terraform apply을 해보았지만 아래와 같이 error가 발생하여 IAM CONSOLE에서 "cmk_admin_policy" 을 수동으로 추가 하였습니다.
📢 CLI 확인
🚩 Console 확인
AWS만이 해당 암호화 키에 액세스할 수 있지만 AWS API 및 CLI를 사용하여 사용할 수 있습니다
💠 데이터베이스 자격 증명과 같은 몇 가지 비밀이 포함된 "db-creds.yml"이라는 파일을 생성합니다.
#! 암호화에 대한 일반 텍스트 입력의 예로 사용
username: admin
password: password
💠 AWS CLI을 통해 "aws kms encrypt" 명령을 사용하고 결과 암호 텍스트를 새 파일에 쓸 수 있는 " encrypt.sh" BASH Script 를 생성합니다.
#!/bin/bash
set -e
if [[ "$#" -ne 4 ]]; then
echo "Usage: encrypt.sh <CMK_ID> <AWS_REGION> <INPUT_FILE> <OUTPUT_FILE>"
exit
fi
CMK_ID="$1"
AWS_REGION="$2"
INPUT_FILE="$3"
OUTPUT_FILE="$4"
echo "Encrypting contents of $INPUT_FILE using CMK $CMK_ID..."
ciphertext=$(aws kms encrypt \
--key-id "$CMK_ID" \
--region "$AWS_REGION" \
--plaintext "fileb://$INPUT_FILE" \
--output text \
--query CiphertextBlob)
echo "Writing result to $OUTPUT_FILE..."
echo "$ciphertext" > "$OUTPUT_FILE"
echo "Done!"
💠 "encrypt.sh" 를 사용하여 이전에 생성한 KMS CMK 로 "db-creds.yml" 파일을 암호화하고 결과 암호문을 "dbcreds.yml.encrypted" 라는 새 파일에 저장합니다.
./encrypt.sh \
alias/kms-cmk-ssoon \
ap-northeast-2 \
db-creds.yml \
db-creds.yml.encrypted
📢 CLI 확인
db-creds.yml(일반 텍스트 파일)을 삭제하고 dbcreds.yml.encrypted(암호화된 파일)를 버전 제어에 안전하게 체크인할 수 있습니다
Terraform 코드에서 해당 파일을 어떻게 사용할 수 있을까요?
💠 "aws_kms_secrets" date source을 사용하여 이 파일의 암호를 해독합니다.
file helper 기능을 사용하여 디스크에서 dbcreds.yml.encrypted를 읽고 KMS에서 해당 키에 액세스할 수 있는 권한이 있다고 가정하고 내용을 해독하고 원본 dbcreds.yml 파일의 내용을 다시 제공합니다.
data "aws_kms_secrets" "creds" {
secret {
name = "db"
payload = file("../kms-cmk/db-creds.yml.encrypted")
}
}
💠 "aws_kms_secrets" date source 에서 데이터베이스 암호를 추출하고 YAML을 구문 분석한 다음 결과를 db_creds라는 로컬 변수에 저장합니다.
#! YAML 구문 분석
locals {
db_creds = yamldecode(data.aws_kms_secrets.creds.plaintext["db"])
}
💠 db_creds 에서 사용자 이름과 암호를 읽고 해당 자격 증명을 aws_db_instance 리소스에 전달합니다.
resource "aws_db_instance" "ssoon_db" {
identifier_prefix = "ssoon"
engine = "mysql"
allocated_storage = 10
instance_class = "db.t2.micro"
skip_final_snapshot = true
db_name = "ssoon"
# Pass the secrets to the resource
username = local.db_creds.username
password = local.db_creds.password
}
🚩 Console 확인
환경 변수를 사용 장점
- 코드 및 버전 제어 시스템에서 일반 텍스트 secrets 을 유지합니다.
- secrets 은 버전 제어에서 암호화된 형식으로 저장되므로 나머지 코드와 함께 버전이 지정되고 패키징되고 테스트됩니다. 하나의 환경(예: 스테이징)에 새암호를 추가했지만 다른 환경(예: 프로덕션)에 추가하는 것을 잊는 것과 같은 구성 오류를 줄이는 데 도움이 됩니다.
- 사용 중인 암호화 형식이 기본적으로 Terraform 또는 타사 플러그인에서 지원된다고 가정하면secrets 검색이 쉽습니다.
- AWS KMS, GCP KMS, PGP 등 다양한 암호화 옵션과 함께 작동합니다.
- 모든 것은 코드에 정의되어 있습니다.
환경 변수를 사용 단점
- secrets 을 저장하는 것은 더 어렵습니다. 많은 명령을 실행해야 합니다(예: aws kms 암호화)
- 테스트 환경에서 암호화 키와 암호화된 테스트 데이터를 사용할 수 있도록 추가 작업을 수행해야 하므로 자동화된 테스트와 통합하는 것이 더 어렵습니다.
- secrets 은 암호화되지만 여전히 버전 제어에 저장되어 있기 때문에 secrets 을 교체하고 취소하는 것은 어렵습니다.
- secrets 에 액세스한 사람을 감사하는 기능은 최소한입니다. 클라우드 키 관리 시스템(예: AWS KMS)을 사용하는 경우 누가 암호화 키를 사용했는지에 대한 감사 로그를 유지할 가능성이 높지만 키가 실제로 무엇에 사용되었는지 알 수 없습니다(예: 어떤 비밀에 액세스했는지).
- 대부분의 관리형 키 서비스는 약간의 비용이 듭니다.
- secrets 관리 관행을 표준화하는 것은 더 어렵습니다.
✅ 비밀 저장소 - Secret stores
'Terraform 101 Study' 카테고리의 다른 글
[7주차] 프로덕션 수준의 테라폼 코드 (0) | 2022.12.06 |
---|---|
[6주차] 06 Terraform으로 Secret 관리 - Terraform과 함께 Secret 관리 도구 사용 (0) | 2022.11.22 |
[6주차] 06 Terraform으로 Secret 관리 - Basic/Tools (0) | 2022.11.22 |
[5주차] 05 테라폼의 팁과 요령 (2) 조건문 - count (0) | 2022.11.19 |
[5주차] 05 테라폼의 팁과 요령 (1) 반복문 - String Directive (0) | 2022.11.17 |