diff --git a/.github/workflows/tf_testing.yml b/.github/workflows/tf_testing.yml index c5a6503ce..4cd002d4d 100644 --- a/.github/workflows/tf_testing.yml +++ b/.github/workflows/tf_testing.yml @@ -22,7 +22,7 @@ env: CORE_TESTING_FOLDER: ${{ github.workspace }} OUTPUT_DIR: ${{ github.workspace }}/auto_policy_testing/output AWS_DEFAULT_REGION: ${{ vars.AWS_REGION }} - resource_priority_list: 'rds' + resource_priority_list: 'secrets' RED: '\033[0;31m' jobs: diff --git a/auto_policy_testing/green/common_resources/vpc.tf b/auto_policy_testing/green/common_resources/vpc.tf index e72bb8a17..a12e8c941 100644 --- a/auto_policy_testing/green/common_resources/vpc.tf +++ b/auto_policy_testing/green/common_resources/vpc.tf @@ -1,5 +1,7 @@ resource "aws_vpc" "this" { cidr_block = "10.0.0.0/16" + enable_dns_support = true + enable_dns_hostnames = true tags = { Name = "${module.naming.resource_prefix.vpc}" } diff --git a/auto_policy_testing/green/secrets/data.tf b/auto_policy_testing/green/secrets/data.tf index 7e99af5fa..c62629298 100644 --- a/auto_policy_testing/green/secrets/data.tf +++ b/auto_policy_testing/green/secrets/data.tf @@ -1,51 +1,35 @@ data "aws_iam_policy_document" "this1" { - statement { - actions = [ - "lambda:GetFunction", - "lambda:InvokeAsync", - "lambda:InvokeFunction"] - - resources = [ - "arn:aws:lambda:::*", - ] - } -} - - -data "aws_iam_policy_document" "this3" { statement { actions = [ "ec2:CreateNetworkInterface", "ec2:DeleteNetworkInterface", "ec2:DescribeNetworkInterfaces", - "ec2:DetachNetworkInterface"] - resources = [aws_secretsmanager_secret.this.arn] + "ec2:DetachNetworkInterface" + ] + resources = ["*"] } } -data "aws_iam_policy_document" "this4" { +data "aws_iam_policy_document" "this2" { statement { actions = [ "kms:Decrypt", "kms:DescribeKey", - "kms:GenerateDataKey"] + "kms:GenerateDataKey" + ] resources = ["*"] } } -data "aws_iam_policy_document" "this2" { +data "aws_iam_policy_document" "this3" { statement { actions = [ "secretsmanager:DescribeSecret", "secretsmanager:GetSecretValue", "secretsmanager:PutSecretValue", - "secretsmanager:UpdateSecretVersionStage"] + "secretsmanager:UpdateSecretVersionStage" + ] resources = ["*"] - condition { - test = "StringEquals" - variable = "secretsmanager:resource/AllowRotationLambdaArn" - values = ["${aws_lambda_function.this.arn}"] - } } statement { actions = ["secretsmanager:GetRandomPassword"] diff --git a/auto_policy_testing/green/secrets/iam.tf b/auto_policy_testing/green/secrets/iam.tf new file mode 100644 index 000000000..f97244e10 --- /dev/null +++ b/auto_policy_testing/green/secrets/iam.tf @@ -0,0 +1,39 @@ +resource "aws_iam_role" "this" { + name = "${module.naming.resource_prefix.iam_role}" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "lambda.amazonaws.com" + } + }, + ] + }) +} + +resource "aws_iam_role_policy" "this1" { + name = "${module.naming.resource_prefix.iam_policy}-1" + role = aws_iam_role.this.name + policy = data.aws_iam_policy_document.this1.json +} + +resource "aws_iam_role_policy" "this2" { + name = "${module.naming.resource_prefix.iam_policy}-2" + role = aws_iam_role.this.name + policy = data.aws_iam_policy_document.this2.json +} + +resource "aws_iam_role_policy" "this3" { + name = "${module.naming.resource_prefix.iam_policy}-3" + role = aws_iam_role.this.name + policy = data.aws_iam_policy_document.this3.json +} + +resource "aws_iam_role_policy_attachment" "this1" { + role = aws_iam_role.this.name + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" +} \ No newline at end of file diff --git a/auto_policy_testing/green/secrets/lambda.tf b/auto_policy_testing/green/secrets/lambda.tf new file mode 100644 index 000000000..cc4fe1409 --- /dev/null +++ b/auto_policy_testing/green/secrets/lambda.tf @@ -0,0 +1,35 @@ +resource "aws_lambda_function" "this" { + filename = "lambda_function.zip" + function_name = "${module.naming.resource_prefix.lambda_function}" + role = aws_iam_role.this.arn + handler = "lambda_function.lambda_handler" + source_code_hash = filebase64sha256("lambda_function.zip") + runtime = "python3.12" + replace_security_groups_on_destroy = true + + environment { + variables = { + SECRETS_MANAGER_ENDPOINT = "https://${aws_vpc_endpoint.this.dns_entry[0].dns_name}" + EXCLUDE_CHRACTERS = "/@\"'\\ " + } + } + + vpc_config { + subnet_ids = [data.terraform_remote_state.common.outputs.vpc_subnet_1_id, data.terraform_remote_state.common.outputs.vpc_subnet_3_id] + security_group_ids = [aws_security_group.this.id] + } + + depends_on = [ + aws_vpc_endpoint.this, + aws_iam_role_policy.this1, + aws_iam_role_policy.this2, + aws_iam_role_policy_attachment.this1 + ] +} + +resource "aws_lambda_permission" "this" { + function_name = aws_lambda_function.this.function_name + statement_id = "AllowExecutionSecretManager" + action = "lambda:InvokeFunction" + principal = "secretsmanager.amazonaws.com" +} \ No newline at end of file diff --git a/auto_policy_testing/green/secrets/rds.tf b/auto_policy_testing/green/secrets/rds.tf new file mode 100644 index 000000000..c86c26ca1 --- /dev/null +++ b/auto_policy_testing/green/secrets/rds.tf @@ -0,0 +1,25 @@ +resource "aws_db_instance" "this" { + identifier = "${module.naming.resource_prefix.rds_instance}" + engine = "mysql" + instance_class = "db.t3.micro" + allocated_storage = 10 + storage_type = "gp2" + username = "adminaccount" + password = random_password.this.result + skip_final_snapshot = true + vpc_security_group_ids = [aws_security_group.this.id] + publicly_accessible = false + db_subnet_group_name = aws_db_subnet_group.this.name + +} + +resource "aws_db_subnet_group" "this" { + name = "${module.naming.resource_prefix.rds_instance}" + subnet_ids = [data.terraform_remote_state.common.outputs.vpc_subnet_1_id, data.terraform_remote_state.common.outputs.vpc_subnet_3_id] +} + +resource "random_password" "this" { + length = 12 + special = true + override_special = "!#$%*()-_=+[]{}:?" +} \ No newline at end of file diff --git a/auto_policy_testing/green/secrets/secrets.tf b/auto_policy_testing/green/secrets/secrets.tf index d6f00fa2c..3fba37a88 100644 --- a/auto_policy_testing/green/secrets/secrets.tf +++ b/auto_policy_testing/green/secrets/secrets.tf @@ -1,114 +1,8 @@ -resource "aws_iam_role" "this" { - name = "${module.naming.resource_prefix.secrets}" - - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Action = "sts:AssumeRole" - Effect = "Allow" - Principal = { - Service = "lambda.amazonaws.com" - } - }, - ] - }) -} - -resource "aws_iam_role_policy" "this1" { - name = "${module.naming.resource_prefix.secrets}-1" - role = aws_iam_role.this.name - policy = data.aws_iam_policy_document.this1.json -} - -resource "aws_iam_role_policy" "this2" { - name = "${module.naming.resource_prefix.secrets}-2" - role = aws_iam_role.this.name - policy = data.aws_iam_policy_document.this2.json -} - -resource "aws_iam_role_policy" "this3" { - name = "${module.naming.resource_prefix.secrets}-3" - role = aws_iam_role.this.name - policy = data.aws_iam_policy_document.this3.json -} - -resource "aws_iam_role_policy" "this4" { - name = "${module.naming.resource_prefix.secrets}-4" - role = aws_iam_role.this.name - policy = data.aws_iam_policy_document.this4.json -} - -resource "aws_iam_role_policy_attachment" "this1" { - role = aws_iam_role.this.name - policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" -} - -resource "aws_iam_role_policy_attachment" "this2" { - role = aws_iam_role.this.name - policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole" -} - -resource "aws_lambda_function" "this" { - filename = "lambda_function.zip" - function_name = "${module.naming.resource_prefix.secrets}" - role = aws_iam_role.this.arn - handler = "lambda_function.lambda_handler" - source_code_hash = filebase64sha256("lambda_function.zip") - runtime = "python3.12" - - environment { - variables = { - SECRETS_MANAGER_ENDPOINT = "https://secretsmanager.us-east-1.amazonaws.com" - EXCLUDE_CHRACTERS = "/@\"'\\ " - } - } - - vpc_config { - subnet_ids = [aws_subnet.this1.id, aws_subnet.this2.id] - security_group_ids = [aws_security_group.this.id] - } - -} - -resource "aws_lambda_permission" "this" { - function_name = aws_lambda_function.this.function_name - statement_id = "AllowExecutionSecretManager" - action = "lambda:InvokeFunction" - principal = "secretsmanager.amazonaws.com" -} - -resource "aws_db_subnet_group" "this" { - name = "${module.naming.resource_prefix.secrets}" - subnet_ids = [aws_subnet.this1.id, aws_subnet.this2.id] -} - -resource "aws_db_instance" "this" { - identifier = "${module.naming.resource_prefix.secrets}" - engine = "mysql" - engine_version = "5.7" - instance_class = "db.t3.micro" - allocated_storage = 10 - storage_type = "gp2" - db_name = "databasegreen" - username = "adminaccount" - password = random_password.this.result - skip_final_snapshot = true - db_subnet_group_name = aws_db_subnet_group.this.name - vpc_security_group_ids = [aws_security_group.this.id] - publicly_accessible = true -} - -resource "random_password" "this" { - length = 12 - special = true - override_special = "!#$%*()-_=+[]{}:?" -} - resource "aws_secretsmanager_secret" "this" { name = "${module.naming.resource_prefix.secrets}" + recovery_window_in_days = 0 - depends_on = [aws_db_instance.this, aws_lambda_function.this] + depends_on = [aws_db_instance.this] } resource "aws_secretsmanager_secret_version" "this" { @@ -134,60 +28,16 @@ EOF resource "aws_secretsmanager_secret_rotation" "this" { secret_id = aws_secretsmanager_secret.this.id rotation_lambda_arn = aws_lambda_function.this.arn - + rotate_immediately = true rotation_rules { - automatically_after_days = 7 + automatically_after_days = 90 } } -resource "aws_vpc" "this" { - cidr_block = "10.0.0.0/16" - enable_dns_hostnames = true - -} - -resource "aws_subnet" "this1" { - cidr_block = "10.0.0.0/24" - vpc_id = aws_vpc.this.id - map_public_ip_on_launch = true - availability_zone = "us-east-1a" -} - -resource "aws_subnet" "this2" { - cidr_block = "10.0.1.0/24" - vpc_id = aws_vpc.this.id - map_public_ip_on_launch = true - availability_zone = "us-east-1b" - -} - -resource "aws_internet_gateway" "this" { - vpc_id = aws_vpc.this.id -} - -resource "aws_route_table" "this" { - vpc_id = aws_vpc.this.id - - route { - cidr_block = "0.0.0.0/0" - gateway_id = aws_internet_gateway.this.id - } - -} - -resource "aws_route_table_association" "this" { - subnet_id = aws_subnet.this1.id - route_table_id = aws_route_table.this.id -} - -resource "aws_route_table_association" "this2" { - subnet_id = aws_subnet.this2.id - route_table_id = aws_route_table.this.id -} resource "aws_security_group" "this" { - name = "${module.naming.resource_prefix.secrets}" - vpc_id = aws_vpc.this.id + name = "${module.naming.resource_prefix.security_group}" + vpc_id = data.terraform_remote_state.common.outputs.vpc_id ingress { from_port = 0 @@ -205,14 +55,14 @@ resource "aws_security_group" "this" { } resource "aws_vpc_endpoint" "this" { - vpc_id = aws_vpc.this.id - service_name = "com.amazonaws.us-east-1.secretsmanager" + vpc_id = data.terraform_remote_state.common.outputs.vpc_id + service_name = "com.amazonaws.${var.region}.secretsmanager" vpc_endpoint_type = "Interface" - private_dns_enabled = true + private_dns_enabled = false - subnet_ids = [aws_subnet.this1.id, aws_subnet.this2.id] + subnet_ids = [data.terraform_remote_state.common.outputs.vpc_subnet_1_id, data.terraform_remote_state.common.outputs.vpc_subnet_3_id] security_group_ids = [ - aws_security_group.this.id, + aws_security_group.this.id ] } diff --git a/auto_policy_testing/red/rds/rds_mariadb.tf b/auto_policy_testing/red/rds/rds_mariadb.tf index c0446ce1d..856b48397 100644 --- a/auto_policy_testing/red/rds/rds_mariadb.tf +++ b/auto_policy_testing/red/rds/rds_mariadb.tf @@ -1,7 +1,7 @@ resource "aws_db_instance" "mariadb" { identifier = "${module.naming.resource_prefix.rds_instance}-mariadb" engine = "mariadb" - engine_version = "10.6.10" + engine_version = "10.6.17" instance_class = "db.t3.micro" allocated_storage = 20 storage_type = "gp2" diff --git a/auto_policy_testing/red/secrets/data.tf b/auto_policy_testing/red/secrets/data.tf new file mode 100644 index 000000000..f193b8a3f --- /dev/null +++ b/auto_policy_testing/red/secrets/data.tf @@ -0,0 +1,11 @@ +data "aws_iam_policy_document" "this1" { + statement { + actions = [ + "ec2:CreateNetworkInterface", + "ec2:DeleteNetworkInterface", + "ec2:DescribeNetworkInterfaces", + "ec2:DetachNetworkInterface" + ] + resources = ["*"] + } +} diff --git a/auto_policy_testing/red/secrets/iam.tf b/auto_policy_testing/red/secrets/iam.tf new file mode 100644 index 000000000..eceaf0e07 --- /dev/null +++ b/auto_policy_testing/red/secrets/iam.tf @@ -0,0 +1,27 @@ +resource "aws_iam_role" "this" { + name = module.naming.resource_prefix.iam_role + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "lambda.amazonaws.com" + } + }, + ] + }) +} + +resource "aws_iam_role_policy" "this1" { + name = "${module.naming.resource_prefix.iam_policy}-1" + role = aws_iam_role.this.name + policy = data.aws_iam_policy_document.this1.json +} + +resource "aws_iam_role_policy_attachment" "this1" { + role = aws_iam_role.this.name + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" +} \ No newline at end of file diff --git a/auto_policy_testing/red/secrets/lambda.tf b/auto_policy_testing/red/secrets/lambda.tf new file mode 100644 index 000000000..73918a457 --- /dev/null +++ b/auto_policy_testing/red/secrets/lambda.tf @@ -0,0 +1,21 @@ +resource "aws_lambda_function" "this" { + filename = "lambda_function.zip" + function_name = module.naming.resource_prefix.lambda_function + role = aws_iam_role.this.arn + handler = "lambda_function.lambda_handler" + source_code_hash = filebase64sha256("lambda_function.zip") + runtime = "python3.12" + replace_security_groups_on_destroy = true + + depends_on = [ + aws_iam_role_policy.this1, + aws_iam_role_policy_attachment.this1 + ] +} + +resource "aws_lambda_permission" "this" { + function_name = aws_lambda_function.this.function_name + statement_id = "AllowExecutionSecretManager" + action = "lambda:InvokeFunction" + principal = "secretsmanager.amazonaws.com" +} \ No newline at end of file diff --git a/auto_policy_testing/red/secrets/lambda_function.zip b/auto_policy_testing/red/secrets/lambda_function.zip new file mode 100644 index 000000000..48742bfe4 Binary files /dev/null and b/auto_policy_testing/red/secrets/lambda_function.zip differ diff --git a/auto_policy_testing/red/secrets/outputs.tf b/auto_policy_testing/red/secrets/outputs.tf index 6bd12fc44..4fc0f4718 100644 --- a/auto_policy_testing/red/secrets/outputs.tf +++ b/auto_policy_testing/red/secrets/outputs.tf @@ -1,5 +1,6 @@ output "secrets" { value = { - secrets-manager = aws_secretsmanager_secret.this.arn + secrets-manager = aws_secretsmanager_secret.this1.arn, + ecc-aws-219-secrets_manager_successful_rotation_check = aws_secretsmanager_secret.this2.arn } } diff --git a/auto_policy_testing/red/secrets/secrets.tf b/auto_policy_testing/red/secrets/secrets.tf deleted file mode 100644 index f0628e421..000000000 --- a/auto_policy_testing/red/secrets/secrets.tf +++ /dev/null @@ -1,9 +0,0 @@ -resource "random_password" "this" { - length = 12 - special = true - override_special = "!#$%*()-_=+[]{}:?" -} - -resource "aws_secretsmanager_secret" "this" { - name = "${module.naming.resource_prefix.secrets}" -} \ No newline at end of file diff --git a/auto_policy_testing/red/secrets/secrets1.tf b/auto_policy_testing/red/secrets/secrets1.tf new file mode 100644 index 000000000..5f6db80b0 --- /dev/null +++ b/auto_policy_testing/red/secrets/secrets1.tf @@ -0,0 +1,4 @@ +resource "aws_secretsmanager_secret" "this1" { + name = "${module.naming.resource_prefix.secrets}-1" + recovery_window_in_days = 0 +} \ No newline at end of file diff --git a/auto_policy_testing/red/secrets/secrets2.tf b/auto_policy_testing/red/secrets/secrets2.tf new file mode 100644 index 000000000..671fbe156 --- /dev/null +++ b/auto_policy_testing/red/secrets/secrets2.tf @@ -0,0 +1,34 @@ +resource "aws_secretsmanager_secret" "this2" { + name = "${module.naming.resource_prefix.secrets}-2" + recovery_window_in_days = 0 +} + +resource "random_password" "this" { + length = 12 + special = true + override_special = "!#$%*()-_=+[]{}:?" +} + +resource "aws_secretsmanager_secret_version" "this" { + secret_id = aws_secretsmanager_secret.this2.id + secret_string = <