Skip to content

Update Terraform implementation with security best practices #299

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion aws_sra_examples/terraform/common/dynamodb/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ resource "aws_dynamodb_table" "terraform_locks" {
#checkov:skip=CKV_AWS_119: Ensure DynamoDB Tables are encrypted using a KMS Customer Managed CMK
name = var.dynamodb_name
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
Expand Down
4 changes: 2 additions & 2 deletions aws_sra_examples/terraform/common/dynamodb/output.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
# SPDX-License-Identifier: MIT-0
########################################################################

output dynamo_db_table_name {
value = aws_dynamodb_table.terraform_locks.name
output "dynamo_db_table_name" {
value = aws_dynamodb_table.terraform_locks.name
}
6 changes: 3 additions & 3 deletions aws_sra_examples/terraform/common/dynamodb/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
########################################################################

variable "dynamodb_name" {
description = "DynamoDB Table Name for state locking"
type = string
default = "sra-tfstate-lock"
description = "DynamoDB Table Name for state locking"
type = string
default = "sra-tfstate-lock"
}

variable "sra_solution_name" {
Expand Down
10 changes: 8 additions & 2 deletions aws_sra_examples/terraform/common/providers.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
########################################################################

terraform {
required_version = ">= 1.0.0"
required_providers {
aws = ">= 5.1.0"
aws = {
source = "hashicorp/aws"
version = ">= 5.31.0"
}
}
}

Expand All @@ -15,7 +19,9 @@ provider "aws" {

default_tags {
tags = {
Owner = "Security"
Owner = "Security"
Environment = "SRA"
Terraform = "true"
}
}
}
139 changes: 131 additions & 8 deletions aws_sra_examples/terraform/common/s3/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@
########################################################################

resource "aws_s3_bucket" "sra_state_bucket" {
#checkov:skip=CKV2_AWS_61: Ensure that an S3 bucket has a lifecycle configuration
#checkov:skip=CKV_AWS_18: Ensure the S3 bucket has access logging enabled
#checkov:skip=CKV2_AWS_62: Ensure S3 buckets should have event notifications enabled
#checkov:skip=CKV_AWS_144: Ensure that S3 bucket has cross-region replication enabled

bucket = "${var.sra_state_bucket_prefix}-${data.aws_region.current.name}-${data.aws_caller_identity.current.account_id}"
force_destroy = true

Expand All @@ -18,14 +13,14 @@ resource "aws_s3_bucket" "sra_state_bucket" {
}

resource "aws_s3_bucket_server_side_encryption_configuration" "sra_state_bucket_see" {
#checkov:skip=CKV2_AWS_67: Ensure AWS S3 bucket encrypted with Customer Managed Key (CMK) has regular rotation
bucket = aws_s3_bucket.sra_state_bucket.id

rule {
apply_server_side_encryption_by_default {
kms_master_key_id = var.kms_key_id
sse_algorithm = "aws:kms"
}
bucket_key_enabled = true
}
}

Expand All @@ -37,10 +32,9 @@ resource "aws_s3_bucket_versioning" "sra_state_bucket_versioning" {
}

resource "aws_s3_bucket_ownership_controls" "sra_state_bucket_ownership_control" {
#checkov:skip=CKV2_AWS_65: Ensure access control lists for S3 buckets are disabled
bucket = aws_s3_bucket.sra_state_bucket.id
rule {
object_ownership = "BucketOwnerPreferred"
object_ownership = "BucketOwnerEnforced"
}
}

Expand All @@ -52,3 +46,132 @@ resource "aws_s3_bucket_public_access_block" "sra_state_bucket_public_access_blo
ignore_public_acls = true
restrict_public_buckets = true
}

resource "aws_s3_bucket_lifecycle_configuration" "sra_state_bucket_lifecycle" {
bucket = aws_s3_bucket.sra_state_bucket.id

rule {
id = "cleanup-old-versions"
status = "Enabled"

noncurrent_version_expiration {
noncurrent_days = 90
}

abort_incomplete_multipart_upload {
days_after_initiation = 7
}
}
}

resource "aws_s3_bucket_logging" "sra_state_bucket_logging" {
bucket = aws_s3_bucket.sra_state_bucket.id

target_bucket = aws_s3_bucket.sra_state_bucket_logs.id
target_prefix = "access-logs/"
}

resource "aws_s3_bucket" "sra_state_bucket_logs" {
bucket = "${var.sra_state_bucket_prefix}-logs-${data.aws_region.current.name}-${data.aws_caller_identity.current.account_id}"
force_destroy = true

tags = {
"sra-solution" = var.sra_solution_name
}
}

resource "aws_s3_bucket_server_side_encryption_configuration" "sra_state_bucket_logs_see" {
bucket = aws_s3_bucket.sra_state_bucket_logs.id

rule {
apply_server_side_encryption_by_default {
kms_master_key_id = var.kms_key_id
sse_algorithm = "aws:kms"
}
bucket_key_enabled = true
}
}

resource "aws_s3_bucket_versioning" "sra_state_bucket_logs_versioning" {
bucket = aws_s3_bucket.sra_state_bucket_logs.id
versioning_configuration {
status = "Enabled"
}
}

resource "aws_s3_bucket_ownership_controls" "sra_state_bucket_logs_ownership_control" {
bucket = aws_s3_bucket.sra_state_bucket_logs.id
rule {
object_ownership = "BucketOwnerEnforced"
}
}

resource "aws_s3_bucket_public_access_block" "sra_state_bucket_logs_public_access_block" {
bucket = aws_s3_bucket.sra_state_bucket_logs.id

block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}

resource "aws_s3_bucket_lifecycle_configuration" "sra_state_bucket_logs_lifecycle" {
bucket = aws_s3_bucket.sra_state_bucket_logs.id

rule {
id = "logs-cleanup"
status = "Enabled"

expiration {
days = 365
}
}
}

resource "aws_s3_bucket_policy" "sra_state_bucket_policy" {
bucket = aws_s3_bucket.sra_state_bucket.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "DenyInsecureTransport"
Effect = "Deny"
Principal = "*"
Action = "s3:*"
Resource = [
aws_s3_bucket.sra_state_bucket.arn,
"${aws_s3_bucket.sra_state_bucket.arn}/*"
]
Condition = {
Bool = {
"aws:SecureTransport" = "false"
}
}
}
]
})
}

