brunch

You can make anything
by writing

C.S.Lewis

by Master Seo Nov 22. 2022

19탄-22. 테라폼-AWS-민감 정보 안전하게 관리

다음은 주말 CloudNet 테라폼 스터디 내용 참고하여  정리한 부분입니다.

https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863


리소스와 데이터 소스  관리


보완 방법 :

Environment variables 환경 변수로 관리

Encrypted files  암복호화로 관리

Secret stores로 관리


기본 서울리전에서 작업하자.

KMS가 리전 서비스 이다.

KMS를 이용하는 예가 있다.

aws configure

ap-northeast-2


디폴트 네트워크가 있어야한다.


mkdir test

cd test



<1> 리소스와 데이터 소스 -Environment variables 환경 변수로 관리

<2> 리소스와 데이터 소스 -Encrypted files  암복호화로 관리

<3> 리소스와 데이터 소스 -Secret stores로 관리

<4> 상태 파일과 planfile  관리



<1> 리소스와 데이터 소스 -Environment variables 환경 변수로 관리


1

리소스와 데이터 소스에 민감 정보 노출 - 예) 데이터베이스 암호 등

[Resources and data sources]Environment variables  환경 변수


2

환경 변수 Environment variables

아래 처럼 DB 계정 정보를 변수로 사용 설정


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

}


3

위 정보를 리소스에 전달


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 = var.db_username

  password = var.db_password

}


4

환경 변수로 전달 : TF_VAR_<변수이름>


export TF_VAR_db_username=(DB_USERNAME)

export TF_VAR_db_password=(DB_PASSWORD)


5

장점 : 모든 언어에서 환경 변수를 설정 및 쉽게 쓸 수 있고, 추가 비용이 들지 않음

단점: 팀원 모두 환경 변수 수동 사용 관리가 필요, (테라폼 외부) 비밀 번호 관리 표준화가 어려움, 각 환경에서 버저닝/패키징/테스트 시 암호 환경 변수 지정 시 설정 오류 발생 가능






<2> 리소스와 데이터 소스 -Encrypted files  암복호화로 관리


# 사전 작업

# aws cli v2 install

curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"

unzip awscliv2.zip

sudo ./aws/install

aws --version

aws-cli/2.0.30




1

암호를 파일에 저장 후 버전 관리 → 암호화 키를 클라우드 공급자 KMS를 통해 안전하게 저장 혹은 PGP 키 사용

Resources and data sources]Encrypted files


2

cli로  kms 키 만들고 사용해보자.


3

# 키 생성(기본값) - 키 생성하고 변수로 등록하자.


# 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


[root@ip-172-31-61-209 ~]# echo $CREATE_KEY_JSON | jq

