diff --git a/terraform-best-practices/aws/s3/abort-incomplete-uploads/README.md b/terraform-best-practices/aws/s3/abort-incomplete-uploads/README.md new file mode 100644 index 00000000..1cb77561 --- /dev/null +++ b/terraform-best-practices/aws/s3/abort-incomplete-uploads/README.md @@ -0,0 +1,27 @@ +Amazon S3 supports a bucket lifecycle rule that you can use to direct Amazon S3 to stop multipart uploads that aren't completed within a specified number of days after being initiated. When a multipart upload isn't completed within the specified time frame, it becomes eligible for an abort operation. Amazon S3 then stops the multipart upload and deletes the parts associated with the multipart upload. + +You need to make sure that the *lifecycle_configuration* is Enabled and *days_after_initiation* is set to an Integer value. If you don't set an Integer value, NULL value will be considered. + +In order to test this policy, use the following commands: + +1. Initialise Terraform in your working directory + ``` + terraform init + ``` + +2. Create a binary of your terraform plan + ``` + terraform plan -out tfplan.binary + ``` + +3. Convert the executable binary into JSON Payload + ``` + terraform show -json tfplan.binary | jq > payload.json + ``` +4. Test the policy using `kyverno-json` command + ``` + kyverno-json scan --payload payload.json --policy policy.yaml + ``` + Since you've set the `Status` field to `Enabled` in *good-terraform.tf* file and *days_after_initiation* argument inside the *abort_incomplete_multipart_upload* set to an Positive Integer value, the policy will give you Passing checks. If you try to change the value of `Status` to *Disabled* or *days_after_initiation* to *NULL* value, the policy will give you failing checks. + + In case you'd like to test this policy for a failing scneario, try to set the payload to `./aws/disable-s3-acl/test/bad-payload-01.json` and run the `kyverno-json scan` command again. \ No newline at end of file diff --git a/terraform-best-practices/aws/s3/abort-incomplete-uploads/abort-incomplete-uploads.yaml b/terraform-best-practices/aws/s3/abort-incomplete-uploads/abort-incomplete-uploads.yaml new file mode 100644 index 00000000..1f50244c --- /dev/null +++ b/terraform-best-practices/aws/s3/abort-incomplete-uploads/abort-incomplete-uploads.yaml @@ -0,0 +1,35 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: abort-incomplete-uploads + annotations: + policies.kyverno.io/title: enable-s3-versioning + policies.kyverno.io/category: AWS S3 Security Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + Amazon S3 supports a bucket lifecycle rule that you can use to direct Amazon S3 + to stop multipart uploads that aren't completed within a specified number of days + after being initiated. When a multipart upload isn't completed within the specified time + frame, it becomes eligible for an abort operation. Amazon S3 then stops the multipart + upload and deletes the parts associated with the multipart upload. +spec: + rules: + - name: abort-incomplete-uploads + match: + all: + - (planned_values.root_module.resources[?type=='aws_s3_bucket'] | length(@) > `0`): true + assert: + all: + - message: Use the `aws_s3_bucket_lifecycle_configuration` resource to enable lifecycle configuration. + check: + (planned_values.root_module.resources[?type=='aws_s3_bucket_lifecycle_configuration'] | length(@) > `0`): true + - message: S3 Bucket Lifecycle Configuration 'status' needs to be set to 'Enabled' + check: + ~.(planned_values.root_module.resources[?type=='aws_s3_bucket_lifecycle_configuration']): + (values.rule[?status=='Enabled'] | length(@) > `0`): true + - message: Set the 'days_after_initiation' argument value to a Positive Integer value in 'abort_incomplete_multipart_upload' inside the lifecycle configuration block + check: + ~.(planned_values.root_module.resources[?type=='aws_s3_bucket_lifecycle_configuration']): + ~.(values.rule[?status=='Enabled'].abort_incomplete_multipart_upload[]): + (days_after_initiation > `0`): true + diff --git a/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/bad-payload-01.json b/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/bad-payload-01.json new file mode 100644 index 00000000..1dedf966 --- /dev/null +++ b/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/bad-payload-01.json @@ -0,0 +1,281 @@ +{ + "format_version": "1.2", + "terraform_version": "1.6.6", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "test-bucket-demo-18012003", + "force_destroy": false, + "tags": null, + "timeouts": null + }, + "sensitive_values": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + }, + { + "address": "aws_s3_bucket_lifecycle_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_lifecycle_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "expected_bucket_owner": null, + "rule": [ + { + "abort_incomplete_multipart_upload": [ + { + "days_after_initiation": null + } + ], + "expiration": [], + "filter": [], + "id": "rule-1", + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "prefix": null, + "status": "Enabled", + "transition": [] + } + ] + }, + "sensitive_values": { + "rule": [ + { + "abort_incomplete_multipart_upload": [ + {} + ], + "expiration": [], + "filter": [], + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "transition": [] + } + ] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "test-bucket-demo-18012003", + "force_destroy": false, + "tags": null, + "timeouts": null + }, + "after_unknown": { + "acceleration_status": true, + "acl": true, + "arn": true, + "bucket_domain_name": true, + "bucket_prefix": true, + "bucket_regional_domain_name": true, + "cors_rule": true, + "grant": true, + "hosted_zone_id": true, + "id": true, + "lifecycle_rule": true, + "logging": true, + "object_lock_configuration": true, + "object_lock_enabled": true, + "policy": true, + "region": true, + "replication_configuration": true, + "request_payer": true, + "server_side_encryption_configuration": true, + "tags_all": true, + "versioning": true, + "website": true, + "website_domain": true, + "website_endpoint": true + }, + "before_sensitive": false, + "after_sensitive": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + } + }, + { + "address": "aws_s3_bucket_lifecycle_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_lifecycle_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "expected_bucket_owner": null, + "rule": [ + { + "abort_incomplete_multipart_upload": [ + { + "days_after_initiation": null + } + ], + "expiration": [], + "filter": [], + "id": "rule-1", + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "prefix": null, + "status": "Enabled", + "transition": [] + } + ] + }, + "after_unknown": { + "bucket": true, + "id": true, + "rule": [ + { + "abort_incomplete_multipart_upload": [ + {} + ], + "expiration": [], + "filter": [], + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "transition": [] + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "rule": [ + { + "abort_incomplete_multipart_upload": [ + {} + ], + "expiration": [], + "filter": [], + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "transition": [] + } + ] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + "access_key": { + "constant_value": "ASIA4JFRUINQBWNEIM6Y" + }, + "region": { + "constant_value": "us-west-2" + }, + "secret_key": { + "constant_value": "Ws1gpfLcATSsRnk/o3tNbieqaWZcLGhXOXzs+UyH" + }, + "token": { + "constant_value": "IQoJb3JpZ2luX2VjEGQaCXVzLWVhc3QtMiJHMEUCIQC5s3XZqe0G6p4C8sqremQwG8Qpn0A7j1V/XhmRRnvDHgIgHspQ9p51MAHsS4IIeg+Iat4DcWR50l9VOgMaD1dnVrMqjgMILRADGgw4NDQzMzM1OTc1MzYiDDJ8P2dn2rVnqFDv7SrrAvGQ5l2a64fPDdxN56wII6zF9YkPHMkYIHgq/11WnNQpAhE1c0EbmZdwObJA9/rdHrSQsmhSuUBAiFU9Ys5Ro/I6fNt7zqotQ/trvgjMDwG4+q3InowH1zuE+1fa4ewQGSG9jrJvlT7X7hWa65lw8Qr5XGSddGeKtby/kDckqkVOJV+wUb2s3cuLW9j7x7hsE/xJRVUA70z0i5rhmXsiR9JP7vFMhmZDu9yH46375tGE7Ih7Mwtd8DejPwlpeMBUMGlcc+xAahcUxP8n+fjwAuZrLO+v0f96uWEHo87foB/SnpGwbitCWGt8UcDtmN0939P9MiMHLitorCtrpQyeUk1DPTdzwNww0nRKEjwtTw9MqRkTI0PG/5SWScphhxjxb/268qJIjS3FE+xG4hulr+gj3KId0sAbPRlUUv12SIbjgH6esD//S5JmxzBMTPQ+8A38fXSiZQ1ZQL1BaktLGbf0x1o+TafmeQSenjCm5eitBjqmAZlxiRWfntKUiH64SawiWbyDJ7kJMfoq6pT59EtNIOa/8rHfx4+aOFAqYCAClJe6Hw8d4RIpfewlaqiJL7Gw5uXc4IcepdOi2KMZ0f32k5HIMa8uKZBWpaUsH8tyWlKKjzRAMM/LsoGSovknkmmwLLkAJ+0Y6YySyQQqv1SpHQuyv7ySbk2qS7+kPplkK8+LQiB21NpHZfGirS6bnRrwLpHZ3TAzNF0=" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "test-bucket-demo-18012003" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_lifecycle_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_lifecycle_configuration", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "rule": [ + { + "abort_incomplete_multipart_upload": [ + {} + ], + "id": { + "constant_value": "rule-1" + }, + "status": { + "constant_value": "Enabled" + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-31T12:04:06Z", + "errored": false +} diff --git a/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/bad-payload-02.json b/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/bad-payload-02.json new file mode 100644 index 00000000..2c06b32a --- /dev/null +++ b/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/bad-payload-02.json @@ -0,0 +1,264 @@ +{ + "format_version": "1.2", + "terraform_version": "1.6.6", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "test-bucket-demo-18012003", + "force_destroy": false, + "tags": null, + "timeouts": null + }, + "sensitive_values": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + }, + { + "address": "aws_s3_bucket_lifecycle_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_lifecycle_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "expected_bucket_owner": null, + "rule": [ + { + "abort_incomplete_multipart_upload": [], + "expiration": [], + "filter": [], + "id": "rule-1", + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "prefix": null, + "status": "Enabled", + "transition": [] + } + ] + }, + "sensitive_values": { + "rule": [ + { + "abort_incomplete_multipart_upload": [], + "expiration": [], + "filter": [], + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "transition": [] + } + ] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "test-bucket-demo-18012003", + "force_destroy": false, + "tags": null, + "timeouts": null + }, + "after_unknown": { + "acceleration_status": true, + "acl": true, + "arn": true, + "bucket_domain_name": true, + "bucket_prefix": true, + "bucket_regional_domain_name": true, + "cors_rule": true, + "grant": true, + "hosted_zone_id": true, + "id": true, + "lifecycle_rule": true, + "logging": true, + "object_lock_configuration": true, + "object_lock_enabled": true, + "policy": true, + "region": true, + "replication_configuration": true, + "request_payer": true, + "server_side_encryption_configuration": true, + "tags_all": true, + "versioning": true, + "website": true, + "website_domain": true, + "website_endpoint": true + }, + "before_sensitive": false, + "after_sensitive": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + } + }, + { + "address": "aws_s3_bucket_lifecycle_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_lifecycle_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "expected_bucket_owner": null, + "rule": [ + { + "abort_incomplete_multipart_upload": [], + "expiration": [], + "filter": [], + "id": "rule-1", + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "prefix": null, + "status": "Enabled", + "transition": [] + } + ] + }, + "after_unknown": { + "bucket": true, + "id": true, + "rule": [ + { + "abort_incomplete_multipart_upload": [], + "expiration": [], + "filter": [], + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "transition": [] + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "rule": [ + { + "abort_incomplete_multipart_upload": [], + "expiration": [], + "filter": [], + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "transition": [] + } + ] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + "access_key": { + "constant_value": "ASIA4JFRUINQBWNEIM6Y" + }, + "region": { + "constant_value": "us-west-2" + }, + "secret_key": { + "constant_value": "Ws1gpfLcATSsRnk/o3tNbieqaWZcLGhXOXzs+UyH" + }, + "token": { + "constant_value": "IQoJb3JpZ2luX2VjEGQaCXVzLWVhc3QtMiJHMEUCIQC5s3XZqe0G6p4C8sqremQwG8Qpn0A7j1V/XhmRRnvDHgIgHspQ9p51MAHsS4IIeg+Iat4DcWR50l9VOgMaD1dnVrMqjgMILRADGgw4NDQzMzM1OTc1MzYiDDJ8P2dn2rVnqFDv7SrrAvGQ5l2a64fPDdxN56wII6zF9YkPHMkYIHgq/11WnNQpAhE1c0EbmZdwObJA9/rdHrSQsmhSuUBAiFU9Ys5Ro/I6fNt7zqotQ/trvgjMDwG4+q3InowH1zuE+1fa4ewQGSG9jrJvlT7X7hWa65lw8Qr5XGSddGeKtby/kDckqkVOJV+wUb2s3cuLW9j7x7hsE/xJRVUA70z0i5rhmXsiR9JP7vFMhmZDu9yH46375tGE7Ih7Mwtd8DejPwlpeMBUMGlcc+xAahcUxP8n+fjwAuZrLO+v0f96uWEHo87foB/SnpGwbitCWGt8UcDtmN0939P9MiMHLitorCtrpQyeUk1DPTdzwNww0nRKEjwtTw9MqRkTI0PG/5SWScphhxjxb/268qJIjS3FE+xG4hulr+gj3KId0sAbPRlUUv12SIbjgH6esD//S5JmxzBMTPQ+8A38fXSiZQ1ZQL1BaktLGbf0x1o+TafmeQSenjCm5eitBjqmAZlxiRWfntKUiH64SawiWbyDJ7kJMfoq6pT59EtNIOa/8rHfx4+aOFAqYCAClJe6Hw8d4RIpfewlaqiJL7Gw5uXc4IcepdOi2KMZ0f32k5HIMa8uKZBWpaUsH8tyWlKKjzRAMM/LsoGSovknkmmwLLkAJ+0Y6YySyQQqv1SpHQuyv7ySbk2qS7+kPplkK8+LQiB21NpHZfGirS6bnRrwLpHZ3TAzNF0=" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "test-bucket-demo-18012003" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_lifecycle_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_lifecycle_configuration", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "rule": [ + { + "id": { + "constant_value": "rule-1" + }, + "status": { + "constant_value": "Enabled" + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-31T12:12:52Z", + "errored": false +} diff --git a/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/bad-terraform-01.tf b/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/bad-terraform-01.tf new file mode 100644 index 00000000..b83959b0 --- /dev/null +++ b/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/bad-terraform-01.tf @@ -0,0 +1,30 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_s3_bucket" "example" { + bucket = "test-bucket-demo-18012003" +} + +resource "aws_s3_bucket_lifecycle_configuration" "example" { + bucket = aws_s3_bucket.example.id + + rule { + id = "rule-1" + status = "Enabled" + abort_incomplete_multipart_upload { + + } + } +} diff --git a/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/bad-terraform-02.tf b/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/bad-terraform-02.tf new file mode 100644 index 00000000..d549a0d1 --- /dev/null +++ b/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/bad-terraform-02.tf @@ -0,0 +1,27 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_s3_bucket" "example" { + bucket = "test-bucket-demo-18012003" +} + +resource "aws_s3_bucket_lifecycle_configuration" "example" { + bucket = aws_s3_bucket.example.id + + rule { + id = "rule-1" + status = "Enabled" + } +} diff --git a/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/good-payload.json b/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/good-payload.json new file mode 100644 index 00000000..b8f95945 --- /dev/null +++ b/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/good-payload.json @@ -0,0 +1,285 @@ +{ + "format_version": "1.2", + "terraform_version": "1.6.6", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "test-bucket-demo-18012003", + "force_destroy": false, + "tags": null, + "timeouts": null + }, + "sensitive_values": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + }, + { + "address": "aws_s3_bucket_lifecycle_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_lifecycle_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "expected_bucket_owner": null, + "rule": [ + { + "abort_incomplete_multipart_upload": [ + { + "days_after_initiation": 12 + } + ], + "expiration": [], + "filter": [], + "id": "rule-1", + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "prefix": null, + "status": "Enabled", + "transition": [] + } + ] + }, + "sensitive_values": { + "rule": [ + { + "abort_incomplete_multipart_upload": [ + {} + ], + "expiration": [], + "filter": [], + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "transition": [] + } + ] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "test-bucket-demo-18012003", + "force_destroy": false, + "tags": null, + "timeouts": null + }, + "after_unknown": { + "acceleration_status": true, + "acl": true, + "arn": true, + "bucket_domain_name": true, + "bucket_prefix": true, + "bucket_regional_domain_name": true, + "cors_rule": true, + "grant": true, + "hosted_zone_id": true, + "id": true, + "lifecycle_rule": true, + "logging": true, + "object_lock_configuration": true, + "object_lock_enabled": true, + "policy": true, + "region": true, + "replication_configuration": true, + "request_payer": true, + "server_side_encryption_configuration": true, + "tags_all": true, + "versioning": true, + "website": true, + "website_domain": true, + "website_endpoint": true + }, + "before_sensitive": false, + "after_sensitive": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + } + }, + { + "address": "aws_s3_bucket_lifecycle_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_lifecycle_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "expected_bucket_owner": null, + "rule": [ + { + "abort_incomplete_multipart_upload": [ + { + "days_after_initiation": 12 + } + ], + "expiration": [], + "filter": [], + "id": "rule-1", + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "prefix": null, + "status": "Enabled", + "transition": [] + } + ] + }, + "after_unknown": { + "bucket": true, + "id": true, + "rule": [ + { + "abort_incomplete_multipart_upload": [ + {} + ], + "expiration": [], + "filter": [], + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "transition": [] + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "rule": [ + { + "abort_incomplete_multipart_upload": [ + {} + ], + "expiration": [], + "filter": [], + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "transition": [] + } + ] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + "access_key": { + "constant_value": "ASIA4JFRUINQBWNEIM6Y" + }, + "region": { + "constant_value": "us-west-2" + }, + "secret_key": { + "constant_value": "Ws1gpfLcATSsRnk/o3tNbieqaWZcLGhXOXzs+UyH" + }, + "token": { + "constant_value": "IQoJb3JpZ2luX2VjEGQaCXVzLWVhc3QtMiJHMEUCIQC5s3XZqe0G6p4C8sqremQwG8Qpn0A7j1V/XhmRRnvDHgIgHspQ9p51MAHsS4IIeg+Iat4DcWR50l9VOgMaD1dnVrMqjgMILRADGgw4NDQzMzM1OTc1MzYiDDJ8P2dn2rVnqFDv7SrrAvGQ5l2a64fPDdxN56wII6zF9YkPHMkYIHgq/11WnNQpAhE1c0EbmZdwObJA9/rdHrSQsmhSuUBAiFU9Ys5Ro/I6fNt7zqotQ/trvgjMDwG4+q3InowH1zuE+1fa4ewQGSG9jrJvlT7X7hWa65lw8Qr5XGSddGeKtby/kDckqkVOJV+wUb2s3cuLW9j7x7hsE/xJRVUA70z0i5rhmXsiR9JP7vFMhmZDu9yH46375tGE7Ih7Mwtd8DejPwlpeMBUMGlcc+xAahcUxP8n+fjwAuZrLO+v0f96uWEHo87foB/SnpGwbitCWGt8UcDtmN0939P9MiMHLitorCtrpQyeUk1DPTdzwNww0nRKEjwtTw9MqRkTI0PG/5SWScphhxjxb/268qJIjS3FE+xG4hulr+gj3KId0sAbPRlUUv12SIbjgH6esD//S5JmxzBMTPQ+8A38fXSiZQ1ZQL1BaktLGbf0x1o+TafmeQSenjCm5eitBjqmAZlxiRWfntKUiH64SawiWbyDJ7kJMfoq6pT59EtNIOa/8rHfx4+aOFAqYCAClJe6Hw8d4RIpfewlaqiJL7Gw5uXc4IcepdOi2KMZ0f32k5HIMa8uKZBWpaUsH8tyWlKKjzRAMM/LsoGSovknkmmwLLkAJ+0Y6YySyQQqv1SpHQuyv7ySbk2qS7+kPplkK8+LQiB21NpHZfGirS6bnRrwLpHZ3TAzNF0=" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "test-bucket-demo-18012003" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_lifecycle_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_lifecycle_configuration", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "rule": [ + { + "abort_incomplete_multipart_upload": [ + { + "days_after_initiation": { + "constant_value": 12 + } + } + ], + "id": { + "constant_value": "rule-1" + }, + "status": { + "constant_value": "Enabled" + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-31T11:57:03Z", + "errored": false +} diff --git a/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/good-terraform.tf b/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/good-terraform.tf new file mode 100644 index 00000000..a3554824 --- /dev/null +++ b/terraform-best-practices/aws/s3/abort-incomplete-uploads/test/good-terraform.tf @@ -0,0 +1,33 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" + access_key = "ASIA4JFRUINQBWNEIM6Y" + secret_key = "Ws1gpfLcATSsRnk/o3tNbieqaWZcLGhXOXzs+UyH" + token = "IQoJb3JpZ2luX2VjEGQaCXVzLWVhc3QtMiJHMEUCIQC5s3XZqe0G6p4C8sqremQwG8Qpn0A7j1V/XhmRRnvDHgIgHspQ9p51MAHsS4IIeg+Iat4DcWR50l9VOgMaD1dnVrMqjgMILRADGgw4NDQzMzM1OTc1MzYiDDJ8P2dn2rVnqFDv7SrrAvGQ5l2a64fPDdxN56wII6zF9YkPHMkYIHgq/11WnNQpAhE1c0EbmZdwObJA9/rdHrSQsmhSuUBAiFU9Ys5Ro/I6fNt7zqotQ/trvgjMDwG4+q3InowH1zuE+1fa4ewQGSG9jrJvlT7X7hWa65lw8Qr5XGSddGeKtby/kDckqkVOJV+wUb2s3cuLW9j7x7hsE/xJRVUA70z0i5rhmXsiR9JP7vFMhmZDu9yH46375tGE7Ih7Mwtd8DejPwlpeMBUMGlcc+xAahcUxP8n+fjwAuZrLO+v0f96uWEHo87foB/SnpGwbitCWGt8UcDtmN0939P9MiMHLitorCtrpQyeUk1DPTdzwNww0nRKEjwtTw9MqRkTI0PG/5SWScphhxjxb/268qJIjS3FE+xG4hulr+gj3KId0sAbPRlUUv12SIbjgH6esD//S5JmxzBMTPQ+8A38fXSiZQ1ZQL1BaktLGbf0x1o+TafmeQSenjCm5eitBjqmAZlxiRWfntKUiH64SawiWbyDJ7kJMfoq6pT59EtNIOa/8rHfx4+aOFAqYCAClJe6Hw8d4RIpfewlaqiJL7Gw5uXc4IcepdOi2KMZ0f32k5HIMa8uKZBWpaUsH8tyWlKKjzRAMM/LsoGSovknkmmwLLkAJ+0Y6YySyQQqv1SpHQuyv7ySbk2qS7+kPplkK8+LQiB21NpHZfGirS6bnRrwLpHZ3TAzNF0=" +} + +resource "aws_s3_bucket" "example" { + bucket = "test-bucket-demo-18012003" +} + +resource "aws_s3_bucket_lifecycle_configuration" "example" { + bucket = aws_s3_bucket.example.id + + rule { + id = "rule-1" + status = "Enabled" + abort_incomplete_multipart_upload { + days_after_initiation = 12 + } + } +} diff --git a/terraform-best-practices/aws/s3/enable-aws-cloudtrail/README.md b/terraform-best-practices/aws/s3/enable-aws-cloudtrail/README.md new file mode 100644 index 00000000..f300ce65 --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-aws-cloudtrail/README.md @@ -0,0 +1,29 @@ +You can use CloudTrail data events to get information about bucket and object-level requests in Amazon S3. To enable CloudTrail data events for all of your buckets or for a list of specific buckets, you must create a trail manually in CloudTrail. + +In your Terraform resource *aws_cloudtrail*, you need to set the value of *enable_logging* to True. This is an optional field and by the default the value is set to True. You can read more about this [here](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudtrail). + +**Test this policy:** + +In order to test this policy, use the following commands: + +1. Initialise Terraform in your working directory + ``` + terraform init + ``` + +2. Create a binary of your terraform plan + ``` + terraform plan -out tfplan.binary + ``` + +3. Convert the executable binary into JSON Payload + ``` + terraform show -json tfplan.binary | jq > payload.json + ``` +4. Test the policy using `kyverno-json` command + ``` + kyverno-json scan --payload good-payload.json --policy enable-aws-cloudtrail.yaml + ``` + Since you've set the `enable_logging` field to `True` in *good-terraform.tf* file, the policy will give you Passing checks. If you try to change the value of `enable_logging` to `False` the policy will give you failing checks on a the new payload. + +In case you'd like to test this policy for a failing scneario, try to set the payload to `./aws/enable-aws-coudtrain/test/bad-payload.json` and run the `kyverno-json scan` command again. \ No newline at end of file diff --git a/terraform-best-practices/aws/s3/enable-aws-cloudtrail/enable-aws-cloudtrail.yaml b/terraform-best-practices/aws/s3/enable-aws-cloudtrail/enable-aws-cloudtrail.yaml new file mode 100644 index 00000000..b272e271 --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-aws-cloudtrail/enable-aws-cloudtrail.yaml @@ -0,0 +1,27 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: enable-aws-cloudtrail + annotations: + policies.kyverno.io/title: enable-aws-cloudtrail + policies.kyverno.io/category: AWS S3 Security Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + CloudTrail stores Amazon S3 data event logs in an S3 bucket of your choosing. + Consider using a bucket in a separate AWS account to better organize events from + multiple buckets that you might own into a central place for easier querying and + analysis. AWS Organizations helps you create an AWS account that is linked to + the account that owns the bucket that you're monitoring. +spec: + rules: + - name: check-aws-cloudtrail-logging + match: + all: + - (planned_values.root_module.resources[?type=='aws_s3_bucket'] | length(@) > `0`): true + assert: + all: + - message: Set the enable_logging argument in aws_cloudtrail resource to true + check: + ~.(planned_values.root_module.resources[?type=='aws_cloudtrail']): + (values.enable_logging): true + \ No newline at end of file diff --git a/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/bad-payload.json b/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/bad-payload.json new file mode 100644 index 00000000..b68b446a --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/bad-payload.json @@ -0,0 +1,892 @@ +{ + "format_version": "1.2", + "terraform_version": "1.7.1", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_cloudtrail.example", + "mode": "managed", + "type": "aws_cloudtrail", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "advanced_event_selector": [], + "cloud_watch_logs_group_arn": null, + "cloud_watch_logs_role_arn": null, + "enable_log_file_validation": false, + "enable_logging": false, + "event_selector": [], + "include_global_service_events": false, + "insight_selector": [], + "is_multi_region_trail": false, + "is_organization_trail": false, + "kms_key_id": null, + "name": "example", + "s3_key_prefix": "prefix", + "sns_topic_name": null, + "tags": null + }, + "sensitive_values": { + "advanced_event_selector": [], + "event_selector": [], + "insight_selector": [], + "tags_all": {} + } + }, + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "tf-test-trail", + "force_destroy": true, + "tags": null, + "timeouts": null + }, + "sensitive_values": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + }, + { + "address": "aws_s3_bucket_policy.example", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "sensitive_values": {} + }, + { + "address": "data.aws_iam_policy_document.example", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "override_json": null, + "override_policy_documents": null, + "policy_id": null, + "source_json": null, + "source_policy_documents": null, + "statement": [ + { + "actions": [ + "s3:GetBucketAcl" + ], + "condition": [ + { + "test": "StringEquals", + "values": [ + "arn:aws:cloudtrail:us-west-2:844333597536:trail/example" + ], + "variable": "aws:SourceArn" + } + ], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [ + { + "identifiers": [ + "cloudtrail.amazonaws.com" + ], + "type": "Service" + } + ], + "resources": [ + null + ], + "sid": "AWSCloudTrailAclCheck" + }, + { + "actions": [ + "s3:PutObject" + ], + "condition": [ + { + "test": "StringEquals", + "values": [ + "arn:aws:cloudtrail:us-west-2:844333597536:trail/example" + ], + "variable": "aws:SourceArn" + }, + { + "test": "StringEquals", + "values": [ + "bucket-owner-full-control" + ], + "variable": "s3:x-amz-acl" + } + ], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [ + { + "identifiers": [ + "cloudtrail.amazonaws.com" + ], + "type": "Service" + } + ], + "resources": [ + null + ], + "sid": "AWSCloudTrailWrite" + } + ], + "version": null + }, + "sensitive_values": { + "statement": [ + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + false + ] + }, + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + }, + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + false + ] + } + ] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "data.aws_iam_policy_document.example", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "read" + ], + "before": null, + "after": { + "override_json": null, + "override_policy_documents": null, + "policy_id": null, + "source_json": null, + "source_policy_documents": null, + "statement": [ + { + "actions": [ + "s3:GetBucketAcl" + ], + "condition": [ + { + "test": "StringEquals", + "values": [ + "arn:aws:cloudtrail:us-west-2:844333597536:trail/example" + ], + "variable": "aws:SourceArn" + } + ], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [ + { + "identifiers": [ + "cloudtrail.amazonaws.com" + ], + "type": "Service" + } + ], + "resources": [ + null + ], + "sid": "AWSCloudTrailAclCheck" + }, + { + "actions": [ + "s3:PutObject" + ], + "condition": [ + { + "test": "StringEquals", + "values": [ + "arn:aws:cloudtrail:us-west-2:844333597536:trail/example" + ], + "variable": "aws:SourceArn" + }, + { + "test": "StringEquals", + "values": [ + "bucket-owner-full-control" + ], + "variable": "s3:x-amz-acl" + } + ], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [ + { + "identifiers": [ + "cloudtrail.amazonaws.com" + ], + "type": "Service" + } + ], + "resources": [ + null + ], + "sid": "AWSCloudTrailWrite" + } + ], + "version": null + }, + "after_unknown": { + "id": true, + "json": true, + "statement": [ + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + true + ] + }, + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + }, + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + true + ] + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "statement": [ + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + false + ] + }, + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + }, + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + false + ] + } + ] + } + }, + "action_reason": "read_because_config_unknown" + }, + { + "address": "aws_cloudtrail.example", + "mode": "managed", + "type": "aws_cloudtrail", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "advanced_event_selector": [], + "cloud_watch_logs_group_arn": null, + "cloud_watch_logs_role_arn": null, + "enable_log_file_validation": false, + "enable_logging": false, + "event_selector": [], + "include_global_service_events": false, + "insight_selector": [], + "is_multi_region_trail": false, + "is_organization_trail": false, + "kms_key_id": null, + "name": "example", + "s3_key_prefix": "prefix", + "sns_topic_name": null, + "tags": null + }, + "after_unknown": { + "advanced_event_selector": [], + "arn": true, + "event_selector": [], + "home_region": true, + "id": true, + "insight_selector": [], + "s3_bucket_name": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "advanced_event_selector": [], + "event_selector": [], + "insight_selector": [], + "tags_all": {} + } + } + }, + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "tf-test-trail", + "force_destroy": true, + "tags": null, + "timeouts": null + }, + "after_unknown": { + "acceleration_status": true, + "acl": true, + "arn": true, + "bucket_domain_name": true, + "bucket_prefix": true, + "bucket_regional_domain_name": true, + "cors_rule": true, + "grant": true, + "hosted_zone_id": true, + "id": true, + "lifecycle_rule": true, + "logging": true, + "object_lock_configuration": true, + "object_lock_enabled": true, + "policy": true, + "region": true, + "replication_configuration": true, + "request_payer": true, + "server_side_encryption_configuration": true, + "tags_all": true, + "versioning": true, + "website": true, + "website_domain": true, + "website_endpoint": true + }, + "before_sensitive": false, + "after_sensitive": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + } + }, + { + "address": "aws_s3_bucket_policy.example", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": {}, + "after_unknown": { + "bucket": true, + "id": true, + "policy": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "prior_state": { + "format_version": "1.0", + "terraform_version": "1.7.1", + "values": { + "root_module": { + "resources": [ + { + "address": "data.aws_caller_identity.current", + "mode": "data", + "type": "aws_caller_identity", + "name": "current", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "account_id": "844333597536", + "arn": "arn:aws:sts::844333597536:assumed-role/AWSReservedSSO_PowerUserAccess_b743e36821508738/nitish.kumar@nirmata.com", + "id": "844333597536", + "user_id": "AROA4JFRUINQC7VCOQ7UD:nitish.kumar@nirmata.com" + }, + "sensitive_values": {} + }, + { + "address": "data.aws_partition.current", + "mode": "data", + "type": "aws_partition", + "name": "current", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "dns_suffix": "amazonaws.com", + "id": "aws", + "partition": "aws", + "reverse_dns_prefix": "com.amazonaws" + }, + "sensitive_values": {} + }, + { + "address": "data.aws_region.current", + "mode": "data", + "type": "aws_region", + "name": "current", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": "US West (Oregon)", + "endpoint": "ec2.us-west-2.amazonaws.com", + "id": "us-west-2", + "name": "us-west-2" + }, + "sensitive_values": {} + } + ] + } + } + }, + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + "access_key": { + "constant_value": "ASIA4JFRUINQGRB5TXNP" + }, + "region": { + "constant_value": "us-west-2" + }, + "secret_key": { + "constant_value": "/Xaejacg3Snm1C7A1DwNBE7r8YxOMDkrkX4x/Cdl" + }, + "token": { + "constant_value": "IQoJb3JpZ2luX2VjEHUaCXVzLWVhc3QtMiJHMEUCIQCltr459nPRo9ZE+g4ceKFn860zygLhpf1rOp2ItfhilQIgBkIvCtKX6aVZulngkH17Lw0jfdXZ7y/ghoQjlqtcgzIqjgMIPhADGgw4NDQzMzM1OTc1MzYiDFy0uJyWkyb+LXGmjirrAsSqyB5Hz9TAiTaQRk6VG2QB0rnKVz9xOYnVeZF/lry4TujtUrP9VTbIqk9btRBd7REt1l7UrQCjZDe6JLrXwKsEFv1+Iky5W+ZAgAYo+h6OgIEE8qnvio4eezsiXi36IRXoDVrpwidggFdzaya1haLYdmypu++LgVAs8KJR0gXKkS9QLSy0LVTINtOOPjqHSZKEdDxDkOCtJL9if1C6QtrIdC6L7ejXPgpnFmZZL5lczbhZhs/HHeVqdebKfTuAng7rKHKoooHBhX9tb2g+HC7uNaI9uicJviGtXfq5AmqRLZLmFGYPKnmxMG6t0OjxQpg//IT8UJ6ggYnrOKikQmm33oEItxUtaXtVe9E3PpzGFv7Hdbe2YR0XW4n1b6RXjMfUxUpwVgp92ylIU7Ysr1I4uF5kDZzI6s9CIw1/tD0PSa+AhM2bGUBi76dTuToAvkkX1B9ct+kxjkcu9uEgz3i8cBK/ZIhNWR6/mTCKyuytBjqmAZDdcZqAxL91vkWiy8KRl5jovTgFBW7KVvheW2+Lcbe8ngV9reoGqB6ieKfNtQp00Nvr9sNHnIIPHkdhgYptkjJGDNWkm9EbLkZKN3Baj8sdHsyX7AuHb8COBYy60T3vRqgolubbbwHiS2tF6PqdH8/7xsMm1XSUIxS9w94WVfpq1hDVq8c5vmibKiQxdp2X3TGajbQFApei8SsdkIjTzQRbNLq3CuA=" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_cloudtrail.example", + "mode": "managed", + "type": "aws_cloudtrail", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "enable_logging": { + "constant_value": false + }, + "include_global_service_events": { + "constant_value": false + }, + "name": { + "constant_value": "example" + }, + "s3_bucket_name": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "s3_key_prefix": { + "constant_value": "prefix" + } + }, + "schema_version": 0, + "depends_on": [ + "aws_s3_bucket_policy.example" + ] + }, + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "tf-test-trail" + }, + "force_destroy": { + "constant_value": true + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_policy.example", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "policy": { + "references": [ + "data.aws_iam_policy_document.example.json", + "data.aws_iam_policy_document.example" + ] + } + }, + "schema_version": 0 + }, + { + "address": "data.aws_caller_identity.current", + "mode": "data", + "type": "aws_caller_identity", + "name": "current", + "provider_config_key": "aws", + "schema_version": 0 + }, + { + "address": "data.aws_iam_policy_document.example", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "s3:GetBucketAcl" + ] + }, + "condition": [ + { + "test": { + "constant_value": "StringEquals" + }, + "values": { + "references": [ + "data.aws_partition.current.partition", + "data.aws_partition.current", + "data.aws_region.current.name", + "data.aws_region.current", + "data.aws_caller_identity.current.account_id", + "data.aws_caller_identity.current" + ] + }, + "variable": { + "constant_value": "aws:SourceArn" + } + } + ], + "effect": { + "constant_value": "Allow" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "cloudtrail.amazonaws.com" + ] + }, + "type": { + "constant_value": "Service" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.example.arn", + "aws_s3_bucket.example" + ] + }, + "sid": { + "constant_value": "AWSCloudTrailAclCheck" + } + }, + { + "actions": { + "constant_value": [ + "s3:PutObject" + ] + }, + "condition": [ + { + "test": { + "constant_value": "StringEquals" + }, + "values": { + "constant_value": [ + "bucket-owner-full-control" + ] + }, + "variable": { + "constant_value": "s3:x-amz-acl" + } + }, + { + "test": { + "constant_value": "StringEquals" + }, + "values": { + "references": [ + "data.aws_partition.current.partition", + "data.aws_partition.current", + "data.aws_region.current.name", + "data.aws_region.current", + "data.aws_caller_identity.current.account_id", + "data.aws_caller_identity.current" + ] + }, + "variable": { + "constant_value": "aws:SourceArn" + } + } + ], + "effect": { + "constant_value": "Allow" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "cloudtrail.amazonaws.com" + ] + }, + "type": { + "constant_value": "Service" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.example.arn", + "aws_s3_bucket.example", + "data.aws_caller_identity.current.account_id", + "data.aws_caller_identity.current" + ] + }, + "sid": { + "constant_value": "AWSCloudTrailWrite" + } + } + ] + }, + "schema_version": 0 + }, + { + "address": "data.aws_partition.current", + "mode": "data", + "type": "aws_partition", + "name": "current", + "provider_config_key": "aws", + "schema_version": 0 + }, + { + "address": "data.aws_region.current", + "mode": "data", + "type": "aws_region", + "name": "current", + "provider_config_key": "aws", + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "data.aws_caller_identity.current", + "attribute": [ + "account_id" + ] + }, + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + }, + { + "resource": "data.aws_iam_policy_document.example", + "attribute": [ + "json" + ] + }, + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "arn" + ] + }, + { + "resource": "data.aws_partition.current", + "attribute": [ + "partition" + ] + }, + { + "resource": "data.aws_region.current", + "attribute": [ + "name" + ] + } + ], + "timestamp": "2024-02-01T05:08:25Z", + "errored": false +} diff --git a/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/bad-terraform.tf b/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/bad-terraform.tf new file mode 100644 index 00000000..c27bb760 --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/bad-terraform.tf @@ -0,0 +1,84 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" + } + +resource "aws_cloudtrail" "example" { + depends_on = [aws_s3_bucket_policy.example] + + name = "example" + s3_bucket_name = aws_s3_bucket.example.id + s3_key_prefix = "prefix" + include_global_service_events = false + enable_logging = false # optional field +} + +resource "aws_s3_bucket" "example" { + bucket = "tf-test-trail" + force_destroy = true +} + +data "aws_iam_policy_document" "example" { + statement { + sid = "AWSCloudTrailAclCheck" + effect = "Allow" + + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + + actions = ["s3:GetBucketAcl"] + resources = [aws_s3_bucket.example.arn] + condition { + test = "StringEquals" + variable = "aws:SourceArn" + values = ["arn:${data.aws_partition.current.partition}:cloudtrail:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:trail/example"] + } + } + + statement { + sid = "AWSCloudTrailWrite" + effect = "Allow" + + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + + actions = ["s3:PutObject"] + resources = ["${aws_s3_bucket.example.arn}/prefix/AWSLogs/${data.aws_caller_identity.current.account_id}/*"] + + condition { + test = "StringEquals" + variable = "s3:x-amz-acl" + values = ["bucket-owner-full-control"] + } + condition { + test = "StringEquals" + variable = "aws:SourceArn" + values = ["arn:${data.aws_partition.current.partition}:cloudtrail:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:trail/example"] + } + } +} + +resource "aws_s3_bucket_policy" "example" { + bucket = aws_s3_bucket.example.id + policy = data.aws_iam_policy_document.example.json +} + +data "aws_caller_identity" "current" {} + +data "aws_partition" "current" {} + +data "aws_region" "current" {} \ No newline at end of file diff --git a/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/good-payload.json b/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/good-payload.json new file mode 100644 index 00000000..10a4c6ba --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/good-payload.json @@ -0,0 +1,892 @@ +{ + "format_version": "1.2", + "terraform_version": "1.7.1", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_cloudtrail.example", + "mode": "managed", + "type": "aws_cloudtrail", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "advanced_event_selector": [], + "cloud_watch_logs_group_arn": null, + "cloud_watch_logs_role_arn": null, + "enable_log_file_validation": false, + "enable_logging": true, + "event_selector": [], + "include_global_service_events": false, + "insight_selector": [], + "is_multi_region_trail": false, + "is_organization_trail": false, + "kms_key_id": null, + "name": "example", + "s3_key_prefix": "prefix", + "sns_topic_name": null, + "tags": null + }, + "sensitive_values": { + "advanced_event_selector": [], + "event_selector": [], + "insight_selector": [], + "tags_all": {} + } + }, + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "tf-test-trail", + "force_destroy": true, + "tags": null, + "timeouts": null + }, + "sensitive_values": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + }, + { + "address": "aws_s3_bucket_policy.example", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "sensitive_values": {} + }, + { + "address": "data.aws_iam_policy_document.example", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "override_json": null, + "override_policy_documents": null, + "policy_id": null, + "source_json": null, + "source_policy_documents": null, + "statement": [ + { + "actions": [ + "s3:GetBucketAcl" + ], + "condition": [ + { + "test": "StringEquals", + "values": [ + "arn:aws:cloudtrail:us-west-2:844333597536:trail/example" + ], + "variable": "aws:SourceArn" + } + ], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [ + { + "identifiers": [ + "cloudtrail.amazonaws.com" + ], + "type": "Service" + } + ], + "resources": [ + null + ], + "sid": "AWSCloudTrailAclCheck" + }, + { + "actions": [ + "s3:PutObject" + ], + "condition": [ + { + "test": "StringEquals", + "values": [ + "arn:aws:cloudtrail:us-west-2:844333597536:trail/example" + ], + "variable": "aws:SourceArn" + }, + { + "test": "StringEquals", + "values": [ + "bucket-owner-full-control" + ], + "variable": "s3:x-amz-acl" + } + ], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [ + { + "identifiers": [ + "cloudtrail.amazonaws.com" + ], + "type": "Service" + } + ], + "resources": [ + null + ], + "sid": "AWSCloudTrailWrite" + } + ], + "version": null + }, + "sensitive_values": { + "statement": [ + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + false + ] + }, + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + }, + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + false + ] + } + ] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "data.aws_iam_policy_document.example", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "read" + ], + "before": null, + "after": { + "override_json": null, + "override_policy_documents": null, + "policy_id": null, + "source_json": null, + "source_policy_documents": null, + "statement": [ + { + "actions": [ + "s3:GetBucketAcl" + ], + "condition": [ + { + "test": "StringEquals", + "values": [ + "arn:aws:cloudtrail:us-west-2:844333597536:trail/example" + ], + "variable": "aws:SourceArn" + } + ], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [ + { + "identifiers": [ + "cloudtrail.amazonaws.com" + ], + "type": "Service" + } + ], + "resources": [ + null + ], + "sid": "AWSCloudTrailAclCheck" + }, + { + "actions": [ + "s3:PutObject" + ], + "condition": [ + { + "test": "StringEquals", + "values": [ + "arn:aws:cloudtrail:us-west-2:844333597536:trail/example" + ], + "variable": "aws:SourceArn" + }, + { + "test": "StringEquals", + "values": [ + "bucket-owner-full-control" + ], + "variable": "s3:x-amz-acl" + } + ], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [ + { + "identifiers": [ + "cloudtrail.amazonaws.com" + ], + "type": "Service" + } + ], + "resources": [ + null + ], + "sid": "AWSCloudTrailWrite" + } + ], + "version": null + }, + "after_unknown": { + "id": true, + "json": true, + "statement": [ + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + true + ] + }, + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + }, + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + true + ] + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "statement": [ + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + false + ] + }, + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + }, + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + false + ] + } + ] + } + }, + "action_reason": "read_because_config_unknown" + }, + { + "address": "aws_cloudtrail.example", + "mode": "managed", + "type": "aws_cloudtrail", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "advanced_event_selector": [], + "cloud_watch_logs_group_arn": null, + "cloud_watch_logs_role_arn": null, + "enable_log_file_validation": false, + "enable_logging": true, + "event_selector": [], + "include_global_service_events": false, + "insight_selector": [], + "is_multi_region_trail": false, + "is_organization_trail": false, + "kms_key_id": null, + "name": "example", + "s3_key_prefix": "prefix", + "sns_topic_name": null, + "tags": null + }, + "after_unknown": { + "advanced_event_selector": [], + "arn": true, + "event_selector": [], + "home_region": true, + "id": true, + "insight_selector": [], + "s3_bucket_name": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "advanced_event_selector": [], + "event_selector": [], + "insight_selector": [], + "tags_all": {} + } + } + }, + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "tf-test-trail", + "force_destroy": true, + "tags": null, + "timeouts": null + }, + "after_unknown": { + "acceleration_status": true, + "acl": true, + "arn": true, + "bucket_domain_name": true, + "bucket_prefix": true, + "bucket_regional_domain_name": true, + "cors_rule": true, + "grant": true, + "hosted_zone_id": true, + "id": true, + "lifecycle_rule": true, + "logging": true, + "object_lock_configuration": true, + "object_lock_enabled": true, + "policy": true, + "region": true, + "replication_configuration": true, + "request_payer": true, + "server_side_encryption_configuration": true, + "tags_all": true, + "versioning": true, + "website": true, + "website_domain": true, + "website_endpoint": true + }, + "before_sensitive": false, + "after_sensitive": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + } + }, + { + "address": "aws_s3_bucket_policy.example", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": {}, + "after_unknown": { + "bucket": true, + "id": true, + "policy": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "prior_state": { + "format_version": "1.0", + "terraform_version": "1.7.1", + "values": { + "root_module": { + "resources": [ + { + "address": "data.aws_caller_identity.current", + "mode": "data", + "type": "aws_caller_identity", + "name": "current", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "account_id": "844333597536", + "arn": "arn:aws:sts::844333597536:assumed-role/AWSReservedSSO_PowerUserAccess_b743e36821508738/nitish.kumar@nirmata.com", + "id": "844333597536", + "user_id": "AROA4JFRUINQC7VCOQ7UD:nitish.kumar@nirmata.com" + }, + "sensitive_values": {} + }, + { + "address": "data.aws_partition.current", + "mode": "data", + "type": "aws_partition", + "name": "current", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "dns_suffix": "amazonaws.com", + "id": "aws", + "partition": "aws", + "reverse_dns_prefix": "com.amazonaws" + }, + "sensitive_values": {} + }, + { + "address": "data.aws_region.current", + "mode": "data", + "type": "aws_region", + "name": "current", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": "US West (Oregon)", + "endpoint": "ec2.us-west-2.amazonaws.com", + "id": "us-west-2", + "name": "us-west-2" + }, + "sensitive_values": {} + } + ] + } + } + }, + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + "access_key": { + "constant_value": "ASIA4JFRUINQGRB5TXNP" + }, + "region": { + "constant_value": "us-west-2" + }, + "secret_key": { + "constant_value": "/Xaejacg3Snm1C7A1DwNBE7r8YxOMDkrkX4x/Cdl" + }, + "token": { + "constant_value": "IQoJb3JpZ2luX2VjEHUaCXVzLWVhc3QtMiJHMEUCIQCltr459nPRo9ZE+g4ceKFn860zygLhpf1rOp2ItfhilQIgBkIvCtKX6aVZulngkH17Lw0jfdXZ7y/ghoQjlqtcgzIqjgMIPhADGgw4NDQzMzM1OTc1MzYiDFy0uJyWkyb+LXGmjirrAsSqyB5Hz9TAiTaQRk6VG2QB0rnKVz9xOYnVeZF/lry4TujtUrP9VTbIqk9btRBd7REt1l7UrQCjZDe6JLrXwKsEFv1+Iky5W+ZAgAYo+h6OgIEE8qnvio4eezsiXi36IRXoDVrpwidggFdzaya1haLYdmypu++LgVAs8KJR0gXKkS9QLSy0LVTINtOOPjqHSZKEdDxDkOCtJL9if1C6QtrIdC6L7ejXPgpnFmZZL5lczbhZhs/HHeVqdebKfTuAng7rKHKoooHBhX9tb2g+HC7uNaI9uicJviGtXfq5AmqRLZLmFGYPKnmxMG6t0OjxQpg//IT8UJ6ggYnrOKikQmm33oEItxUtaXtVe9E3PpzGFv7Hdbe2YR0XW4n1b6RXjMfUxUpwVgp92ylIU7Ysr1I4uF5kDZzI6s9CIw1/tD0PSa+AhM2bGUBi76dTuToAvkkX1B9ct+kxjkcu9uEgz3i8cBK/ZIhNWR6/mTCKyuytBjqmAZDdcZqAxL91vkWiy8KRl5jovTgFBW7KVvheW2+Lcbe8ngV9reoGqB6ieKfNtQp00Nvr9sNHnIIPHkdhgYptkjJGDNWkm9EbLkZKN3Baj8sdHsyX7AuHb8COBYy60T3vRqgolubbbwHiS2tF6PqdH8/7xsMm1XSUIxS9w94WVfpq1hDVq8c5vmibKiQxdp2X3TGajbQFApei8SsdkIjTzQRbNLq3CuA=" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_cloudtrail.example", + "mode": "managed", + "type": "aws_cloudtrail", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "enable_logging": { + "constant_value": true + }, + "include_global_service_events": { + "constant_value": false + }, + "name": { + "constant_value": "example" + }, + "s3_bucket_name": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "s3_key_prefix": { + "constant_value": "prefix" + } + }, + "schema_version": 0, + "depends_on": [ + "aws_s3_bucket_policy.example" + ] + }, + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "tf-test-trail" + }, + "force_destroy": { + "constant_value": true + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_policy.example", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "policy": { + "references": [ + "data.aws_iam_policy_document.example.json", + "data.aws_iam_policy_document.example" + ] + } + }, + "schema_version": 0 + }, + { + "address": "data.aws_caller_identity.current", + "mode": "data", + "type": "aws_caller_identity", + "name": "current", + "provider_config_key": "aws", + "schema_version": 0 + }, + { + "address": "data.aws_iam_policy_document.example", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "s3:GetBucketAcl" + ] + }, + "condition": [ + { + "test": { + "constant_value": "StringEquals" + }, + "values": { + "references": [ + "data.aws_partition.current.partition", + "data.aws_partition.current", + "data.aws_region.current.name", + "data.aws_region.current", + "data.aws_caller_identity.current.account_id", + "data.aws_caller_identity.current" + ] + }, + "variable": { + "constant_value": "aws:SourceArn" + } + } + ], + "effect": { + "constant_value": "Allow" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "cloudtrail.amazonaws.com" + ] + }, + "type": { + "constant_value": "Service" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.example.arn", + "aws_s3_bucket.example" + ] + }, + "sid": { + "constant_value": "AWSCloudTrailAclCheck" + } + }, + { + "actions": { + "constant_value": [ + "s3:PutObject" + ] + }, + "condition": [ + { + "test": { + "constant_value": "StringEquals" + }, + "values": { + "constant_value": [ + "bucket-owner-full-control" + ] + }, + "variable": { + "constant_value": "s3:x-amz-acl" + } + }, + { + "test": { + "constant_value": "StringEquals" + }, + "values": { + "references": [ + "data.aws_partition.current.partition", + "data.aws_partition.current", + "data.aws_region.current.name", + "data.aws_region.current", + "data.aws_caller_identity.current.account_id", + "data.aws_caller_identity.current" + ] + }, + "variable": { + "constant_value": "aws:SourceArn" + } + } + ], + "effect": { + "constant_value": "Allow" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "cloudtrail.amazonaws.com" + ] + }, + "type": { + "constant_value": "Service" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.example.arn", + "aws_s3_bucket.example", + "data.aws_caller_identity.current.account_id", + "data.aws_caller_identity.current" + ] + }, + "sid": { + "constant_value": "AWSCloudTrailWrite" + } + } + ] + }, + "schema_version": 0 + }, + { + "address": "data.aws_partition.current", + "mode": "data", + "type": "aws_partition", + "name": "current", + "provider_config_key": "aws", + "schema_version": 0 + }, + { + "address": "data.aws_region.current", + "mode": "data", + "type": "aws_region", + "name": "current", + "provider_config_key": "aws", + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "data.aws_region.current", + "attribute": [ + "name" + ] + }, + { + "resource": "data.aws_caller_identity.current", + "attribute": [ + "account_id" + ] + }, + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + }, + { + "resource": "data.aws_iam_policy_document.example", + "attribute": [ + "json" + ] + }, + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "arn" + ] + }, + { + "resource": "data.aws_partition.current", + "attribute": [ + "partition" + ] + } + ], + "timestamp": "2024-02-01T04:59:58Z", + "errored": false +} diff --git a/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/good-payload2.json b/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/good-payload2.json new file mode 100644 index 00000000..2bcf6b1e --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/good-payload2.json @@ -0,0 +1,783 @@ +{ + "format_version": "1.2", + "terraform_version": "1.7.1", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "tf-test-trail", + "force_destroy": true, + "tags": null, + "timeouts": null + }, + "sensitive_values": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + }, + { + "address": "aws_s3_bucket_policy.example", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "sensitive_values": {} + }, + { + "address": "data.aws_iam_policy_document.example", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "override_json": null, + "override_policy_documents": null, + "policy_id": null, + "source_json": null, + "source_policy_documents": null, + "statement": [ + { + "actions": [ + "s3:GetBucketAcl" + ], + "condition": [ + { + "test": "StringEquals", + "values": [ + "arn:aws:cloudtrail:us-west-2:844333597536:trail/example" + ], + "variable": "aws:SourceArn" + } + ], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [ + { + "identifiers": [ + "cloudtrail.amazonaws.com" + ], + "type": "Service" + } + ], + "resources": [ + null + ], + "sid": "AWSCloudTrailAclCheck" + }, + { + "actions": [ + "s3:PutObject" + ], + "condition": [ + { + "test": "StringEquals", + "values": [ + "arn:aws:cloudtrail:us-west-2:844333597536:trail/example" + ], + "variable": "aws:SourceArn" + }, + { + "test": "StringEquals", + "values": [ + "bucket-owner-full-control" + ], + "variable": "s3:x-amz-acl" + } + ], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [ + { + "identifiers": [ + "cloudtrail.amazonaws.com" + ], + "type": "Service" + } + ], + "resources": [ + null + ], + "sid": "AWSCloudTrailWrite" + } + ], + "version": null + }, + "sensitive_values": { + "statement": [ + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + false + ] + }, + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + }, + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + false + ] + } + ] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "data.aws_iam_policy_document.example", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "read" + ], + "before": null, + "after": { + "override_json": null, + "override_policy_documents": null, + "policy_id": null, + "source_json": null, + "source_policy_documents": null, + "statement": [ + { + "actions": [ + "s3:GetBucketAcl" + ], + "condition": [ + { + "test": "StringEquals", + "values": [ + "arn:aws:cloudtrail:us-west-2:844333597536:trail/example" + ], + "variable": "aws:SourceArn" + } + ], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [ + { + "identifiers": [ + "cloudtrail.amazonaws.com" + ], + "type": "Service" + } + ], + "resources": [ + null + ], + "sid": "AWSCloudTrailAclCheck" + }, + { + "actions": [ + "s3:PutObject" + ], + "condition": [ + { + "test": "StringEquals", + "values": [ + "arn:aws:cloudtrail:us-west-2:844333597536:trail/example" + ], + "variable": "aws:SourceArn" + }, + { + "test": "StringEquals", + "values": [ + "bucket-owner-full-control" + ], + "variable": "s3:x-amz-acl" + } + ], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [ + { + "identifiers": [ + "cloudtrail.amazonaws.com" + ], + "type": "Service" + } + ], + "resources": [ + null + ], + "sid": "AWSCloudTrailWrite" + } + ], + "version": null + }, + "after_unknown": { + "id": true, + "json": true, + "statement": [ + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + true + ] + }, + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + }, + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + true + ] + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "statement": [ + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + false + ] + }, + { + "actions": [ + false + ], + "condition": [ + { + "values": [ + false + ] + }, + { + "values": [ + false + ] + } + ], + "not_principals": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [ + false + ] + } + ] + } + }, + "action_reason": "read_because_config_unknown" + }, + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "tf-test-trail", + "force_destroy": true, + "tags": null, + "timeouts": null + }, + "after_unknown": { + "acceleration_status": true, + "acl": true, + "arn": true, + "bucket_domain_name": true, + "bucket_prefix": true, + "bucket_regional_domain_name": true, + "cors_rule": true, + "grant": true, + "hosted_zone_id": true, + "id": true, + "lifecycle_rule": true, + "logging": true, + "object_lock_configuration": true, + "object_lock_enabled": true, + "policy": true, + "region": true, + "replication_configuration": true, + "request_payer": true, + "server_side_encryption_configuration": true, + "tags_all": true, + "versioning": true, + "website": true, + "website_domain": true, + "website_endpoint": true + }, + "before_sensitive": false, + "after_sensitive": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + } + }, + { + "address": "aws_s3_bucket_policy.example", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": {}, + "after_unknown": { + "bucket": true, + "id": true, + "policy": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "prior_state": { + "format_version": "1.0", + "terraform_version": "1.7.1", + "values": { + "root_module": { + "resources": [ + { + "address": "data.aws_caller_identity.current", + "mode": "data", + "type": "aws_caller_identity", + "name": "current", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "account_id": "844333597536", + "arn": "arn:aws:sts::844333597536:assumed-role/AWSReservedSSO_PowerUserAccess_b743e36821508738/nitish.kumar@nirmata.com", + "id": "844333597536", + "user_id": "AROA4JFRUINQC7VCOQ7UD:nitish.kumar@nirmata.com" + }, + "sensitive_values": {} + }, + { + "address": "data.aws_partition.current", + "mode": "data", + "type": "aws_partition", + "name": "current", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "dns_suffix": "amazonaws.com", + "id": "aws", + "partition": "aws", + "reverse_dns_prefix": "com.amazonaws" + }, + "sensitive_values": {} + }, + { + "address": "data.aws_region.current", + "mode": "data", + "type": "aws_region", + "name": "current", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": "US West (Oregon)", + "endpoint": "ec2.us-west-2.amazonaws.com", + "id": "us-west-2", + "name": "us-west-2" + }, + "sensitive_values": {} + } + ] + } + } + }, + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + "access_key": { + "constant_value": "ASIA4JFRUINQGRB5TXNP" + }, + "region": { + "constant_value": "us-west-2" + }, + "secret_key": { + "constant_value": "/Xaejacg3Snm1C7A1DwNBE7r8YxOMDkrkX4x/Cdl" + }, + "token": { + "constant_value": "IQoJb3JpZ2luX2VjEHUaCXVzLWVhc3QtMiJHMEUCIQCltr459nPRo9ZE+g4ceKFn860zygLhpf1rOp2ItfhilQIgBkIvCtKX6aVZulngkH17Lw0jfdXZ7y/ghoQjlqtcgzIqjgMIPhADGgw4NDQzMzM1OTc1MzYiDFy0uJyWkyb+LXGmjirrAsSqyB5Hz9TAiTaQRk6VG2QB0rnKVz9xOYnVeZF/lry4TujtUrP9VTbIqk9btRBd7REt1l7UrQCjZDe6JLrXwKsEFv1+Iky5W+ZAgAYo+h6OgIEE8qnvio4eezsiXi36IRXoDVrpwidggFdzaya1haLYdmypu++LgVAs8KJR0gXKkS9QLSy0LVTINtOOPjqHSZKEdDxDkOCtJL9if1C6QtrIdC6L7ejXPgpnFmZZL5lczbhZhs/HHeVqdebKfTuAng7rKHKoooHBhX9tb2g+HC7uNaI9uicJviGtXfq5AmqRLZLmFGYPKnmxMG6t0OjxQpg//IT8UJ6ggYnrOKikQmm33oEItxUtaXtVe9E3PpzGFv7Hdbe2YR0XW4n1b6RXjMfUxUpwVgp92ylIU7Ysr1I4uF5kDZzI6s9CIw1/tD0PSa+AhM2bGUBi76dTuToAvkkX1B9ct+kxjkcu9uEgz3i8cBK/ZIhNWR6/mTCKyuytBjqmAZDdcZqAxL91vkWiy8KRl5jovTgFBW7KVvheW2+Lcbe8ngV9reoGqB6ieKfNtQp00Nvr9sNHnIIPHkdhgYptkjJGDNWkm9EbLkZKN3Baj8sdHsyX7AuHb8COBYy60T3vRqgolubbbwHiS2tF6PqdH8/7xsMm1XSUIxS9w94WVfpq1hDVq8c5vmibKiQxdp2X3TGajbQFApei8SsdkIjTzQRbNLq3CuA=" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "tf-test-trail" + }, + "force_destroy": { + "constant_value": true + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_policy.example", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "policy": { + "references": [ + "data.aws_iam_policy_document.example.json", + "data.aws_iam_policy_document.example" + ] + } + }, + "schema_version": 0 + }, + { + "address": "data.aws_caller_identity.current", + "mode": "data", + "type": "aws_caller_identity", + "name": "current", + "provider_config_key": "aws", + "schema_version": 0 + }, + { + "address": "data.aws_iam_policy_document.example", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "s3:GetBucketAcl" + ] + }, + "condition": [ + { + "test": { + "constant_value": "StringEquals" + }, + "values": { + "references": [ + "data.aws_partition.current.partition", + "data.aws_partition.current", + "data.aws_region.current.name", + "data.aws_region.current", + "data.aws_caller_identity.current.account_id", + "data.aws_caller_identity.current" + ] + }, + "variable": { + "constant_value": "aws:SourceArn" + } + } + ], + "effect": { + "constant_value": "Allow" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "cloudtrail.amazonaws.com" + ] + }, + "type": { + "constant_value": "Service" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.example.arn", + "aws_s3_bucket.example" + ] + }, + "sid": { + "constant_value": "AWSCloudTrailAclCheck" + } + }, + { + "actions": { + "constant_value": [ + "s3:PutObject" + ] + }, + "condition": [ + { + "test": { + "constant_value": "StringEquals" + }, + "values": { + "constant_value": [ + "bucket-owner-full-control" + ] + }, + "variable": { + "constant_value": "s3:x-amz-acl" + } + }, + { + "test": { + "constant_value": "StringEquals" + }, + "values": { + "references": [ + "data.aws_partition.current.partition", + "data.aws_partition.current", + "data.aws_region.current.name", + "data.aws_region.current", + "data.aws_caller_identity.current.account_id", + "data.aws_caller_identity.current" + ] + }, + "variable": { + "constant_value": "aws:SourceArn" + } + } + ], + "effect": { + "constant_value": "Allow" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "cloudtrail.amazonaws.com" + ] + }, + "type": { + "constant_value": "Service" + } + } + ], + "resources": { + "references": [ + "aws_s3_bucket.example.arn", + "aws_s3_bucket.example", + "data.aws_caller_identity.current.account_id", + "data.aws_caller_identity.current" + ] + }, + "sid": { + "constant_value": "AWSCloudTrailWrite" + } + } + ] + }, + "schema_version": 0 + }, + { + "address": "data.aws_partition.current", + "mode": "data", + "type": "aws_partition", + "name": "current", + "provider_config_key": "aws", + "schema_version": 0 + }, + { + "address": "data.aws_region.current", + "mode": "data", + "type": "aws_region", + "name": "current", + "provider_config_key": "aws", + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + }, + { + "resource": "data.aws_iam_policy_document.example", + "attribute": [ + "json" + ] + }, + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "arn" + ] + }, + { + "resource": "data.aws_partition.current", + "attribute": [ + "partition" + ] + }, + { + "resource": "data.aws_region.current", + "attribute": [ + "name" + ] + }, + { + "resource": "data.aws_caller_identity.current", + "attribute": [ + "account_id" + ] + } + ], + "timestamp": "2024-02-01T05:06:19Z", + "errored": false +} diff --git a/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/good-terraform-01.tf b/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/good-terraform-01.tf new file mode 100644 index 00000000..54173b67 --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/good-terraform-01.tf @@ -0,0 +1,87 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" + access_key = "ASIA4JFRUINQGRB5TXNP" + secret_key = "/Xaejacg3Snm1C7A1DwNBE7r8YxOMDkrkX4x/Cdl" + token = "IQoJb3JpZ2luX2VjEHUaCXVzLWVhc3QtMiJHMEUCIQCltr459nPRo9ZE+g4ceKFn860zygLhpf1rOp2ItfhilQIgBkIvCtKX6aVZulngkH17Lw0jfdXZ7y/ghoQjlqtcgzIqjgMIPhADGgw4NDQzMzM1OTc1MzYiDFy0uJyWkyb+LXGmjirrAsSqyB5Hz9TAiTaQRk6VG2QB0rnKVz9xOYnVeZF/lry4TujtUrP9VTbIqk9btRBd7REt1l7UrQCjZDe6JLrXwKsEFv1+Iky5W+ZAgAYo+h6OgIEE8qnvio4eezsiXi36IRXoDVrpwidggFdzaya1haLYdmypu++LgVAs8KJR0gXKkS9QLSy0LVTINtOOPjqHSZKEdDxDkOCtJL9if1C6QtrIdC6L7ejXPgpnFmZZL5lczbhZhs/HHeVqdebKfTuAng7rKHKoooHBhX9tb2g+HC7uNaI9uicJviGtXfq5AmqRLZLmFGYPKnmxMG6t0OjxQpg//IT8UJ6ggYnrOKikQmm33oEItxUtaXtVe9E3PpzGFv7Hdbe2YR0XW4n1b6RXjMfUxUpwVgp92ylIU7Ysr1I4uF5kDZzI6s9CIw1/tD0PSa+AhM2bGUBi76dTuToAvkkX1B9ct+kxjkcu9uEgz3i8cBK/ZIhNWR6/mTCKyuytBjqmAZDdcZqAxL91vkWiy8KRl5jovTgFBW7KVvheW2+Lcbe8ngV9reoGqB6ieKfNtQp00Nvr9sNHnIIPHkdhgYptkjJGDNWkm9EbLkZKN3Baj8sdHsyX7AuHb8COBYy60T3vRqgolubbbwHiS2tF6PqdH8/7xsMm1XSUIxS9w94WVfpq1hDVq8c5vmibKiQxdp2X3TGajbQFApei8SsdkIjTzQRbNLq3CuA=" +} + +resource "aws_cloudtrail" "example" { + depends_on = [aws_s3_bucket_policy.example] + + name = "example" + s3_bucket_name = aws_s3_bucket.example.id + s3_key_prefix = "prefix" + include_global_service_events = false + enable_logging = true # optional field +} + +resource "aws_s3_bucket" "example" { + bucket = "tf-test-trail" + force_destroy = true +} + +data "aws_iam_policy_document" "example" { + statement { + sid = "AWSCloudTrailAclCheck" + effect = "Allow" + + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + + actions = ["s3:GetBucketAcl"] + resources = [aws_s3_bucket.example.arn] + condition { + test = "StringEquals" + variable = "aws:SourceArn" + values = ["arn:${data.aws_partition.current.partition}:cloudtrail:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:trail/example"] + } + } + + statement { + sid = "AWSCloudTrailWrite" + effect = "Allow" + + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + + actions = ["s3:PutObject"] + resources = ["${aws_s3_bucket.example.arn}/prefix/AWSLogs/${data.aws_caller_identity.current.account_id}/*"] + + condition { + test = "StringEquals" + variable = "s3:x-amz-acl" + values = ["bucket-owner-full-control"] + } + condition { + test = "StringEquals" + variable = "aws:SourceArn" + values = ["arn:${data.aws_partition.current.partition}:cloudtrail:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:trail/example"] + } + } +} + +resource "aws_s3_bucket_policy" "example" { + bucket = aws_s3_bucket.example.id + policy = data.aws_iam_policy_document.example.json +} + +data "aws_caller_identity" "current" {} + +data "aws_partition" "current" {} + +data "aws_region" "current" {} \ No newline at end of file diff --git a/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/good-terraform-02.tf b/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/good-terraform-02.tf new file mode 100644 index 00000000..70a907d8 --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-aws-cloudtrail/test/good-terraform-02.tf @@ -0,0 +1,87 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" + access_key = "ASIA4JFRUINQGRB5TXNP" + secret_key = "/Xaejacg3Snm1C7A1DwNBE7r8YxOMDkrkX4x/Cdl" + token = "IQoJb3JpZ2luX2VjEHUaCXVzLWVhc3QtMiJHMEUCIQCltr459nPRo9ZE+g4ceKFn860zygLhpf1rOp2ItfhilQIgBkIvCtKX6aVZulngkH17Lw0jfdXZ7y/ghoQjlqtcgzIqjgMIPhADGgw4NDQzMzM1OTc1MzYiDFy0uJyWkyb+LXGmjirrAsSqyB5Hz9TAiTaQRk6VG2QB0rnKVz9xOYnVeZF/lry4TujtUrP9VTbIqk9btRBd7REt1l7UrQCjZDe6JLrXwKsEFv1+Iky5W+ZAgAYo+h6OgIEE8qnvio4eezsiXi36IRXoDVrpwidggFdzaya1haLYdmypu++LgVAs8KJR0gXKkS9QLSy0LVTINtOOPjqHSZKEdDxDkOCtJL9if1C6QtrIdC6L7ejXPgpnFmZZL5lczbhZhs/HHeVqdebKfTuAng7rKHKoooHBhX9tb2g+HC7uNaI9uicJviGtXfq5AmqRLZLmFGYPKnmxMG6t0OjxQpg//IT8UJ6ggYnrOKikQmm33oEItxUtaXtVe9E3PpzGFv7Hdbe2YR0XW4n1b6RXjMfUxUpwVgp92ylIU7Ysr1I4uF5kDZzI6s9CIw1/tD0PSa+AhM2bGUBi76dTuToAvkkX1B9ct+kxjkcu9uEgz3i8cBK/ZIhNWR6/mTCKyuytBjqmAZDdcZqAxL91vkWiy8KRl5jovTgFBW7KVvheW2+Lcbe8ngV9reoGqB6ieKfNtQp00Nvr9sNHnIIPHkdhgYptkjJGDNWkm9EbLkZKN3Baj8sdHsyX7AuHb8COBYy60T3vRqgolubbbwHiS2tF6PqdH8/7xsMm1XSUIxS9w94WVfpq1hDVq8c5vmibKiQxdp2X3TGajbQFApei8SsdkIjTzQRbNLq3CuA=" +} + +resource "aws_cloudtrail" "example" { + depends_on = [aws_s3_bucket_policy.example] + + name = "example" + s3_bucket_name = aws_s3_bucket.example.id + s3_key_prefix = "prefix" + include_global_service_events = false +# enable_logging = true +} + +resource "aws_s3_bucket" "example" { + bucket = "tf-test-trail" + force_destroy = true +} + +data "aws_iam_policy_document" "example" { + statement { + sid = "AWSCloudTrailAclCheck" + effect = "Allow" + + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + + actions = ["s3:GetBucketAcl"] + resources = [aws_s3_bucket.example.arn] + condition { + test = "StringEquals" + variable = "aws:SourceArn" + values = ["arn:${data.aws_partition.current.partition}:cloudtrail:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:trail/example"] + } + } + + statement { + sid = "AWSCloudTrailWrite" + effect = "Allow" + + principals { + type = "Service" + identifiers = ["cloudtrail.amazonaws.com"] + } + + actions = ["s3:PutObject"] + resources = ["${aws_s3_bucket.example.arn}/prefix/AWSLogs/${data.aws_caller_identity.current.account_id}/*"] + + condition { + test = "StringEquals" + variable = "s3:x-amz-acl" + values = ["bucket-owner-full-control"] + } + condition { + test = "StringEquals" + variable = "aws:SourceArn" + values = ["arn:${data.aws_partition.current.partition}:cloudtrail:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:trail/example"] + } + } +} + +resource "aws_s3_bucket_policy" "example" { + bucket = aws_s3_bucket.example.id + policy = data.aws_iam_policy_document.example.json +} + +data "aws_caller_identity" "current" {} + +data "aws_partition" "current" {} + +data "aws_region" "current" {} \ No newline at end of file diff --git a/terraform-best-practices/aws/s3/enable-lifecycle-configuration/README.md b/terraform-best-practices/aws/s3/enable-lifecycle-configuration/README.md new file mode 100644 index 00000000..5d2c66a4 --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-lifecycle-configuration/README.md @@ -0,0 +1,30 @@ +To manage your objects so that they are stored cost effectively throughout their lifecycle, configure their Amazon S3 Lifecycle. An S3 Lifecycle configuration is a set of rules that define actions that Amazon S3 applies to a group of objects. There are two types of actions: + +- **Transition actions** – These actions define when objects transition to another storage class. For example, you might choose to transition objects to the S3 Standard-IA storage class 30 days after creating them, or archive objects to the S3 Glacier Flexible Retrieval storage class one year after creating them. + +There are costs associated with lifecycle transition requests. For pricing information, see Amazon S3 pricing. + +- **Expiration actions** – These actions define when objects expire. Amazon S3 deletes expired objects on your behalf. + +Lifecycle expiration costs depend on when you choose to expire objects. For more information, see Expiring objects. + +In order to set lifecycle configurationaws_s3_bucket_lifecycle_configuration using Terraform, you need to use the [aws_s3_bucket_versioning block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_lifecycle_configuration) in your Terraform and set the value for *Status* field to *Enabled* in order to enable *lifecycle configuration*. By default, the field is set to *Disabled*. This means that if you don't specify this block in your Terraform file, the *lifecycle configuration* will be *Disabled* by default. It is mandatory to specify the *aws_s3_bucket_lifecycle_configuration* block. Also *Status* field is mandatory to be set and if you're using the *aws_s3_bucket_lifecycle_configuration* block, you can't comment any field. + +In order to test this policy, use the following commands: + +1. Navigate to the `aws/s3/terraform/enable-lifecycle-configuration` directory. All the payloads along with Terraform files are present in the `test` directory. + +2. Assume you're trying to get the payload using the *good-terraform.tf* file, use the following commands: + ``` + terraform plan -out tfplan.binary + ``` +3. Convert this binary into JSON payload using `terraform show` command + ``` + terraform show -json tfplan.binary | jq > payload.json + ``` +4. Test your payload against the policy using `kyverno-json scan` command + ``` + kyverno-json scan --payload good-payload.json --policy enable-lifecycle-configuration.yaml + ``` + Since you've set the value of *Status* field to *Enabled*, the policy will give you PASS checks. If you try to modify this value (say Disabled), get the new payload again, and test it again using the above command, you'll get FAIL checks. You can also modify your Terraform file to exclude that block and get a new payload. When you try to scan for a payload that has come from a Terraform file for which the *aws_s3_bucket_lifecycle_configuration* block has not been specified, the policy will give you failing checks since the default value is *Disabled*. + \ No newline at end of file diff --git a/terraform-best-practices/aws/s3/enable-lifecycle-configuration/enable-lifecycle-configuration.yaml b/terraform-best-practices/aws/s3/enable-lifecycle-configuration/enable-lifecycle-configuration.yaml new file mode 100644 index 00000000..68c8587d --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-lifecycle-configuration/enable-lifecycle-configuration.yaml @@ -0,0 +1,28 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: s3-lifecycle-configuration + annotations: + policies.kyverno.io/title: s3-lifecycle-configuration + policies.kyverno.io/category: AWS S3 Security Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + S3 Lifecycle manage your objects so that they are stored cost effectively + throughout their lifecycle. This policy ensures the lifecycle_configuration + is set when creating an S3 bucket. +spec: + rules: + - name: check-s3-lifecycle-configuration + match: + all: + - (planned_values.root_module.resources[?type=='aws_s3_bucket'] | length(@) > `0`): true + assert: + all: + - message: Use the `aws_s3_bucket_lifecycle_configuration` resource to enable lifecycle configuration. + check: + (planned_values.root_module.resources[?type=='aws_s3_bucket_lifecycle_configuration'] | length(@) > `0`): true + - message: S3 Bucket Lifecycle Configuration 'status' needs to be set to 'Enabled' + check: + ~.(planned_values.root_module.resources[?type=='aws_s3_bucket_lifecycle_configuration']): + (values.rule[?status=='Enabled'] | length(@) > `0`): true + diff --git a/terraform-best-practices/aws/s3/enable-lifecycle-configuration/test/bad-payload.json b/terraform-best-practices/aws/s3/enable-lifecycle-configuration/test/bad-payload.json new file mode 100644 index 00000000..4de7b565 --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-lifecycle-configuration/test/bad-payload.json @@ -0,0 +1,264 @@ +{ + "format_version": "1.2", + "terraform_version": "1.6.6", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "test-bucket-demo-18012003", + "force_destroy": false, + "tags": null, + "timeouts": null + }, + "sensitive_values": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + }, + { + "address": "aws_s3_bucket_lifecycle_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_lifecycle_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "expected_bucket_owner": null, + "rule": [ + { + "abort_incomplete_multipart_upload": [], + "expiration": [], + "filter": [], + "id": "rule-1", + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "prefix": null, + "status": "Disabled", + "transition": [] + } + ] + }, + "sensitive_values": { + "rule": [ + { + "abort_incomplete_multipart_upload": [], + "expiration": [], + "filter": [], + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "transition": [] + } + ] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "test-bucket-demo-18012003", + "force_destroy": false, + "tags": null, + "timeouts": null + }, + "after_unknown": { + "acceleration_status": true, + "acl": true, + "arn": true, + "bucket_domain_name": true, + "bucket_prefix": true, + "bucket_regional_domain_name": true, + "cors_rule": true, + "grant": true, + "hosted_zone_id": true, + "id": true, + "lifecycle_rule": true, + "logging": true, + "object_lock_configuration": true, + "object_lock_enabled": true, + "policy": true, + "region": true, + "replication_configuration": true, + "request_payer": true, + "server_side_encryption_configuration": true, + "tags_all": true, + "versioning": true, + "website": true, + "website_domain": true, + "website_endpoint": true + }, + "before_sensitive": false, + "after_sensitive": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + } + }, + { + "address": "aws_s3_bucket_lifecycle_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_lifecycle_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "expected_bucket_owner": null, + "rule": [ + { + "abort_incomplete_multipart_upload": [], + "expiration": [], + "filter": [], + "id": "rule-1", + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "prefix": null, + "status": "Disabled", + "transition": [] + } + ] + }, + "after_unknown": { + "bucket": true, + "id": true, + "rule": [ + { + "abort_incomplete_multipart_upload": [], + "expiration": [], + "filter": [], + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "transition": [] + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "rule": [ + { + "abort_incomplete_multipart_upload": [], + "expiration": [], + "filter": [], + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "transition": [] + } + ] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + "access_key": { + "constant_value": "ASIA4JFRUINQIFWDIFNR" + }, + "region": { + "constant_value": "us-west-2" + }, + "secret_key": { + "constant_value": "XHQAb4QjabkUEUaxMRod4u03+zQkVgywJojN51tz" + }, + "token": { + "constant_value": "IQoJb3JpZ2luX2VjEEoaCXVzLWVhc3QtMiJHMEUCIDKxIOki1iWLlNfZYeaVoYZrQtUoUGhd2TQi3kJ8n+iqAiEAoOgPn1CTJwfJ0alpkwQFlUcuL8hoB4udMG/+ZxFhmk0qjgMIExADGgw4NDQzMzM1OTc1MzYiDJhI+QtghEujocUUDSrrAvGO9zK4xlV3T9VdP8p1aseC3/BiR/pNKlPyChFMTxQ8rnf9tkXqac49tgCAB/jU8KkJ9t0D/o7pDKOibz1i7TP6jNmbrNdBjS4VX/uMhtZekmKx+NDEZPZ2b0UW12fgMjwLD8yBcyVIkF7aHg5TfdA61aBkpnQQ8z+yyFSj+7ksnTjaxnuQDnbsWhT5MAw0t9G1bnbNMtKRalJM2fbBMYULKTl5IDA3K4zjcM9/8QcSkHPXtfnmFrthEcHRqBJZgTwVn0HToqrkANlt16dYdQmVbQBm2DIvB0a7KGL03EmlZ3rS8FHyr/FdKDqbTf62KYDBVUc5zOVEY5s9z5cNlxxi8irFiOkA9DXlOPAqA8YYYrEpc/oZSSn9vx7bPVIK1+TsaHgIgBTF9V7qnQH0D3ndRElJyenyDHJvKc6k51l4MK7+jwlquoffgp8J6z+fU8T4hZoX6df/zRyoRPSH9YDRcfIJReGFXPTS6jDujOOtBjqmAencXph5ZanyPDKAbVjSJGFzbor0XdFCPcKlhz6gAlDYsB0hjdaCuVgxU2nG2Ma3eCQRvdyl1NykDCaygrACQruTNzR46u/fDa62sENqUb+rKSQo+EYSBm4hlyLF2WoGUbZ9/DEBbWuvan+wAmSKGZ5igmJ6f+aH6WkACd/UI7vPjeQ9+SM37GQvBwLbXpLVbMkEm3yV7cuV3ewVVRBWeeIuXLw/m3Q=" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "test-bucket-demo-18012003" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_lifecycle_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_lifecycle_configuration", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "rule": [ + { + "id": { + "constant_value": "rule-1" + }, + "status": { + "constant_value": "Disabled" + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-30T09:58:18Z", + "errored": false +} diff --git a/terraform-best-practices/aws/s3/enable-lifecycle-configuration/test/bad-terraform.tf b/terraform-best-practices/aws/s3/enable-lifecycle-configuration/test/bad-terraform.tf new file mode 100644 index 00000000..80a6930e --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-lifecycle-configuration/test/bad-terraform.tf @@ -0,0 +1,27 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_s3_bucket" "example" { + bucket = "test-bucket-demo-18012003" +} + +resource "aws_s3_bucket_lifecycle_configuration" "example" { + bucket = aws_s3_bucket.example.id + + rule { + id = "rule-1" + status = "Disabled" + } +} diff --git a/terraform-best-practices/aws/s3/enable-lifecycle-configuration/test/good-payload.json b/terraform-best-practices/aws/s3/enable-lifecycle-configuration/test/good-payload.json new file mode 100644 index 00000000..36342b71 --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-lifecycle-configuration/test/good-payload.json @@ -0,0 +1,264 @@ +{ + "format_version": "1.2", + "terraform_version": "1.6.6", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "test-bucket-demo-18012003", + "force_destroy": false, + "tags": null, + "timeouts": null + }, + "sensitive_values": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + }, + { + "address": "aws_s3_bucket_lifecycle_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_lifecycle_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "expected_bucket_owner": null, + "rule": [ + { + "abort_incomplete_multipart_upload": [], + "expiration": [], + "filter": [], + "id": "rule-1", + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "prefix": null, + "status": "Enabled", + "transition": [] + } + ] + }, + "sensitive_values": { + "rule": [ + { + "abort_incomplete_multipart_upload": [], + "expiration": [], + "filter": [], + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "transition": [] + } + ] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "test-bucket-demo-18012003", + "force_destroy": false, + "tags": null, + "timeouts": null + }, + "after_unknown": { + "acceleration_status": true, + "acl": true, + "arn": true, + "bucket_domain_name": true, + "bucket_prefix": true, + "bucket_regional_domain_name": true, + "cors_rule": true, + "grant": true, + "hosted_zone_id": true, + "id": true, + "lifecycle_rule": true, + "logging": true, + "object_lock_configuration": true, + "object_lock_enabled": true, + "policy": true, + "region": true, + "replication_configuration": true, + "request_payer": true, + "server_side_encryption_configuration": true, + "tags_all": true, + "versioning": true, + "website": true, + "website_domain": true, + "website_endpoint": true + }, + "before_sensitive": false, + "after_sensitive": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + } + }, + { + "address": "aws_s3_bucket_lifecycle_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_lifecycle_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "expected_bucket_owner": null, + "rule": [ + { + "abort_incomplete_multipart_upload": [], + "expiration": [], + "filter": [], + "id": "rule-1", + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "prefix": null, + "status": "Enabled", + "transition": [] + } + ] + }, + "after_unknown": { + "bucket": true, + "id": true, + "rule": [ + { + "abort_incomplete_multipart_upload": [], + "expiration": [], + "filter": [], + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "transition": [] + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "rule": [ + { + "abort_incomplete_multipart_upload": [], + "expiration": [], + "filter": [], + "noncurrent_version_expiration": [], + "noncurrent_version_transition": [], + "transition": [] + } + ] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + "access_key": { + "constant_value": "ASIA4JFRUINQIFWDIFNR" + }, + "region": { + "constant_value": "us-west-2" + }, + "secret_key": { + "constant_value": "XHQAb4QjabkUEUaxMRod4u03+zQkVgywJojN51tz" + }, + "token": { + "constant_value": "IQoJb3JpZ2luX2VjEEoaCXVzLWVhc3QtMiJHMEUCIDKxIOki1iWLlNfZYeaVoYZrQtUoUGhd2TQi3kJ8n+iqAiEAoOgPn1CTJwfJ0alpkwQFlUcuL8hoB4udMG/+ZxFhmk0qjgMIExADGgw4NDQzMzM1OTc1MzYiDJhI+QtghEujocUUDSrrAvGO9zK4xlV3T9VdP8p1aseC3/BiR/pNKlPyChFMTxQ8rnf9tkXqac49tgCAB/jU8KkJ9t0D/o7pDKOibz1i7TP6jNmbrNdBjS4VX/uMhtZekmKx+NDEZPZ2b0UW12fgMjwLD8yBcyVIkF7aHg5TfdA61aBkpnQQ8z+yyFSj+7ksnTjaxnuQDnbsWhT5MAw0t9G1bnbNMtKRalJM2fbBMYULKTl5IDA3K4zjcM9/8QcSkHPXtfnmFrthEcHRqBJZgTwVn0HToqrkANlt16dYdQmVbQBm2DIvB0a7KGL03EmlZ3rS8FHyr/FdKDqbTf62KYDBVUc5zOVEY5s9z5cNlxxi8irFiOkA9DXlOPAqA8YYYrEpc/oZSSn9vx7bPVIK1+TsaHgIgBTF9V7qnQH0D3ndRElJyenyDHJvKc6k51l4MK7+jwlquoffgp8J6z+fU8T4hZoX6df/zRyoRPSH9YDRcfIJReGFXPTS6jDujOOtBjqmAencXph5ZanyPDKAbVjSJGFzbor0XdFCPcKlhz6gAlDYsB0hjdaCuVgxU2nG2Ma3eCQRvdyl1NykDCaygrACQruTNzR46u/fDa62sENqUb+rKSQo+EYSBm4hlyLF2WoGUbZ9/DEBbWuvan+wAmSKGZ5igmJ6f+aH6WkACd/UI7vPjeQ9+SM37GQvBwLbXpLVbMkEm3yV7cuV3ewVVRBWeeIuXLw/m3Q=" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "test-bucket-demo-18012003" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_lifecycle_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_lifecycle_configuration", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "rule": [ + { + "id": { + "constant_value": "rule-1" + }, + "status": { + "constant_value": "Enabled" + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-30T09:56:27Z", + "errored": false +} diff --git a/terraform-best-practices/aws/s3/enable-lifecycle-configuration/test/good-terraform.tf b/terraform-best-practices/aws/s3/enable-lifecycle-configuration/test/good-terraform.tf new file mode 100644 index 00000000..d549a0d1 --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-lifecycle-configuration/test/good-terraform.tf @@ -0,0 +1,27 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_s3_bucket" "example" { + bucket = "test-bucket-demo-18012003" +} + +resource "aws_s3_bucket_lifecycle_configuration" "example" { + bucket = aws_s3_bucket.example.id + + rule { + id = "rule-1" + status = "Enabled" + } +} diff --git a/terraform-best-practices/aws/s3/enable-s3-versioning/README.md b/terraform-best-practices/aws/s3/enable-s3-versioning/README.md new file mode 100644 index 00000000..ce03dcb1 --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-s3-versioning/README.md @@ -0,0 +1,39 @@ +Versioning in Amazon S3 is a means of keeping multiple variants of an object in the same bucket. You can use the S3 Versioning feature to preserve, retrieve, and restore every version of every object stored in your buckets. With versioning you can recover more easily from both unintended user actions and application failures. After versioning is enabled for a bucket, if Amazon S3 receives multiple write requests for the same object simultaneously, it stores all of those objects. + +Versioning-enabled buckets can help you recover objects from accidental deletion or overwrite. For example, if you delete an object, Amazon S3 inserts a delete marker instead of removing the object permanently. The delete marker becomes the current object version. If you overwrite an object, it results in a new object version in the bucket. You can always restore the previous version. For more information, see Deleting object versions from a versioning-enabled bucket. + +By default, S3 Versioning is disabled on buckets, and you must explicitly enable it. Buckets can be in one of three states: + +- Unversioned (the default) + +- Versioning-enabled + +- Versioning-suspended + +You enable and suspend versioning at the bucket level. After you version-enable a bucket, it can never return to an unversioned state. But you can suspend versioning on that bucket. + +The versioning state applies to all (never some) of the objects in that bucket. When you enable versioning in a bucket, all new objects are versioned and given a unique version ID. Objects that already existed in the bucket at the time versioning was enabled will thereafter always be versioned and given a unique version ID when they are modified by future requests. Note the following: + +- Objects that are stored in your bucket before you set the versioning state have a version ID of null. When you enable versioning, existing objects in your bucket do not change. What changes is how Amazon S3 handles the objects in future requests. + +- The bucket owner (or any user with appropriate permissions) can suspend versioning to stop accruing object versions. When you suspend versioning, existing objects in your bucket do not change. What changes is how Amazon S3 handles objects in future requests. + +In order to set versioning using Terraform, you need to use the [aws_s3_bucket_versioning block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_versioning#versioning_configuration) in your Terraform and set the value for *status* field to *Enabled* in order to enable versioning. By default, the field is set to *Disabled*. This means that if you don't specify this block in your Terraform file, the versioning will be *Disabled* by default. + +In order to test this policy, use the following commands: + +1. Navigate to the `aws/s3/terraform/enable-s3-versioning` directory. All the payloads along with Terraform files are present in the `test` directory. + +2. Assume you're trying to get the payload using the *good-terraform.tf* file, use the following commands: + ``` + terraform plan -out tfplan.binary + ``` +3. Convert this binary into JSON payload using `terraform show` command + ``` + terraform show -json tfplan.binary | jq > payload.json + ``` +4. Test your payload against the policy using `kyverno-json scan` command + ``` + kyverno-json scan --payload payload.json --policy enable-kms-encryption.yaml + ``` + Since you've set the value of *status* field to *Enabled*, the policy will give you PASS checks. If you try to modify this value (say foo), get the new payload again, and test it again using the above command, you'll get FAIL checks. You can also modify your Terraform file to exclude that block and get a new payload. When you try to scan for a payload that has come from a Terraform file for which the *aws_s3_bucket_versioning block* block has not been specified, the policy will give you failing checks since the default value is *Disabled*. \ No newline at end of file diff --git a/terraform-best-practices/aws/s3/enable-s3-versioning/s3-enable-versioning.yaml b/terraform-best-practices/aws/s3/enable-s3-versioning/s3-enable-versioning.yaml new file mode 100644 index 00000000..0014d495 --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-s3-versioning/s3-enable-versioning.yaml @@ -0,0 +1,32 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: enable-s3-versioning + annotations: + policies.kyverno.io/title: enable-s3-versioning + policies.kyverno.io/category: AWS S3 Security Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + Versioning in Amazon S3 is a means of keeping multiple variants of an object + in the same bucket. You can use the S3 Versioning feature to preserve, retrieve, + and restore every version of every object stored in your buckets. With versioning + you can recover more easily from both unintended user actions and application + failures. After versioning is enabled for a bucket, if Amazon S3 receives multiple + write requests for the same object simultaneously, it stores all of those objects. +spec: + rules: + - name: check-s3-versioning-setting + match: + all: + - (planned_values.root_module.resources[?type=='aws_s3_bucket'] | length(@) > `0`): true + assert: + all: + - message: Use the `aws_s3_bucket_versioning` resource to enable versioning. + check: + (planned_values.root_module.resources[?type=='aws_s3_bucket_versioning'] | length(@) > `0`): true + - message: S3 Bucket Versioning needs to be set to 'Enabled' + check: + ~.(planned_values.root_module.resources[?type=='aws_s3_bucket_versioning']): + (values.versioning_configuration[?status=='Enabled'] | length(@) > `0`): true + + \ No newline at end of file diff --git a/terraform-best-practices/aws/s3/enable-s3-versioning/test/bad-payload-01.json b/terraform-best-practices/aws/s3/enable-s3-versioning/test/bad-payload-01.json new file mode 100644 index 00000000..ceab4bd9 --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-s3-versioning/test/bad-payload-01.json @@ -0,0 +1,228 @@ +{ + "format_version": "1.2", + "terraform_version": "1.6.6", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "test-bucket-demo-18012003", + "force_destroy": false, + "tags": null, + "timeouts": null + }, + "sensitive_values": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + }, + { + "address": "aws_s3_bucket_versioning.versioning_example", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "versioning_example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + { + "status": "Disabled" + } + ] + }, + "sensitive_values": { + "versioning_configuration": [ + {} + ] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "test-bucket-demo-18012003", + "force_destroy": false, + "tags": null, + "timeouts": null + }, + "after_unknown": { + "acceleration_status": true, + "acl": true, + "arn": true, + "bucket_domain_name": true, + "bucket_prefix": true, + "bucket_regional_domain_name": true, + "cors_rule": true, + "grant": true, + "hosted_zone_id": true, + "id": true, + "lifecycle_rule": true, + "logging": true, + "object_lock_configuration": true, + "object_lock_enabled": true, + "policy": true, + "region": true, + "replication_configuration": true, + "request_payer": true, + "server_side_encryption_configuration": true, + "tags_all": true, + "versioning": true, + "website": true, + "website_domain": true, + "website_endpoint": true + }, + "before_sensitive": false, + "after_sensitive": { + "cors_rule": [], + "grant": [], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [], + "tags_all": {}, + "versioning": [], + "website": [] + } + } + }, + { + "address": "aws_s3_bucket_versioning.versioning_example", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "versioning_example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + { + "status": "Disabled" + } + ] + }, + "after_unknown": { + "bucket": true, + "id": true, + "versioning_configuration": [ + { + "mfa_delete": true + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "versioning_configuration": [ + {} + ] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + "access_key": { + "constant_value": "ASIA4JFRUINQBMQQJ3W3" + }, + "region": { + "constant_value": "us-west-2" + }, + "secret_key": { + "constant_value": "4PxPNx0vkdZc1yVyD0LwAtYFmLoFl5QIcmOR5FTa" + }, + "token": { + "constant_value": "IQoJb3JpZ2luX2VjEKT//////////wEaCXVzLWVhc3QtMiJGMEQCIGWSSoA+mJPg9zLlxzNZksgKQCsqtYsEIplQvbgwcJmgAiBNxZ7hyPFORmLps3rSbyQs/OkN6N5ycxuru3Paons1GSqOAwhdEAMaDDg0NDMzMzU5NzUzNiIMV51T3H3mRwwxLVykKusC9wvfWonATRhipeSU8mj8Pi7/amzFwxLb6GhnDlLnuRV/caVOpjDR7WjJao5u1F4tO3wV7BTdlvotta5Px7flYorNqgHLtvHqgvA1FNmspk68/vNqS/fsT3gt+WGiUMRk/jel3nwz1pDbRZzwZw09ypAbayk0kpBHCl5ERPsnB+tKkmsByPc59UULMaLQvr6hl3x/AU+bxuUyhuOQMT+s0PoQvFLKh/tSDXqCZrSKnjl4cUYswKFuOTPk/9YBOcC/MQOjgN0SNM2Lq5i29MBmfFJYN0HZlJFlmvTTY0+hUqWCQ+d3qxfx57WZguKJMOObN0rnQ839wC+PlpE+TFFOl5WD/1d84cyZGnbqXHsuoRIfRW00Ty/9hSEJN0GdeKAv0O5GTrvT2dX7YsBgMIDmAE03ntz58Wy04WxRSrdVaM9kkIC7SuOiwm2BD9hJ46OU8fLntzrHoCm+VLSwSGDi0zRUTMXjqeeyGGIRMKTMvq0GOqcB5taXpMIF83kPcI659QQ1Hi7b9TxP/Y9M9Zai3IfPeKmWspIc03a9IbhrWm4v74dML693AfR4TSkDtUxOJ27dpmXYDHnpTz0oFHuXoCuPAYZis68qYg21RPaoVuWLMFR+QMsl4eVFXkkr59cCfP35AzzZmWImt4tKD1kf2hGQxmYkGPObkV1BZRR5rzM2gIZER69R0aPL765f45Q7myDdonJcxeK62PU=" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "test-bucket-demo-18012003" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_versioning.versioning_example", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "versioning_example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "versioning_configuration": [ + { + "status": { + "constant_value": "Disabled" + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-23T11:46:49Z", + "errored": false +} diff --git a/terraform-best-practices/aws/s3/enable-s3-versioning/test/bad-payload-02.json b/terraform-best-practices/aws/s3/enable-s3-versioning/test/bad-payload-02.json new file mode 100644 index 00000000..8dedc852 --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-s3-versioning/test/bad-payload-02.json @@ -0,0 +1,641 @@ +{ + "format_version": "1.2", + "terraform_version": "1.6.6", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::test-bucket-demo-18012003", + "bucket": "test-bucket-demo-18012003", + "bucket_domain_name": "test-bucket-demo-18012003.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "test-bucket-demo-18012003.s3.us-west-2.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z3BJ6K6RIION7M", + "id": "test-bucket-demo-18012003", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "us-west-2", + "replication_configuration": [], + "request_payer": "BucketOwner", + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": "", + "sse_algorithm": "AES256" + } + ], + "bucket_key_enabled": false + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "timeouts": null, + "versioning": [ + { + "enabled": false, + "mfa_delete": false + } + ], + "website": [], + "website_domain": null, + "website_endpoint": null + }, + "sensitive_values": { + "cors_rule": [], + "grant": [ + { + "permissions": [ + false + ] + } + ], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + {} + ] + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "versioning": [ + {} + ], + "website": [] + } + } + ] + } + }, + "resource_drift": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "update" + ], + "before": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::test-bucket-demo-18012003", + "bucket": "test-bucket-demo-18012003", + "bucket_domain_name": "test-bucket-demo-18012003.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "test-bucket-demo-18012003.s3.us-west-2.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z3BJ6K6RIION7M", + "id": "test-bucket-demo-18012003", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "us-west-2", + "replication_configuration": [], + "request_payer": "BucketOwner", + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": "", + "sse_algorithm": "AES256" + } + ], + "bucket_key_enabled": false + } + ] + } + ], + "tags": null, + "tags_all": {}, + "timeouts": null, + "versioning": [ + { + "enabled": false, + "mfa_delete": false + } + ], + "website": [], + "website_domain": null, + "website_endpoint": null + }, + "after": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::test-bucket-demo-18012003", + "bucket": "test-bucket-demo-18012003", + "bucket_domain_name": "test-bucket-demo-18012003.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "test-bucket-demo-18012003.s3.us-west-2.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z3BJ6K6RIION7M", + "id": "test-bucket-demo-18012003", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "us-west-2", + "replication_configuration": [], + "request_payer": "BucketOwner", + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": "", + "sse_algorithm": "AES256" + } + ], + "bucket_key_enabled": false + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "timeouts": null, + "versioning": [ + { + "enabled": false, + "mfa_delete": false + } + ], + "website": [], + "website_domain": null, + "website_endpoint": null + }, + "after_unknown": {}, + "before_sensitive": { + "cors_rule": [], + "grant": [ + { + "permissions": [ + false + ] + } + ], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + {} + ] + } + ] + } + ], + "tags_all": {}, + "versioning": [ + {} + ], + "website": [] + }, + "after_sensitive": { + "cors_rule": [], + "grant": [ + { + "permissions": [ + false + ] + } + ], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + {} + ] + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "versioning": [ + {} + ], + "website": [] + } + } + } + ], + "resource_changes": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "no-op" + ], + "before": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::test-bucket-demo-18012003", + "bucket": "test-bucket-demo-18012003", + "bucket_domain_name": "test-bucket-demo-18012003.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "test-bucket-demo-18012003.s3.us-west-2.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z3BJ6K6RIION7M", + "id": "test-bucket-demo-18012003", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "us-west-2", + "replication_configuration": [], + "request_payer": "BucketOwner", + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": "", + "sse_algorithm": "AES256" + } + ], + "bucket_key_enabled": false + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "timeouts": null, + "versioning": [ + { + "enabled": false, + "mfa_delete": false + } + ], + "website": [], + "website_domain": null, + "website_endpoint": null + }, + "after": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::test-bucket-demo-18012003", + "bucket": "test-bucket-demo-18012003", + "bucket_domain_name": "test-bucket-demo-18012003.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "test-bucket-demo-18012003.s3.us-west-2.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z3BJ6K6RIION7M", + "id": "test-bucket-demo-18012003", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "us-west-2", + "replication_configuration": [], + "request_payer": "BucketOwner", + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": "", + "sse_algorithm": "AES256" + } + ], + "bucket_key_enabled": false + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "timeouts": null, + "versioning": [ + { + "enabled": false, + "mfa_delete": false + } + ], + "website": [], + "website_domain": null, + "website_endpoint": null + }, + "after_unknown": {}, + "before_sensitive": { + "cors_rule": [], + "grant": [ + { + "permissions": [ + false + ] + } + ], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + {} + ] + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "versioning": [ + {} + ], + "website": [] + }, + "after_sensitive": { + "cors_rule": [], + "grant": [ + { + "permissions": [ + false + ] + } + ], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + {} + ] + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "versioning": [ + {} + ], + "website": [] + } + } + } + ], + "prior_state": { + "format_version": "1.0", + "terraform_version": "1.6.6", + "values": { + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::test-bucket-demo-18012003", + "bucket": "test-bucket-demo-18012003", + "bucket_domain_name": "test-bucket-demo-18012003.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "test-bucket-demo-18012003.s3.us-west-2.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z3BJ6K6RIION7M", + "id": "test-bucket-demo-18012003", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "us-west-2", + "replication_configuration": [], + "request_payer": "BucketOwner", + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": "", + "sse_algorithm": "AES256" + } + ], + "bucket_key_enabled": false + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "timeouts": null, + "versioning": [ + { + "enabled": false, + "mfa_delete": false + } + ], + "website": [], + "website_domain": null, + "website_endpoint": null + }, + "sensitive_values": { + "cors_rule": [], + "grant": [ + { + "permissions": [ + false + ] + } + ], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + {} + ] + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "versioning": [ + {} + ], + "website": [] + } + } + ] + } + } + }, + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + "access_key": { + "constant_value": "ASIA4JFRUINQBMQQJ3W3" + }, + "region": { + "constant_value": "us-west-2" + }, + "secret_key": { + "constant_value": "4PxPNx0vkdZc1yVyD0LwAtYFmLoFl5QIcmOR5FTa" + }, + "token": { + "constant_value": "IQoJb3JpZ2luX2VjEKT//////////wEaCXVzLWVhc3QtMiJGMEQCIGWSSoA+mJPg9zLlxzNZksgKQCsqtYsEIplQvbgwcJmgAiBNxZ7hyPFORmLps3rSbyQs/OkN6N5ycxuru3Paons1GSqOAwhdEAMaDDg0NDMzMzU5NzUzNiIMV51T3H3mRwwxLVykKusC9wvfWonATRhipeSU8mj8Pi7/amzFwxLb6GhnDlLnuRV/caVOpjDR7WjJao5u1F4tO3wV7BTdlvotta5Px7flYorNqgHLtvHqgvA1FNmspk68/vNqS/fsT3gt+WGiUMRk/jel3nwz1pDbRZzwZw09ypAbayk0kpBHCl5ERPsnB+tKkmsByPc59UULMaLQvr6hl3x/AU+bxuUyhuOQMT+s0PoQvFLKh/tSDXqCZrSKnjl4cUYswKFuOTPk/9YBOcC/MQOjgN0SNM2Lq5i29MBmfFJYN0HZlJFlmvTTY0+hUqWCQ+d3qxfx57WZguKJMOObN0rnQ839wC+PlpE+TFFOl5WD/1d84cyZGnbqXHsuoRIfRW00Ty/9hSEJN0GdeKAv0O5GTrvT2dX7YsBgMIDmAE03ntz58Wy04WxRSrdVaM9kkIC7SuOiwm2BD9hJ46OU8fLntzrHoCm+VLSwSGDi0zRUTMXjqeeyGGIRMKTMvq0GOqcB5taXpMIF83kPcI659QQ1Hi7b9TxP/Y9M9Zai3IfPeKmWspIc03a9IbhrWm4v74dML693AfR4TSkDtUxOJ27dpmXYDHnpTz0oFHuXoCuPAYZis68qYg21RPaoVuWLMFR+QMsl4eVFXkkr59cCfP35AzzZmWImt4tKD1kf2hGQxmYkGPObkV1BZRR5rzM2gIZER69R0aPL765f45Q7myDdonJcxeK62PU=" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "test-bucket-demo-18012003" + } + }, + "schema_version": 0 + } + ] + } + }, + "timestamp": "2024-01-23T11:51:06Z", + "errored": false +} diff --git a/terraform-best-practices/aws/s3/enable-s3-versioning/test/bad-terraform-01.tf b/terraform-best-practices/aws/s3/enable-s3-versioning/test/bad-terraform-01.tf new file mode 100644 index 00000000..7921f554 --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-s3-versioning/test/bad-terraform-01.tf @@ -0,0 +1,25 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_s3_bucket" "example" { + bucket = "test-bucket-demo-18012003" +} + +resource "aws_s3_bucket_versioning" "versioning_example" { + bucket = aws_s3_bucket.example.id + versioning_configuration { + status = "Disabled" + } +} diff --git a/terraform-best-practices/aws/s3/enable-s3-versioning/test/bad-terraform-02.tf b/terraform-best-practices/aws/s3/enable-s3-versioning/test/bad-terraform-02.tf new file mode 100644 index 00000000..1867ba52 --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-s3-versioning/test/bad-terraform-02.tf @@ -0,0 +1,18 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_s3_bucket" "example" { + bucket = "test-bucket-demo-18012003" +} diff --git a/terraform-best-practices/aws/s3/enable-s3-versioning/test/good-payload.json b/terraform-best-practices/aws/s3/enable-s3-versioning/test/good-payload.json new file mode 100644 index 00000000..29821ccd --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-s3-versioning/test/good-payload.json @@ -0,0 +1,732 @@ +{ + "format_version": "1.2", + "terraform_version": "1.6.6", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::test-bucket-demo-18012003", + "bucket": "test-bucket-demo-18012003", + "bucket_domain_name": "test-bucket-demo-18012003.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "test-bucket-demo-18012003.s3.us-west-2.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z3BJ6K6RIION7M", + "id": "test-bucket-demo-18012003", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "us-west-2", + "replication_configuration": [], + "request_payer": "BucketOwner", + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": "", + "sse_algorithm": "AES256" + } + ], + "bucket_key_enabled": false + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "timeouts": null, + "versioning": [ + { + "enabled": false, + "mfa_delete": false + } + ], + "website": [], + "website_domain": null, + "website_endpoint": null + }, + "sensitive_values": { + "cors_rule": [], + "grant": [ + { + "permissions": [ + false + ] + } + ], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + {} + ] + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "versioning": [ + {} + ], + "website": [] + } + }, + { + "address": "aws_s3_bucket_versioning.versioning_example", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "versioning_example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "test-bucket-demo-18012003", + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + { + "status": "Enabled" + } + ] + }, + "sensitive_values": { + "versioning_configuration": [ + {} + ] + } + } + ] + } + }, + "resource_drift": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "update" + ], + "before": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::test-bucket-demo-18012003", + "bucket": "test-bucket-demo-18012003", + "bucket_domain_name": "test-bucket-demo-18012003.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "test-bucket-demo-18012003.s3.us-west-2.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z3BJ6K6RIION7M", + "id": "test-bucket-demo-18012003", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "us-west-2", + "replication_configuration": [], + "request_payer": "BucketOwner", + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": "", + "sse_algorithm": "AES256" + } + ], + "bucket_key_enabled": false + } + ] + } + ], + "tags": null, + "tags_all": {}, + "timeouts": null, + "versioning": [ + { + "enabled": false, + "mfa_delete": false + } + ], + "website": [], + "website_domain": null, + "website_endpoint": null + }, + "after": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::test-bucket-demo-18012003", + "bucket": "test-bucket-demo-18012003", + "bucket_domain_name": "test-bucket-demo-18012003.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "test-bucket-demo-18012003.s3.us-west-2.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z3BJ6K6RIION7M", + "id": "test-bucket-demo-18012003", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "us-west-2", + "replication_configuration": [], + "request_payer": "BucketOwner", + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": "", + "sse_algorithm": "AES256" + } + ], + "bucket_key_enabled": false + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "timeouts": null, + "versioning": [ + { + "enabled": false, + "mfa_delete": false + } + ], + "website": [], + "website_domain": null, + "website_endpoint": null + }, + "after_unknown": {}, + "before_sensitive": { + "cors_rule": [], + "grant": [ + { + "permissions": [ + false + ] + } + ], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + {} + ] + } + ] + } + ], + "tags_all": {}, + "versioning": [ + {} + ], + "website": [] + }, + "after_sensitive": { + "cors_rule": [], + "grant": [ + { + "permissions": [ + false + ] + } + ], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + {} + ] + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "versioning": [ + {} + ], + "website": [] + } + } + } + ], + "resource_changes": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "no-op" + ], + "before": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::test-bucket-demo-18012003", + "bucket": "test-bucket-demo-18012003", + "bucket_domain_name": "test-bucket-demo-18012003.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "test-bucket-demo-18012003.s3.us-west-2.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z3BJ6K6RIION7M", + "id": "test-bucket-demo-18012003", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "us-west-2", + "replication_configuration": [], + "request_payer": "BucketOwner", + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": "", + "sse_algorithm": "AES256" + } + ], + "bucket_key_enabled": false + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "timeouts": null, + "versioning": [ + { + "enabled": false, + "mfa_delete": false + } + ], + "website": [], + "website_domain": null, + "website_endpoint": null + }, + "after": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::test-bucket-demo-18012003", + "bucket": "test-bucket-demo-18012003", + "bucket_domain_name": "test-bucket-demo-18012003.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "test-bucket-demo-18012003.s3.us-west-2.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z3BJ6K6RIION7M", + "id": "test-bucket-demo-18012003", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "us-west-2", + "replication_configuration": [], + "request_payer": "BucketOwner", + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": "", + "sse_algorithm": "AES256" + } + ], + "bucket_key_enabled": false + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "timeouts": null, + "versioning": [ + { + "enabled": false, + "mfa_delete": false + } + ], + "website": [], + "website_domain": null, + "website_endpoint": null + }, + "after_unknown": {}, + "before_sensitive": { + "cors_rule": [], + "grant": [ + { + "permissions": [ + false + ] + } + ], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + {} + ] + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "versioning": [ + {} + ], + "website": [] + }, + "after_sensitive": { + "cors_rule": [], + "grant": [ + { + "permissions": [ + false + ] + } + ], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + {} + ] + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "versioning": [ + {} + ], + "website": [] + } + } + }, + { + "address": "aws_s3_bucket_versioning.versioning_example", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "versioning_example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "test-bucket-demo-18012003", + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + { + "status": "Enabled" + } + ] + }, + "after_unknown": { + "id": true, + "versioning_configuration": [ + { + "mfa_delete": true + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "versioning_configuration": [ + {} + ] + } + } + } + ], + "prior_state": { + "format_version": "1.0", + "terraform_version": "1.6.6", + "values": { + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::test-bucket-demo-18012003", + "bucket": "test-bucket-demo-18012003", + "bucket_domain_name": "test-bucket-demo-18012003.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "test-bucket-demo-18012003.s3.us-west-2.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z3BJ6K6RIION7M", + "id": "test-bucket-demo-18012003", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "us-west-2", + "replication_configuration": [], + "request_payer": "BucketOwner", + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": "", + "sse_algorithm": "AES256" + } + ], + "bucket_key_enabled": false + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "timeouts": null, + "versioning": [ + { + "enabled": false, + "mfa_delete": false + } + ], + "website": [], + "website_domain": null, + "website_endpoint": null + }, + "sensitive_values": { + "cors_rule": [], + "grant": [ + { + "permissions": [ + false + ] + } + ], + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "replication_configuration": [], + "server_side_encryption_configuration": [ + { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + {} + ] + } + ] + } + ], + "tags": {}, + "tags_all": {}, + "versioning": [ + {} + ], + "website": [] + } + } + ] + } + } + }, + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + "access_key": { + "constant_value": "ASIA4JFRUINQBMQQJ3W3" + }, + "region": { + "constant_value": "us-west-2" + }, + "secret_key": { + "constant_value": "4PxPNx0vkdZc1yVyD0LwAtYFmLoFl5QIcmOR5FTa" + }, + "token": { + "constant_value": "IQoJb3JpZ2luX2VjEKT//////////wEaCXVzLWVhc3QtMiJGMEQCIGWSSoA+mJPg9zLlxzNZksgKQCsqtYsEIplQvbgwcJmgAiBNxZ7hyPFORmLps3rSbyQs/OkN6N5ycxuru3Paons1GSqOAwhdEAMaDDg0NDMzMzU5NzUzNiIMV51T3H3mRwwxLVykKusC9wvfWonATRhipeSU8mj8Pi7/amzFwxLb6GhnDlLnuRV/caVOpjDR7WjJao5u1F4tO3wV7BTdlvotta5Px7flYorNqgHLtvHqgvA1FNmspk68/vNqS/fsT3gt+WGiUMRk/jel3nwz1pDbRZzwZw09ypAbayk0kpBHCl5ERPsnB+tKkmsByPc59UULMaLQvr6hl3x/AU+bxuUyhuOQMT+s0PoQvFLKh/tSDXqCZrSKnjl4cUYswKFuOTPk/9YBOcC/MQOjgN0SNM2Lq5i29MBmfFJYN0HZlJFlmvTTY0+hUqWCQ+d3qxfx57WZguKJMOObN0rnQ839wC+PlpE+TFFOl5WD/1d84cyZGnbqXHsuoRIfRW00Ty/9hSEJN0GdeKAv0O5GTrvT2dX7YsBgMIDmAE03ntz58Wy04WxRSrdVaM9kkIC7SuOiwm2BD9hJ46OU8fLntzrHoCm+VLSwSGDi0zRUTMXjqeeyGGIRMKTMvq0GOqcB5taXpMIF83kPcI659QQ1Hi7b9TxP/Y9M9Zai3IfPeKmWspIc03a9IbhrWm4v74dML693AfR4TSkDtUxOJ27dpmXYDHnpTz0oFHuXoCuPAYZis68qYg21RPaoVuWLMFR+QMsl4eVFXkkr59cCfP35AzzZmWImt4tKD1kf2hGQxmYkGPObkV1BZRR5rzM2gIZER69R0aPL765f45Q7myDdonJcxeK62PU=" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "test-bucket-demo-18012003" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_versioning.versioning_example", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "versioning_example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "versioning_configuration": [ + { + "status": { + "constant_value": "Enabled" + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-23T12:10:49Z", + "errored": false +} diff --git a/terraform-best-practices/aws/s3/enable-s3-versioning/test/good-terraform.tf b/terraform-best-practices/aws/s3/enable-s3-versioning/test/good-terraform.tf new file mode 100644 index 00000000..fd608df2 --- /dev/null +++ b/terraform-best-practices/aws/s3/enable-s3-versioning/test/good-terraform.tf @@ -0,0 +1,25 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_s3_bucket" "example" { + bucket = "test-bucket-demo-18012003" +} + +resource "aws_s3_bucket_versioning" "versioning_example" { + bucket = aws_s3_bucket.example.id + versioning_configuration { + status = "Enabled" + } +}