resource "aws_s3_bucket_policy" "sra_state_bucket_logs_policy" {
bucket = aws_s3_bucket.sra_state_bucket_logs.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "DenyInsecureTransport"
Effect = "Deny"
Principal = "*"
Action = "s3:*"
Resource = [
aws_s3_bucket.sra_state_bucket_logs.arn,
"${aws_s3_bucket.sra_state_bucket_logs.arn}/*"
]
Condition = {
Bool = {
"aws:SecureTransport" = "false"
}
}
}
]
})
}
4 changes: 2 additions & 2 deletions aws_sra_examples/terraform/common/s3/output.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
# SPDX-License-Identifier: MIT-0
########################################################################

output bucket_name {
value = aws_s3_bucket.sra_state_bucket.id
output "bucket_name" {
value = aws_s3_bucket.sra_state_bucket.id
}
2 changes: 1 addition & 1 deletion aws_sra_examples/terraform/common/s3/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ variable "sra_state_bucket_prefix" {
default = "sra-tfstate-files"
}

variable kms_key_id {
variable "kms_key_id" {
description = "KMS Key ID"
type = string
}
Expand Down
2 changes: 1 addition & 1 deletion aws_sra_examples/terraform/common/secrets_kms/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ data "aws_iam_policy_document" "sra_secrets_key_policy" {
#checkov:skip=CKV_AWS_109: Ensure IAM policies does not allow permissions management without constraints
#checkov:skip=CKV_AWS_111: Ensure IAM policies does not allow write access without constraints
#checkov:skip=CKV_AWS_356: Ensure no IAM policies documents allow "*" as a statement's resource for restrictable actions

statement {
sid = "Enable IAM User Permissions"
effect = "Allow"
Expand Down
4 changes: 2 additions & 2 deletions aws_sra_examples/terraform/common/secrets_kms/output.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
# SPDX-License-Identifier: MIT-0
########################################################################

output kms_key_arn {
value = aws_kms_key.sra_secrets_key.arn
output "kms_key_arn" {
value = aws_kms_key.sra_secrets_key.arn
}
2 changes: 1 addition & 1 deletion aws_sra_examples/terraform/common/ssm_parameters/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ data "aws_iam_policy_document" "cloudwatch_policy" {

data "aws_iam_policy_document" "management_account_parameters_lambda_ssm_policy" {
#checkov:skip=CKV_AWS_356: Ensure no IAM policies documents allow "*" as a statement's resource for restrictable actions

statement {
sid = "STSOrganizationRead"
effect = "Allow"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ resource "aws_lambda_function" "cloudtrail_org_lambda_function" {
#checkov:skip=CKV_AWS_115: Ensure that AWS Lambda function is configured for function-level concurrent execution limit
#checkov:skip=CKV_AWS_117: Ensure that AWS Lambda function is configured inside a VPC
#checkov:skip=CKV_AWS_50: X-Ray tracing is enabled for Lambda

description = "Creates an Organization CloudTrail"
function_name = var.cloudtrail_lambda_function_name
role = aws_iam_role.cloudtrail_lambda_role.arn
Expand Down
Loading