해당 내용은 cloudNet@ 팀의 가시다 님이 진행하는 테라폼 스터디 T101 4기에서 학습한 내용을 정리한 것입니다.
4. State file encryption - AWS KMS
- AWS KMS 소개
- AWS 키 관리 서비스 KMS는 공유 하드웨어 보안 모듈HSM 을 사용하면서 암호화키를 생성하고 관리할 수 있게 도와준다.
- CloudHSM은 AWS 내에서 암호화키를 관리할 수 있지만 보안 강화를 위해 전용 HSM을 사용할 수 있는 서비스다.
- [사전준비] AWS KMS 생성 및 실습 : 대칭 키 생성 후 평문 파일을 암호화 및 복호화
# 키 생성(기본값)
# 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=<각자 닉네임>
export ALIAS_SUFFIX=smlim
aws kms create-alias --alias-name alias/$ALIAS_SUFFIX --target-key-id $KEY_ID
# 생성한 별칭 확인 : 키 ID 메모하두기, 아래 테라폼 코드에서 사용
aws kms list-aliases
aws kms list-aliases --query "Aliases[?AliasName=='alias/<각자 닉네임>'].TargetKeyId" --output text
aws kms list-aliases --query "Aliases[?AliasName=='alias/smlim'].TargetKeyId" --output text
c0bfc529-1ede-44f3-a7e5-ae60814c1ca1
# 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
실습
- 8.3 디렉토리 backend.tf 파일 수정
terraform {
backend "s3" {
bucket = "smlim-t1014" # 각자 자신의 S3 버킷명
key = "terraform.tfstate"
region = "ap-northeast-2"
encrypt = true
}
encryption {
key_provider "aws_kms" "kms" {
kms_key_id = "f8a70e42-e7b6-456b-bf1c-d71b7937a09b" # 각자 자신의 KMS ID
region = "ap-northeast-2"
key_spec = "AES_256"
}
method "aes_gcm" "my_method" {
keys = key_provider.aws_kms.kms
}
## Remove this after the migration:
method "unencrypted" "migration" {
}
state {
method = method.aes_gcm.my_method
## Remove the fallback block after migration:
fallback{
method = method.unencrypted.migration
}
# Enable this after migration:
#enforced = false
}
}
}
5. Removed block
- Removed block을 사용하면 상태 파일에서 리소스를 제거하면서도 인프라에 유지할 수 있습니다.
튜토리얼
resource "local_file" "test" {
content = "Hello world!"
filename = "test.txt"
}
- 위 리소스 apply 한 후에 main.tf 파일 수정
removed {
from = local_file.test
}
- 다시 apply
실습
- 8.3 에서 사용한 main.tf 파일 복사
mkdir 8.4 && cd 8.4
cp ../8.3/main.tf .
touch backend.tf
- main.tf 작성
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}
variable "instance_ids" {
type = list(string)
default = ["i-0fb60867d197a2ee8", "i-065168c51db4e2f00"] # 각자 자신의 EC2 ID를 기입 할 것
}
variable "instance_tags" {
type = list(string)
default = ["web", "app"]
}
resource "aws_instance" "this" {
count = length(var.instance_tags)
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
tags = {
Name = var.instance_tags[count.index]
}
}
import {
for_each = { for idx, item in var.instance_ids : idx => item }
to = aws_instance.this[tonumber(each.key)]
id = each.value
}
resource "aws_ssm_parameter" "this" {
count = length(var.instance_tags)
name = var.instance_tags[count.index]
type = "String"
value = aws_instance.this[count.index].id
}
#
tofu init
tree .terraform
# 2개 리소스는 import , 2개 리소스는 생성
tofu apply -auto-approve
Plan: 2 to import, 2 to add, 0 to change, 0 to destroy.
aws_instance.this[0]: Importing... [id=i-0e2d4475790337a81]
aws_instance.this[0]: Import complete [id=i-0e2d4475790337a81]
aws_instance.this[1]: Importing... [id=i-00a4daebb71942280]
aws_instance.this[1]: Import complete [id=i-00a4daebb71942280]
aws_ssm_parameter.this[1]: Creating...
aws_ssm_parameter.this[0]: Creating...
aws_ssm_parameter.this[1]: Creation complete after 0s [id=app]
aws_ssm_parameter.this[0]: Creation complete after 0s [id=web]
#
tofu state ls
tofu show
tofu state show 'aws_ssm_parameter.this[0]'
tofu state show 'aws_ssm_parameter.this[1]'
# tfstate 파일 확인 : VSCODE에서 열어보기
cat terraform.tfstate | jq
...
"type": "aws_ssm_parameter",
"name": "this",
"provider": "provider[\"registry.opentofu.org/hashicorp/aws\"]",
"instances": [
{
"index_key": 0,
"schema_version": 0,
"attributes": {
"allowed_pattern": "",
"arn": "arn:aws:ssm:ap-northeast-2:911283464785:parameter/web",
"data_type": "text",
"description": "",
"id": "web",
"insecure_value": null,
"key_id": "",
"name": "web",
"overwrite": null,
"tags": null,
"tags_all": {},
"tier": "Standard",
"type": "String",
"value": "i-0e2d4475790337a81",
...
# parameters 정보 확인
aws ssm describe-parameters | jq
aws ssm get-parameter --name "web"
aws ssm get-parameter --name "web" --query "Parameter.Value" --output text
aws ssm get-parameter --name "app"
aws ssm get-parameter --name "app" --query "Parameter.Value" --output text
- 파라미터 스토어 리소스만 tfstate 에서 제거하고, AWS 상에는 유지하도록 설정
- main.tf 파일 수정
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
owners = ["099720109477"] # Canonical
}
variable "instance_ids" {
type = list(string)
default = ["i-0fb60867d197a2ee8", "i-065168c51db4e2f00"] # 각자 자신의 EC2 ID를 기입 할 것
}
variable "instance_tags" {
type = list(string)
default = ["web", "app"]
}
resource "aws_instance" "this" {
count = length(var.instance_tags)
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
tags = {
Name = var.instance_tags[count.index]
}
}
import {
for_each = { for idx, item in var.instance_ids : idx => item }
to = aws_instance.this[tonumber(each.key)]
id = each.value
}
# resource "aws_ssm_parameter" "this" {
# count = length(var.instance_tags)
# name = var.instance_tags[count.index]
# type = "String"
# value = aws_instance.this[count.index].id
# }
removed {
from = aws_ssm_parameter.this
}
6. Test
- tofu test 명령을 사용하면 실제 인프라를 생성하고 필요한 조건이 충족되는지 확인하여 OpenTofu 구성을 테스트할 수 있습니다. 테스트가 완료되면 OpenTofu는 생성한 리소스를 삭제합니다.
- Usage : tofu test [options]
- 이 command은 현재 디렉토리나 tests라는 디렉토리에 있는 모든 *.tftest.hcl 파일을 실행합니다.
실습
mkdir 8.5 && cd 8.5
touch main.tf
mkdir tests
touch tests/main.tftest.hcl
touch tests/terraform.tfvars
- main.tf 파일 작성
variable "test" {
type = string
}
resource "local_file" "this" {
filename = "${path.module}/test.txt"
content = var.test
}
- tests/main.tftest.hcl 파일 작성
run "test" {
assert {
condition = file(local_file.this.filename) == var.test
error_message = "Incorrect content in file"
}
}
- tests/terraform.tfvars 파일 작성
test = "t101-study-end"
- 실행 후 확인
# Test 실행
tofu test
# Apply 확인
tofu apply -auto-approve
tofu state list
cat test.txt
'DevOps' 카테고리의 다른 글
[T1014-실습] OpenTofu 1.7.0 (0) | 2024.08.02 |
---|---|
[T1014-이론] OpenTofu 소개 (0) | 2024.07.31 |
[T1014-실습] Terraform 으로 AWS EKS 배포하기 (0) | 2024.07.24 |
[T1014-이론] EKS? Kubernetes? Karpenter? Helm? ArgoCD? (1) | 2024.07.24 |
[T1014-실습] Terraform Runner (1) | 2024.07.14 |