{

  "KeyMetadata": {

    "Origin": "AWS_KMS",

    "KeyId": "b44d1",

    "Description": "my text encrypt descript demo",

    "KeyManager": "CUSTOMER",

    "EncryptionAlgorithms": [

      "SYMMETRIC_DEFAULT"

    ],

    "Enabled": true,

    "CustomerMasterKeySpec": "SYMMETRIC_DEFAULT",


콘솔에서 확인

해당 리전으로 이동 > KMS로 이동 >고객 관리형키가 만들어져 있다.



4

# 키 ID를 뽑아낸다.

KEY_ID=$(echo $CREATE_KEY_JSON | jq -r ".KeyMetadata.KeyId")

echo $KEY_ID


5

# 키 alias 생성

export ALIAS_SUFFIX=<각자 닉네임>

export ALIAS_SUFFIX=masterseo

aws kms create-alias --alias-name alias/$ALIAS_SUFFIX --target-key-id $KEY_ID

aws kms list-aliases

# 별칭 확인

"AliasName": "alias/masterseo",



# 콘솔에서 별칭 확인


6

CMK 평문 실습해보기 !!!


# CMK로 평문을 암호화해보기, 파일로 만들기

echo "Hello 123123" > secrect.txt


aws kms encrypt --key-id alias/$ALIAS_SUFFIX --cli-binary-format raw-in-base64-out --plaintext file://secrect.txt --output text --query CiphertextBlob | base64 --decode > secrect.txt.encrypted


# 파일 암호문 확인

cat secrect.txt.encrypted


# 파일 복호화

aws kms decrypt --ciphertext-blob fileb://secrect.txt.encrypted --output text --query Plaintext | base64 --decode

Hello 123123



7

AWS CMK(KMS Key) 생성을 위해 Key policy 생성

현재 사용자가 CMK 권한을 가질 수 있게 코드 설정해보자~~~


# aws cli 로 현재 사용자 정보 확인

aws sts get-caller-identity | jq

{

  "Account": "45xxxxxxxxxxx83",

  "UserId": "AIxxxxxxxxxxxxxxUYL",

  "Arn": "arn:aws:iam::45xxxxxxx83:user/aws111"

}



8

# 테라폼에서 aws_caller_identity 데이터소스로 사용자 정보 확인


provider "aws" {

  region = "ap-northeast-2"

}

# Look up the details of the current user

data "aws_caller_identity" "self" {}


9

현재 사용자에 KMS 권한 부여 정책 생성한다.


data "aws_iam_policy_document" "cmk_admin_policy" {

  statement {

    effect    = "Allow"

    resources = ["*"]

    actions   = ["kms:*"]

    principals {

      type        = "AWS"

      identifiers = [data.aws_caller_identity.self.arn]

    }

  }

}


10

resource "aws_kms_key" "cmk" {

  policy = data.aws_iam_policy_document.cmk_admin_policy.json

}


11

kms는 id로 된  긴숫자 대신 ,  alias로 사용하자.


resource "aws_kms_alias" "cmk" {

  name          = "alias/kms-cmk-example"

  target_key_id = aws_kms_key.cmk.id

}


12

cmk 생성완료



13

실습

DB계정 정보가 포함된 db-creds.yml 파일을 생성


cat <<EOT > db-creds.yml

username: admin

password: password

EOT



14

암호화

aws kms encrypt --key-id alias/$ALIAS_SUFFIX  --cli-binary-format raw-in-base64-out --plaintext file://db-creds.yml --output text --query CiphertextBlob | base64 --decode | tee db-creds.yml.encrypted

u0s0nۺ▒`▒He.0▒M?e_▒7▒7FH▒3▒4U▒B(@'(▒j▒▒[▒▒


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.encrypted2

AQICAHgSmCTHsrGP27rx/drzj4pFwzYY7U0/Z

// 이 타입만 됨


# 암호문 확인

cat db-creds.yml.encrypted

cat db-creds.yml.encrypted2


# 복호화해보기

cat db-creds.yml.encrypted  = 복호화 됨

cat db-creds.yml.encrypted2 = 복호화 안됨


aws kms decrypt --ciphertext-blob fileb://db-creds.yml.encrypted --output text --query Plaintext | base64 --decode

username: admin

password: password



15

테라폼 코드에서 암호화(파일) 활용 할 수 있게 설정


data "aws_kms_secrets" "creds" {

  secret {

    name    = "db"

    payload = file("${path.module}/db-creds.yml.encrypted")

  }

}


16

복호화된 값을 로컬 변수로 지정

locals {

  db_creds = yamldecode(data.aws_kms_secrets.creds.plaintext["db"])

}


17

DB 계정과 암호를 aws_kms_secrets 의 복호화된 로컬 변수를 전달


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

}


18

이제 안전하게 암호를 저장할 수 있고, 암호화된 파일은 버전 관리를 할 수 있습니다.

테라폼 코드에서 암호를 다시 읽을 수 있습니다.




19

rds.tf 코드 파일 생성


cat <<EOT > rds.tf

provider "aws" {

  region = "ap-northeast-2"

}

data "aws_kms_secrets" "creds" {

  secret {

    name    = "db"

    payload = file("\${path.module}/db-creds.yml.encrypted2")

  }

}


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

}

EOT



20

variables.tf 코드 파일 생성


cat <<EOT > variables.tf

variable "db_name" {

  description = "The name to use for the database"

  type        = string

  default     = "example"

}

EOT



21

outputs.tf 코드 파일 생성


cat <<EOT > 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"

}

EOT



cat db-creds.yml.encrypted2

AQICApFwzYY7U0/ZV+JN2TJ/WrPQJntcHP3CEQjAAAAgTB/BgkqhkiG9w0BBwa



22

확인

terraform init

terraform plan


terraform apply -auto-approve



실습을 위해 내용 다운로드



23

확인

aws rds describe-db-instances --query "*[].[DBInstanceIdentifier,MasterUsername,Endpoint.Address,Endpoint.Port]" --output text




24

삭제

terraform destroy -auto-approve



25

# 생성한 키 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




26

장점 : 암호를 평문 사용 절대 금지, 클라우드 KMS 활용

단점 : 도구 학습 필요, 자동화 환경에 적용 시 어려움, 여전히 암호 변경 어려움, 감사 로그 취약, 비밀 번호 관리 표준화 어려움






<3> 리소스와 데이터 소스 -Secret stores로 관리


1

중앙 집중식 비밀 저장소 서비스 사용 - AWS Secrets Manager, Google Secret Manager 등

[Resources and data sources]Secret stores




<4> 상태파일과 planfile  관리


상태 파일과 플랜 파일에 민감 정보 노출


State files : 테라폼 리소스와 데이터 소스에 전달되는 모든 민감정보는 테라폼 상태 파일에 평문으로 저장됨

백엔드 저장소에 저장 시 암호화 Store Terraform state in a backend that supports encryption

백엔드 액세스에 대한 접근 통제 Strictly control who can access your Terraform backend




다음 과정

https://brunch.co.kr/@topasvga/2844






https://brunch.co.kr/@topasvga/2421

감사합니다.

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari