2022.011. 이장재 📧 [email protected] 📂 https://github.com/jangjaelee 📒 http://www.awx.kr
Terraform-compliance는 terraform에 의해 정의된 인프라의 규정 준수를 검증하는 프레임워크이며, 이는 인프라를 검증하기 위해 함께 작동하는 부정적인 테스트 및 BDD를 기반으로 합니다. 이 게시물은 이 프레임워크를 구현하고 IaC를 배포하는 데 사용되는 DevOps 파이프라인에 추가하는 방법을 보여줍니다
- Terraform IaaS(Infrastructure-as-code)를 위한 경량, 보안 및 규정 준수에 중점을 둔 테스트 프레임워크입니다.
- 코드로서의 인프라에 대한 부정적인 테스트 기능을 활성화합니다.
- 구현된 코드가 보안 요구 사항을 충족하는지 확인합니다.
- 표준 규정을 사용자 정의할 수 있습니다.
- Python 3.x
- Terraform 0.12+
Terraform-compliance는 AWS S3 Bucket에서 활성화된 암호화, 태그가 잘 지정된 리소스 등과 같이 인프라에 반드시 있어야 하는 기능을 정의하는 정책을 사용합니다. 이러한 정책은 Terraform이 생성하는 계획에 대해 실행되고 행동 주도 개발(BDD) 원칙을 사용하여 정의합니다.
또한, 클라우드의 상세한 Billing report를 보기 위해서는 각 클라우드 제공자에서 요구하는 비용 할당 태그가 필요한데 이때 BDD원칙을 사용하여 누락되는 태그가 없게 규정을 준수할 수 있습니다.
정책을 정의하기 위해 언어(language)로 영어를 사용합니다.
Terraform으로 작업하기위해 파일 확장자로 feature 사용하고 평가하려는 시나리오가 포함된 BDD 원칙을 사용하여 정책이 정의된 파일을 만들어 사용합니다.
파일의 구조는 다음과 같습니다.
- Feature : 검증할 사항에 대한 요약
- Senario / Senario Outline : 실행할 테스트를 정의하는 시나리오 입니다. 여기에는 아래의 BDD 지시문이 포함됩니다.
- Given : 확인하려는 리소스 또는 데이터의 목록이 될 수 있는 context를 정의하는데 사용되며 모든 시나리오를 정의하는 첫 번째 단계입니다.
- When : 예를 들어, 정의된 context가 모든 S3 Bucket을 평가한다고 말하면 위에서 정의한 context를 필터링합니다. 예를 들어 WHEN을 사용하여 tag로 필터링할 수 있습니다. 조건이 통과하지 못하면 실패 대신 다음 줄로 건너뜁니다.
- Then : WHEN과 유사한 기능을 가지고 있지만 조건이 통과하지 않으면 시나리오가 실패합니다.
- And : 시나리오에 추가 조건을 정의하는 데 사용되며 이는 선택적 명령문입니다.
- Steps : 테스트의 성공 여부를 확인하는 데 필요한 작업을 실제로 실행하는 기능 테스트입니다.
정책파일 예시는 다음과 같습니다.
Feature: Test tagging compliance
Scenario: Ensure all resources have tags
Given I have resource that supports tags defined
Then it must contain tags
And its value must not be null
Scenario Outline: Ensure that specific tags are defined
Given I have resource that supports tags defined
When it has tags
Then it must contain <tags>
And its value must match the "<value>" regex
Examples:
| tags | value |
| Name | .+ |
| Environment | ^(prod\|uat\|dev)$ |
각 BDD directive(지시문)에는 더 많은 기능이 있으며, terraform-compliance의 BDD Reference에서 확인할 수 있습니다.
파이썬 3.x 이상이 필요하며, PyPi 패키지가 설치되어 있어야 합니다.
$ pip install terraform-compliance
$ terraform-compliance -h
terraform-compliance v1.3.34 initiated
usage: terraform-compliance [-h] [--terraform [terraform_file]] --features feature directory --planfile plan_file [--quit-early] [--no-failure] [--silent]
[--identity [ssh private key]] [--debug] [--version]
BDD Test Framework for Hashicorp terraform
options:
-h, --help show this help message and exit
--terraform [terraform_file], -t [terraform_file]
The absolute path to the terraform executable.
--features feature directory, -f feature directory
Directory (or git repository with "git:" prefix) consists of BDD features
--planfile plan_file, -p plan_file
Plan output file generated by Terraform
--quit-early, -q Stops executing any more steps in a scenario on first failure.
--no-failure, -n Skip all the tests that is failed, but giving proper failure message
--silent, -S Do not output any scenarios, just write results or failures
--identity [ssh private key], -i [ssh private key]
SSH Private key that will be use on git authentication.
--debug, -d Turns on debugging mode
--version, -v show program's version number and exit
Docker container image도 제공되고 있어 아래의 명령으로 컨테이너를 다운로드 받을 수 있습니다.
$ docker pull eerkunt/terraform-compliance
아래 테라폼 코드를 사용하여 AWS S3 Bucket을 생성하고 태그이름을 설정합니다.
provider "aws" {
region = var.region
allowed_account_ids = var.account_id
profile = "default"
}
variable "region" {
description = "AWS Region"
type = string
default = "ap-northeast-2"
}
variable "account_id" {
description = "List of Allowed AWS account IDs"
type = list(string)
default = ["1234567890"]
}
variable "bucket" {
description = "S3 bucket for terraform-state-backend"
type = string
default = "tf101-state-backend"
}
variable "s3_acl" {
description = "ACL of S3 Bucket"
type = string
default = "private"
}
resource "aws_s3_bucket" "terraform_state_backend" {
bucket = var.bucket
lifecycle {
prevent_destroy = false
}
tags = {
Name = var.bucket
}
}
resource "aws_s3_bucket_acl" "terraform_state_backend_acl" {
bucket = aws_s3_bucket.terraform_state_backend.id
acl = var.s3_acl
}
resource "aws_s3_bucket_versioning" "terraform_state_backend_versioning" {
bucket = aws_s3_bucket.terraform_state_backend.id
versioning_configuration {
status = "Enabled"
}
}
resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state_backend_encryption" {
bucket = aws_s3_bucket.terraform_state_backend.id
rule {
apply_server_side_encryption_by_default {
#kms_master_key_id = aws_kms_key.mykey.arn
#sse_algorithm = "aws:kms"
sse_algorithm = "AES256"
}
}
}
output "s3_bucket_name" {
value = aws_s3_bucket.terraform_state_backend.bucket
}
$ terraform fmt
$ terraform init
$ terraform validate
$ terraform plan -out=plan.out
$ terraform show -json plan.out > plan.out.json
$ cat plan.out.json | jq
$ terraform-compliance -f compliance/ -p plan.out.json
terraform-compliance v1.3.34 initiated
🚩 Features : /mnt/c/Users/이장재/Desktop/terraform/terraform-backend/compliance/
🚩 Plan File : /mnt/c/Users/이장재/Desktop/terraform/terraform-backend/plan.json
🚩 Running tests. 🎉
Feature: Check tags on the S3 resource # /mnt/c/Users/이장재/Desktop/terraform/terraform-backend/compliance/s3.feature
Scenario: Ensure all resources have tags
Given I have resource that supports tags defined
Then it must contain tags
And its value must not be null
Scenario Outline: Ensure that specific tags are defined
Given I have aws_s3_bucket that supports tags defined
When it has tags
Then it must contain <tags>
And its value must not be null
Examples:
| tags |
💡 SKIPPING: Can not find aws_s3_bucket that supports tags defined in target terraform plan.
| Name |
Feature: This is base for check basic of s3 # /mnt/c/Users/이장재/Desktop/terraform/terraform-backend/compliance/s3attr.feature
Scenario Outline: S3 resources must be configured
Given I have AWS S3 Bucket defined
Then it must contain <attributes>
Examples:
| attributes |
| tags |
Feature: Check if s3 bucket has encrypted # /mnt/c/Users/이장재/Desktop/terraform/terraform-backend/compliance/s3encrypt.feature
Scenario: Ensure all S3 buckets are encrypted
Given I have aws_s3_bucket_server_side_encryption_configuration defined
When it has rule
Then it must contain sse_algorithm
And its value must contain AES256
Feature: Check if s3 bucket has private # /mnt/c/Users/이장재/Desktop/terraform/terraform-backend/compliance/s3private.feature
Scenario: Ensure all S3 buckets are private
Given I have aws_s3_bucket_acl defined
When it has acl
Then its value must contain private
Feature: Test tagging compliance # /mnt/c/Users/이장재/Desktop/terraform/terraform-backend/compliance/tagging.feature
Scenario: Ensure all resources have tags
Given I have resource that supports tags defined
Then it must contain tags
And its value must not be null
Scenario Outline: Ensure that specific tags are defined
Given I have resource that supports tags defined
When it has tags
Then it must contain <tags>
And its value must match the "<value>" regex
Examples:
| tags | value |
| Name | .+ |
Failure: aws_dynamodb_table.terraform_state_locks (aws_dynamodb_table) does not have Environment property.
Failure: aws_s3_bucket.terraform_state_backend (aws_s3_bucket) does not have Environment property.
| Environment | ^(prod|uat|dev)$ |
Failure:
5 features (3 passed, 1 failed, 1 skipped)
8 scenarios (6 passed, 1 failed, 1 skipped)
27 steps (21 passed, 1 failed, 2 skipped)
Run 1668277974 finished within a moment
$ terraform apply
- Website
- GitHub
- PyPI
- Implement compliance testing with Terraform and Azure
- Announcing policy guardrails for Terraform on Google Cloud CLI preview
- Enforce Policy with Sentinel
- TFLint
- Terraform Security Checks - aqua tfsec
- How to test Terraform compliance using the Open Policy Agent (OPA)
- Terraform Test Framework [Web] [GitHub]
- radish-BDD - python BDD tool
- Gherkin Reference
END