Terraform-secrets-관리

테라폼 secrets 관리가 왜 중요한가?

테라폼을 이용한 IaC (Infrastructure as code) 시 보안을 위해 각종 secrets 에 대한 관리 방안을 항상 마련해 놓아야 합니다. 그렇지 않을 경우, 코드에 포함된 secrets 들이 형상관리 시스템이나 스토리지 저장소에 그대로 노출이 되어 보안적 사고로 이어질 수 있습니다.

secrets 라고 하면 인프라를 구성하는데 사용되는 credentials 로서 흔히 DB 패스워드, API Key 등을 포함할 수 있습니다. 이는 항상 코드에 그대로 저장되어선 않되며 별도의 공간에 암호화하여 안전하게 저장하어야 합니다.

이번에는 테라포밍 과정에서 secrets 관리 방법에 대해 공유해보고자 합니다.

테라폼 secrets 보안적 관리 방안

1. 환경 변수를 이용한 관리

테라폼에서는 plan, apply 동작시 기본적으로 확인하고 내부 변수로 맵핑하여 사용할 수 있는 환경변수가 있습니다. 이 환경변수들을 이용하면 테라폼 코드에 직접적인 secrets 정보를 포함하지 않고 저장이 가능합니다.

# 시스템 환경변수 설정
# TF_VAR_ 로 시작하고 뒤에 테라폼 코드에서 사용할 변수명 입력
export TF_VAR_username=idtest
export TF_VAR_password=passwordtest1234!

위와 같이 환경변수를 지정한 다음 테라폼 코드에서 사용할 수 있도록 변수 선언을 먼저 합니다.

# variables.tf
variable "username" {
  description = "username"
  type = string
  sensitive = true
}

variable "password" {
  description = "password"
  type = string
  sensitive = true
}

그리고 해당 변수를 resource 정의시 사용하면 테라폼은 알아서 환경변수에서 맵핑되는 값을 불러와 사용할 수 있게 됩니다.

# db.tf
resource "aws_db_instance" "this" {
  allocated_storage    = 10
  db_name              = "mydb"
  engine               = "mysql"
  engine_version       = "5.7"
  instance_class       = "db.t3.micro"
  username             = var.username
  password             = var.password
  parameter_group_name = "default.mysql5.7"
  skip_final_snapshot  = true
}

환경변수를 이용하면 추가적인 1password 나 다른 password manager 의 CLI 명령어를 통합하여 사용도 가능합니다.

이 방법은 심플하나 OS 접근권한을 가지고 있는 사용자라면 환경변수 조회를 통해 credential 을 plain text 로 확인할 수 있다는 단점이 있습니다.

2. AWS Secrets Manager 이용한 관리

AWS Secrets Manager 는 AWS 에서 제공하는 Secrets 을 안전하게 보관할 수 있도록 해주는 서비스입니다. 이 서비스를 이용하여 secrets 를 안전하게 저장하고 테라폼 코드에서는 data 를 이용하여 secrets 를 불러와 사용할 수 있습니다. 개인적으로는 해당 방법을 주로 이용하고 있습니다.

먼저 AWS Secrets Manager 에서 Manually 하게 secrets 를 추가합니다. secret type 은 적절한 타입으로 선택하고, Next 후 name 및 rotation 설정을 적절하게 설정해줍니다.

AWS-Secrets-Manager

그리고 테라폼 코드에서 data 를 이용하여 해당 secrets 정보를 가지고 온 다음, local 변수로 받아 사용을 하게 됩니다. 아래는 간단한 사용 예시 코드 입니다.

# db.tf
data "aws_secretsmanager_secret_version" "rds_credentials" {
  secret_id = "rds/credentials"
}

locals {
  secret_data = jsondecode(data.aws_secretsmanager_secret_version.rds_credentials.secret_string)
  username    = local.secret_data["username"]
  password    = local.secret_data["password"]

}

resource "aws_db_instance" "this" {
  allocated_storage    = 10
  db_name              = "mydb"
  engine               = "mysql"
  engine_version       = "5.7"
  instance_class       = "db.t3.micro"
  username             = local.username
  password             = local.password
  parameter_group_name = "default.mysql5.7"
  skip_final_snapshot  = true
}

해당 방법을 AWS Secrets Manager 가 Secrets 를 안전하게 보관하고 있기 때문에 코드나 환경변수단에서 secrets 정보를 저장할 필요가 없습니다.

다만 상태파일인 tfstate 파일에는 위에서 언급한 어떤 방법을 사용하든 plain text 로 secrets 를 노출하게 되는데요. 이 부분은 어떻게 처리할지 살펴보겠습니다.

3. tfstate 파일 보안 관리

개인 프로젝트로 IaC를 할 경우에는 tfstate 파일을 로컬에 저장을 해도 크게 상관은 없습니다만, 팀으로서 다른 구성원과의 협업이 필요할 경우에는 backend 구성을 통해 모두가 접근이 가능한 storage 에 안전하게 tfstate 파일을 저장하게 되는데요.

테라폼에서는 tfstate 파일에서 secrets 에 대한 기본적인 암호화 저장할 수 있도록하는 기능을 제공해주지 않고 있습니다. 그래서 위에서 언급했던 방법들을 이용하여 테라폼 코드에 secrets 를 직접적으로 포함하지 않도록 하더라도 apply 후 저장되는 tfstate 파일에는 결국 plain text 의 secrets 가 저장되게 됩니다. 🙁

(hashcorp 에서는 아마 terraform enterprise 나 terraform cloud 사용을 권장하기 위해 기능추가를 해주지 않는듯 합니다..)

이 문제는 tfstate 를 저장하게 되는 storage 에서 지원하는 암호화 기능을 이용하여야 합니다. AWS 경우에서는 s3 를 backend storage 로 보통 사용하게 되는데, s3 의 암호화 저장 기능을 이용하는 것이지요.

aws-s3-암호화-설정

마치며..

클라우드 환경에서의 보안사고들 중 secrets 관리 미흡으로 인한 보안사고는 항상 탑으로 발생하고 있는데요. IaC 에서도 secrets 관리를 어떻게 하면 보안적으로 안전하면서도 파이프라인에서 효율적으로 관리할 수 있을지 항상 고민하는게 중요한 듯합니다.

Refs

Series Navigation<< Terraform IaC Scanning Tools 비교

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

Back To Top