From f7a6a1df6e69311b27eaa8783605536551999367 Mon Sep 17 00:00:00 2001 From: Chandan-DK Date: Wed, 24 Jul 2024 17:04:04 +0000 Subject: [PATCH 1/3] add s3 best practices policies Signed-off-by: Chandan-DK --- .../abort-incomplete-uploads/README.md | 27 + .../abort-incomplete-uploads.yaml | 36 + .../test/bad-payload-01.json | 135 + .../test/bad-payload-02.json | 252 ++ .../test/bad-payload-03.json | 261 ++ .../test/bad-terraform-01.tf | 30 + .../test/bad-terraform-02.tf | 27 + .../test/bad-terraform-03.tf | 30 + .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 123 + .../test/good-payload.json | 278 +++ .../test/good-terraform.tf | 30 + .../disable-s3-acl/README.md | 35 + .../disable-s3-acl/disable-s3-acl.yaml | 28 + .../disable-s3-acl/test/bad-payload.json | 210 ++ .../disable-s3-acl/test/bad-terraform.tf | 26 + .../disable-s3-acl/test/binding.yaml | 3 + .../disable-s3-acl/test/chainsaw-test.yaml | 59 + .../disable-s3-acl/test/good-payload.json | 210 ++ .../disable-s3-acl/test/good-terraform.tf | 25 + .../enable-aws-cloudtrail/README.md | 29 + .../enable-aws-cloudtrail.yaml | 28 + .../test/bad-payload.json | 880 +++++++ .../test/bad-terraform.tf | 84 + .../enable-aws-cloudtrail/test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 86 + .../test/good-payload.json | 880 +++++++ .../test/good-payload2.json | 771 ++++++ .../test/good-terraform-01.tf | 84 + .../test/good-terraform-02.tf | 84 + .../enable-kms-encryption/README.md | 31 + .../enable-kms-encryption.yaml | 34 + .../test/bad-payload-01.json | 326 +++ .../test/bad-payload-02.json | 794 ++++++ .../test/bad-payload-03.json | 712 ++++++ .../test/bad-terraform-01.tf | 34 + .../test/bad-terraform-02.tf | 32 + .../test/bad-terraform-03.tf | 38 + .../enable-kms-encryption/test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 123 + .../test/good-payload.json | 326 +++ .../test/good-terraform.tf | 34 + .../enable-lifecycle-configuration/README.md | 30 + .../enable-lifecycle-configuration.yaml | 29 + .../test/bad-payload-01.json | 135 + .../test/bad-payload-02.json | 252 ++ .../test/bad-terraform-01.tf | 27 + .../test/bad-terraform-02.tf | 27 + .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 59 + .../test/good-payload.json | 252 ++ .../test/good-terraform.tf | 27 + .../README.md | 29 + .../s3-cross-region-replication.yaml | 32 + .../test/bad-payload-02.json | 1083 ++++++++ .../test/bad-payload.json | 1316 ++++++++++ .../test/bad-terraform.tf | 125 + .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 91 + .../test/good-payload.json | 2222 +++++++++++++++++ .../test/good-terraform.tf | 125 + .../enable-s3-server-access-logging/README.md | 33 + .../enable-server-access-logging.yaml | 28 + .../test/bad-payload.json | 357 +++ .../test/bad-terraform.tf | 32 + .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 59 + .../test/good-payload.json | 426 ++++ .../test/good-terraform.tf | 39 + .../enable-s3-versioning/README.md | 39 + .../s3-enable-versioning.yaml | 33 + .../test/bad-payload-01.json | 216 ++ .../test/bad-payload-02.json | 629 +++++ .../test/bad-terraform-01.tf | 25 + .../test/bad-terraform-02.tf | 18 + .../enable-s3-versioning/test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 91 + .../test/good-payload.json | 720 ++++++ .../test/good-terraform.tf | 25 + .../public-access-block/README.md | 79 + .../test/bad-payload-01.json | 202 ++ .../test/bad-payload-02.json | 202 ++ .../test/bad-payload-03.json | 203 ++ .../test/bad-payload-04.json | 203 ++ .../test/bad-terraform-01.tf | 27 + .../test/bad-terraform-02.tf | 27 + .../test/bad-terraform-03.tf | 27 + .../test/bad-terraform-04.tf | 27 + .../public-access-block/test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 182 ++ .../test/good-payload-01.json | 202 ++ .../test/good-payload-02.json | 203 ++ .../test/good-terraform-01.tf | 27 + .../test/good-terraform-02.tf | 27 + .../validate-public-access-block.yaml | 40 + .../validate-any-prinicpal/README.md | 59 + .../test/bad-payload-02.json | 255 ++ .../test/bad-payload.json | 260 ++ .../test/bad-terraform-01.tf | 48 + .../test/bad-terraform-02.tf | 50 + .../validate-any-prinicpal/test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 91 + .../test/good-payload.json | 260 ++ .../test/good-terraform.tf | 48 + .../validate-any-principal.yaml | 36 + 105 files changed, 18678 insertions(+) create mode 100644 terraform/plan/s3-best-practices/abort-incomplete-uploads/README.md create mode 100644 terraform/plan/s3-best-practices/abort-incomplete-uploads/abort-incomplete-uploads.yaml create mode 100644 terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-payload-01.json create mode 100644 terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-payload-02.json create mode 100644 terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-payload-03.json create mode 100644 terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-terraform-01.tf create mode 100644 terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-terraform-02.tf create mode 100644 terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-terraform-03.tf create mode 100644 terraform/plan/s3-best-practices/abort-incomplete-uploads/test/binding.yaml create mode 100644 terraform/plan/s3-best-practices/abort-incomplete-uploads/test/chainsaw-test.yaml create mode 100644 terraform/plan/s3-best-practices/abort-incomplete-uploads/test/good-payload.json create mode 100644 terraform/plan/s3-best-practices/abort-incomplete-uploads/test/good-terraform.tf create mode 100644 terraform/plan/s3-best-practices/disable-s3-acl/README.md create mode 100644 terraform/plan/s3-best-practices/disable-s3-acl/disable-s3-acl.yaml create mode 100644 terraform/plan/s3-best-practices/disable-s3-acl/test/bad-payload.json create mode 100644 terraform/plan/s3-best-practices/disable-s3-acl/test/bad-terraform.tf create mode 100644 terraform/plan/s3-best-practices/disable-s3-acl/test/binding.yaml create mode 100644 terraform/plan/s3-best-practices/disable-s3-acl/test/chainsaw-test.yaml create mode 100644 terraform/plan/s3-best-practices/disable-s3-acl/test/good-payload.json create mode 100644 terraform/plan/s3-best-practices/disable-s3-acl/test/good-terraform.tf create mode 100644 terraform/plan/s3-best-practices/enable-aws-cloudtrail/README.md create mode 100644 terraform/plan/s3-best-practices/enable-aws-cloudtrail/enable-aws-cloudtrail.yaml create mode 100644 terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/bad-payload.json create mode 100644 terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/bad-terraform.tf create mode 100644 terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/binding.yaml create mode 100644 terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/chainsaw-test.yaml create mode 100644 terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/good-payload.json create mode 100644 terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/good-payload2.json create mode 100644 terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/good-terraform-01.tf create mode 100644 terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/good-terraform-02.tf create mode 100644 terraform/plan/s3-best-practices/enable-kms-encryption/README.md create mode 100644 terraform/plan/s3-best-practices/enable-kms-encryption/enable-kms-encryption.yaml create mode 100644 terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-payload-01.json create mode 100644 terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-payload-02.json create mode 100644 terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-payload-03.json create mode 100644 terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-terraform-01.tf create mode 100644 terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-terraform-02.tf create mode 100644 terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-terraform-03.tf create mode 100644 terraform/plan/s3-best-practices/enable-kms-encryption/test/binding.yaml create mode 100644 terraform/plan/s3-best-practices/enable-kms-encryption/test/chainsaw-test.yaml create mode 100644 terraform/plan/s3-best-practices/enable-kms-encryption/test/good-payload.json create mode 100644 terraform/plan/s3-best-practices/enable-kms-encryption/test/good-terraform.tf create mode 100644 terraform/plan/s3-best-practices/enable-lifecycle-configuration/README.md create mode 100644 terraform/plan/s3-best-practices/enable-lifecycle-configuration/enable-lifecycle-configuration.yaml create mode 100644 terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/bad-payload-01.json create mode 100644 terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/bad-payload-02.json create mode 100644 terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/bad-terraform-01.tf create mode 100644 terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/bad-terraform-02.tf create mode 100644 terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/binding.yaml create mode 100644 terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/chainsaw-test.yaml create mode 100644 terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/good-payload.json create mode 100644 terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/good-terraform.tf create mode 100644 terraform/plan/s3-best-practices/enable-s3-cross-region-replication/README.md create mode 100644 terraform/plan/s3-best-practices/enable-s3-cross-region-replication/s3-cross-region-replication.yaml create mode 100644 terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/bad-payload-02.json create mode 100644 terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/bad-payload.json create mode 100644 terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/bad-terraform.tf create mode 100644 terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/binding.yaml create mode 100644 terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/chainsaw-test.yaml create mode 100644 terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/good-payload.json create mode 100644 terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/good-terraform.tf create mode 100644 terraform/plan/s3-best-practices/enable-s3-server-access-logging/README.md create mode 100644 terraform/plan/s3-best-practices/enable-s3-server-access-logging/enable-server-access-logging.yaml create mode 100644 terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/bad-payload.json create mode 100644 terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/bad-terraform.tf create mode 100644 terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/binding.yaml create mode 100644 terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/chainsaw-test.yaml create mode 100644 terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/good-payload.json create mode 100644 terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/good-terraform.tf create mode 100644 terraform/plan/s3-best-practices/enable-s3-versioning/README.md create mode 100644 terraform/plan/s3-best-practices/enable-s3-versioning/s3-enable-versioning.yaml create mode 100644 terraform/plan/s3-best-practices/enable-s3-versioning/test/bad-payload-01.json create mode 100644 terraform/plan/s3-best-practices/enable-s3-versioning/test/bad-payload-02.json create mode 100644 terraform/plan/s3-best-practices/enable-s3-versioning/test/bad-terraform-01.tf create mode 100644 terraform/plan/s3-best-practices/enable-s3-versioning/test/bad-terraform-02.tf create mode 100644 terraform/plan/s3-best-practices/enable-s3-versioning/test/binding.yaml create mode 100644 terraform/plan/s3-best-practices/enable-s3-versioning/test/chainsaw-test.yaml create mode 100644 terraform/plan/s3-best-practices/enable-s3-versioning/test/good-payload.json create mode 100644 terraform/plan/s3-best-practices/enable-s3-versioning/test/good-terraform.tf create mode 100644 terraform/plan/s3-best-practices/public-access-block/README.md create mode 100644 terraform/plan/s3-best-practices/public-access-block/test/bad-payload-01.json create mode 100644 terraform/plan/s3-best-practices/public-access-block/test/bad-payload-02.json create mode 100644 terraform/plan/s3-best-practices/public-access-block/test/bad-payload-03.json create mode 100644 terraform/plan/s3-best-practices/public-access-block/test/bad-payload-04.json create mode 100644 terraform/plan/s3-best-practices/public-access-block/test/bad-terraform-01.tf create mode 100644 terraform/plan/s3-best-practices/public-access-block/test/bad-terraform-02.tf create mode 100644 terraform/plan/s3-best-practices/public-access-block/test/bad-terraform-03.tf create mode 100644 terraform/plan/s3-best-practices/public-access-block/test/bad-terraform-04.tf create mode 100644 terraform/plan/s3-best-practices/public-access-block/test/binding.yaml create mode 100644 terraform/plan/s3-best-practices/public-access-block/test/chainsaw-test.yaml create mode 100644 terraform/plan/s3-best-practices/public-access-block/test/good-payload-01.json create mode 100644 terraform/plan/s3-best-practices/public-access-block/test/good-payload-02.json create mode 100644 terraform/plan/s3-best-practices/public-access-block/test/good-terraform-01.tf create mode 100644 terraform/plan/s3-best-practices/public-access-block/test/good-terraform-02.tf create mode 100644 terraform/plan/s3-best-practices/public-access-block/validate-public-access-block.yaml create mode 100644 terraform/plan/s3-best-practices/validate-any-prinicpal/README.md create mode 100644 terraform/plan/s3-best-practices/validate-any-prinicpal/test/bad-payload-02.json create mode 100644 terraform/plan/s3-best-practices/validate-any-prinicpal/test/bad-payload.json create mode 100644 terraform/plan/s3-best-practices/validate-any-prinicpal/test/bad-terraform-01.tf create mode 100644 terraform/plan/s3-best-practices/validate-any-prinicpal/test/bad-terraform-02.tf create mode 100644 terraform/plan/s3-best-practices/validate-any-prinicpal/test/binding.yaml create mode 100644 terraform/plan/s3-best-practices/validate-any-prinicpal/test/chainsaw-test.yaml create mode 100644 terraform/plan/s3-best-practices/validate-any-prinicpal/test/good-payload.json create mode 100644 terraform/plan/s3-best-practices/validate-any-prinicpal/test/good-terraform.tf create mode 100644 terraform/plan/s3-best-practices/validate-any-prinicpal/validate-any-principal.yaml diff --git a/terraform/plan/s3-best-practices/abort-incomplete-uploads/README.md b/terraform/plan/s3-best-practices/abort-incomplete-uploads/README.md new file mode 100644 index 00000000..d8045664 --- /dev/null +++ b/terraform/plan/s3-best-practices/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 --bindings ./binding.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/plan/s3-best-practices/abort-incomplete-uploads/abort-incomplete-uploads.yaml b/terraform/plan/s3-best-practices/abort-incomplete-uploads/abort-incomplete-uploads.yaml new file mode 100644 index 00000000..05e4ffc7 --- /dev/null +++ b/terraform/plan/s3-best-practices/abort-incomplete-uploads/abort-incomplete-uploads.yaml @@ -0,0 +1,36 @@ +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: + - ($analyzer.resource.type): terraform-plan + - (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 || `-1`) > `0`): true + diff --git a/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-payload-01.json b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-payload-01.json new file mode 100644 index 00000000..af06160d --- /dev/null +++ b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-payload-01.json @@ -0,0 +1,135 @@ +{ + "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": [] + } + } + ] + } + }, + "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": [] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + } + } + }, + "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 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-31T12:04:06Z", + "errored": false + } + \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-payload-02.json b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-payload-02.json new file mode 100644 index 00000000..e49a6966 --- /dev/null +++ b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-payload-02.json @@ -0,0 +1,252 @@ +{ + "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": { + } + } + }, + "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-31T12:12:52Z", + "errored": false +} diff --git a/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-payload-03.json b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-payload-03.json new file mode 100644 index 00000000..e0a8be4a --- /dev/null +++ b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-payload-03.json @@ -0,0 +1,261 @@ +{ + "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": [ + { + "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": { + } + } + }, + "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:04:06Z", + "errored": false +} diff --git a/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-terraform-01.tf b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-terraform-01.tf new file mode 100644 index 00000000..a5481c00 --- /dev/null +++ b/terraform/plan/s3-best-practices/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/plan/s3-best-practices/abort-incomplete-uploads/test/bad-terraform-02.tf b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-terraform-02.tf new file mode 100644 index 00000000..d549a0d1 --- /dev/null +++ b/terraform/plan/s3-best-practices/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/plan/s3-best-practices/abort-incomplete-uploads/test/bad-terraform-03.tf b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-terraform-03.tf new file mode 100644 index 00000000..85984b15 --- /dev/null +++ b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/bad-terraform-03.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 = "Disabled" + abort_incomplete_multipart_upload { + + } + } +} diff --git a/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/binding.yaml b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/chainsaw-test.yaml b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/chainsaw-test.yaml new file mode 100644 index 00000000..fb96d5a4 --- /dev/null +++ b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/chainsaw-test.yaml @@ -0,0 +1,123 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../abort-incomplete-uploads.yaml --payload ./good-payload.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: abort-incomplete-uploads + rules: + - rule: + name: abort-incomplete-uploads + error: ~ + violations: ~ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../abort-incomplete-uploads.yaml --payload ./bad-payload-01.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: abort-incomplete-uploads + rules: + - rule: + name: abort-incomplete-uploads + error: ~ + violations: + - message: Use the `aws_s3_bucket_lifecycle_configuration` resource to enable lifecycle configuration. + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-02 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../abort-incomplete-uploads.yaml --payload ./bad-payload-02.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: abort-incomplete-uploads + rules: + - rule: + name: abort-incomplete-uploads + error: ~ + violations: + - message: S3 Bucket Lifecycle Configuration 'status' needs to be set to 'Enabled' + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-03 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../abort-incomplete-uploads.yaml --payload ./bad-payload-03.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: abort-incomplete-uploads + rules: + - rule: + name: abort-incomplete-uploads + error: ~ + violations: + - message: Set the 'days_after_initiation' argument value to a Positive Integer value in 'abort_incomplete_multipart_upload' inside the lifecycle configuration block + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/good-payload.json b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/good-payload.json new file mode 100644 index 00000000..80915e23 --- /dev/null +++ b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/good-payload.json @@ -0,0 +1,278 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "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": { + "region": { + "constant_value": "us-west-2" + } + } + } + }, + "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-07-15T10:46:28Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/good-terraform.tf b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/good-terraform.tf new file mode 100644 index 00000000..559aac67 --- /dev/null +++ b/terraform/plan/s3-best-practices/abort-incomplete-uploads/test/good-terraform.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 { + days_after_initiation = 12 + } + } +} diff --git a/terraform/plan/s3-best-practices/disable-s3-acl/README.md b/terraform/plan/s3-best-practices/disable-s3-acl/README.md new file mode 100644 index 00000000..8b78b0f7 --- /dev/null +++ b/terraform/plan/s3-best-practices/disable-s3-acl/README.md @@ -0,0 +1,35 @@ +The Access Control List (ACL) by default is disabled for an S3 Bucket. However, if you'd like to disable the ACL while creating an S3 Bucket from a Terraform file, there are three options that you can provide to the `object_ownership` field in your Terraform file. + +**ACLs disabled**: +- *Bucket owner enforced (default)* – ACLs are disabled, and the bucket owner automatically owns and has full control over every object in the bucket. ACLs no longer affect permissions to data in the S3 bucket. The bucket uses policies to define access control. + +**ACLs enabled**: +- *Bucket owner preferred* – The bucket owner owns and has full control over new objects that other accounts write to the bucket with the bucket-owner-full-control canned ACL. + +- *Object writer* – The AWS account that uploads an object owns the object, has full control over it, and can grant other users access to it through ACLs. + +You can read more information about [Controlling ownership of objects and disabling ACLs for your bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/about-object-ownership.html?icmpid=docs_amazons3_console). + +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 --bindings ./binding.yaml + ``` + Since you've set the `object_ownership` field to `BucketOwnerEnforced` in *s3-disable.tf* file, the policy will give you Passing checks. If you try to change the value of `object_ownership` to either `BucketOwnerPreferred` or `ObjectWriter` 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/policy-test/bad-payload.json` and run the `kyverno-json scan` command again. \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/disable-s3-acl/disable-s3-acl.yaml b/terraform/plan/s3-best-practices/disable-s3-acl/disable-s3-acl.yaml new file mode 100644 index 00000000..373c40b4 --- /dev/null +++ b/terraform/plan/s3-best-practices/disable-s3-acl/disable-s3-acl.yaml @@ -0,0 +1,28 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: disable-s3-access-control-list + annotations: + policies.kyverno.io/title: Disable S3 Access Control List + policies.kyverno.io/category: AWS S3 Security Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + S3 Object Ownership is an Amazon S3 bucket-level setting that + you can use to control ownership of objects uploaded to your bucket + and to disable or enable ACLs. By default, Object Ownership is set to + the Bucket owner enforced setting and all ACLs are disabled. + When ACLs are disabled, the bucket owner owns all the objects in the bucket + and manages access to data exclusively using access management policies. +spec: + rules: + - name: disable-s3-access-control-list + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_s3_bucket_ownership_controls' || type=='aws_s3_bucket'] | length(@) > `0`): true + assert: + all: + - message: Access Control List(ACL) should be disabled for an S3 Bucket + check: + ~.(planned_values.root_module.resources[?type=='aws_s3_bucket_ownership_controls'].values.rule[]): + object_ownership: BucketOwnerEnforced \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/disable-s3-acl/test/bad-payload.json b/terraform/plan/s3-best-practices/disable-s3-acl/test/bad-payload.json new file mode 100644 index 00000000..1e9ffa56 --- /dev/null +++ b/terraform/plan/s3-best-practices/disable-s3-acl/test/bad-payload.json @@ -0,0 +1,210 @@ +{ + "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-19012003", + "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_ownership_controls.example", + "mode": "managed", + "type": "aws_s3_bucket_ownership_controls", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "rule": [ + { + "object_ownership": "ObjectWriter" + } + ] + }, + "sensitive_values": { + "rule": [ + {} + ] + } + } + ] + } + }, + "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-19012003", + "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_ownership_controls.example", + "mode": "managed", + "type": "aws_s3_bucket_ownership_controls", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "rule": [ + { + "object_ownership": "ObjectWriter" + } + ] + }, + "after_unknown": { + "bucket": true, + "id": true, + "rule": [ + {} + ] + }, + "before_sensitive": false, + "after_sensitive": { + "rule": [ + {} + ] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + } + } + }, + "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-19012003" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_ownership_controls.example", + "mode": "managed", + "type": "aws_s3_bucket_ownership_controls", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "rule": [ + { + "object_ownership": { + "constant_value": "ObjectWriter" + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-19T13:21:17Z", + "errored": false +} diff --git a/terraform/plan/s3-best-practices/disable-s3-acl/test/bad-terraform.tf b/terraform/plan/s3-best-practices/disable-s3-acl/test/bad-terraform.tf new file mode 100644 index 00000000..49c49d3d --- /dev/null +++ b/terraform/plan/s3-best-practices/disable-s3-acl/test/bad-terraform.tf @@ -0,0 +1,26 @@ +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-19012003" +} + +resource "aws_s3_bucket_ownership_controls" "example" { + bucket = aws_s3_bucket.example.id + rule { + object_ownership = "ObjectWriter" + } +} + diff --git a/terraform/plan/s3-best-practices/disable-s3-acl/test/binding.yaml b/terraform/plan/s3-best-practices/disable-s3-acl/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/s3-best-practices/disable-s3-acl/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/disable-s3-acl/test/chainsaw-test.yaml b/terraform/plan/s3-best-practices/disable-s3-acl/test/chainsaw-test.yaml new file mode 100644 index 00000000..8edbd01f --- /dev/null +++ b/terraform/plan/s3-best-practices/disable-s3-acl/test/chainsaw-test.yaml @@ -0,0 +1,59 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../disable-s3-acl.yaml --payload ./good-payload.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: disable-s3-access-control-list + rules: + - rule: + name: disable-s3-access-control-list + error: ~ + violations: ~ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../disable-s3-acl.yaml --payload ./bad-payload.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: disable-s3-access-control-list + rules: + - rule: + name: disable-s3-access-control-list + error: ~ + violations: + - message: Access Control List(ACL) should be disabled for an S3 Bucket + errors: + - type: FieldValueInvalid + (value=='BucketOwnerEnforced'): false + detail: "Expected value: \"BucketOwnerEnforced\"" diff --git a/terraform/plan/s3-best-practices/disable-s3-acl/test/good-payload.json b/terraform/plan/s3-best-practices/disable-s3-acl/test/good-payload.json new file mode 100644 index 00000000..81de3c48 --- /dev/null +++ b/terraform/plan/s3-best-practices/disable-s3-acl/test/good-payload.json @@ -0,0 +1,210 @@ +{ + "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_ownership_controls.example", + "mode": "managed", + "type": "aws_s3_bucket_ownership_controls", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "rule": [ + { + "object_ownership": "BucketOwnerEnforced" + } + ] + }, + "sensitive_values": { + "rule": [ + {} + ] + } + } + ] + } + }, + "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_ownership_controls.example", + "mode": "managed", + "type": "aws_s3_bucket_ownership_controls", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "rule": [ + { + "object_ownership": "BucketOwnerEnforced" + } + ] + }, + "after_unknown": { + "bucket": true, + "id": true, + "rule": [ + {} + ] + }, + "before_sensitive": false, + "after_sensitive": { + "rule": [ + {} + ] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + } + } + }, + "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_ownership_controls.example", + "mode": "managed", + "type": "aws_s3_bucket_ownership_controls", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "rule": [ + { + "object_ownership": { + "constant_value": "BucketOwnerEnforced" + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-19T12:05:57Z", + "errored": false +} diff --git a/terraform/plan/s3-best-practices/disable-s3-acl/test/good-terraform.tf b/terraform/plan/s3-best-practices/disable-s3-acl/test/good-terraform.tf new file mode 100644 index 00000000..5f3a7cbc --- /dev/null +++ b/terraform/plan/s3-best-practices/disable-s3-acl/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_ownership_controls" "example" { + bucket = aws_s3_bucket.example.id + rule { + object_ownership = "BucketOwnerEnforced" + } +} diff --git a/terraform/plan/s3-best-practices/enable-aws-cloudtrail/README.md b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/README.md new file mode 100644 index 00000000..3f1c2db7 --- /dev/null +++ b/terraform/plan/s3-best-practices/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 --bindings ./binding.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/plan/s3-best-practices/enable-aws-cloudtrail/enable-aws-cloudtrail.yaml b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/enable-aws-cloudtrail.yaml new file mode 100644 index 00000000..a2a300c8 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/enable-aws-cloudtrail.yaml @@ -0,0 +1,28 @@ +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: + - ($analyzer.resource.type): terraform-plan + - (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/plan/s3-best-practices/enable-aws-cloudtrail/test/bad-payload.json b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/bad-payload.json new file mode 100644 index 00000000..cc93105b --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/bad-payload.json @@ -0,0 +1,880 @@ +{ + "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": { + } + } + }, + "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/plan/s3-best-practices/enable-aws-cloudtrail/test/bad-terraform.tf b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/bad-terraform.tf new file mode 100644 index 00000000..c27bb760 --- /dev/null +++ b/terraform/plan/s3-best-practices/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/plan/s3-best-practices/enable-aws-cloudtrail/test/binding.yaml b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/chainsaw-test.yaml b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/chainsaw-test.yaml new file mode 100644 index 00000000..83e09a46 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/chainsaw-test.yaml @@ -0,0 +1,86 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../enable-aws-cloudtrail.yaml --payload ./good-payload.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: enable-aws-cloudtrail + rules: + - rule: + name: check-aws-cloudtrail-logging + error: ~ + violations: ~ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test-02 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../enable-aws-cloudtrail.yaml --payload ./good-payload2.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: enable-aws-cloudtrail + rules: + - rule: + name: check-aws-cloudtrail-logging + error: ~ + violations: ~ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../enable-aws-cloudtrail.yaml --payload ./bad-payload.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: enable-aws-cloudtrail + rules: + - rule: + name: check-aws-cloudtrail-logging + error: ~ + violations: + - message: Set the enable_logging argument in aws_cloudtrail resource to true + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' diff --git a/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/good-payload.json b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/good-payload.json new file mode 100644 index 00000000..3ec747bb --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/good-payload.json @@ -0,0 +1,880 @@ +{ + "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": { + } + } + }, + "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/plan/s3-best-practices/enable-aws-cloudtrail/test/good-payload2.json b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/good-payload2.json new file mode 100644 index 00000000..30b3c7bc --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/good-payload2.json @@ -0,0 +1,771 @@ +{ + "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": { + } + } + }, + "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/plan/s3-best-practices/enable-aws-cloudtrail/test/good-terraform-01.tf b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/good-terraform-01.tf new file mode 100644 index 00000000..202b3448 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/good-terraform-01.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 = 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/plan/s3-best-practices/enable-aws-cloudtrail/test/good-terraform-02.tf b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/good-terraform-02.tf new file mode 100644 index 00000000..6f719180 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-aws-cloudtrail/test/good-terraform-02.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 = 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/plan/s3-best-practices/enable-kms-encryption/README.md b/terraform/plan/s3-best-practices/enable-kms-encryption/README.md new file mode 100644 index 00000000..3f8cfe3f --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-kms-encryption/README.md @@ -0,0 +1,31 @@ +Server-side encryption is the encryption of data at its destination by the application or service that receives it. Amazon S3 encrypts your data at the object level as it writes it to disks in AWS data centers and decrypts it for you when you access it. As long as you authenticate your request and you have access permissions, there is no difference in the way you access encrypted or unencrypted objects. For example, if you share your objects by using a presigned URL, that URL works the same way for both encrypted and unencrypted objects. Additionally, when you list objects in your bucket, the list API operations return a list of all objects, regardless of whether they are encrypted. + +You have four mutually exclusive options for server-side encryption, depending on how you choose to manage the encryption keys and the number of encryption layers that you want to apply. + +1. **Server-side encryption with Amazon S3 managed keys (SSE-S3):** All Amazon S3 buckets have encryption configured by default. The default option for server-side encryption is with Amazon S3 managed keys (SSE-S3). Each object is encrypted with a unique key. As an additional safeguard, SSE-S3 encrypts the key itself with a root key that it regularly rotates. SSE-S3 uses one of the strongest block ciphers available, 256-bit Advanced Encryption Standard (AES-256), to encrypt your data. For more information, see Using server-side encryption with Amazon S3 managed keys (SSE-S3). + +2. **Server-side encryption with AWS Key Management Service (AWS KMS) keys (SSE-KMS):** Server-side encryption with AWS KMS keys (SSE-KMS) is provided through an integration of the AWS KMS service with Amazon S3. With AWS KMS, you have more control over your keys. For example, you can view separate keys, edit control policies, and follow the keys in AWS CloudTrail. Additionally, you can create and manage customer managed keys or use AWS managed keys that are unique to you, your service, and your Region. For more information, see Using server-side encryption with AWS KMS keys (SSE-KMS). + +3. **Dual-layer server-side encryption with AWS Key Management Service (AWS KMS) keys (DSSE-KMS):** Dual-layer server-side encryption with AWS KMS keys (DSSE-KMS) is similar to SSE-KMS, but DSSE-KMS applies two individual layers of object-level encryption instead of one layer. Because both layers of encryption are applied to an object on the server side, you can use a wide range of AWS services and tools to analyze data in S3 while using an encryption method that can satisfy your compliance requirements. For more information, see Using dual-layer server-side encryption with AWS KMS keys (DSSE-KMS). + +4. **Server-side encryption with customer-provided keys (SSE-C):** With server-side encryption with customer-provided keys (SSE-C), you manage the encryption keys, and Amazon S3 manages the encryption as it writes to disks and the decryption when you access your objects. For more information, see Using server-side encryption with customer-provided keys (SSE-C). + +It is important to note that the *sse_algorithm* is the field in the terraform file that will determine what type of encryption will be applied to S3. By default, if you don't specify any value or don't use the block, *sse_algorithm* will be set to *AES256*. You can read more about the *aws_s3_bucket_server_side_encryption_configuration* block [here](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_server_side_encryption_configuration). + +In order to test this policy, use the following commands: + +1. Navigate to the `aws/s3/terraform/enable-kms-encryption` 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 --bindings ./binding.yaml + ``` + Since you've set the value of *sse_algorithm* to *aws:kms*, 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. \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-kms-encryption/enable-kms-encryption.yaml b/terraform/plan/s3-best-practices/enable-kms-encryption/enable-kms-encryption.yaml new file mode 100644 index 00000000..b8686e37 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-kms-encryption/enable-kms-encryption.yaml @@ -0,0 +1,34 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: s3-enable-kms-encryption + annotations: + policies.kyverno.io/title: s3-enable-kms-encryption + policies.kyverno.io/category: AWS S3 Security Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + All Amazon S3 buckets have encryption configured by default, + and all new objects that are uploaded to an S3 bucket are automatically + encrypted at rest. Server-side encryption with Amazon S3 managed keys (SSE-S3) + is the default encryption configuration for every bucket in Amazon S3. To use a + different type of encryption, you can either specify the type of server-side encryption + to use in your S3 PUT requests, or you can set the default encryption configuration in + the destination bucket. +spec: + rules: + - name: check-encryption-setting + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_s3_bucket'] | length(@) > `0`): true + assert: + all: + - message: Use the `aws_s3_bucket_server_side_encryption_configuration ` resource to set the S3 server side encryption to KMS + check: + (planned_values.root_module.resources[?type=='aws_s3_bucket_server_side_encryption_configuration'] | length(@) > `0`): true + - message: S3 server side encryption is not set to KMS + check: + ~.(planned_values.root_module.resources[?type=='aws_s3_bucket_server_side_encryption_configuration']): + ~.(values.rule[]): + (apply_server_side_encryption_by_default[?sse_algorithm=='aws:kms'] | length(@) > `0`): true + diff --git a/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-payload-01.json b/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-payload-01.json new file mode 100644 index 00000000..243ec858 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-payload-01.json @@ -0,0 +1,326 @@ +{ + "format_version": "1.2", + "terraform_version": "1.6.6", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_kms_key.mykey", + "mode": "managed", + "type": "aws_kms_key", + "name": "mykey", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bypass_policy_lockout_safety_check": false, + "custom_key_store_id": null, + "customer_master_key_spec": "SYMMETRIC_DEFAULT", + "deletion_window_in_days": 10, + "description": "This key is used to encrypt bucket objects", + "enable_key_rotation": false, + "is_enabled": true, + "key_usage": "ENCRYPT_DECRYPT", + "tags": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_s3_bucket.mybucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "mybucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "test-bucket-23-01-2024", + "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_server_side_encryption_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_server_side_encryption_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "expected_bucket_owner": null, + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "sse_algorithm": "AES256" + } + ], + "bucket_key_enabled": null + } + ] + }, + "sensitive_values": { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + {} + ] + } + ] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_kms_key.mykey", + "mode": "managed", + "type": "aws_kms_key", + "name": "mykey", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bypass_policy_lockout_safety_check": false, + "custom_key_store_id": null, + "customer_master_key_spec": "SYMMETRIC_DEFAULT", + "deletion_window_in_days": 10, + "description": "This key is used to encrypt bucket objects", + "enable_key_rotation": false, + "is_enabled": true, + "key_usage": "ENCRYPT_DECRYPT", + "tags": null + }, + "after_unknown": { + "arn": true, + "id": true, + "key_id": true, + "multi_region": true, + "policy": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_s3_bucket.mybucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "mybucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "test-bucket-23-01-2024", + "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_server_side_encryption_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_server_side_encryption_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "expected_bucket_owner": null, + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "sse_algorithm": "AES256" + } + ], + "bucket_key_enabled": null + } + ] + }, + "after_unknown": { + "bucket": true, + "id": true, + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": true + } + ] + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + {} + ] + } + ] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_kms_key.mykey", + "mode": "managed", + "type": "aws_kms_key", + "name": "mykey", + "provider_config_key": "aws", + "expressions": { + "deletion_window_in_days": { + "constant_value": 10 + }, + "description": { + "constant_value": "This key is used to encrypt bucket objects" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket.mybucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "mybucket", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "test-bucket-23-01-2024" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_server_side_encryption_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_server_side_encryption_configuration", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.mybucket.id", + "aws_s3_bucket.mybucket" + ] + }, + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": { + "references": [ + "aws_kms_key.mykey.arn", + "aws_kms_key.mykey" + ] + }, + "sse_algorithm": { + "constant_value": "AES256" + } + } + ] + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.mybucket", + "attribute": [ + "id" + ] + }, + { + "resource": "aws_kms_key.mykey", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-01-23T10:20:26Z", + "errored": false +} diff --git a/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-payload-02.json b/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-payload-02.json new file mode 100644 index 00000000..93e583d0 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-payload-02.json @@ -0,0 +1,794 @@ +{ + "format_version": "1.2", + "terraform_version": "1.6.6", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_kms_key.mykey", + "mode": "managed", + "type": "aws_kms_key", + "name": "mykey", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bypass_policy_lockout_safety_check": false, + "custom_key_store_id": null, + "customer_master_key_spec": "SYMMETRIC_DEFAULT", + "deletion_window_in_days": 10, + "description": "This key is used to encrypt bucket objects", + "enable_key_rotation": false, + "is_enabled": true, + "key_usage": "ENCRYPT_DECRYPT", + "tags": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_s3_bucket.mybucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "mybucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::nitish-s3-bucket-encryption", + "bucket": "nitish-s3-bucket-encryption", + "bucket_domain_name": "nitish-s3-bucket-encryption.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "nitish-s3-bucket-encryption.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": "nitish-s3-bucket-encryption", + "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_server_side_encryption_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_server_side_encryption_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "nitish-s3-bucket-encryption", + "expected_bucket_owner": null, + "rule": [ + { + "apply_server_side_encryption_by_default": [], + "bucket_key_enabled": null + } + ] + }, + "sensitive_values": { + "rule": [ + { + "apply_server_side_encryption_by_default": [] + } + ] + } + } + ] + } + }, + "resource_drift": [ + { + "address": "aws_s3_bucket.mybucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "mybucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "update" + ], + "before": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::nitish-s3-bucket-encryption", + "bucket": "nitish-s3-bucket-encryption", + "bucket_domain_name": "nitish-s3-bucket-encryption.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "nitish-s3-bucket-encryption.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": "nitish-s3-bucket-encryption", + "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:::nitish-s3-bucket-encryption", + "bucket": "nitish-s3-bucket-encryption", + "bucket_domain_name": "nitish-s3-bucket-encryption.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "nitish-s3-bucket-encryption.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": "nitish-s3-bucket-encryption", + "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_kms_key.mykey", + "mode": "managed", + "type": "aws_kms_key", + "name": "mykey", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bypass_policy_lockout_safety_check": false, + "custom_key_store_id": null, + "customer_master_key_spec": "SYMMETRIC_DEFAULT", + "deletion_window_in_days": 10, + "description": "This key is used to encrypt bucket objects", + "enable_key_rotation": false, + "is_enabled": true, + "key_usage": "ENCRYPT_DECRYPT", + "tags": null + }, + "after_unknown": { + "arn": true, + "id": true, + "key_id": true, + "multi_region": true, + "policy": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_s3_bucket.mybucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "mybucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "no-op" + ], + "before": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::nitish-s3-bucket-encryption", + "bucket": "nitish-s3-bucket-encryption", + "bucket_domain_name": "nitish-s3-bucket-encryption.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "nitish-s3-bucket-encryption.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": "nitish-s3-bucket-encryption", + "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:::nitish-s3-bucket-encryption", + "bucket": "nitish-s3-bucket-encryption", + "bucket_domain_name": "nitish-s3-bucket-encryption.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "nitish-s3-bucket-encryption.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": "nitish-s3-bucket-encryption", + "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_server_side_encryption_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_server_side_encryption_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "nitish-s3-bucket-encryption", + "expected_bucket_owner": null, + "rule": [ + { + "apply_server_side_encryption_by_default": [], + "bucket_key_enabled": null + } + ] + }, + "after_unknown": { + "id": true, + "rule": [ + { + "apply_server_side_encryption_by_default": [] + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "rule": [ + { + "apply_server_side_encryption_by_default": [] + } + ] + } + } + } + ], + "prior_state": { + "format_version": "1.0", + "terraform_version": "1.6.6", + "values": { + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.mybucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "mybucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::nitish-s3-bucket-encryption", + "bucket": "nitish-s3-bucket-encryption", + "bucket_domain_name": "nitish-s3-bucket-encryption.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "nitish-s3-bucket-encryption.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": "nitish-s3-bucket-encryption", + "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": { + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_kms_key.mykey", + "mode": "managed", + "type": "aws_kms_key", + "name": "mykey", + "provider_config_key": "aws", + "expressions": { + "deletion_window_in_days": { + "constant_value": 10 + }, + "description": { + "constant_value": "This key is used to encrypt bucket objects" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket.mybucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "mybucket", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "nitish-s3-bucket-encryption" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_server_side_encryption_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_server_side_encryption_configuration", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.mybucket.id", + "aws_s3_bucket.mybucket" + ] + }, + "rule": [ + {} + ] + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.mybucket", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-18T19:12:30Z", + "errored": false +} diff --git a/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-payload-03.json b/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-payload-03.json new file mode 100644 index 00000000..a94a2d20 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-payload-03.json @@ -0,0 +1,712 @@ +{ + "format_version": "1.2", + "terraform_version": "1.6.6", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_kms_key.mykey", + "mode": "managed", + "type": "aws_kms_key", + "name": "mykey", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bypass_policy_lockout_safety_check": false, + "custom_key_store_id": null, + "customer_master_key_spec": "SYMMETRIC_DEFAULT", + "deletion_window_in_days": 10, + "description": "This key is used to encrypt bucket objects", + "enable_key_rotation": false, + "is_enabled": true, + "key_usage": "ENCRYPT_DECRYPT", + "tags": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_s3_bucket.mybucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "mybucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::nitish-s3-bucket-encryption", + "bucket": "nitish-s3-bucket-encryption", + "bucket_domain_name": "nitish-s3-bucket-encryption.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "nitish-s3-bucket-encryption.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": "nitish-s3-bucket-encryption", + "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.mybucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "mybucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "update" + ], + "before": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::nitish-s3-bucket-encryption", + "bucket": "nitish-s3-bucket-encryption", + "bucket_domain_name": "nitish-s3-bucket-encryption.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "nitish-s3-bucket-encryption.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": "nitish-s3-bucket-encryption", + "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:::nitish-s3-bucket-encryption", + "bucket": "nitish-s3-bucket-encryption", + "bucket_domain_name": "nitish-s3-bucket-encryption.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "nitish-s3-bucket-encryption.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": "nitish-s3-bucket-encryption", + "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_kms_key.mykey", + "mode": "managed", + "type": "aws_kms_key", + "name": "mykey", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bypass_policy_lockout_safety_check": false, + "custom_key_store_id": null, + "customer_master_key_spec": "SYMMETRIC_DEFAULT", + "deletion_window_in_days": 10, + "description": "This key is used to encrypt bucket objects", + "enable_key_rotation": false, + "is_enabled": true, + "key_usage": "ENCRYPT_DECRYPT", + "tags": null + }, + "after_unknown": { + "arn": true, + "id": true, + "key_id": true, + "multi_region": true, + "policy": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_s3_bucket.mybucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "mybucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "no-op" + ], + "before": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::nitish-s3-bucket-encryption", + "bucket": "nitish-s3-bucket-encryption", + "bucket_domain_name": "nitish-s3-bucket-encryption.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "nitish-s3-bucket-encryption.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": "nitish-s3-bucket-encryption", + "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:::nitish-s3-bucket-encryption", + "bucket": "nitish-s3-bucket-encryption", + "bucket_domain_name": "nitish-s3-bucket-encryption.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "nitish-s3-bucket-encryption.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": "nitish-s3-bucket-encryption", + "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.mybucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "mybucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::nitish-s3-bucket-encryption", + "bucket": "nitish-s3-bucket-encryption", + "bucket_domain_name": "nitish-s3-bucket-encryption.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "nitish-s3-bucket-encryption.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": "nitish-s3-bucket-encryption", + "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": { + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_kms_key.mykey", + "mode": "managed", + "type": "aws_kms_key", + "name": "mykey", + "provider_config_key": "aws", + "expressions": { + "deletion_window_in_days": { + "constant_value": 10 + }, + "description": { + "constant_value": "This key is used to encrypt bucket objects" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket.mybucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "mybucket", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "nitish-s3-bucket-encryption" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.mybucket", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-18T19:12:30Z", + "errored": false + } + \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-terraform-01.tf b/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-terraform-01.tf new file mode 100644 index 00000000..6f3c54b6 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-terraform-01.tf @@ -0,0 +1,34 @@ +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" "mybucket" { + bucket = "test-bucket-23-01-2024" +} + +resource "aws_kms_key" "mykey" { + description = "This key is used to encrypt bucket objects" + deletion_window_in_days = 10 +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "example" { + bucket = aws_s3_bucket.mybucket.id + + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = aws_kms_key.mykey.arn + sse_algorithm = "AES256" + } + } +} \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-terraform-02.tf b/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-terraform-02.tf new file mode 100644 index 00000000..276a6ada --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-terraform-02.tf @@ -0,0 +1,32 @@ +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" "mybucket" { + bucket = "test-bucket-23-01-2024" +} + +resource "aws_kms_key" "mykey" { + description = "This key is used to encrypt bucket objects" + deletion_window_in_days = 10 +} + +// empty rule (default value will be used in this case) +resource "aws_s3_bucket_server_side_encryption_configuration" "example" { + bucket = aws_s3_bucket.mybucket.id + + rule { + + } +} \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-terraform-03.tf b/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-terraform-03.tf new file mode 100644 index 00000000..f1eaf4f9 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-kms-encryption/test/bad-terraform-03.tf @@ -0,0 +1,38 @@ +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" "mybucket" { + bucket = "test-bucket-23-01-2024" +} + +resource "aws_kms_key" "mykey" { + description = "This key is used to encrypt bucket objects" + deletion_window_in_days = 10 +} + +/* +resource "aws_s3_bucket_server_side_encryption_configuration" "example" { + bucket = aws_s3_bucket.mybucket.id + + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = aws_kms_key.mykey.arn + sse_algorithm = "AES256" + } + } +} +*/ + +# No resource block specified, hence default value for server side encryption will be used here \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-kms-encryption/test/binding.yaml b/terraform/plan/s3-best-practices/enable-kms-encryption/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-kms-encryption/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-kms-encryption/test/chainsaw-test.yaml b/terraform/plan/s3-best-practices/enable-kms-encryption/test/chainsaw-test.yaml new file mode 100644 index 00000000..90eb1f70 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-kms-encryption/test/chainsaw-test.yaml @@ -0,0 +1,123 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../enable-kms-encryption.yaml --payload ./good-payload.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: s3-enable-kms-encryption + rules: + - rule: + name: check-encryption-setting + error: ~ + violations: ~ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../enable-kms-encryption.yaml --payload ./bad-payload-01.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: s3-enable-kms-encryption + rules: + - rule: + name: check-encryption-setting + error: ~ + violations: + - message: S3 server side encryption is not set to KMS + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-02 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../enable-kms-encryption.yaml --payload ./bad-payload-02.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: s3-enable-kms-encryption + rules: + - rule: + name: check-encryption-setting + error: ~ + violations: + - message: S3 server side encryption is not set to KMS + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-03 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../enable-kms-encryption.yaml --payload ./bad-payload-03.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: s3-enable-kms-encryption + rules: + - rule: + name: check-encryption-setting + error: ~ + violations: + - message: Use the `aws_s3_bucket_server_side_encryption_configuration ` resource to set the S3 server side encryption to KMS + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' diff --git a/terraform/plan/s3-best-practices/enable-kms-encryption/test/good-payload.json b/terraform/plan/s3-best-practices/enable-kms-encryption/test/good-payload.json new file mode 100644 index 00000000..70aa6ecd --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-kms-encryption/test/good-payload.json @@ -0,0 +1,326 @@ +{ + "format_version": "1.2", + "terraform_version": "1.6.6", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_kms_key.mykey", + "mode": "managed", + "type": "aws_kms_key", + "name": "mykey", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bypass_policy_lockout_safety_check": false, + "custom_key_store_id": null, + "customer_master_key_spec": "SYMMETRIC_DEFAULT", + "deletion_window_in_days": 10, + "description": "This key is used to encrypt bucket objects", + "enable_key_rotation": false, + "is_enabled": true, + "key_usage": "ENCRYPT_DECRYPT", + "tags": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_s3_bucket.mybucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "mybucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "test-bucket-23-01-2024", + "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_server_side_encryption_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_server_side_encryption_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "expected_bucket_owner": null, + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "sse_algorithm": "aws:kms" + } + ], + "bucket_key_enabled": null + } + ] + }, + "sensitive_values": { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + {} + ] + } + ] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_kms_key.mykey", + "mode": "managed", + "type": "aws_kms_key", + "name": "mykey", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bypass_policy_lockout_safety_check": false, + "custom_key_store_id": null, + "customer_master_key_spec": "SYMMETRIC_DEFAULT", + "deletion_window_in_days": 10, + "description": "This key is used to encrypt bucket objects", + "enable_key_rotation": false, + "is_enabled": true, + "key_usage": "ENCRYPT_DECRYPT", + "tags": null + }, + "after_unknown": { + "arn": true, + "id": true, + "key_id": true, + "multi_region": true, + "policy": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_s3_bucket.mybucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "mybucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "test-bucket-23-01-2024", + "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_server_side_encryption_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_server_side_encryption_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "expected_bucket_owner": null, + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "sse_algorithm": "aws:kms" + } + ], + "bucket_key_enabled": null + } + ] + }, + "after_unknown": { + "bucket": true, + "id": true, + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": true + } + ] + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "rule": [ + { + "apply_server_side_encryption_by_default": [ + {} + ] + } + ] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_kms_key.mykey", + "mode": "managed", + "type": "aws_kms_key", + "name": "mykey", + "provider_config_key": "aws", + "expressions": { + "deletion_window_in_days": { + "constant_value": 10 + }, + "description": { + "constant_value": "This key is used to encrypt bucket objects" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket.mybucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "mybucket", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "test-bucket-23-01-2024" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_server_side_encryption_configuration.example", + "mode": "managed", + "type": "aws_s3_bucket_server_side_encryption_configuration", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.mybucket.id", + "aws_s3_bucket.mybucket" + ] + }, + "rule": [ + { + "apply_server_side_encryption_by_default": [ + { + "kms_master_key_id": { + "references": [ + "aws_kms_key.mykey.arn", + "aws_kms_key.mykey" + ] + }, + "sse_algorithm": { + "constant_value": "aws:kms" + } + } + ] + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.mybucket", + "attribute": [ + "id" + ] + }, + { + "resource": "aws_kms_key.mykey", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-01-23T08:08:09Z", + "errored": false +} diff --git a/terraform/plan/s3-best-practices/enable-kms-encryption/test/good-terraform.tf b/terraform/plan/s3-best-practices/enable-kms-encryption/test/good-terraform.tf new file mode 100644 index 00000000..19267cff --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-kms-encryption/test/good-terraform.tf @@ -0,0 +1,34 @@ +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" "mybucket" { + bucket = "test-bucket-23-01-2024" +} + +resource "aws_kms_key" "mykey" { + description = "This key is used to encrypt bucket objects" + deletion_window_in_days = 10 +} + +resource "aws_s3_bucket_server_side_encryption_configuration" "example" { + bucket = aws_s3_bucket.mybucket.id + + rule { + apply_server_side_encryption_by_default { + kms_master_key_id = aws_kms_key.mykey.arn + sse_algorithm = "aws:kms" + } + } +} \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-lifecycle-configuration/README.md b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/README.md new file mode 100644 index 00000000..e0ca6c0b --- /dev/null +++ b/terraform/plan/s3-best-practices/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 --bindings ./binding.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/plan/s3-best-practices/enable-lifecycle-configuration/enable-lifecycle-configuration.yaml b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/enable-lifecycle-configuration.yaml new file mode 100644 index 00000000..f9f62204 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/enable-lifecycle-configuration.yaml @@ -0,0 +1,29 @@ +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: + - ($analyzer.resource.type): terraform-plan + - (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/plan/s3-best-practices/enable-lifecycle-configuration/test/bad-payload-01.json b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/bad-payload-01.json new file mode 100644 index 00000000..ae3b70c9 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/bad-payload-01.json @@ -0,0 +1,135 @@ +{ + "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": [] + } + } + ] + } + }, + "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": [] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + } + } + }, + "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 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-30T09:58:18Z", + "errored": false + } + \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/bad-payload-02.json b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/bad-payload-02.json new file mode 100644 index 00000000..1b5ce0d3 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/bad-payload-02.json @@ -0,0 +1,252 @@ +{ + "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": { + } + } + }, + "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/plan/s3-best-practices/enable-lifecycle-configuration/test/bad-terraform-01.tf b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/bad-terraform-01.tf new file mode 100644 index 00000000..90c0026c --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/bad-terraform-01.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/plan/s3-best-practices/enable-lifecycle-configuration/test/bad-terraform-02.tf b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/bad-terraform-02.tf new file mode 100644 index 00000000..80a6930e --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/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 = "Disabled" + } +} diff --git a/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/binding.yaml b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/chainsaw-test.yaml b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/chainsaw-test.yaml new file mode 100644 index 00000000..cae58d0d --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/chainsaw-test.yaml @@ -0,0 +1,59 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../enable-lifecycle-configuration.yaml --payload ./good-payload.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: s3-lifecycle-configuration + rules: + - rule: + name: check-s3-lifecycle-configuration + error: ~ + violations: ~ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-02 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../enable-lifecycle-configuration.yaml --payload ./bad-payload-02.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: s3-lifecycle-configuration + rules: + - rule: + name: check-s3-lifecycle-configuration + error: ~ + violations: + - message: S3 Bucket Lifecycle Configuration 'status' needs to be set to 'Enabled' + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' diff --git a/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/good-payload.json b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/good-payload.json new file mode 100644 index 00000000..e365a683 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/good-payload.json @@ -0,0 +1,252 @@ +{ + "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": { + } + } + }, + "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/plan/s3-best-practices/enable-lifecycle-configuration/test/good-terraform.tf b/terraform/plan/s3-best-practices/enable-lifecycle-configuration/test/good-terraform.tf new file mode 100644 index 00000000..d549a0d1 --- /dev/null +++ b/terraform/plan/s3-best-practices/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/plan/s3-best-practices/enable-s3-cross-region-replication/README.md b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/README.md new file mode 100644 index 00000000..b3ca3723 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/README.md @@ -0,0 +1,29 @@ +Replication enables automatic, asynchronous copying of objects across Amazon S3 buckets. Buckets that are configured for object replication can be owned by the same AWS account or by different accounts. You can replicate objects to a single destination bucket or to multiple destination buckets. The destination buckets can be in different AWS Regions or within the same Region as the source bucket. + +To automatically replicate new objects as they are written to the bucket, use live replication, such as Cross-Region Replication (CRR). To replicate existing objects to a different bucket on demand, use S3 Batch Replication. + +In order to *Enable* the cross-region replication for an S3 Bucket, you need to use the *aws_s3_bucket_replication_configuration* resource block in your Terraform file. The *status* field which is a mandatory field will determine whether you'd like to enable the Cross Region Replication or not. The required values for *Status* are *Enabled* or *Disabled* which means you can neither set any other value (say foo) for status field nor exclude the status field from your resource block. You can read more about this in [Terraform documentation](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_replication_configuration#status). + +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 s3-cross-region-replication.yaml --bindings ./binding.yaml + ``` + Since you've set the `status` field to `Enabled` in *good-terraform.tf* file, the policy will give you Passing checks. If you try to change the value of `status` to `Disabled` 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-s3-cross-region-replication/test/bad-payload.json` and run the `kyverno-json scan` command again. \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/s3-cross-region-replication.yaml b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/s3-cross-region-replication.yaml new file mode 100644 index 00000000..be498ae6 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/s3-cross-region-replication.yaml @@ -0,0 +1,32 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: enable-s3-cross-region-replication + annotations: + policies.kyverno.io/title: enable-s3-cross-region-replication + policies.kyverno.io/category: AWS S3 Security Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + Replication enables automatic, asynchronous copying of objects + across Amazon S3 buckets. Buckets that are configured for object + replication can be owned by the same AWS account or by different + accounts. You can replicate objects to a single destination bucket + or to multiple destination buckets. The destination buckets can be + in different AWS Regions or within the same Region as the source bucket. +spec: + rules: + - name: check-s3-cross-region-replication + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_s3_bucket'] | length(@) > `0`): true + assert: + all: + - message: Use the `aws_s3_bucket_replication_configuration` resource to set the status to Enabled + check: + (planned_values.root_module.resources[?type=='aws_s3_bucket_replication_configuration'] | length(@) > `0`): true + - message: Set S3 Bucket Cross Region Replication status to 'Enabled' + check: + ~.(planned_values.root_module.resources[?type=='aws_s3_bucket_replication_configuration']): + (values.rule[?status=='Enabled'] | length(@) > `0`): true + \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/bad-payload-02.json b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/bad-payload-02.json new file mode 100644 index 00000000..7fd6e40f --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/bad-payload-02.json @@ -0,0 +1,1083 @@ +{ + "format_version": "1.2", + "terraform_version": "1.6.6", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.replication", + "mode": "managed", + "type": "aws_iam_policy", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": null, + "name": "tf-iam-role-policy-replication-12345", + "path": "/", + "tags": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_iam_role.replication", + "mode": "managed", + "type": "aws_iam_role", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "tf-iam-role-replication-12345", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.replication", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "role": "tf-iam-role-replication-12345" + }, + "sensitive_values": {} + }, + { + "address": "aws_s3_bucket.destination", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "destination", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "tf-test-bucket-destination-nitish-12345", + "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.source", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "source", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "tf-test-bucket-source-nitish-12345", + "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.destination", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "destination", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + { + "status": "Enabled" + } + ] + }, + "sensitive_values": { + "versioning_configuration": [ + {} + ] + } + }, + { + "address": "aws_s3_bucket_versioning.source", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "source", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + { + "status": "Enabled" + } + ] + }, + "sensitive_values": { + "versioning_configuration": [ + {} + ] + } + }, + { + "address": "data.aws_iam_policy_document.replication", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "override_policy_documents": null, + "policy_id": null, + "source_policy_documents": null, + "statement": [ + { + "actions": [ + "s3:GetReplicationConfiguration", + "s3:ListBucket" + ], + "condition": [], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [], + "resources": [ + null + ], + "sid": null + }, + { + "actions": [ + "s3:GetObjectVersionAcl", + "s3:GetObjectVersionForReplication", + "s3:GetObjectVersionTagging" + ], + "condition": [], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [], + "resources": [ + null + ], + "sid": null + }, + { + "actions": [ + "s3:ReplicateObject", + "s3:ReplicateTags" + ], + "condition": [], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [], + "resources": [ + null + ], + "sid": null + } + ], + "version": null + }, + "sensitive_values": { + "statement": [ + { + "actions": [ + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + false + ] + }, + { + "actions": [ + false, + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + false + ] + }, + { + "actions": [ + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + false + ] + } + ] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "data.aws_iam_policy_document.replication", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "read" + ], + "before": null, + "after": { + "override_policy_documents": null, + "policy_id": null, + "source_policy_documents": null, + "statement": [ + { + "actions": [ + "s3:GetReplicationConfiguration", + "s3:ListBucket" + ], + "condition": [], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [], + "resources": [ + null + ], + "sid": null + }, + { + "actions": [ + "s3:GetObjectVersionAcl", + "s3:GetObjectVersionForReplication", + "s3:GetObjectVersionTagging" + ], + "condition": [], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [], + "resources": [ + null + ], + "sid": null + }, + { + "actions": [ + "s3:ReplicateObject", + "s3:ReplicateTags" + ], + "condition": [], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [], + "resources": [ + null + ], + "sid": null + } + ], + "version": null + }, + "after_unknown": { + "id": true, + "json": true, + "statement": [ + { + "actions": [ + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + true + ] + }, + { + "actions": [ + false, + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + true + ] + }, + { + "actions": [ + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + true + ] + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "statement": [ + { + "actions": [ + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + false + ] + }, + { + "actions": [ + false, + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + false + ] + }, + { + "actions": [ + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + false + ] + } + ] + } + }, + "action_reason": "read_because_config_unknown" + }, + { + "address": "aws_iam_policy.replication", + "mode": "managed", + "type": "aws_iam_policy", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": null, + "name": "tf-iam-role-policy-replication-12345", + "path": "/", + "tags": null + }, + "after_unknown": { + "arn": true, + "id": true, + "name_prefix": true, + "policy": true, + "policy_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role.replication", + "mode": "managed", + "type": "aws_iam_role", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "tf-iam-role-replication-12345", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.replication", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "role": "tf-iam-role-replication-12345" + }, + "after_unknown": { + "id": true, + "policy_arn": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_s3_bucket.destination", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "destination", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "tf-test-bucket-destination-nitish-12345", + "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.source", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "source", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "tf-test-bucket-source-nitish-12345", + "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.destination", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "destination", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + { + "status": "Enabled" + } + ] + }, + "after_unknown": { + "bucket": true, + "id": true, + "versioning_configuration": [ + { + "mfa_delete": true + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "versioning_configuration": [ + {} + ] + } + } + }, + { + "address": "aws_s3_bucket_versioning.source", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "source", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + { + "status": "Enabled" + } + ] + }, + "after_unknown": { + "bucket": true, + "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": "data.aws_iam_policy_document.assume_role", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "assume_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "id": "1765856792", + "json": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"s3.amazonaws.com\"\n }\n }\n ]\n}", + "override_policy_documents": null, + "policy_id": null, + "source_policy_documents": null, + "statement": [ + { + "actions": [ + "sts:AssumeRole" + ], + "condition": [], + "effect": "Allow", + "not_actions": [], + "not_principals": [], + "not_resources": [], + "principals": [ + { + "identifiers": [ + "s3.amazonaws.com" + ], + "type": "Service" + } + ], + "resources": [], + "sid": "" + } + ], + "version": "2012-10-17" + }, + "sensitive_values": { + "statement": [ + { + "actions": [ + false + ], + "condition": [], + "not_actions": [], + "not_principals": [], + "not_resources": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [] + } + ] + } + } + ] + } + } + }, + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "expressions": { + } + }, + "aws.central": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "alias": "central", + "expressions": { + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.replication", + "mode": "managed", + "type": "aws_iam_policy", + "name": "replication", + "provider_config_key": "aws", + "expressions": { + "name": { + "constant_value": "tf-iam-role-policy-replication-12345" + }, + "policy": { + "references": [ + "data.aws_iam_policy_document.replication.json", + "data.aws_iam_policy_document.replication" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.replication", + "mode": "managed", + "type": "aws_iam_role", + "name": "replication", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "references": [ + "data.aws_iam_policy_document.assume_role.json", + "data.aws_iam_policy_document.assume_role" + ] + }, + "name": { + "constant_value": "tf-iam-role-replication-12345" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.replication", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "replication", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.replication.arn", + "aws_iam_policy.replication" + ] + }, + "role": { + "references": [ + "aws_iam_role.replication.name", + "aws_iam_role.replication" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket.destination", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "destination", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "tf-test-bucket-destination-nitish-12345" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket.source", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "source", + "provider_config_key": "aws.central", + "expressions": { + "bucket": { + "constant_value": "tf-test-bucket-source-nitish-12345" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_versioning.destination", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "destination", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.destination.id", + "aws_s3_bucket.destination" + ] + }, + "versioning_configuration": [ + { + "status": { + "constant_value": "Enabled" + } + } + ] + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_versioning.source", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "source", + "provider_config_key": "aws.central", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.source.id", + "aws_s3_bucket.source" + ] + }, + "versioning_configuration": [ + { + "status": { + "constant_value": "Enabled" + } + } + ] + }, + "schema_version": 0 + }, + { + "address": "data.aws_iam_policy_document.assume_role", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "assume_role", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "sts:AssumeRole" + ] + }, + "effect": { + "constant_value": "Allow" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "s3.amazonaws.com" + ] + }, + "type": { + "constant_value": "Service" + } + } + ] + } + ] + }, + "schema_version": 0 + }, + { + "address": "data.aws_iam_policy_document.replication", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "replication", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "s3:GetReplicationConfiguration", + "s3:ListBucket" + ] + }, + "effect": { + "constant_value": "Allow" + }, + "resources": { + "references": [ + "aws_s3_bucket.source.arn", + "aws_s3_bucket.source" + ] + } + }, + { + "actions": { + "constant_value": [ + "s3:GetObjectVersionForReplication", + "s3:GetObjectVersionAcl", + "s3:GetObjectVersionTagging" + ] + }, + "effect": { + "constant_value": "Allow" + }, + "resources": { + "references": [ + "aws_s3_bucket.source.arn", + "aws_s3_bucket.source" + ] + } + }, + { + "actions": { + "constant_value": [ + "s3:ReplicateObject", + "s3:ReplicateTags" + ] + }, + "effect": { + "constant_value": "Allow" + }, + "resources": { + "references": [ + "aws_s3_bucket.destination.arn", + "aws_s3_bucket.destination" + ] + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.source", + "attribute": [ + "id" + ] + }, + { + "resource": "data.aws_iam_policy_document.replication", + "attribute": [ + "json" + ] + }, + { + "resource": "aws_iam_role.replication", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_role.replication", + "attribute": [ + "name" + ] + }, + { + "resource": "data.aws_iam_policy_document.assume_role", + "attribute": [ + "json" + ] + }, + { + "resource": "aws_s3_bucket.destination", + "attribute": [ + "id" + ] + }, + { + "resource": "aws_s3_bucket.source", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_s3_bucket.destination", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_policy.replication", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-01-24T11:12:11Z", + "errored": false + } + \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/bad-payload.json b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/bad-payload.json new file mode 100644 index 00000000..caf62d35 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/bad-payload.json @@ -0,0 +1,1316 @@ +{ + "format_version": "1.2", + "terraform_version": "1.6.6", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.replication", + "mode": "managed", + "type": "aws_iam_policy", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": null, + "name": "tf-iam-role-policy-replication-12345", + "path": "/", + "tags": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_iam_role.replication", + "mode": "managed", + "type": "aws_iam_role", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "tf-iam-role-replication-12345", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.replication", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "role": "tf-iam-role-replication-12345" + }, + "sensitive_values": {} + }, + { + "address": "aws_s3_bucket.destination", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "destination", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "tf-test-bucket-destination-nitish-12345", + "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.source", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "source", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "tf-test-bucket-source-nitish-12345", + "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_replication_configuration.replication", + "mode": "managed", + "type": "aws_s3_bucket_replication_configuration", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "rule": [ + { + "delete_marker_replication": [ + { + "status": "Enabled" + } + ], + "destination": [ + { + "access_control_translation": [], + "account": null, + "encryption_configuration": [], + "metrics": [], + "replication_time": [], + "storage_class": "STANDARD" + } + ], + "existing_object_replication": [], + "filter": [ + { + "and": [], + "prefix": "foo", + "tag": [] + } + ], + "id": "foobar", + "prefix": null, + "priority": null, + "source_selection_criteria": [], + "status": "Disabled" + } + ], + "token": null + }, + "sensitive_values": { + "rule": [ + { + "delete_marker_replication": [ + {} + ], + "destination": [ + { + "access_control_translation": [], + "encryption_configuration": [], + "metrics": [], + "replication_time": [] + } + ], + "existing_object_replication": [], + "filter": [ + { + "and": [], + "tag": [] + } + ], + "source_selection_criteria": [] + } + ] + } + }, + { + "address": "aws_s3_bucket_versioning.destination", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "destination", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + { + "status": "Enabled" + } + ] + }, + "sensitive_values": { + "versioning_configuration": [ + {} + ] + } + }, + { + "address": "aws_s3_bucket_versioning.source", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "source", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + { + "status": "Enabled" + } + ] + }, + "sensitive_values": { + "versioning_configuration": [ + {} + ] + } + }, + { + "address": "data.aws_iam_policy_document.replication", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "override_policy_documents": null, + "policy_id": null, + "source_policy_documents": null, + "statement": [ + { + "actions": [ + "s3:GetReplicationConfiguration", + "s3:ListBucket" + ], + "condition": [], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [], + "resources": [ + null + ], + "sid": null + }, + { + "actions": [ + "s3:GetObjectVersionAcl", + "s3:GetObjectVersionForReplication", + "s3:GetObjectVersionTagging" + ], + "condition": [], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [], + "resources": [ + null + ], + "sid": null + }, + { + "actions": [ + "s3:ReplicateObject", + "s3:ReplicateTags" + ], + "condition": [], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [], + "resources": [ + null + ], + "sid": null + } + ], + "version": null + }, + "sensitive_values": { + "statement": [ + { + "actions": [ + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + false + ] + }, + { + "actions": [ + false, + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + false + ] + }, + { + "actions": [ + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + false + ] + } + ] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "data.aws_iam_policy_document.replication", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "read" + ], + "before": null, + "after": { + "override_policy_documents": null, + "policy_id": null, + "source_policy_documents": null, + "statement": [ + { + "actions": [ + "s3:GetReplicationConfiguration", + "s3:ListBucket" + ], + "condition": [], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [], + "resources": [ + null + ], + "sid": null + }, + { + "actions": [ + "s3:GetObjectVersionAcl", + "s3:GetObjectVersionForReplication", + "s3:GetObjectVersionTagging" + ], + "condition": [], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [], + "resources": [ + null + ], + "sid": null + }, + { + "actions": [ + "s3:ReplicateObject", + "s3:ReplicateTags" + ], + "condition": [], + "effect": "Allow", + "not_actions": null, + "not_principals": [], + "not_resources": null, + "principals": [], + "resources": [ + null + ], + "sid": null + } + ], + "version": null + }, + "after_unknown": { + "id": true, + "json": true, + "statement": [ + { + "actions": [ + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + true + ] + }, + { + "actions": [ + false, + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + true + ] + }, + { + "actions": [ + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + true + ] + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "statement": [ + { + "actions": [ + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + false + ] + }, + { + "actions": [ + false, + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + false + ] + }, + { + "actions": [ + false, + false + ], + "condition": [], + "not_principals": [], + "principals": [], + "resources": [ + false + ] + } + ] + } + }, + "action_reason": "read_because_config_unknown" + }, + { + "address": "aws_iam_policy.replication", + "mode": "managed", + "type": "aws_iam_policy", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": null, + "name": "tf-iam-role-policy-replication-12345", + "path": "/", + "tags": null + }, + "after_unknown": { + "arn": true, + "id": true, + "name_prefix": true, + "policy": true, + "policy_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role.replication", + "mode": "managed", + "type": "aws_iam_role", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "tf-iam-role-replication-12345", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.replication", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "role": "tf-iam-role-replication-12345" + }, + "after_unknown": { + "id": true, + "policy_arn": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_s3_bucket.destination", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "destination", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "tf-test-bucket-destination-nitish-12345", + "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.source", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "source", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "tf-test-bucket-source-nitish-12345", + "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_replication_configuration.replication", + "mode": "managed", + "type": "aws_s3_bucket_replication_configuration", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "rule": [ + { + "delete_marker_replication": [ + { + "status": "Enabled" + } + ], + "destination": [ + { + "access_control_translation": [], + "account": null, + "encryption_configuration": [], + "metrics": [], + "replication_time": [], + "storage_class": "STANDARD" + } + ], + "existing_object_replication": [], + "filter": [ + { + "and": [], + "prefix": "foo", + "tag": [] + } + ], + "id": "foobar", + "prefix": null, + "priority": null, + "source_selection_criteria": [], + "status": "Disabled" + } + ], + "token": null + }, + "after_unknown": { + "bucket": true, + "id": true, + "role": true, + "rule": [ + { + "delete_marker_replication": [ + {} + ], + "destination": [ + { + "access_control_translation": [], + "bucket": true, + "encryption_configuration": [], + "metrics": [], + "replication_time": [] + } + ], + "existing_object_replication": [], + "filter": [ + { + "and": [], + "tag": [] + } + ], + "source_selection_criteria": [] + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "rule": [ + { + "delete_marker_replication": [ + {} + ], + "destination": [ + { + "access_control_translation": [], + "encryption_configuration": [], + "metrics": [], + "replication_time": [] + } + ], + "existing_object_replication": [], + "filter": [ + { + "and": [], + "tag": [] + } + ], + "source_selection_criteria": [] + } + ], + "token": true + } + } + }, + { + "address": "aws_s3_bucket_versioning.destination", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "destination", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + { + "status": "Enabled" + } + ] + }, + "after_unknown": { + "bucket": true, + "id": true, + "versioning_configuration": [ + { + "mfa_delete": true + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "versioning_configuration": [ + {} + ] + } + } + }, + { + "address": "aws_s3_bucket_versioning.source", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "source", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "expected_bucket_owner": null, + "mfa": null, + "versioning_configuration": [ + { + "status": "Enabled" + } + ] + }, + "after_unknown": { + "bucket": true, + "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": "data.aws_iam_policy_document.assume_role", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "assume_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "id": "1765856792", + "json": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"s3.amazonaws.com\"\n }\n }\n ]\n}", + "override_policy_documents": null, + "policy_id": null, + "source_policy_documents": null, + "statement": [ + { + "actions": [ + "sts:AssumeRole" + ], + "condition": [], + "effect": "Allow", + "not_actions": [], + "not_principals": [], + "not_resources": [], + "principals": [ + { + "identifiers": [ + "s3.amazonaws.com" + ], + "type": "Service" + } + ], + "resources": [], + "sid": "" + } + ], + "version": "2012-10-17" + }, + "sensitive_values": { + "statement": [ + { + "actions": [ + false + ], + "condition": [], + "not_actions": [], + "not_principals": [], + "not_resources": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [] + } + ] + } + } + ] + } + } + }, + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "expressions": { + } + }, + "aws.central": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "alias": "central", + "expressions": { + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.replication", + "mode": "managed", + "type": "aws_iam_policy", + "name": "replication", + "provider_config_key": "aws", + "expressions": { + "name": { + "constant_value": "tf-iam-role-policy-replication-12345" + }, + "policy": { + "references": [ + "data.aws_iam_policy_document.replication.json", + "data.aws_iam_policy_document.replication" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.replication", + "mode": "managed", + "type": "aws_iam_role", + "name": "replication", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "references": [ + "data.aws_iam_policy_document.assume_role.json", + "data.aws_iam_policy_document.assume_role" + ] + }, + "name": { + "constant_value": "tf-iam-role-replication-12345" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.replication", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "replication", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.replication.arn", + "aws_iam_policy.replication" + ] + }, + "role": { + "references": [ + "aws_iam_role.replication.name", + "aws_iam_role.replication" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket.destination", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "destination", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "tf-test-bucket-destination-nitish-12345" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket.source", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "source", + "provider_config_key": "aws.central", + "expressions": { + "bucket": { + "constant_value": "tf-test-bucket-source-nitish-12345" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_replication_configuration.replication", + "mode": "managed", + "type": "aws_s3_bucket_replication_configuration", + "name": "replication", + "provider_config_key": "aws.central", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.source.id", + "aws_s3_bucket.source" + ] + }, + "role": { + "references": [ + "aws_iam_role.replication.arn", + "aws_iam_role.replication" + ] + }, + "rule": [ + { + "delete_marker_replication": [ + { + "status": { + "constant_value": "Enabled" + } + } + ], + "destination": [ + { + "bucket": { + "references": [ + "aws_s3_bucket.destination.arn", + "aws_s3_bucket.destination" + ] + }, + "storage_class": { + "constant_value": "STANDARD" + } + } + ], + "filter": [ + { + "prefix": { + "constant_value": "foo" + } + } + ], + "id": { + "constant_value": "foobar" + }, + "status": { + "constant_value": "Disabled" + } + } + ] + }, + "schema_version": 0, + "depends_on": [ + "aws_s3_bucket_versioning.source" + ] + }, + { + "address": "aws_s3_bucket_versioning.destination", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "destination", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.destination.id", + "aws_s3_bucket.destination" + ] + }, + "versioning_configuration": [ + { + "status": { + "constant_value": "Enabled" + } + } + ] + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_versioning.source", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "source", + "provider_config_key": "aws.central", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.source.id", + "aws_s3_bucket.source" + ] + }, + "versioning_configuration": [ + { + "status": { + "constant_value": "Enabled" + } + } + ] + }, + "schema_version": 0 + }, + { + "address": "data.aws_iam_policy_document.assume_role", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "assume_role", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "sts:AssumeRole" + ] + }, + "effect": { + "constant_value": "Allow" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "s3.amazonaws.com" + ] + }, + "type": { + "constant_value": "Service" + } + } + ] + } + ] + }, + "schema_version": 0 + }, + { + "address": "data.aws_iam_policy_document.replication", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "replication", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "s3:GetReplicationConfiguration", + "s3:ListBucket" + ] + }, + "effect": { + "constant_value": "Allow" + }, + "resources": { + "references": [ + "aws_s3_bucket.source.arn", + "aws_s3_bucket.source" + ] + } + }, + { + "actions": { + "constant_value": [ + "s3:GetObjectVersionForReplication", + "s3:GetObjectVersionAcl", + "s3:GetObjectVersionTagging" + ] + }, + "effect": { + "constant_value": "Allow" + }, + "resources": { + "references": [ + "aws_s3_bucket.source.arn", + "aws_s3_bucket.source" + ] + } + }, + { + "actions": { + "constant_value": [ + "s3:ReplicateObject", + "s3:ReplicateTags" + ] + }, + "effect": { + "constant_value": "Allow" + }, + "resources": { + "references": [ + "aws_s3_bucket.destination.arn", + "aws_s3_bucket.destination" + ] + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.source", + "attribute": [ + "id" + ] + }, + { + "resource": "data.aws_iam_policy_document.replication", + "attribute": [ + "json" + ] + }, + { + "resource": "aws_iam_role.replication", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_role.replication", + "attribute": [ + "name" + ] + }, + { + "resource": "data.aws_iam_policy_document.assume_role", + "attribute": [ + "json" + ] + }, + { + "resource": "aws_s3_bucket.destination", + "attribute": [ + "id" + ] + }, + { + "resource": "aws_s3_bucket.source", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_s3_bucket.destination", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_policy.replication", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-01-24T11:12:11Z", + "errored": false +} diff --git a/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/bad-terraform.tf b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/bad-terraform.tf new file mode 100644 index 00000000..49cb3c5b --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/bad-terraform.tf @@ -0,0 +1,125 @@ +provider "aws" { + region = "eu-west-1" +} + +provider "aws" { + alias = "central" + region = "eu-central-1" +} + +data "aws_iam_policy_document" "assume_role" { + statement { + effect = "Allow" + + principals { + type = "Service" + identifiers = ["s3.amazonaws.com"] + } + + actions = ["sts:AssumeRole"] + } +} + +resource "aws_iam_role" "replication" { + name = "tf-iam-role-replication-12345" + assume_role_policy = data.aws_iam_policy_document.assume_role.json +} + +data "aws_iam_policy_document" "replication" { + statement { + effect = "Allow" + + actions = [ + "s3:GetReplicationConfiguration", + "s3:ListBucket", + ] + + resources = [aws_s3_bucket.source.arn] + } + + statement { + effect = "Allow" + + actions = [ + "s3:GetObjectVersionForReplication", + "s3:GetObjectVersionAcl", + "s3:GetObjectVersionTagging", + ] + + resources = ["${aws_s3_bucket.source.arn}/*"] + } + + statement { + effect = "Allow" + + actions = [ + "s3:ReplicateObject", + "s3:ReplicateTags", + ] + + resources = ["${aws_s3_bucket.destination.arn}/*"] + } +} + +resource "aws_iam_policy" "replication" { + name = "tf-iam-role-policy-replication-12345" + policy = data.aws_iam_policy_document.replication.json +} + +resource "aws_iam_role_policy_attachment" "replication" { + role = aws_iam_role.replication.name + policy_arn = aws_iam_policy.replication.arn +} + +resource "aws_s3_bucket" "destination" { + bucket = "tf-test-bucket-destination-nitish-12345" +} + +resource "aws_s3_bucket_versioning" "destination" { + bucket = aws_s3_bucket.destination.id + versioning_configuration { + status = "Enabled" + } +} + +resource "aws_s3_bucket" "source" { + provider = aws.central + bucket = "tf-test-bucket-source-nitish-12345" +} + +resource "aws_s3_bucket_versioning" "source" { + provider = aws.central + + bucket = aws_s3_bucket.source.id + versioning_configuration { + status = "Enabled" + } +} + +resource "aws_s3_bucket_replication_configuration" "replication" { + provider = aws.central + # Must have bucket versioning enabled first + depends_on = [aws_s3_bucket_versioning.source] + + role = aws_iam_role.replication.arn + bucket = aws_s3_bucket.source.id + + rule { + id = "foobar" + + filter { + prefix = "foo" + } + + status = "Disabled" + + destination { + bucket = aws_s3_bucket.destination.arn + storage_class = "STANDARD" + } + + delete_marker_replication { + status = "Enabled" + } + } +} \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/binding.yaml b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/chainsaw-test.yaml b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/chainsaw-test.yaml new file mode 100644 index 00000000..95e1e704 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/chainsaw-test.yaml @@ -0,0 +1,91 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../s3-cross-region-replication.yaml --payload ./good-payload.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: enable-s3-cross-region-replication + rules: + - rule: + name: check-s3-cross-region-replication + error: ~ + violations: ~ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../s3-cross-region-replication.yaml --payload ./bad-payload.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: enable-s3-cross-region-replication + rules: + - rule: + name: check-s3-cross-region-replication + error: ~ + violations: + - message: Set S3 Bucket Cross Region Replication status to 'Enabled' + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../s3-cross-region-replication.yaml --payload ./bad-payload-02.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: enable-s3-cross-region-replication + rules: + - rule: + name: check-s3-cross-region-replication + error: ~ + violations: + - message: Use the `aws_s3_bucket_replication_configuration` resource to set the status to Enabled + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/good-payload.json b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/good-payload.json new file mode 100644 index 00000000..348f482b --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/good-payload.json @@ -0,0 +1,2222 @@ +{ + "format_version": "1.2", + "terraform_version": "1.6.6", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.replication", + "mode": "managed", + "type": "aws_iam_policy", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "arn": "arn:aws:iam::844333597536:policy/tf-iam-role-policy-replication-12345", + "description": "", + "id": "arn:aws:iam::844333597536:policy/tf-iam-role-policy-replication-12345", + "name": "tf-iam-role-policy-replication-12345", + "name_prefix": "", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"s3:ListBucket\",\"s3:GetReplicationConfiguration\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:s3:::tf-test-bucket-source-nitish-12345\"},{\"Action\":[\"s3:GetObjectVersionTagging\",\"s3:GetObjectVersionForReplication\",\"s3:GetObjectVersionAcl\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:s3:::tf-test-bucket-source-nitish-12345/*\"},{\"Action\":[\"s3:ReplicateTags\",\"s3:ReplicateObject\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:s3:::tf-test-bucket-destination-nitish-12345/*\"}],\"Version\":\"2012-10-17\"}", + "policy_id": "ANPA4JFRUINQLTD64575W", + "tags": {}, + "tags_all": {} + }, + "sensitive_values": { + "tags": {}, + "tags_all": {} + } + }, + { + "address": "aws_iam_role.replication", + "mode": "managed", + "type": "aws_iam_role", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "arn": "arn:aws:iam::844333597536:role/tf-iam-role-replication-12345", + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "create_date": "2024-01-24T10:55:42Z", + "description": "", + "force_detach_policies": false, + "id": "tf-iam-role-replication-12345", + "inline_policy": [], + "managed_policy_arns": [ + "arn:aws:iam::844333597536:policy/tf-iam-role-policy-replication-12345" + ], + "max_session_duration": 3600, + "name": "tf-iam-role-replication-12345", + "name_prefix": "", + "path": "/", + "permissions_boundary": "", + "tags": {}, + "tags_all": {}, + "unique_id": "AROA4JFRUINQIGIEP43IO" + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [ + false + ], + "tags": {}, + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.replication", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "id": "tf-iam-role-replication-12345-20240124105702515800000001", + "policy_arn": "arn:aws:iam::844333597536:policy/tf-iam-role-policy-replication-12345", + "role": "tf-iam-role-replication-12345" + }, + "sensitive_values": {} + }, + { + "address": "aws_s3_bucket.destination", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "destination", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::tf-test-bucket-destination-nitish-12345", + "bucket": "tf-test-bucket-destination-nitish-12345", + "bucket_domain_name": "tf-test-bucket-destination-nitish-12345.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "tf-test-bucket-destination-nitish-12345.s3.eu-west-1.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z1BKCTXD74EZPE", + "id": "tf-test-bucket-destination-nitish-12345", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "eu-west-1", + "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": true, + "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.source", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "source", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::tf-test-bucket-source-nitish-12345", + "bucket": "tf-test-bucket-source-nitish-12345", + "bucket_domain_name": "tf-test-bucket-source-nitish-12345.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "tf-test-bucket-source-nitish-12345.s3.eu-central-1.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z21DNDUVLTQW6Q", + "id": "tf-test-bucket-source-nitish-12345", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "eu-central-1", + "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": true, + "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_replication_configuration.replication", + "mode": "managed", + "type": "aws_s3_bucket_replication_configuration", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "tf-test-bucket-source-nitish-12345", + "role": "arn:aws:iam::844333597536:role/tf-iam-role-replication-12345", + "rule": [ + { + "delete_marker_replication": [ + { + "status": "Enabled" + } + ], + "destination": [ + { + "access_control_translation": [], + "account": null, + "bucket": "arn:aws:s3:::tf-test-bucket-destination-nitish-12345", + "encryption_configuration": [], + "metrics": [], + "replication_time": [], + "storage_class": "STANDARD" + } + ], + "existing_object_replication": [], + "filter": [ + { + "and": [], + "prefix": "foo", + "tag": [] + } + ], + "id": "foobar", + "prefix": null, + "priority": null, + "source_selection_criteria": [], + "status": "Enabled" + } + ], + "token": null + }, + "sensitive_values": { + "rule": [ + { + "delete_marker_replication": [ + {} + ], + "destination": [ + { + "access_control_translation": [], + "encryption_configuration": [], + "metrics": [], + "replication_time": [] + } + ], + "existing_object_replication": [], + "filter": [ + { + "and": [], + "tag": [] + } + ], + "source_selection_criteria": [] + } + ] + } + }, + { + "address": "aws_s3_bucket_versioning.destination", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "destination", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "tf-test-bucket-destination-nitish-12345", + "expected_bucket_owner": "", + "id": "tf-test-bucket-destination-nitish-12345", + "mfa": null, + "versioning_configuration": [ + { + "mfa_delete": "", + "status": "Enabled" + } + ] + }, + "sensitive_values": { + "versioning_configuration": [ + {} + ] + } + }, + { + "address": "aws_s3_bucket_versioning.source", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "source", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "tf-test-bucket-source-nitish-12345", + "expected_bucket_owner": "", + "id": "tf-test-bucket-source-nitish-12345", + "mfa": null, + "versioning_configuration": [ + { + "mfa_delete": "", + "status": "Enabled" + } + ] + }, + "sensitive_values": { + "versioning_configuration": [ + {} + ] + } + } + ] + } + }, + "resource_drift": [ + { + "address": "aws_s3_bucket.source", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "source", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "update" + ], + "before": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::tf-test-bucket-source-nitish-12345", + "bucket": "tf-test-bucket-source-nitish-12345", + "bucket_domain_name": "tf-test-bucket-source-nitish-12345.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "tf-test-bucket-source-nitish-12345.s3.eu-central-1.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z21DNDUVLTQW6Q", + "id": "tf-test-bucket-source-nitish-12345", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "eu-central-1", + "replication_configuration": [ + { + "role": "arn:aws:iam::844333597536:role/tf-iam-role-replication-12345", + "rules": [ + { + "delete_marker_replication_status": "Enabled", + "destination": [ + { + "access_control_translation": [], + "account_id": "", + "bucket": "arn:aws:s3:::tf-test-bucket-destination-nitish-12345", + "metrics": [], + "replica_kms_key_id": "", + "replication_time": [], + "storage_class": "STANDARD" + } + ], + "filter": [ + { + "prefix": "foo", + "tags": {} + } + ], + "id": "foobar", + "prefix": "", + "priority": 0, + "source_selection_criteria": [], + "status": "Disabled" + } + ] + } + ], + "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": true, + "mfa_delete": false + } + ], + "website": [], + "website_domain": null, + "website_endpoint": null + }, + "after": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::tf-test-bucket-source-nitish-12345", + "bucket": "tf-test-bucket-source-nitish-12345", + "bucket_domain_name": "tf-test-bucket-source-nitish-12345.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "tf-test-bucket-source-nitish-12345.s3.eu-central-1.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z21DNDUVLTQW6Q", + "id": "tf-test-bucket-source-nitish-12345", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "eu-central-1", + "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": true, + "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": [ + { + "rules": [ + { + "destination": [ + { + "access_control_translation": [], + "metrics": [], + "replication_time": [] + } + ], + "filter": [ + { + "tags": {} + } + ], + "source_selection_criteria": [] + } + ] + } + ], + "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": [] + } + } + } + ], + "resource_changes": [ + { + "address": "aws_iam_policy.replication", + "mode": "managed", + "type": "aws_iam_policy", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "no-op" + ], + "before": { + "arn": "arn:aws:iam::844333597536:policy/tf-iam-role-policy-replication-12345", + "description": "", + "id": "arn:aws:iam::844333597536:policy/tf-iam-role-policy-replication-12345", + "name": "tf-iam-role-policy-replication-12345", + "name_prefix": "", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"s3:ListBucket\",\"s3:GetReplicationConfiguration\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:s3:::tf-test-bucket-source-nitish-12345\"},{\"Action\":[\"s3:GetObjectVersionTagging\",\"s3:GetObjectVersionForReplication\",\"s3:GetObjectVersionAcl\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:s3:::tf-test-bucket-source-nitish-12345/*\"},{\"Action\":[\"s3:ReplicateTags\",\"s3:ReplicateObject\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:s3:::tf-test-bucket-destination-nitish-12345/*\"}],\"Version\":\"2012-10-17\"}", + "policy_id": "ANPA4JFRUINQLTD64575W", + "tags": {}, + "tags_all": {} + }, + "after": { + "arn": "arn:aws:iam::844333597536:policy/tf-iam-role-policy-replication-12345", + "description": "", + "id": "arn:aws:iam::844333597536:policy/tf-iam-role-policy-replication-12345", + "name": "tf-iam-role-policy-replication-12345", + "name_prefix": "", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"s3:ListBucket\",\"s3:GetReplicationConfiguration\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:s3:::tf-test-bucket-source-nitish-12345\"},{\"Action\":[\"s3:GetObjectVersionTagging\",\"s3:GetObjectVersionForReplication\",\"s3:GetObjectVersionAcl\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:s3:::tf-test-bucket-source-nitish-12345/*\"},{\"Action\":[\"s3:ReplicateTags\",\"s3:ReplicateObject\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:s3:::tf-test-bucket-destination-nitish-12345/*\"}],\"Version\":\"2012-10-17\"}", + "policy_id": "ANPA4JFRUINQLTD64575W", + "tags": {}, + "tags_all": {} + }, + "after_unknown": {}, + "before_sensitive": { + "tags": {}, + "tags_all": {} + }, + "after_sensitive": { + "tags": {}, + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role.replication", + "mode": "managed", + "type": "aws_iam_role", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "no-op" + ], + "before": { + "arn": "arn:aws:iam::844333597536:role/tf-iam-role-replication-12345", + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "create_date": "2024-01-24T10:55:42Z", + "description": "", + "force_detach_policies": false, + "id": "tf-iam-role-replication-12345", + "inline_policy": [], + "managed_policy_arns": [ + "arn:aws:iam::844333597536:policy/tf-iam-role-policy-replication-12345" + ], + "max_session_duration": 3600, + "name": "tf-iam-role-replication-12345", + "name_prefix": "", + "path": "/", + "permissions_boundary": "", + "tags": {}, + "tags_all": {}, + "unique_id": "AROA4JFRUINQIGIEP43IO" + }, + "after": { + "arn": "arn:aws:iam::844333597536:role/tf-iam-role-replication-12345", + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "create_date": "2024-01-24T10:55:42Z", + "description": "", + "force_detach_policies": false, + "id": "tf-iam-role-replication-12345", + "inline_policy": [], + "managed_policy_arns": [ + "arn:aws:iam::844333597536:policy/tf-iam-role-policy-replication-12345" + ], + "max_session_duration": 3600, + "name": "tf-iam-role-replication-12345", + "name_prefix": "", + "path": "/", + "permissions_boundary": "", + "tags": {}, + "tags_all": {}, + "unique_id": "AROA4JFRUINQIGIEP43IO" + }, + "after_unknown": {}, + "before_sensitive": { + "inline_policy": [], + "managed_policy_arns": [ + false + ], + "tags": {}, + "tags_all": {} + }, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [ + false + ], + "tags": {}, + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.replication", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "no-op" + ], + "before": { + "id": "tf-iam-role-replication-12345-20240124105702515800000001", + "policy_arn": "arn:aws:iam::844333597536:policy/tf-iam-role-policy-replication-12345", + "role": "tf-iam-role-replication-12345" + }, + "after": { + "id": "tf-iam-role-replication-12345-20240124105702515800000001", + "policy_arn": "arn:aws:iam::844333597536:policy/tf-iam-role-policy-replication-12345", + "role": "tf-iam-role-replication-12345" + }, + "after_unknown": {}, + "before_sensitive": {}, + "after_sensitive": {} + } + }, + { + "address": "aws_s3_bucket.destination", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "destination", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "no-op" + ], + "before": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::tf-test-bucket-destination-nitish-12345", + "bucket": "tf-test-bucket-destination-nitish-12345", + "bucket_domain_name": "tf-test-bucket-destination-nitish-12345.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "tf-test-bucket-destination-nitish-12345.s3.eu-west-1.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z1BKCTXD74EZPE", + "id": "tf-test-bucket-destination-nitish-12345", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "eu-west-1", + "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": true, + "mfa_delete": false + } + ], + "website": [], + "website_domain": null, + "website_endpoint": null + }, + "after": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::tf-test-bucket-destination-nitish-12345", + "bucket": "tf-test-bucket-destination-nitish-12345", + "bucket_domain_name": "tf-test-bucket-destination-nitish-12345.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "tf-test-bucket-destination-nitish-12345.s3.eu-west-1.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z1BKCTXD74EZPE", + "id": "tf-test-bucket-destination-nitish-12345", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "eu-west-1", + "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": true, + "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.source", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "source", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "no-op" + ], + "before": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::tf-test-bucket-source-nitish-12345", + "bucket": "tf-test-bucket-source-nitish-12345", + "bucket_domain_name": "tf-test-bucket-source-nitish-12345.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "tf-test-bucket-source-nitish-12345.s3.eu-central-1.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z21DNDUVLTQW6Q", + "id": "tf-test-bucket-source-nitish-12345", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "eu-central-1", + "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": true, + "mfa_delete": false + } + ], + "website": [], + "website_domain": null, + "website_endpoint": null + }, + "after": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::tf-test-bucket-source-nitish-12345", + "bucket": "tf-test-bucket-source-nitish-12345", + "bucket_domain_name": "tf-test-bucket-source-nitish-12345.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "tf-test-bucket-source-nitish-12345.s3.eu-central-1.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z21DNDUVLTQW6Q", + "id": "tf-test-bucket-source-nitish-12345", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "eu-central-1", + "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": true, + "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_replication_configuration.replication", + "mode": "managed", + "type": "aws_s3_bucket_replication_configuration", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "tf-test-bucket-source-nitish-12345", + "role": "arn:aws:iam::844333597536:role/tf-iam-role-replication-12345", + "rule": [ + { + "delete_marker_replication": [ + { + "status": "Enabled" + } + ], + "destination": [ + { + "access_control_translation": [], + "account": null, + "bucket": "arn:aws:s3:::tf-test-bucket-destination-nitish-12345", + "encryption_configuration": [], + "metrics": [], + "replication_time": [], + "storage_class": "STANDARD" + } + ], + "existing_object_replication": [], + "filter": [ + { + "and": [], + "prefix": "foo", + "tag": [] + } + ], + "id": "foobar", + "prefix": null, + "priority": null, + "source_selection_criteria": [], + "status": "Enabled" + } + ], + "token": null + }, + "after_unknown": { + "id": true, + "rule": [ + { + "delete_marker_replication": [ + {} + ], + "destination": [ + { + "access_control_translation": [], + "encryption_configuration": [], + "metrics": [], + "replication_time": [] + } + ], + "existing_object_replication": [], + "filter": [ + { + "and": [], + "tag": [] + } + ], + "source_selection_criteria": [] + } + ] + }, + "before_sensitive": false, + "after_sensitive": { + "rule": [ + { + "delete_marker_replication": [ + {} + ], + "destination": [ + { + "access_control_translation": [], + "encryption_configuration": [], + "metrics": [], + "replication_time": [] + } + ], + "existing_object_replication": [], + "filter": [ + { + "and": [], + "tag": [] + } + ], + "source_selection_criteria": [] + } + ], + "token": true + } + } + }, + { + "address": "aws_s3_bucket_versioning.destination", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "destination", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "no-op" + ], + "before": { + "bucket": "tf-test-bucket-destination-nitish-12345", + "expected_bucket_owner": "", + "id": "tf-test-bucket-destination-nitish-12345", + "mfa": null, + "versioning_configuration": [ + { + "mfa_delete": "", + "status": "Enabled" + } + ] + }, + "after": { + "bucket": "tf-test-bucket-destination-nitish-12345", + "expected_bucket_owner": "", + "id": "tf-test-bucket-destination-nitish-12345", + "mfa": null, + "versioning_configuration": [ + { + "mfa_delete": "", + "status": "Enabled" + } + ] + }, + "after_unknown": {}, + "before_sensitive": { + "versioning_configuration": [ + {} + ] + }, + "after_sensitive": { + "versioning_configuration": [ + {} + ] + } + } + }, + { + "address": "aws_s3_bucket_versioning.source", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "source", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "no-op" + ], + "before": { + "bucket": "tf-test-bucket-source-nitish-12345", + "expected_bucket_owner": "", + "id": "tf-test-bucket-source-nitish-12345", + "mfa": null, + "versioning_configuration": [ + { + "mfa_delete": "", + "status": "Enabled" + } + ] + }, + "after": { + "bucket": "tf-test-bucket-source-nitish-12345", + "expected_bucket_owner": "", + "id": "tf-test-bucket-source-nitish-12345", + "mfa": null, + "versioning_configuration": [ + { + "mfa_delete": "", + "status": "Enabled" + } + ] + }, + "after_unknown": {}, + "before_sensitive": { + "versioning_configuration": [ + {} + ] + }, + "after_sensitive": { + "versioning_configuration": [ + {} + ] + } + } + } + ], + "prior_state": { + "format_version": "1.0", + "terraform_version": "1.6.6", + "values": { + "root_module": { + "resources": [ + { + "address": "data.aws_iam_policy_document.assume_role", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "assume_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "id": "1765856792", + "json": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"s3.amazonaws.com\"\n }\n }\n ]\n}", + "override_policy_documents": null, + "policy_id": null, + "source_policy_documents": null, + "statement": [ + { + "actions": [ + "sts:AssumeRole" + ], + "condition": [], + "effect": "Allow", + "not_actions": [], + "not_principals": [], + "not_resources": [], + "principals": [ + { + "identifiers": [ + "s3.amazonaws.com" + ], + "type": "Service" + } + ], + "resources": [], + "sid": "" + } + ], + "version": "2012-10-17" + }, + "sensitive_values": { + "statement": [ + { + "actions": [ + false + ], + "condition": [], + "not_actions": [], + "not_principals": [], + "not_resources": [], + "principals": [ + { + "identifiers": [ + false + ] + } + ], + "resources": [] + } + ] + } + }, + { + "address": "data.aws_iam_policy_document.replication", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "id": "912466413", + "json": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"s3:ListBucket\",\n \"s3:GetReplicationConfiguration\"\n ],\n \"Resource\": \"arn:aws:s3:::tf-test-bucket-source-nitish-12345\"\n },\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"s3:GetObjectVersionTagging\",\n \"s3:GetObjectVersionForReplication\",\n \"s3:GetObjectVersionAcl\"\n ],\n \"Resource\": \"arn:aws:s3:::tf-test-bucket-source-nitish-12345/*\"\n },\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n \"s3:ReplicateTags\",\n \"s3:ReplicateObject\"\n ],\n \"Resource\": \"arn:aws:s3:::tf-test-bucket-destination-nitish-12345/*\"\n }\n ]\n}", + "override_policy_documents": null, + "policy_id": null, + "source_policy_documents": null, + "statement": [ + { + "actions": [ + "s3:GetReplicationConfiguration", + "s3:ListBucket" + ], + "condition": [], + "effect": "Allow", + "not_actions": [], + "not_principals": [], + "not_resources": [], + "principals": [], + "resources": [ + "arn:aws:s3:::tf-test-bucket-source-nitish-12345" + ], + "sid": "" + }, + { + "actions": [ + "s3:GetObjectVersionAcl", + "s3:GetObjectVersionForReplication", + "s3:GetObjectVersionTagging" + ], + "condition": [], + "effect": "Allow", + "not_actions": [], + "not_principals": [], + "not_resources": [], + "principals": [], + "resources": [ + "arn:aws:s3:::tf-test-bucket-source-nitish-12345/*" + ], + "sid": "" + }, + { + "actions": [ + "s3:ReplicateObject", + "s3:ReplicateTags" + ], + "condition": [], + "effect": "Allow", + "not_actions": [], + "not_principals": [], + "not_resources": [], + "principals": [], + "resources": [ + "arn:aws:s3:::tf-test-bucket-destination-nitish-12345/*" + ], + "sid": "" + } + ], + "version": "2012-10-17" + }, + "sensitive_values": { + "statement": [ + { + "actions": [ + false, + false + ], + "condition": [], + "not_actions": [], + "not_principals": [], + "not_resources": [], + "principals": [], + "resources": [ + false + ] + }, + { + "actions": [ + false, + false, + false + ], + "condition": [], + "not_actions": [], + "not_principals": [], + "not_resources": [], + "principals": [], + "resources": [ + false + ] + }, + { + "actions": [ + false, + false + ], + "condition": [], + "not_actions": [], + "not_principals": [], + "not_resources": [], + "principals": [], + "resources": [ + false + ] + } + ] + } + }, + { + "address": "aws_iam_policy.replication", + "mode": "managed", + "type": "aws_iam_policy", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "arn": "arn:aws:iam::844333597536:policy/tf-iam-role-policy-replication-12345", + "description": "", + "id": "arn:aws:iam::844333597536:policy/tf-iam-role-policy-replication-12345", + "name": "tf-iam-role-policy-replication-12345", + "name_prefix": "", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"s3:ListBucket\",\"s3:GetReplicationConfiguration\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:s3:::tf-test-bucket-source-nitish-12345\"},{\"Action\":[\"s3:GetObjectVersionTagging\",\"s3:GetObjectVersionForReplication\",\"s3:GetObjectVersionAcl\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:s3:::tf-test-bucket-source-nitish-12345/*\"},{\"Action\":[\"s3:ReplicateTags\",\"s3:ReplicateObject\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:s3:::tf-test-bucket-destination-nitish-12345/*\"}],\"Version\":\"2012-10-17\"}", + "policy_id": "ANPA4JFRUINQLTD64575W", + "tags": {}, + "tags_all": {} + }, + "sensitive_values": { + "tags": {}, + "tags_all": {} + }, + "depends_on": [ + "aws_s3_bucket.destination", + "aws_s3_bucket.source", + "data.aws_iam_policy_document.replication" + ] + }, + { + "address": "aws_iam_role.replication", + "mode": "managed", + "type": "aws_iam_role", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "arn": "arn:aws:iam::844333597536:role/tf-iam-role-replication-12345", + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"s3.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "create_date": "2024-01-24T10:55:42Z", + "description": "", + "force_detach_policies": false, + "id": "tf-iam-role-replication-12345", + "inline_policy": [], + "managed_policy_arns": [ + "arn:aws:iam::844333597536:policy/tf-iam-role-policy-replication-12345" + ], + "max_session_duration": 3600, + "name": "tf-iam-role-replication-12345", + "name_prefix": "", + "path": "/", + "permissions_boundary": "", + "tags": {}, + "tags_all": {}, + "unique_id": "AROA4JFRUINQIGIEP43IO" + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [ + false + ], + "tags": {}, + "tags_all": {} + }, + "depends_on": [ + "data.aws_iam_policy_document.assume_role" + ] + }, + { + "address": "aws_iam_role_policy_attachment.replication", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "replication", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "id": "tf-iam-role-replication-12345-20240124105702515800000001", + "policy_arn": "arn:aws:iam::844333597536:policy/tf-iam-role-policy-replication-12345", + "role": "tf-iam-role-replication-12345" + }, + "sensitive_values": {}, + "depends_on": [ + "aws_iam_policy.replication", + "aws_iam_role.replication", + "aws_s3_bucket.destination", + "aws_s3_bucket.source", + "data.aws_iam_policy_document.assume_role", + "data.aws_iam_policy_document.replication" + ] + }, + { + "address": "aws_s3_bucket.destination", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "destination", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::tf-test-bucket-destination-nitish-12345", + "bucket": "tf-test-bucket-destination-nitish-12345", + "bucket_domain_name": "tf-test-bucket-destination-nitish-12345.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "tf-test-bucket-destination-nitish-12345.s3.eu-west-1.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z1BKCTXD74EZPE", + "id": "tf-test-bucket-destination-nitish-12345", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "eu-west-1", + "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": true, + "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.source", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "source", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acceleration_status": "", + "acl": null, + "arn": "arn:aws:s3:::tf-test-bucket-source-nitish-12345", + "bucket": "tf-test-bucket-source-nitish-12345", + "bucket_domain_name": "tf-test-bucket-source-nitish-12345.s3.amazonaws.com", + "bucket_prefix": "", + "bucket_regional_domain_name": "tf-test-bucket-source-nitish-12345.s3.eu-central-1.amazonaws.com", + "cors_rule": [], + "force_destroy": false, + "grant": [ + { + "id": "62ea66bd2e8f7e76e4fb466e942a41389d6057fcc90d732feaac373bb0d0a7a5", + "permissions": [ + "FULL_CONTROL" + ], + "type": "CanonicalUser", + "uri": "" + } + ], + "hosted_zone_id": "Z21DNDUVLTQW6Q", + "id": "tf-test-bucket-source-nitish-12345", + "lifecycle_rule": [], + "logging": [], + "object_lock_configuration": [], + "object_lock_enabled": false, + "policy": "", + "region": "eu-central-1", + "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": true, + "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.destination", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "destination", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "tf-test-bucket-destination-nitish-12345", + "expected_bucket_owner": "", + "id": "tf-test-bucket-destination-nitish-12345", + "mfa": null, + "versioning_configuration": [ + { + "mfa_delete": "", + "status": "Enabled" + } + ] + }, + "sensitive_values": { + "versioning_configuration": [ + {} + ] + }, + "depends_on": [ + "aws_s3_bucket.destination" + ] + }, + { + "address": "aws_s3_bucket_versioning.source", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "source", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "tf-test-bucket-source-nitish-12345", + "expected_bucket_owner": "", + "id": "tf-test-bucket-source-nitish-12345", + "mfa": null, + "versioning_configuration": [ + { + "mfa_delete": "", + "status": "Enabled" + } + ] + }, + "sensitive_values": { + "versioning_configuration": [ + {} + ] + }, + "depends_on": [ + "aws_s3_bucket.source" + ] + } + ] + } + } + }, + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "expressions": { + } + }, + "aws.central": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "alias": "central", + "expressions": { + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.replication", + "mode": "managed", + "type": "aws_iam_policy", + "name": "replication", + "provider_config_key": "aws", + "expressions": { + "name": { + "constant_value": "tf-iam-role-policy-replication-12345" + }, + "policy": { + "references": [ + "data.aws_iam_policy_document.replication.json", + "data.aws_iam_policy_document.replication" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.replication", + "mode": "managed", + "type": "aws_iam_role", + "name": "replication", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "references": [ + "data.aws_iam_policy_document.assume_role.json", + "data.aws_iam_policy_document.assume_role" + ] + }, + "name": { + "constant_value": "tf-iam-role-replication-12345" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.replication", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "replication", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.replication.arn", + "aws_iam_policy.replication" + ] + }, + "role": { + "references": [ + "aws_iam_role.replication.name", + "aws_iam_role.replication" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket.destination", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "destination", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "tf-test-bucket-destination-nitish-12345" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket.source", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "source", + "provider_config_key": "aws.central", + "expressions": { + "bucket": { + "constant_value": "tf-test-bucket-source-nitish-12345" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_replication_configuration.replication", + "mode": "managed", + "type": "aws_s3_bucket_replication_configuration", + "name": "replication", + "provider_config_key": "aws.central", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.source.id", + "aws_s3_bucket.source" + ] + }, + "role": { + "references": [ + "aws_iam_role.replication.arn", + "aws_iam_role.replication" + ] + }, + "rule": [ + { + "delete_marker_replication": [ + { + "status": { + "constant_value": "Enabled" + } + } + ], + "destination": [ + { + "bucket": { + "references": [ + "aws_s3_bucket.destination.arn", + "aws_s3_bucket.destination" + ] + }, + "storage_class": { + "constant_value": "STANDARD" + } + } + ], + "filter": [ + { + "prefix": { + "constant_value": "foo" + } + } + ], + "id": { + "constant_value": "foobar" + }, + "status": { + "constant_value": "Enabled" + } + } + ] + }, + "schema_version": 0, + "depends_on": [ + "aws_s3_bucket_versioning.source" + ] + }, + { + "address": "aws_s3_bucket_versioning.destination", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "destination", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.destination.id", + "aws_s3_bucket.destination" + ] + }, + "versioning_configuration": [ + { + "status": { + "constant_value": "Enabled" + } + } + ] + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_versioning.source", + "mode": "managed", + "type": "aws_s3_bucket_versioning", + "name": "source", + "provider_config_key": "aws.central", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.source.id", + "aws_s3_bucket.source" + ] + }, + "versioning_configuration": [ + { + "status": { + "constant_value": "Enabled" + } + } + ] + }, + "schema_version": 0 + }, + { + "address": "data.aws_iam_policy_document.assume_role", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "assume_role", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "sts:AssumeRole" + ] + }, + "effect": { + "constant_value": "Allow" + }, + "principals": [ + { + "identifiers": { + "constant_value": [ + "s3.amazonaws.com" + ] + }, + "type": { + "constant_value": "Service" + } + } + ] + } + ] + }, + "schema_version": 0 + }, + { + "address": "data.aws_iam_policy_document.replication", + "mode": "data", + "type": "aws_iam_policy_document", + "name": "replication", + "provider_config_key": "aws", + "expressions": { + "statement": [ + { + "actions": { + "constant_value": [ + "s3:GetReplicationConfiguration", + "s3:ListBucket" + ] + }, + "effect": { + "constant_value": "Allow" + }, + "resources": { + "references": [ + "aws_s3_bucket.source.arn", + "aws_s3_bucket.source" + ] + } + }, + { + "actions": { + "constant_value": [ + "s3:GetObjectVersionForReplication", + "s3:GetObjectVersionAcl", + "s3:GetObjectVersionTagging" + ] + }, + "effect": { + "constant_value": "Allow" + }, + "resources": { + "references": [ + "aws_s3_bucket.source.arn", + "aws_s3_bucket.source" + ] + } + }, + { + "actions": { + "constant_value": [ + "s3:ReplicateObject", + "s3:ReplicateTags" + ] + }, + "effect": { + "constant_value": "Allow" + }, + "resources": { + "references": [ + "aws_s3_bucket.destination.arn", + "aws_s3_bucket.destination" + ] + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.replication", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_s3_bucket.source", + "attribute": [ + "id" + ] + }, + { + "resource": "aws_s3_bucket.destination", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-01-24T11:08:21Z", + "errored": false +} diff --git a/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/good-terraform.tf b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/good-terraform.tf new file mode 100644 index 00000000..90bfbdf0 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-cross-region-replication/test/good-terraform.tf @@ -0,0 +1,125 @@ +provider "aws" { + region = "eu-west-1" +} + +provider "aws" { + alias = "central" + region = "eu-central-1" +} + +data "aws_iam_policy_document" "assume_role" { + statement { + effect = "Allow" + + principals { + type = "Service" + identifiers = ["s3.amazonaws.com"] + } + + actions = ["sts:AssumeRole"] + } +} + +resource "aws_iam_role" "replication" { + name = "tf-iam-role-replication-12345" + assume_role_policy = data.aws_iam_policy_document.assume_role.json +} + +data "aws_iam_policy_document" "replication" { + statement { + effect = "Allow" + + actions = [ + "s3:GetReplicationConfiguration", + "s3:ListBucket", + ] + + resources = [aws_s3_bucket.source.arn] + } + + statement { + effect = "Allow" + + actions = [ + "s3:GetObjectVersionForReplication", + "s3:GetObjectVersionAcl", + "s3:GetObjectVersionTagging", + ] + + resources = ["${aws_s3_bucket.source.arn}/*"] + } + + statement { + effect = "Allow" + + actions = [ + "s3:ReplicateObject", + "s3:ReplicateTags", + ] + + resources = ["${aws_s3_bucket.destination.arn}/*"] + } +} + +resource "aws_iam_policy" "replication" { + name = "tf-iam-role-policy-replication-12345" + policy = data.aws_iam_policy_document.replication.json +} + +resource "aws_iam_role_policy_attachment" "replication" { + role = aws_iam_role.replication.name + policy_arn = aws_iam_policy.replication.arn +} + +resource "aws_s3_bucket" "destination" { + bucket = "tf-test-bucket-destination-nitish-12345" +} + +resource "aws_s3_bucket_versioning" "destination" { + bucket = aws_s3_bucket.destination.id + versioning_configuration { + status = "Enabled" + } +} + +resource "aws_s3_bucket" "source" { + provider = aws.central + bucket = "tf-test-bucket-source-nitish-12345" +} + +resource "aws_s3_bucket_versioning" "source" { + provider = aws.central + + bucket = aws_s3_bucket.source.id + versioning_configuration { + status = "Enabled" + } +} + +resource "aws_s3_bucket_replication_configuration" "replication" { + provider = aws.central + # Must have bucket versioning enabled first + depends_on = [aws_s3_bucket_versioning.source] + + role = aws_iam_role.replication.arn + bucket = aws_s3_bucket.source.id + + rule { + id = "foobar" + + filter { + prefix = "foo" + } + + status = "Enabled" + + destination { + bucket = aws_s3_bucket.destination.arn + storage_class = "STANDARD" + } + + delete_marker_replication { + status = "Enabled" + } + } +} \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-s3-server-access-logging/README.md b/terraform/plan/s3-best-practices/enable-s3-server-access-logging/README.md new file mode 100644 index 00000000..f8f17a03 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-server-access-logging/README.md @@ -0,0 +1,33 @@ +Server access logging is a feature provided by Amazon Simple Storage Service (S3) that allows you to track and log requests for access to your S3 bucket. When enabled, S3 will generate log records for each request made to the bucket, recording details such as the requester's IP address, the request time, the HTTP method used, the requested resource, the response status code, and more. + +In order to enable server access logging for your S3 Bucket with the help of Terraform, you need to use *aws_s3_server_access_logging* block. The required fields are bucket name, target bucket name, and target bucket prefix. + +``` +resource "aws_s3_bucket_logging" "example" { + bucket = aws_s3_bucket.example.id + + target_bucket = aws_s3_bucket.log_bucket.id + target_prefix = "log/" +} +``` + +If you're not using the *aws_s3_bucket_logging* block in your Terraform file, this means that server-access-logging is set to be disabled. By default, it is set to disabled as well. + +**In order to test this policy, perform the following steps:** + +1. Navigate to the `aws/s3/terraform/enable-s3-server-access-logging` 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 --bindings ./binding.yaml + ``` + Since you've used the *aws_s3_bucket_logging* block in your Terraform file, this means that the server access loggin is set to be Enabled. Hence, the policy will give you Passing checks. If you try to remove the block, get a payload out of it(*bad-terraform.tf*), and test your policy against the *bad-payload.json* again using the above command, you'll get FAIL checks. + \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-s3-server-access-logging/enable-server-access-logging.yaml b/terraform/plan/s3-best-practices/enable-s3-server-access-logging/enable-server-access-logging.yaml new file mode 100644 index 00000000..5d728dda --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-server-access-logging/enable-server-access-logging.yaml @@ -0,0 +1,28 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: enable-s3-server-access-logging + annotations: + policies.kyverno.io/title: enable-s3-server-access-logging + policies.kyverno.io/category: AWS S3 Security Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + Server access logging provides detailed records for the + requests that are made to an Amazon S3 bucket. Server access + logs are useful for many applications. For example, access + log information can be useful in security and access audits. + This information can also help you learn about your customer + base and understand your Amazon S3 bill. +spec: + rules: + - name: enable-s3-server-access-logging + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_s3_bucket'] | length(@) > `0`): true + assert: + all: + - message: Use the aws_s3_bucket_logging resource to enable server access logging + check: + (planned_values.root_module.resources[?type=='aws_s3_bucket_logging'] | length(@) > `0`): true + \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/bad-payload.json b/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/bad-payload.json new file mode 100644 index 00000000..e5c6f813 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/bad-payload.json @@ -0,0 +1,357 @@ +{ + "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": "my-tf-example-bucket", + "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.log_bucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "log_bucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "my-tf-log-bucket", + "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_acl.example", + "mode": "managed", + "type": "aws_s3_bucket_acl", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acl": "private", + "expected_bucket_owner": null + }, + "sensitive_values": { + "access_control_policy": [] + } + }, + { + "address": "aws_s3_bucket_acl.log_bucket_acl", + "mode": "managed", + "type": "aws_s3_bucket_acl", + "name": "log_bucket_acl", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acl": "log-delivery-write", + "expected_bucket_owner": null + }, + "sensitive_values": { + "access_control_policy": [] + } + } + ] + } + }, + "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": "my-tf-example-bucket", + "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.log_bucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "log_bucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "my-tf-log-bucket", + "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_acl.example", + "mode": "managed", + "type": "aws_s3_bucket_acl", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "acl": "private", + "expected_bucket_owner": null + }, + "after_unknown": { + "access_control_policy": true, + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": { + "access_control_policy": [] + } + } + }, + { + "address": "aws_s3_bucket_acl.log_bucket_acl", + "mode": "managed", + "type": "aws_s3_bucket_acl", + "name": "log_bucket_acl", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "acl": "log-delivery-write", + "expected_bucket_owner": null + }, + "after_unknown": { + "access_control_policy": true, + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": { + "access_control_policy": [] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "my-tf-example-bucket" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket.log_bucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "log_bucket", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "my-tf-log-bucket" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_acl.example", + "mode": "managed", + "type": "aws_s3_bucket_acl", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "acl": { + "constant_value": "private" + }, + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_acl.log_bucket_acl", + "mode": "managed", + "type": "aws_s3_bucket_acl", + "name": "log_bucket_acl", + "provider_config_key": "aws", + "expressions": { + "acl": { + "constant_value": "log-delivery-write" + }, + "bucket": { + "references": [ + "aws_s3_bucket.log_bucket.id", + "aws_s3_bucket.log_bucket" + ] + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + }, + { + "resource": "aws_s3_bucket.log_bucket", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-02-06T06:52:22Z", + "errored": false +} diff --git a/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/bad-terraform.tf b/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/bad-terraform.tf new file mode 100644 index 00000000..b26eb026 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/bad-terraform.tf @@ -0,0 +1,32 @@ +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 = "my-tf-example-bucket" +} + +resource "aws_s3_bucket_acl" "example" { + bucket = aws_s3_bucket.example.id + acl = "private" +} + +resource "aws_s3_bucket" "log_bucket" { + bucket = "my-tf-log-bucket" +} + +resource "aws_s3_bucket_acl" "log_bucket_acl" { + bucket = aws_s3_bucket.log_bucket.id + acl = "log-delivery-write" +} diff --git a/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/binding.yaml b/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/chainsaw-test.yaml b/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/chainsaw-test.yaml new file mode 100644 index 00000000..fed725e7 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/chainsaw-test.yaml @@ -0,0 +1,59 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../enable-server-access-logging.yaml --payload ./good-payload.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: enable-s3-server-access-logging + rules: + - rule: + name: enable-s3-server-access-logging + error: ~ + violations: ~ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../enable-server-access-logging.yaml --payload ./bad-payload.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: enable-s3-server-access-logging + rules: + - rule: + name: enable-s3-server-access-logging + error: ~ + violations: + - message: Use the aws_s3_bucket_logging resource to enable server access logging + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' diff --git a/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/good-payload.json b/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/good-payload.json new file mode 100644 index 00000000..30d23683 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/good-payload.json @@ -0,0 +1,426 @@ +{ + "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": "my-tf-example-bucket", + "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.log_bucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "log_bucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "my-tf-log-bucket", + "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_acl.example", + "mode": "managed", + "type": "aws_s3_bucket_acl", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acl": "private", + "expected_bucket_owner": null + }, + "sensitive_values": { + "access_control_policy": [] + } + }, + { + "address": "aws_s3_bucket_acl.log_bucket_acl", + "mode": "managed", + "type": "aws_s3_bucket_acl", + "name": "log_bucket_acl", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "acl": "log-delivery-write", + "expected_bucket_owner": null + }, + "sensitive_values": { + "access_control_policy": [] + } + }, + { + "address": "aws_s3_bucket_logging.example", + "mode": "managed", + "type": "aws_s3_bucket_logging", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "expected_bucket_owner": null, + "target_grant": [], + "target_prefix": "log/" + }, + "sensitive_values": { + "target_grant": [] + } + } + ] + } + }, + "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": "my-tf-example-bucket", + "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.log_bucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "log_bucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "my-tf-log-bucket", + "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_acl.example", + "mode": "managed", + "type": "aws_s3_bucket_acl", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "acl": "private", + "expected_bucket_owner": null + }, + "after_unknown": { + "access_control_policy": true, + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": { + "access_control_policy": [] + } + } + }, + { + "address": "aws_s3_bucket_acl.log_bucket_acl", + "mode": "managed", + "type": "aws_s3_bucket_acl", + "name": "log_bucket_acl", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "acl": "log-delivery-write", + "expected_bucket_owner": null + }, + "after_unknown": { + "access_control_policy": true, + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": { + "access_control_policy": [] + } + } + }, + { + "address": "aws_s3_bucket_logging.example", + "mode": "managed", + "type": "aws_s3_bucket_logging", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "expected_bucket_owner": null, + "target_grant": [], + "target_prefix": "log/" + }, + "after_unknown": { + "bucket": true, + "id": true, + "target_bucket": true, + "target_grant": [] + }, + "before_sensitive": false, + "after_sensitive": { + "target_grant": [] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.example", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "my-tf-example-bucket" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket.log_bucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "log_bucket", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "my-tf-log-bucket" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_acl.example", + "mode": "managed", + "type": "aws_s3_bucket_acl", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "acl": { + "constant_value": "private" + }, + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_acl.log_bucket_acl", + "mode": "managed", + "type": "aws_s3_bucket_acl", + "name": "log_bucket_acl", + "provider_config_key": "aws", + "expressions": { + "acl": { + "constant_value": "log-delivery-write" + }, + "bucket": { + "references": [ + "aws_s3_bucket.log_bucket.id", + "aws_s3_bucket.log_bucket" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_logging.example", + "mode": "managed", + "type": "aws_s3_bucket_logging", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "target_bucket": { + "references": [ + "aws_s3_bucket.log_bucket.id", + "aws_s3_bucket.log_bucket" + ] + }, + "target_prefix": { + "constant_value": "log/" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + }, + { + "resource": "aws_s3_bucket.log_bucket", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-02-06T06:50:06Z", + "errored": false +} diff --git a/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/good-terraform.tf b/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/good-terraform.tf new file mode 100644 index 00000000..d626d0f4 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-server-access-logging/test/good-terraform.tf @@ -0,0 +1,39 @@ +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 = "my-tf-example-bucket" +} + +resource "aws_s3_bucket_acl" "example" { + bucket = aws_s3_bucket.example.id + acl = "private" +} + +resource "aws_s3_bucket" "log_bucket" { + bucket = "my-tf-log-bucket" +} + +resource "aws_s3_bucket_acl" "log_bucket_acl" { + bucket = aws_s3_bucket.log_bucket.id + acl = "log-delivery-write" +} + +resource "aws_s3_bucket_logging" "example" { + bucket = aws_s3_bucket.example.id + + target_bucket = aws_s3_bucket.log_bucket.id + target_prefix = "log/" +} \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-s3-versioning/README.md b/terraform/plan/s3-best-practices/enable-s3-versioning/README.md new file mode 100644 index 00000000..7aa0943b --- /dev/null +++ b/terraform/plan/s3-best-practices/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 --bindings ./binding.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/plan/s3-best-practices/enable-s3-versioning/s3-enable-versioning.yaml b/terraform/plan/s3-best-practices/enable-s3-versioning/s3-enable-versioning.yaml new file mode 100644 index 00000000..233c5f72 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-versioning/s3-enable-versioning.yaml @@ -0,0 +1,33 @@ +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: + - ($analyzer.resource.type): terraform-plan + - (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/plan/s3-best-practices/enable-s3-versioning/test/bad-payload-01.json b/terraform/plan/s3-best-practices/enable-s3-versioning/test/bad-payload-01.json new file mode 100644 index 00000000..ce71c2cf --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-versioning/test/bad-payload-01.json @@ -0,0 +1,216 @@ +{ + "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": { + } + } + }, + "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/plan/s3-best-practices/enable-s3-versioning/test/bad-payload-02.json b/terraform/plan/s3-best-practices/enable-s3-versioning/test/bad-payload-02.json new file mode 100644 index 00000000..dba5e5a5 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-versioning/test/bad-payload-02.json @@ -0,0 +1,629 @@ +{ + "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": { + } + } + }, + "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/plan/s3-best-practices/enable-s3-versioning/test/bad-terraform-01.tf b/terraform/plan/s3-best-practices/enable-s3-versioning/test/bad-terraform-01.tf new file mode 100644 index 00000000..7921f554 --- /dev/null +++ b/terraform/plan/s3-best-practices/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/plan/s3-best-practices/enable-s3-versioning/test/bad-terraform-02.tf b/terraform/plan/s3-best-practices/enable-s3-versioning/test/bad-terraform-02.tf new file mode 100644 index 00000000..1867ba52 --- /dev/null +++ b/terraform/plan/s3-best-practices/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/plan/s3-best-practices/enable-s3-versioning/test/binding.yaml b/terraform/plan/s3-best-practices/enable-s3-versioning/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-versioning/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-s3-versioning/test/chainsaw-test.yaml b/terraform/plan/s3-best-practices/enable-s3-versioning/test/chainsaw-test.yaml new file mode 100644 index 00000000..27894020 --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-versioning/test/chainsaw-test.yaml @@ -0,0 +1,91 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../s3-enable-versioning.yaml --payload ./good-payload.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: enable-s3-versioning + rules: + - rule: + name: check-s3-versioning-setting + error: ~ + violations: ~ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../s3-enable-versioning.yaml --payload ./bad-payload-01.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: enable-s3-versioning + rules: + - rule: + name: check-s3-versioning-setting + error: ~ + violations: + - message: S3 Bucket Versioning needs to be set to 'Enabled' + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../s3-enable-versioning.yaml --payload ./bad-payload-02.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: enable-s3-versioning + rules: + - rule: + name: check-s3-versioning-setting + error: ~ + violations: + - message: Use the `aws_s3_bucket_versioning` resource to enable versioning. + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/enable-s3-versioning/test/good-payload.json b/terraform/plan/s3-best-practices/enable-s3-versioning/test/good-payload.json new file mode 100644 index 00000000..2488f4ce --- /dev/null +++ b/terraform/plan/s3-best-practices/enable-s3-versioning/test/good-payload.json @@ -0,0 +1,720 @@ +{ + "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": { + } + } + }, + "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/plan/s3-best-practices/enable-s3-versioning/test/good-terraform.tf b/terraform/plan/s3-best-practices/enable-s3-versioning/test/good-terraform.tf new file mode 100644 index 00000000..fd608df2 --- /dev/null +++ b/terraform/plan/s3-best-practices/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" + } +} diff --git a/terraform/plan/s3-best-practices/public-access-block/README.md b/terraform/plan/s3-best-practices/public-access-block/README.md new file mode 100644 index 00000000..a92b792a --- /dev/null +++ b/terraform/plan/s3-best-practices/public-access-block/README.md @@ -0,0 +1,79 @@ +Amazon S3 Block Public Access provides settings for access points, buckets, and accounts to help you manage public access to Amazon S3 resources. By default, new buckets, access points, and objects do not allow public access. + +In order to configure public block access settings for your S3 buckets, read [here](https://docs.aws.amazon.com/AmazonS3/latest/userguide/configuring-block-public-access-bucket.html) + +S3 Block Public Access provides four settings. You can apply these settings in any combination to individual access points, buckets, or entire AWS accounts. If you apply a setting to an account, it applies to all buckets and access points that are owned by that account. Similarly, if you apply a setting to a bucket, it applies to all access points associated with that bucket. + +The four settings mentioned above are: + +1. *BlockPublicAcls*: When this is turned on, it prevents anyone from making data in a bucket public by using Access Control Lists (ACLs). ACLs are like a list of who can and cannot access stuff in the bucket. + +2. *IgnorePublicAcls*: If this is enabled, it means the system ignores any public access settings set by Access Control Lists (ACLs). In simpler terms, it doesn't pay attention to certain rules that might make data public. + +3. *BlockPublicPolicy*: This setting stops people from making data public by using bucket policies. Bucket policies are like rules you set for who can access your bucket and how. When you enable this, it prevents public access through these policies. + +4. *RestrictPublicBuckets*: Turning this on limits public access to buckets. It means you're putting restrictions on making your buckets and the data inside them public. This helps in adding an extra layer of control to prevent accidental exposure of your data to the public. + +A brief details about these options have been mentioned in the [AWS Documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-control-block-public-access.html). + +Now, if you'd like to disable the public access block for your S3 bucket, you need to make sure that all the above four settings are enabled. Terraform provides you the `aws_s3_bucket_public_access_block` resource to configure these settings + +``` +resource "aws_s3_bucket_public_access_block" "example" { + bucket = aws_s3_bucket.example.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} +``` + +**It is important to note that all the argument should be set to *true* in order to disable the public access control. If any one of the argument is set to false, there will be public access configured based on the above settings defined.** + +If you'd like to learn more about this, head over to the [Argument Reference](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_public_access_block#argument-reference) for public access block in Terraform. + +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 --bindings ./binding.yaml + ``` + + Since you've set all the fields for S3 public access block in your Terraform file to *true*, the policy will give you *Passing checks*. + +**Failing Scenario:** If you set any of the argument in your Terraform S3 public access block to false, the policy will be failed. Why? Because you are trying to enable the public access block. A Terraform S3 public access block that could give failing scenario is given below: + +``` +resource "aws_s3_bucket_public_access_block" "example" { + bucket = aws_s3_bucket.example.id + + block_public_acls = false + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = false +} +``` + +Ideally, you can test your policy for the *bad-payload.json* that is present at `./aws/s3/public-access-block/policy-test` using the following command from root: + +``` +kyverno-json scan --payload ./aws/s3/public-access-block/policy-test/bad-payload.json --policy policy.yaml --bindings ./binding.yaml +``` + +There is also `bad-s3.tf` file provided under `policy-test` directory that you can use to build your payload and use in the above command as an argument to `--policy` flag. \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/public-access-block/test/bad-payload-01.json b/terraform/plan/s3-best-practices/public-access-block/test/bad-payload-01.json new file mode 100644 index 00000000..3f75bb8a --- /dev/null +++ b/terraform/plan/s3-best-practices/public-access-block/test/bad-payload-01.json @@ -0,0 +1,202 @@ +{ + "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": "tf-bucket-demo", + "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_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_public_acls": false, + "block_public_policy": true, + "ignore_public_acls": true, + "restrict_public_buckets": true + }, + "sensitive_values": {} + } + ] + } + }, + "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": "tf-bucket-demo", + "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_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_public_acls": false, + "block_public_policy": true, + "ignore_public_acls": true, + "restrict_public_buckets": true + }, + "after_unknown": { + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + } + } + }, + "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-bucket-demo" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "block_public_acls": { + "constant_value": false + }, + "block_public_policy": { + "constant_value": true + }, + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "ignore_public_acls": { + "constant_value": true + }, + "restrict_public_buckets": { + "constant_value": true + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-12T15:00:06Z", + "errored": false +} diff --git a/terraform/plan/s3-best-practices/public-access-block/test/bad-payload-02.json b/terraform/plan/s3-best-practices/public-access-block/test/bad-payload-02.json new file mode 100644 index 00000000..ebb9e453 --- /dev/null +++ b/terraform/plan/s3-best-practices/public-access-block/test/bad-payload-02.json @@ -0,0 +1,202 @@ +{ + "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": "tf-bucket-demo", + "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_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_public_acls": true, + "block_public_policy": false, + "ignore_public_acls": true, + "restrict_public_buckets": true + }, + "sensitive_values": {} + } + ] + } + }, + "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": "tf-bucket-demo", + "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_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_public_acls": true, + "block_public_policy": false, + "ignore_public_acls": true, + "restrict_public_buckets": true + }, + "after_unknown": { + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + } + } + }, + "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-bucket-demo" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "block_public_acls": { + "constant_value": true + }, + "block_public_policy": { + "constant_value": false + }, + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "ignore_public_acls": { + "constant_value": true + }, + "restrict_public_buckets": { + "constant_value": true + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-12T15:00:06Z", + "errored": false +} diff --git a/terraform/plan/s3-best-practices/public-access-block/test/bad-payload-03.json b/terraform/plan/s3-best-practices/public-access-block/test/bad-payload-03.json new file mode 100644 index 00000000..e0ca63e1 --- /dev/null +++ b/terraform/plan/s3-best-practices/public-access-block/test/bad-payload-03.json @@ -0,0 +1,203 @@ +{ + "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": "tf-bucket-demo", + "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_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_public_acls": true, + "block_public_policy": true, + "ignore_public_acls": false, + "restrict_public_buckets": true + }, + "sensitive_values": {} + } + ] + } + }, + "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": "tf-bucket-demo", + "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_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_public_acls": true, + "block_public_policy": true, + "ignore_public_acls": false, + "restrict_public_buckets": true + }, + "after_unknown": { + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + } + } + }, + "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-bucket-demo" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "block_public_acls": { + "constant_value": true + }, + "block_public_policy": { + "constant_value": true + }, + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "ignore_public_acls": { + "constant_value": false + }, + "restrict_public_buckets": { + "constant_value": true + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-12T15:00:06Z", + "errored": false + } + \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/public-access-block/test/bad-payload-04.json b/terraform/plan/s3-best-practices/public-access-block/test/bad-payload-04.json new file mode 100644 index 00000000..f9530abc --- /dev/null +++ b/terraform/plan/s3-best-practices/public-access-block/test/bad-payload-04.json @@ -0,0 +1,203 @@ +{ + "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": "tf-bucket-demo", + "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_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_public_acls": true, + "block_public_policy": true, + "ignore_public_acls": true, + "restrict_public_buckets": false + }, + "sensitive_values": {} + } + ] + } + }, + "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": "tf-bucket-demo", + "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_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_public_acls": true, + "block_public_policy": true, + "ignore_public_acls": true, + "restrict_public_buckets": false + }, + "after_unknown": { + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + } + } + }, + "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-bucket-demo" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "block_public_acls": { + "constant_value": true + }, + "block_public_policy": { + "constant_value": true + }, + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "ignore_public_acls": { + "constant_value": true + }, + "restrict_public_buckets": { + "constant_value": false + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-12T15:00:06Z", + "errored": false + } + \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/public-access-block/test/bad-terraform-01.tf b/terraform/plan/s3-best-practices/public-access-block/test/bad-terraform-01.tf new file mode 100644 index 00000000..41957570 --- /dev/null +++ b/terraform/plan/s3-best-practices/public-access-block/test/bad-terraform-01.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" "test-bucket" { + bucket = "tf-bucket-demo" +} + +resource "aws_s3_bucket_public_access_block" "test-bucket" { + bucket = aws_s3_bucket.example.id + + block_public_acls = false + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} diff --git a/terraform/plan/s3-best-practices/public-access-block/test/bad-terraform-02.tf b/terraform/plan/s3-best-practices/public-access-block/test/bad-terraform-02.tf new file mode 100644 index 00000000..97d92dca --- /dev/null +++ b/terraform/plan/s3-best-practices/public-access-block/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" "test-bucket" { + bucket = "tf-bucket-demo" +} + +resource "aws_s3_bucket_public_access_block" "test-bucket" { + bucket = aws_s3_bucket.example.id + + block_public_acls = true + block_public_policy = false + ignore_public_acls = true + restrict_public_buckets = true +} diff --git a/terraform/plan/s3-best-practices/public-access-block/test/bad-terraform-03.tf b/terraform/plan/s3-best-practices/public-access-block/test/bad-terraform-03.tf new file mode 100644 index 00000000..1fb32464 --- /dev/null +++ b/terraform/plan/s3-best-practices/public-access-block/test/bad-terraform-03.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" "test-bucket" { + bucket = "tf-bucket-demo" +} + +resource "aws_s3_bucket_public_access_block" "test-bucket" { + bucket = aws_s3_bucket.example.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = false + restrict_public_buckets = true +} diff --git a/terraform/plan/s3-best-practices/public-access-block/test/bad-terraform-04.tf b/terraform/plan/s3-best-practices/public-access-block/test/bad-terraform-04.tf new file mode 100644 index 00000000..473bd6f9 --- /dev/null +++ b/terraform/plan/s3-best-practices/public-access-block/test/bad-terraform-04.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" "test-bucket" { + bucket = "tf-bucket-demo" +} + +resource "aws_s3_bucket_public_access_block" "test-bucket" { + bucket = aws_s3_bucket.example.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = false +} diff --git a/terraform/plan/s3-best-practices/public-access-block/test/binding.yaml b/terraform/plan/s3-best-practices/public-access-block/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/s3-best-practices/public-access-block/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/public-access-block/test/chainsaw-test.yaml b/terraform/plan/s3-best-practices/public-access-block/test/chainsaw-test.yaml new file mode 100644 index 00000000..6f0dcff6 --- /dev/null +++ b/terraform/plan/s3-best-practices/public-access-block/test/chainsaw-test.yaml @@ -0,0 +1,182 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../validate-public-access-block.yaml --payload ./good-payload-01.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: block-s3-public-access-setting + rules: + - rule: + name: validate-block-s3-public-access-setting + error: ~ + violations: ~ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test-02 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../validate-public-access-block.yaml --payload ./good-payload-02.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: block-s3-public-access-setting + rules: + - rule: + name: validate-block-s3-public-access-setting + error: ~ + violations: ~ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../validate-public-access-block.yaml --payload ./bad-payload-01.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: block-s3-public-access-setting + rules: + - rule: + name: validate-block-s3-public-access-setting + error: ~ + violations: + - message: Block Public ACLs should be set to true + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-02 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../validate-public-access-block.yaml --payload ./bad-payload-02.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: block-s3-public-access-setting + rules: + - rule: + name: validate-block-s3-public-access-setting + error: ~ + violations: + - message: Block Public Policy should be set to true + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-03 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../validate-public-access-block.yaml --payload ./bad-payload-03.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: block-s3-public-access-setting + rules: + - rule: + name: validate-block-s3-public-access-setting + error: ~ + violations: + - message: Ignore Public ACLs should be set to true + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-04 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --policy ../validate-public-access-block.yaml --payload ./bad-payload-04.json --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: block-s3-public-access-setting + rules: + - rule: + name: validate-block-s3-public-access-setting + error: ~ + violations: + - message: Restrict Public Buckets should be set to true + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' diff --git a/terraform/plan/s3-best-practices/public-access-block/test/good-payload-01.json b/terraform/plan/s3-best-practices/public-access-block/test/good-payload-01.json new file mode 100644 index 00000000..34cb9b07 --- /dev/null +++ b/terraform/plan/s3-best-practices/public-access-block/test/good-payload-01.json @@ -0,0 +1,202 @@ +{ + "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", + "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_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_public_acls": true, + "block_public_policy": true, + "ignore_public_acls": true, + "restrict_public_buckets": true + }, + "sensitive_values": {} + } + ] + } + }, + "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", + "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_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_public_acls": true, + "block_public_policy": true, + "ignore_public_acls": true, + "restrict_public_buckets": true + }, + "after_unknown": { + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + } + } + }, + "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" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "block_public_acls": { + "constant_value": true + }, + "block_public_policy": { + "constant_value": true + }, + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "ignore_public_acls": { + "constant_value": true + }, + "restrict_public_buckets": { + "constant_value": true + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-10T17:51:08Z", + "errored": false +} diff --git a/terraform/plan/s3-best-practices/public-access-block/test/good-payload-02.json b/terraform/plan/s3-best-practices/public-access-block/test/good-payload-02.json new file mode 100644 index 00000000..f40836f7 --- /dev/null +++ b/terraform/plan/s3-best-practices/public-access-block/test/good-payload-02.json @@ -0,0 +1,203 @@ +{ + "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", + "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_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_public_acls": true, + "block_public_policy": true, + "ignore_public_acls": true, + "restrict_public_buckets": true + }, + "sensitive_values": {} + } + ] + } + }, + "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", + "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_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_public_acls": true, + "block_public_policy": true, + "ignore_public_acls": true, + "restrict_public_buckets": true + }, + "after_unknown": { + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + } + } + }, + "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" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "block_public_acls": { + "constant_value": true + }, + "block_public_policy": { + "constant_value": true + }, + "bucket": { + "references": [ + "aws_s3_bucket.example.id", + "aws_s3_bucket.example" + ] + }, + "ignore_public_acls": { + "constant_value": true + }, + "restrict_public_buckets": { + "constant_value": true + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-01-10T17:51:08Z", + "errored": false + } + \ No newline at end of file diff --git a/terraform/plan/s3-best-practices/public-access-block/test/good-terraform-01.tf b/terraform/plan/s3-best-practices/public-access-block/test/good-terraform-01.tf new file mode 100644 index 00000000..adad5a78 --- /dev/null +++ b/terraform/plan/s3-best-practices/public-access-block/test/good-terraform-01.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-nitish-009" +} + +resource "aws_s3_bucket_public_access_block" "example" { + bucket = aws_s3_bucket.example.id + + # block_public_acls = true + # block_public_policy = true + # ignore_public_acls = true + # restrict_public_buckets = true +} diff --git a/terraform/plan/s3-best-practices/public-access-block/test/good-terraform-02.tf b/terraform/plan/s3-best-practices/public-access-block/test/good-terraform-02.tf new file mode 100644 index 00000000..46d8440e --- /dev/null +++ b/terraform/plan/s3-best-practices/public-access-block/test/good-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-nitish-009" +} + +resource "aws_s3_bucket_public_access_block" "example" { + bucket = aws_s3_bucket.example.id + + block_public_acls = true + block_public_policy = true + ignore_public_acls = true + restrict_public_buckets = true +} diff --git a/terraform/plan/s3-best-practices/public-access-block/validate-public-access-block.yaml b/terraform/plan/s3-best-practices/public-access-block/validate-public-access-block.yaml new file mode 100644 index 00000000..04897a66 --- /dev/null +++ b/terraform/plan/s3-best-practices/public-access-block/validate-public-access-block.yaml @@ -0,0 +1,40 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: block-s3-public-access-setting + annotations: + policies.kyverno.io/title: block-s3-public-access-setting + policies.kyverno.io/category: AWS S3 Security Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + The Amazon S3 Block Public Access feature provides settings for access points, + buckets, and accounts to help you manage public access to Amazon S3 resources. + By default, new buckets, access points, and objects don't allow public access. + However, users can modify bucket policies, access point policies, or object + permissions to allow public access. S3 Block Public Access settings override + these policies and permissions so that you can limit public access to these resources. +spec: + rules: + - name: validate-block-s3-public-access-setting + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_s3_bucket_public_access_block' || type=='aws_s3_bucket'] | length(@) > `0`): true + assert: + all: + - message: Block Public ACLs should be set to true + check: + ~.(planned_values.root_module.resources[?type=='aws_s3_bucket_public_access_block'].values): + block_public_acls: true + - message: Block Public Policy should be set to true + check: + ~.(planned_values.root_module.resources[?type=='aws_s3_bucket_public_access_block'].values): + block_public_policy: true + - message: Ignore Public ACLs should be set to true + check: + ~.(planned_values.root_module.resources[?type=='aws_s3_bucket_public_access_block'].values): + ignore_public_acls: true + - message: Restrict Public Buckets should be set to true + check: + ~.(planned_values.root_module.resources[?type=='aws_s3_bucket_public_access_block'].values): + restrict_public_buckets: true diff --git a/terraform/plan/s3-best-practices/validate-any-prinicpal/README.md b/terraform/plan/s3-best-practices/validate-any-prinicpal/README.md new file mode 100644 index 00000000..172ed857 --- /dev/null +++ b/terraform/plan/s3-best-practices/validate-any-prinicpal/README.md @@ -0,0 +1,59 @@ +The principal can be an AWS account, an IAM (Identity and Access Management) user, a federated user, an EC2 instance, or even an AWS service. + +When you create a bucket policy for an S3 bucket, you define statements that specify the actions allowed or denied for a given principal. Here's a breakdown of the components in a bucket policy statement related to the principal: + +1. **Effect:** It specifies whether the statement allows or denies the specified actions. It can be either "Allow" or "Deny." + +2. **Principal:** This is where you specify the entity (AWS account, IAM user, federated user, etc.) to which the policy applies. You can use the wildcard "*" to represent any principal, or you can specify a specific AWS account ID, IAM user ARN (Amazon Resource Name), or other identifiers. + +3. **Action:** It defines the specific actions (e.g., "s3:GetObject", "s3:PutObject") that are allowed or denied. + +4. **Resource:** It specifies the S3 resources (e.g., bucket names, object keys) to which the policy applies. + +``` + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::123456789012:user/example-user" + }, + "Action": "s3:ListBucket", + "Resource": "arn:aws:s3:::example-bucket" + } + ] +} +``` + +In this example: + +- Effect: It allows the specified actions. +- Principal: It specifies the IAM user with the ARN "arn:aws:iam::123456789012:user/example-user." +- Action: It allows the "s3:ListBucket" action. +- Resource: It specifies the S3 bucket with the ARN "arn:aws:s3:::example-bucket." + +This Policy ensures that the Principal value in the AWS S3 Bucket Policy is not set to `*`. If the Principal value is set to `*`, the policy will give you failing checks. + +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 scan` command + ``` + kyverno-json scan --payload payload.json --policy validate-any-principal.yaml --bindings ./binding.yaml + ``` +In order to run the policy for the failing checks, run it against the *bad-payload.json* present in the *test* folder. diff --git a/terraform/plan/s3-best-practices/validate-any-prinicpal/test/bad-payload-02.json b/terraform/plan/s3-best-practices/validate-any-prinicpal/test/bad-payload-02.json new file mode 100644 index 00000000..6e79b3d7 --- /dev/null +++ b/terraform/plan/s3-best-practices/validate-any-prinicpal/test/bad-payload-02.json @@ -0,0 +1,255 @@ +{ + "format_version": "1.2", + "terraform_version": "1.7.1", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.test_bucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "test_bucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "test-bucket-nitish-demo", + "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_policy.bucket_policy", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "bucket_policy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "policy": "{\"Statement\":[{\"Action\":[\"s3:GetObject\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Resource\":[\"arn:aws:s3:::test-bucket-nitish-demo/*\"],\"Sid\":\"PublicRead\"}],\"Version\":\"2012-10-17\"}" + }, + "sensitive_values": {} + }, + { + "address": "aws_s3_bucket_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_public_acls": false, + "block_public_policy": false, + "ignore_public_acls": false, + "restrict_public_buckets": false + }, + "sensitive_values": {} + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_s3_bucket.test_bucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "test_bucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "test-bucket-nitish-demo", + "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_policy.bucket_policy", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "bucket_policy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "policy": "{\"Statement\":[{\"Action\":[\"s3:GetObject\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Resource\":[\"arn:aws:s3:::test-bucket-nitish-demo/*\"],\"Sid\":\"PublicRead\"}],\"Version\":\"2012-10-17\"}" + }, + "after_unknown": { + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_s3_bucket_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_public_acls": false, + "block_public_policy": false, + "ignore_public_acls": false, + "restrict_public_buckets": false + }, + "after_unknown": { + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.test_bucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "test_bucket", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "test-bucket-nitish-demo" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_policy.bucket_policy", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "bucket_policy", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.test_bucket.id", + "aws_s3_bucket.test_bucket" + ] + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"PublicRead\",\n \"Effect\": \"Allow\",\n \"Principal\": { \"AWS\" : \"*\" },\n \"Action\": [\"s3:GetObject\"],\n \"Resource\": [\n \"arn:aws:s3:::test-bucket-nitish-demo/*\"\n ]\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "block_public_acls": { + "constant_value": false + }, + "block_public_policy": { + "constant_value": false + }, + "bucket": { + "references": [ + "aws_s3_bucket.test_bucket.id", + "aws_s3_bucket.test_bucket" + ] + }, + "ignore_public_acls": { + "constant_value": false + }, + "restrict_public_buckets": { + "constant_value": false + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.test_bucket", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-02-04T13:19:07Z", + "errored": false +} diff --git a/terraform/plan/s3-best-practices/validate-any-prinicpal/test/bad-payload.json b/terraform/plan/s3-best-practices/validate-any-prinicpal/test/bad-payload.json new file mode 100644 index 00000000..ca31ef73 --- /dev/null +++ b/terraform/plan/s3-best-practices/validate-any-prinicpal/test/bad-payload.json @@ -0,0 +1,260 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.test_bucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "test_bucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bucket": "test-bucket-nitish-demo", + "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_policy.bucket_policy", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "bucket_policy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "policy": "{\"Statement\":[{\"Action\":[\"s3:GetObject\"],\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":[\"arn:aws:s3:::test-bucket-nitish-demo/*\"],\"Sid\":\"PublicRead\"}],\"Version\":\"2012-10-17\"}" + }, + "sensitive_values": {} + }, + { + "address": "aws_s3_bucket_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_public_acls": false, + "block_public_policy": false, + "ignore_public_acls": false, + "restrict_public_buckets": false + }, + "sensitive_values": {} + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_s3_bucket.test_bucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "test_bucket", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bucket": "test-bucket-nitish-demo", + "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_policy.bucket_policy", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "bucket_policy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "policy": "{\"Statement\":[{\"Action\":[\"s3:GetObject\"],\"Effect\":\"Allow\",\"Principal\":\"*\",\"Resource\":[\"arn:aws:s3:::test-bucket-nitish-demo/*\"],\"Sid\":\"PublicRead\"}],\"Version\":\"2012-10-17\"}" + }, + "after_unknown": { + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_s3_bucket_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_public_acls": false, + "block_public_policy": false, + "ignore_public_acls": false, + "restrict_public_buckets": false + }, + "after_unknown": { + "bucket": true, + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": { + "region": { + "constant_value": "us-west-2" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.test_bucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "test_bucket", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "test-bucket-nitish-demo" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_policy.bucket_policy", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "bucket_policy", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.test_bucket.id", + "aws_s3_bucket.test_bucket" + ] + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"PublicRead\",\n \"Effect\": \"Allow\",\n \"Principal\": \"*\",\n \"Action\": [\"s3:GetObject\"],\n \"Resource\": [\n \"arn:aws:s3:::test-bucket-nitish-demo/*\"\n ]\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "block_public_acls": { + "constant_value": false + }, + "block_public_policy": { + "constant_value": false + }, + "bucket": { + "references": [ + "aws_s3_bucket.test_bucket.id", + "aws_s3_bucket.test_bucket" + ] + }, + "ignore_public_acls": { + "constant_value": false + }, + "restrict_public_buckets": { + "constant_value": false + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.test_bucket", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-07-15T11:37:57Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/s3-best-practices/validate-any-prinicpal/test/bad-terraform-01.tf b/terraform/plan/s3-best-practices/validate-any-prinicpal/test/bad-terraform-01.tf new file mode 100644 index 00000000..929e4d90 --- /dev/null +++ b/terraform/plan/s3-best-practices/validate-any-prinicpal/test/bad-terraform-01.tf @@ -0,0 +1,48 @@ +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" "test_bucket" { + bucket = "test-bucket-nitish-demo" +} + +resource "aws_s3_bucket_public_access_block" "example" { + bucket = aws_s3_bucket.test_bucket.id + + block_public_acls = false + block_public_policy = false + ignore_public_acls = false + restrict_public_buckets = false +} + +resource "aws_s3_bucket_policy" "bucket_policy" { + bucket = aws_s3_bucket.test_bucket.id + + policy = < 4.16", + "expressions": { + "region": { + "constant_value": "us-west-2" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_s3_bucket.test_bucket", + "mode": "managed", + "type": "aws_s3_bucket", + "name": "test_bucket", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "constant_value": "test-bucket-nitish-demo" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_policy.bucket_policy", + "mode": "managed", + "type": "aws_s3_bucket_policy", + "name": "bucket_policy", + "provider_config_key": "aws", + "expressions": { + "bucket": { + "references": [ + "aws_s3_bucket.test_bucket.id", + "aws_s3_bucket.test_bucket" + ] + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Sid\": \"PublicRead\",\n \"Effect\": \"Allow\",\n \"Principal\": { \"Service\": \"s3.ap-east-1.amazonaws.com\" },\n \"Action\": [\"s3:GetObject\"],\n \"Resource\": [\n \"arn:aws:s3:::test-bucket-nitish-demo/*\"\n ]\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_s3_bucket_public_access_block.example", + "mode": "managed", + "type": "aws_s3_bucket_public_access_block", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "block_public_acls": { + "constant_value": false + }, + "block_public_policy": { + "constant_value": false + }, + "bucket": { + "references": [ + "aws_s3_bucket.test_bucket.id", + "aws_s3_bucket.test_bucket" + ] + }, + "ignore_public_acls": { + "constant_value": false + }, + "restrict_public_buckets": { + "constant_value": false + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_s3_bucket.test_bucket", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-07-15T10:49:52Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/s3-best-practices/validate-any-prinicpal/test/good-terraform.tf b/terraform/plan/s3-best-practices/validate-any-prinicpal/test/good-terraform.tf new file mode 100644 index 00000000..8caeeec0 --- /dev/null +++ b/terraform/plan/s3-best-practices/validate-any-prinicpal/test/good-terraform.tf @@ -0,0 +1,48 @@ +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" "test_bucket" { + bucket = "test-bucket-nitish-demo" +} + +resource "aws_s3_bucket_public_access_block" "example" { + bucket = aws_s3_bucket.test_bucket.id + + block_public_acls = false + block_public_policy = false + ignore_public_acls = false + restrict_public_buckets = false +} + +resource "aws_s3_bucket_policy" "bucket_policy" { + bucket = aws_s3_bucket.test_bucket.id + + policy = <- + Principal value in an IAM policy specifies which user or entity + is allowed or denied access to a resource. For policies attached + to an S3 bucket, this policy validates if the Principal allowed is + `*`, which means ANY Principal is allowed access to the resource. +spec: + rules: + - name: validate-any-principal + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_s3_bucket_policy'] | length(@) > `0`): true + assert: + all: + - message: Principal should not be set to `*` in the Bucket Policy. + check: + ~.(planned_values.root_module.resources[?type=='aws_s3_bucket_policy']): + values: + (json_parse(policy)): + (Statement[?Principal=='*'] | length(@) > `0`): false + - message: AWS should not be set to `*` in the Principal field for Bucket Policy + check: + ~.(planned_values.root_module.resources[?type=='aws_s3_bucket_policy']): + values: + (json_parse(policy)): + ~.(Statement): + Principal: + (AWS=='*'): false From 68b10b817987889c6db94d5bb3851e78544f70aa Mon Sep 17 00:00:00 2001 From: Chandan-DK Date: Wed, 24 Jul 2024 17:05:06 +0000 Subject: [PATCH 2/3] add lambda best practices policies Signed-off-by: Chandan-DK --- .../check-dead-letter-queue-config/README.md | 69 ++ .../check-dead-letter-queue-config.yaml | 24 + .../test/bad-test/bad-01.tf | 45 ++ .../test/bad-test/bad-payload-01.json | 340 +++++++++ .../test/chainsaw-test.yaml | 61 ++ .../test/good-test/good-01.tf | 48 ++ .../test/good-test/good-payload-01.json | 361 +++++++++ .../check-env-var-encryption/README.md | 42 ++ .../check-env-var-encryption.yaml | 24 + .../test/bad-test/bad-payload-01.json | 536 ++++++++++++++ .../test/bad-test/bad-payload-02.json | 537 ++++++++++++++ .../test/bad-test/terraform-01.tf | 84 +++ .../test/bad-test/terraform-02.tf | 84 +++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 93 +++ .../test/good-test/good-payload.json | 536 ++++++++++++++ .../test/good-test/main.tf | 84 +++ .../check-function-concurrency/README.md | 46 ++ .../check-function-concurrency.yaml | 24 + .../test/bad-test/bad-payload-01.json | 420 +++++++++++ .../test/bad-test/bad-payload-02.json | 421 +++++++++++ .../test/bad-test/terraform-01.tf | 71 ++ .../test/bad-test/terraform-02.tf | 71 ++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 93 +++ .../test/good-test/good-payload.json | 420 +++++++++++ .../test/good-test/terraform.tf | 71 ++ .../check-lambda-code-signing/README.md | 44 ++ .../check-lambda-code-signing.yaml | 24 + .../test/bad-test/bad-payload-02.json | 492 +++++++++++++ .../test/bad-test/bad-payload.json | 496 +++++++++++++ .../test/bad-test/terraform-01.tf | 80 ++ .../test/bad-test/terraform-02.tf | 80 ++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 60 ++ .../test/good-test/good-payload.json | 496 +++++++++++++ .../test/good-test/main.tf | 80 ++ .../check-lambda-public-access/README.md | 71 ++ .../check-lambda-public-access.yaml | 24 + .../test/bad-test/bad-01.tf | 51 ++ .../test/bad-test/bad-payload-01.json | 419 +++++++++++ .../test/chainsaw-test.yaml | 61 ++ .../test/good-test/good-01.tf | 51 ++ .../test/good-test/good-payload-01.json | 419 +++++++++++ .../check-lambda-runtime/README.md | 35 + .../check-lambda-runtime.yaml | 51 ++ .../test/bad-test/bad-payload.json | 487 +++++++++++++ .../test/bad-test/terraform.tf | 75 ++ .../check-lambda-runtime/test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 60 ++ .../test/good-test/good-payload.json | 487 +++++++++++++ .../test/good-test/terraform.tf | 75 ++ .../check-source-arn-account/README.md | 69 ++ .../check-source-arn-account.yaml | 23 + .../test/bad-test/bad-01.tf | 51 ++ .../test/bad-test/bad-payload-01.json | 419 +++++++++++ .../test/chainsaw-test.yaml | 61 ++ .../test/good-test/good-01.tf | 67 ++ .../test/good-test/good-payload-01.json | 577 +++++++++++++++ .../check-url-auth-type/README.md | 54 ++ .../check-url-auth-type.yaml | 25 + .../test/bad-test/bad-payload.json | 687 ++++++++++++++++++ .../test/bad-test/terraform.tf | 91 +++ .../check-url-auth-type/test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 60 ++ .../test/good-test/good-payload.json | 687 ++++++++++++++++++ .../test/good-test/terraform.tf | 90 +++ .../check-x-ray-tracing-enabled/README.md | 55 ++ .../check-x-ray-tracing-enabled.yaml | 28 + .../test/bad-test/bad-payload.json | 487 +++++++++++++ .../test/bad-test/bad-terraform.tf | 80 ++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 60 ++ .../test/good-test/good-payload.json | 510 +++++++++++++ .../test/good-test/good-terraform.tf | 80 ++ 75 files changed, 13102 insertions(+) create mode 100644 terraform/plan/lambda-best-practices/check-dead-letter-queue-config/README.md create mode 100644 terraform/plan/lambda-best-practices/check-dead-letter-queue-config/check-dead-letter-queue-config.yaml create mode 100644 terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/bad-test/bad-01.tf create mode 100644 terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/chainsaw-test.yaml create mode 100644 terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/good-test/good-01.tf create mode 100644 terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/good-test/good-payload-01.json create mode 100644 terraform/plan/lambda-best-practices/check-env-var-encryption/README.md create mode 100644 terraform/plan/lambda-best-practices/check-env-var-encryption/check-env-var-encryption.yaml create mode 100644 terraform/plan/lambda-best-practices/check-env-var-encryption/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/lambda-best-practices/check-env-var-encryption/test/bad-test/bad-payload-02.json create mode 100644 terraform/plan/lambda-best-practices/check-env-var-encryption/test/bad-test/terraform-01.tf create mode 100644 terraform/plan/lambda-best-practices/check-env-var-encryption/test/bad-test/terraform-02.tf create mode 100644 terraform/plan/lambda-best-practices/check-env-var-encryption/test/binding.yaml create mode 100644 terraform/plan/lambda-best-practices/check-env-var-encryption/test/chainsaw-test.yaml create mode 100644 terraform/plan/lambda-best-practices/check-env-var-encryption/test/good-test/good-payload.json create mode 100644 terraform/plan/lambda-best-practices/check-env-var-encryption/test/good-test/main.tf create mode 100644 terraform/plan/lambda-best-practices/check-function-concurrency/README.md create mode 100644 terraform/plan/lambda-best-practices/check-function-concurrency/check-function-concurrency.yaml create mode 100644 terraform/plan/lambda-best-practices/check-function-concurrency/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/lambda-best-practices/check-function-concurrency/test/bad-test/bad-payload-02.json create mode 100644 terraform/plan/lambda-best-practices/check-function-concurrency/test/bad-test/terraform-01.tf create mode 100644 terraform/plan/lambda-best-practices/check-function-concurrency/test/bad-test/terraform-02.tf create mode 100644 terraform/plan/lambda-best-practices/check-function-concurrency/test/binding.yaml create mode 100644 terraform/plan/lambda-best-practices/check-function-concurrency/test/chainsaw-test.yaml create mode 100644 terraform/plan/lambda-best-practices/check-function-concurrency/test/good-test/good-payload.json create mode 100644 terraform/plan/lambda-best-practices/check-function-concurrency/test/good-test/terraform.tf create mode 100644 terraform/plan/lambda-best-practices/check-lambda-code-signing/README.md create mode 100644 terraform/plan/lambda-best-practices/check-lambda-code-signing/check-lambda-code-signing.yaml create mode 100644 terraform/plan/lambda-best-practices/check-lambda-code-signing/test/bad-test/bad-payload-02.json create mode 100644 terraform/plan/lambda-best-practices/check-lambda-code-signing/test/bad-test/bad-payload.json create mode 100644 terraform/plan/lambda-best-practices/check-lambda-code-signing/test/bad-test/terraform-01.tf create mode 100644 terraform/plan/lambda-best-practices/check-lambda-code-signing/test/bad-test/terraform-02.tf create mode 100644 terraform/plan/lambda-best-practices/check-lambda-code-signing/test/binding.yaml create mode 100644 terraform/plan/lambda-best-practices/check-lambda-code-signing/test/chainsaw-test.yaml create mode 100644 terraform/plan/lambda-best-practices/check-lambda-code-signing/test/good-test/good-payload.json create mode 100644 terraform/plan/lambda-best-practices/check-lambda-code-signing/test/good-test/main.tf create mode 100644 terraform/plan/lambda-best-practices/check-lambda-public-access/README.md create mode 100644 terraform/plan/lambda-best-practices/check-lambda-public-access/check-lambda-public-access.yaml create mode 100644 terraform/plan/lambda-best-practices/check-lambda-public-access/test/bad-test/bad-01.tf create mode 100644 terraform/plan/lambda-best-practices/check-lambda-public-access/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/lambda-best-practices/check-lambda-public-access/test/chainsaw-test.yaml create mode 100644 terraform/plan/lambda-best-practices/check-lambda-public-access/test/good-test/good-01.tf create mode 100644 terraform/plan/lambda-best-practices/check-lambda-public-access/test/good-test/good-payload-01.json create mode 100644 terraform/plan/lambda-best-practices/check-lambda-runtime/README.md create mode 100644 terraform/plan/lambda-best-practices/check-lambda-runtime/check-lambda-runtime.yaml create mode 100644 terraform/plan/lambda-best-practices/check-lambda-runtime/test/bad-test/bad-payload.json create mode 100644 terraform/plan/lambda-best-practices/check-lambda-runtime/test/bad-test/terraform.tf create mode 100644 terraform/plan/lambda-best-practices/check-lambda-runtime/test/binding.yaml create mode 100644 terraform/plan/lambda-best-practices/check-lambda-runtime/test/chainsaw-test.yaml create mode 100644 terraform/plan/lambda-best-practices/check-lambda-runtime/test/good-test/good-payload.json create mode 100644 terraform/plan/lambda-best-practices/check-lambda-runtime/test/good-test/terraform.tf create mode 100644 terraform/plan/lambda-best-practices/check-source-arn-account/README.md create mode 100644 terraform/plan/lambda-best-practices/check-source-arn-account/check-source-arn-account.yaml create mode 100644 terraform/plan/lambda-best-practices/check-source-arn-account/test/bad-test/bad-01.tf create mode 100644 terraform/plan/lambda-best-practices/check-source-arn-account/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/lambda-best-practices/check-source-arn-account/test/chainsaw-test.yaml create mode 100644 terraform/plan/lambda-best-practices/check-source-arn-account/test/good-test/good-01.tf create mode 100644 terraform/plan/lambda-best-practices/check-source-arn-account/test/good-test/good-payload-01.json create mode 100644 terraform/plan/lambda-best-practices/check-url-auth-type/README.md create mode 100644 terraform/plan/lambda-best-practices/check-url-auth-type/check-url-auth-type.yaml create mode 100644 terraform/plan/lambda-best-practices/check-url-auth-type/test/bad-test/bad-payload.json create mode 100644 terraform/plan/lambda-best-practices/check-url-auth-type/test/bad-test/terraform.tf create mode 100644 terraform/plan/lambda-best-practices/check-url-auth-type/test/binding.yaml create mode 100644 terraform/plan/lambda-best-practices/check-url-auth-type/test/chainsaw-test.yaml create mode 100644 terraform/plan/lambda-best-practices/check-url-auth-type/test/good-test/good-payload.json create mode 100644 terraform/plan/lambda-best-practices/check-url-auth-type/test/good-test/terraform.tf create mode 100644 terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/README.md create mode 100644 terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/check-x-ray-tracing-enabled.yaml create mode 100644 terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/test/bad-test/bad-payload.json create mode 100644 terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/test/bad-test/bad-terraform.tf create mode 100644 terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/test/binding.yaml create mode 100644 terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/test/chainsaw-test.yaml create mode 100644 terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/test/good-test/good-payload.json create mode 100644 terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/test/good-test/good-terraform.tf diff --git a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/README.md b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/README.md new file mode 100644 index 00000000..ddff17ed --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/README.md @@ -0,0 +1,69 @@ +# Check Dead Letter Queue Config + +Dead Letter Queues (DLQs) allow Lambda functions to be set up with an SQS queue or SNS topic to capture information about failed asynchronous requests. When a Lambda function's processing fails and the request has exhausted its retries, the Lambda service can store details of the failed request to the configured DLQ. These failed messages can then be examined to determine the cause of failures. + +## Policy Details: + +- **Policy Name:** check-dead-letter-queue-config +- **Check Description:** This policy ensures that AWS Lambda function is configured for a Dead Letter Queue(DLQ) +- **Policy Category:** AWS Lambda Best Practices + +### Policy Validation Testing Instructions + +For testing this policy you will need to: +- Make sure you have `kyverno-json` installed on the machine +- Properly authenticate with AWS + +1. **Initialize Terraform:** + ```bash + terraform init + ``` + +2. **Create Binary Terraform Plan:** + ```bash + terraform plan -out tfplan.binary + ``` + +3. **Convert Binary to JSON Payload:** + ```bash + terraform show -json tfplan.binary | jq > payload.json + ``` + +4. **Test the Policy with Kyverno:** + ``` + kyverno-json scan --payload payload.json --policy policy.yaml + ``` + + a. **Test Policy Against Valid Payload:** + ``` + kyverno-json scan --payload test/good-test/good-payload-01.json --policy check-dead-letter-queue-config.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - check-dead-letter-queue-config / check-dead-letter-queue-config / PASSED + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-dead-letter-queue-config.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - check-dead-letter-queue-config / check-dead-letter-queue-config / FAILED + -> AWS Lambda function should be configured for a Dead Letter Queue(DLQ) + -> all[0].check.~.(planned_values.root_module.resources[?type=='aws_lambda_function'])[0].values.(dead_letter_config != `[]`): Invalid value: false: Expected value: true + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/check-dead-letter-queue-config.yaml b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/check-dead-letter-queue-config.yaml new file mode 100644 index 00000000..3f10f69a --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/check-dead-letter-queue-config.yaml @@ -0,0 +1,24 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-dead-letter-queue-config + annotations: + policies.kyverno.io/title: check-dead-letter-queue-config + policies.kyverno.io/category: AWS Lambda Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + Ensure that AWS Lambda function is configured for a Dead Letter Queue(DLQ) +spec: + rules: + - name: check-dead-letter-queue-config + match: + all: + - (planned_values.root_module.resources[?type=='aws_lambda_function'] | length(@) > `0`): true + assert: + all: + - message: AWS Lambda function should be configured for a Dead Letter Queue(DLQ) + check: + ~.(planned_values.root_module.resources[?type=='aws_lambda_function']): + values: + (dead_letter_config != `[]`): true + diff --git a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/bad-test/bad-01.tf b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/bad-test/bad-01.tf new file mode 100644 index 00000000..90ef5ad6 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/bad-test/bad-01.tf @@ -0,0 +1,45 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_lambda_function" "example" { + function_name = "example_lambda" + handler = "index.lambda_handler" + role = aws_iam_role.lambda_exec.arn + runtime = "python3.8" + filename = "" +} + +resource "aws_iam_role" "lambda_exec" { + name = "lambda_exec_role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "lambda.amazonaws.com" + } + }, + ] + }) +} + +resource "aws_iam_role_policy_attachment" "lambda_exec_policy" { + role = aws_iam_role.lambda_exec.name + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" +} + diff --git a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/bad-test/bad-payload-01.json b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..48e0ddd8 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/bad-test/bad-payload-01.json @@ -0,0 +1,340 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "lambda_exec_role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "role": "lambda_exec_role" + }, + "sensitive_values": {} + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "", + "function_name": "example_lambda", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "sensitive_values": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "lambda_exec_role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "role": "lambda_exec_role" + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "", + "function_name": "example_lambda", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "after_unknown": { + "architectures": true, + "arn": true, + "code_sha256": true, + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": true, + "file_system_config": [], + "id": true, + "image_config": [], + "invoke_arn": true, + "last_modified": true, + "logging_config": true, + "qualified_arn": true, + "qualified_invoke_arn": true, + "role": true, + "signing_job_arn": true, + "signing_profile_version_arn": true, + "snap_start": [], + "source_code_hash": true, + "source_code_size": true, + "tags_all": true, + "tracing_config": true, + "version": true, + "vpc_config": [] + }, + "before_sensitive": false, + "after_sensitive": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": ">= 5.32.0", + "expressions": { + "region": { + "constant_value": "us-west-2" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": {}, + "name": { + "constant_value": "lambda_exec_role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "constant_value": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + }, + "role": { + "references": [ + "aws_iam_role.lambda_exec.name", + "aws_iam_role.lambda_exec" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "filename": { + "constant_value": "" + }, + "function_name": { + "constant_value": "example_lambda" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "role": { + "references": [ + "aws_iam_role.lambda_exec.arn", + "aws_iam_role.lambda_exec" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_exec", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_role.lambda_exec", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-07-03T18:08:59Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/chainsaw-test.yaml b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/chainsaw-test.yaml new file mode 100644 index 00000000..6daeffb8 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/chainsaw-test.yaml @@ -0,0 +1,61 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./good-test/good-payload-01.json --policy ../check-dead-letter-queue-config.yaml --output json + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-dead-letter-queue-config + rules: + - rule: + name: check-dead-letter-queue-config + error: ~ + violations: ~ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./bad-test/bad-payload-01.json --policy ../check-dead-letter-queue-config.yaml --output json + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-dead-letter-queue-config + rules: + - rule: + name: check-dead-letter-queue-config + error: ~ + violations: + - message: AWS Lambda function should be configured for a Dead Letter Queue(DLQ) + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' + diff --git a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/good-test/good-01.tf b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/good-test/good-01.tf new file mode 100644 index 00000000..e71b5080 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/good-test/good-01.tf @@ -0,0 +1,48 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_lambda_function" "example" { + function_name = "example_lambda" + handler = "index.lambda_handler" + role = aws_iam_role.lambda_exec.arn + runtime = "python3.8" + filename = "" + dead_letter_config { + target_arn = "arn:aws:sqs:us-west-2:123456789012:example_queue" + } +} + +resource "aws_iam_role" "lambda_exec" { + name = "lambda_exec_role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "lambda.amazonaws.com" + } + }, + ] + }) +} + +resource "aws_iam_role_policy_attachment" "lambda_exec_policy" { + role = aws_iam_role.lambda_exec.name + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" +} + diff --git a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/good-test/good-payload-01.json b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/good-test/good-payload-01.json new file mode 100644 index 00000000..ac24f302 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/good-test/good-payload-01.json @@ -0,0 +1,361 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "lambda_exec_role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "role": "lambda_exec_role" + }, + "sensitive_values": {} + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "code_signing_config_arn": null, + "dead_letter_config": [ + { + "target_arn": "arn:aws:sqs:us-west-2:123456789012:example_queue" + } + ], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "", + "function_name": "example_lambda", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "sensitive_values": { + "architectures": [], + "dead_letter_config": [ + {} + ], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "lambda_exec_role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "role": "lambda_exec_role" + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "code_signing_config_arn": null, + "dead_letter_config": [ + { + "target_arn": "arn:aws:sqs:us-west-2:123456789012:example_queue" + } + ], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "", + "function_name": "example_lambda", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "after_unknown": { + "architectures": true, + "arn": true, + "code_sha256": true, + "dead_letter_config": [ + {} + ], + "environment": [], + "ephemeral_storage": true, + "file_system_config": [], + "id": true, + "image_config": [], + "invoke_arn": true, + "last_modified": true, + "logging_config": true, + "qualified_arn": true, + "qualified_invoke_arn": true, + "role": true, + "signing_job_arn": true, + "signing_profile_version_arn": true, + "snap_start": [], + "source_code_hash": true, + "source_code_size": true, + "tags_all": true, + "tracing_config": true, + "version": true, + "vpc_config": [] + }, + "before_sensitive": false, + "after_sensitive": { + "architectures": [], + "dead_letter_config": [ + {} + ], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": ">= 5.32.0", + "expressions": { + "region": { + "constant_value": "us-west-2" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": {}, + "name": { + "constant_value": "lambda_exec_role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "constant_value": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + }, + "role": { + "references": [ + "aws_iam_role.lambda_exec.name", + "aws_iam_role.lambda_exec" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "dead_letter_config": [ + { + "target_arn": { + "constant_value": "arn:aws:sqs:us-west-2:123456789012:example_queue" + } + } + ], + "filename": { + "constant_value": "" + }, + "function_name": { + "constant_value": "example_lambda" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "role": { + "references": [ + "aws_iam_role.lambda_exec.arn", + "aws_iam_role.lambda_exec" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_exec", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_role.lambda_exec", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-07-03T18:11:12Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-env-var-encryption/README.md b/terraform/plan/lambda-best-practices/check-env-var-encryption/README.md new file mode 100644 index 00000000..1e0bfb98 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-env-var-encryption/README.md @@ -0,0 +1,42 @@ +Encrypting environment variables of an AWS Lambda function using Terraform involves several steps within Terraform's resource blocks. First, you create a Key Management Service (KMS) key using the aws_kms_key resource block, specifying details like description, key rotation, and deletion window. This key will be used to encrypt and decrypt the environment variables. Next, in the aws_lambda_function resource block that defines your Lambda function, you specify the kms_key_arn parameter with the ARN of the KMS key created earlier. Within the environment block of the Lambda function resource, you define the environment variables you want to encrypt, setting their values as plaintext. When Terraform deploys these resources, it encrypts the specified environment variables using the specified KMS key. + + +``` +resource "aws_lambda_function" "my_lambda_function" { + function_name = "my-lambda-function" + handler = "index.handler" + runtime = "nodejs14.x" + role = aws_iam_role.lambda_role.arn + filename = "path/to/lambda_function.zip" + kms_key_arn = "arn:aws:signer:us-west-2:123456789012" +} +``` + +In this configuration: + +- `kms_key_arn` specifies the ARN of the aws_kms_key created in AWS Console. + +You need to make sure that the *kms_key_arn* attribute is provided a valid string value in the *aws_lambda_function* resource block. If you do, the Policy will give you passing checks else failing checks. + +In order to test this policy, use the following commands: + +1. Navigate to the `aws/lambda/terraform/check-env-var-encryption` 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 *main.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 check-env-var-encryption.yaml --bindings ./binding.yaml + ``` + Since you have provided a valid string value to the *kms_key_arn* attribute in the *aws_lambda_function* resource block, the policy will give you passing checks. If you would have specifed an empty string or might have not used the attribute, the Policy will give you failing checks. + + In order to test the policy for bad payload, run the following command: + ``` + kyverno-json scan --payload bad-payload.json --policy check-env-var-encryption.yaml --bindings ./binding.yaml + ``` \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-env-var-encryption/check-env-var-encryption.yaml b/terraform/plan/lambda-best-practices/check-env-var-encryption/check-env-var-encryption.yaml new file mode 100644 index 00000000..1a3056fb --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-env-var-encryption/check-env-var-encryption.yaml @@ -0,0 +1,24 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-env-var-encryption + annotations: + policies.kyverno.io/title: check-env-var-encryption + policies.kyverno.io/category: AWS Lambda Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy ensures that if environment variables are used in a Lambda function, they should be encrypted. +spec: + rules: + - name: check-env-var-encryption + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_lambda_function'] | length(@) > `0`): true + assert: + all: + - message: Enable the encryption of environment variable for the AWS Lambda function by specifying correct value to 'kms_key_arn' attribute in 'aws_lambda_function' resource block + check: + ~.(planned_values.root_module.resources[?type=='aws_lambda_function']): + values: + ((kms_key_arn || '') != ''): true \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-env-var-encryption/test/bad-test/bad-payload-01.json b/terraform/plan/lambda-best-practices/check-env-var-encryption/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..a6f486c3 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-env-var-encryption/test/bad-test/bad-payload-01.json @@ -0,0 +1,536 @@ +{ + "format_version": "1.2", + "terraform_version": "1.7.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "sensitive_values": {} + }, + { + "address": "aws_kms_key.a", + "mode": "managed", + "type": "aws_kms_key", + "name": "a", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bypass_policy_lockout_safety_check": false, + "custom_key_store_id": null, + "customer_master_key_spec": "SYMMETRIC_DEFAULT", + "deletion_window_in_days": 10, + "description": "KMS key 1", + "enable_key_rotation": false, + "is_enabled": true, + "key_usage": "ENCRYPT_DECRYPT", + "tags": null, + "timeouts": null, + "xks_key_id": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [ + { + "variables": { + "SECRET_KEY": "Terraform key" + } + } + ], + "file_system_config": [], + "filename": "", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": "", + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "sensitive_values": { + "architectures": [], + "dead_letter_config": [], + "environment": [ + { + "variables": {} + } + ], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "after_unknown": { + "arn": true, + "id": true, + "name_prefix": true, + "policy_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "after_unknown": { + "id": true, + "policy_arn": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_kms_key.a", + "mode": "managed", + "type": "aws_kms_key", + "name": "a", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bypass_policy_lockout_safety_check": false, + "custom_key_store_id": null, + "customer_master_key_spec": "SYMMETRIC_DEFAULT", + "deletion_window_in_days": 10, + "description": "KMS key 1", + "enable_key_rotation": false, + "is_enabled": true, + "key_usage": "ENCRYPT_DECRYPT", + "tags": null, + "timeouts": null, + "xks_key_id": null + }, + "after_unknown": { + "arn": true, + "id": true, + "key_id": true, + "multi_region": true, + "policy": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [ + { + "variables": { + "SECRET_KEY": "Terraform key" + } + } + ], + "file_system_config": [], + "filename": "", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": "", + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "after_unknown": { + "architectures": true, + "arn": true, + "dead_letter_config": [], + "environment": [ + { + "variables": {} + } + ], + "ephemeral_storage": true, + "file_system_config": [], + "id": true, + "image_config": [], + "invoke_arn": true, + "last_modified": true, + "logging_config": true, + "qualified_arn": true, + "qualified_invoke_arn": true, + "role": true, + "signing_job_arn": true, + "signing_profile_version_arn": true, + "snap_start": [], + "source_code_hash": true, + "source_code_size": true, + "tags_all": true, + "tracing_config": true, + "version": true, + "vpc_config": [] + }, + "before_sensitive": false, + "after_sensitive": { + "architectures": [], + "dead_letter_config": [], + "environment": [ + { + "variables": {} + } + ], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": ">= 5.32.0", + "expressions": {} + }, + "random": { + "name": "random", + "full_name": "registry.terraform.io/hashicorp/random", + "version_constraint": ">= 2.0.0" + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_config_key": "aws", + "expressions": { + "description": { + "constant_value": "AWS IAM Policy for managing aws lambda role" + }, + "name": { + "constant_value": "aws_iam_policy_for_terraform_aws_lambda_role" + }, + "path": { + "constant_value": "/" + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": [\n \"logs:CreateLogGroup\",\n \"logs:CreateLogStream\",\n \"logs:PutLogEvents\"\n ],\n \"Resource\": \"arn:aws:logs:*:*:*\",\n \"Effect\": \"Allow\"\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"lambda.amazonaws.com\"\n },\n \"Effect\": \"Allow\",\n \"Sid\": \"\"\n }\n ]\n}\n" + }, + "name": { + "constant_value": "Spacelift_Test_Lambda_Function_Role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.iam_policy_for_lambda.arn", + "aws_iam_policy.iam_policy_for_lambda" + ] + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.name", + "aws_iam_role.lambda_role" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_kms_key.a", + "mode": "managed", + "type": "aws_kms_key", + "name": "a", + "provider_config_key": "aws", + "expressions": { + "deletion_window_in_days": { + "constant_value": 10 + }, + "description": { + "constant_value": "KMS key 1" + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_config_key": "aws", + "expressions": { + "environment": [ + { + "variables": { + "constant_value": { + "SECRET_KEY": "Terraform key" + } + } + } + ], + "filename": { + "constant_value": "" + }, + "function_name": { + "constant_value": "Spacelift_Test_Lambda_Function" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "kms_key_arn": { + "constant_value": "" + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.arn", + "aws_iam_role.lambda_role" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0, + "depends_on": [ + "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role" + ] + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_policy.iam_policy_for_lambda", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-04-01T16:22:42Z", + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-env-var-encryption/test/bad-test/bad-payload-02.json b/terraform/plan/lambda-best-practices/check-env-var-encryption/test/bad-test/bad-payload-02.json new file mode 100644 index 00000000..a45d521c --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-env-var-encryption/test/bad-test/bad-payload-02.json @@ -0,0 +1,537 @@ +{ + "format_version": "1.2", + "terraform_version": "1.7.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "sensitive_values": {} + }, + { + "address": "aws_kms_key.a", + "mode": "managed", + "type": "aws_kms_key", + "name": "a", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "bypass_policy_lockout_safety_check": false, + "custom_key_store_id": null, + "customer_master_key_spec": "SYMMETRIC_DEFAULT", + "deletion_window_in_days": 10, + "description": "KMS key 1", + "enable_key_rotation": false, + "is_enabled": true, + "key_usage": "ENCRYPT_DECRYPT", + "tags": null, + "timeouts": null, + "xks_key_id": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [ + { + "variables": { + "SECRET_KEY": "Terraform key" + } + } + ], + "file_system_config": [], + "filename": "", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": "", + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "sensitive_values": { + "architectures": [], + "dead_letter_config": [], + "environment": [ + { + "variables": {} + } + ], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "after_unknown": { + "arn": true, + "id": true, + "name_prefix": true, + "policy_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "after_unknown": { + "id": true, + "policy_arn": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_kms_key.a", + "mode": "managed", + "type": "aws_kms_key", + "name": "a", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "bypass_policy_lockout_safety_check": false, + "custom_key_store_id": null, + "customer_master_key_spec": "SYMMETRIC_DEFAULT", + "deletion_window_in_days": 10, + "description": "KMS key 1", + "enable_key_rotation": false, + "is_enabled": true, + "key_usage": "ENCRYPT_DECRYPT", + "tags": null, + "timeouts": null, + "xks_key_id": null + }, + "after_unknown": { + "arn": true, + "id": true, + "key_id": true, + "multi_region": true, + "policy": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [ + { + "variables": { + "SECRET_KEY": "Terraform key" + } + } + ], + "file_system_config": [], + "filename": "", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": "", + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "after_unknown": { + "architectures": true, + "arn": true, + "dead_letter_config": [], + "environment": [ + { + "variables": {} + } + ], + "ephemeral_storage": true, + "file_system_config": [], + "id": true, + "image_config": [], + "invoke_arn": true, + "last_modified": true, + "logging_config": true, + "qualified_arn": true, + "qualified_invoke_arn": true, + "role": true, + "signing_job_arn": true, + "signing_profile_version_arn": true, + "snap_start": [], + "source_code_hash": true, + "source_code_size": true, + "tags_all": true, + "tracing_config": true, + "version": true, + "vpc_config": [] + }, + "before_sensitive": false, + "after_sensitive": { + "architectures": [], + "dead_letter_config": [], + "environment": [ + { + "variables": {} + } + ], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": ">= 5.32.0", + "expressions": {} + }, + "random": { + "name": "random", + "full_name": "registry.terraform.io/hashicorp/random", + "version_constraint": ">= 2.0.0" + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_config_key": "aws", + "expressions": { + "description": { + "constant_value": "AWS IAM Policy for managing aws lambda role" + }, + "name": { + "constant_value": "aws_iam_policy_for_terraform_aws_lambda_role" + }, + "path": { + "constant_value": "/" + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": [\n \"logs:CreateLogGroup\",\n \"logs:CreateLogStream\",\n \"logs:PutLogEvents\"\n ],\n \"Resource\": \"arn:aws:logs:*:*:*\",\n \"Effect\": \"Allow\"\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"lambda.amazonaws.com\"\n },\n \"Effect\": \"Allow\",\n \"Sid\": \"\"\n }\n ]\n}\n" + }, + "name": { + "constant_value": "Spacelift_Test_Lambda_Function_Role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.iam_policy_for_lambda.arn", + "aws_iam_policy.iam_policy_for_lambda" + ] + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.name", + "aws_iam_role.lambda_role" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_kms_key.a", + "mode": "managed", + "type": "aws_kms_key", + "name": "a", + "provider_config_key": "aws", + "expressions": { + "deletion_window_in_days": { + "constant_value": 10 + }, + "description": { + "constant_value": "KMS key 1" + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_config_key": "aws", + "expressions": { + "environment": [ + { + "variables": { + "constant_value": { + "SECRET_KEY": "Terraform key" + } + } + } + ], + "filename": { + "constant_value": "" + }, + "function_name": { + "constant_value": "Spacelift_Test_Lambda_Function" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "kms_key_arn": { + "constant_value": "" + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.arn", + "aws_iam_role.lambda_role" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0, + "depends_on": [ + "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role" + ] + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_policy.iam_policy_for_lambda", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-04-01T16:22:42Z", + "errored": false + } + \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-env-var-encryption/test/bad-test/terraform-01.tf b/terraform/plan/lambda-best-practices/check-env-var-encryption/test/bad-test/terraform-01.tf new file mode 100644 index 00000000..2a518af8 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-env-var-encryption/test/bad-test/terraform-01.tf @@ -0,0 +1,84 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + random = { + source = "hashicorp/random" + version = ">= 2.0" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_iam_role" "lambda_role" { +name = "Spacelift_Test_Lambda_Function_Role" +assume_role_policy = <= 5.32.0", + "expressions": {} + }, + "random": { + "name": "random", + "full_name": "registry.terraform.io/hashicorp/random", + "version_constraint": ">= 2.0.0" + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_config_key": "aws", + "expressions": { + "description": { + "constant_value": "AWS IAM Policy for managing aws lambda role" + }, + "name": { + "constant_value": "aws_iam_policy_for_terraform_aws_lambda_role" + }, + "path": { + "constant_value": "/" + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": [\n \"logs:CreateLogGroup\",\n \"logs:CreateLogStream\",\n \"logs:PutLogEvents\"\n ],\n \"Resource\": \"arn:aws:logs:*:*:*\",\n \"Effect\": \"Allow\"\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"lambda.amazonaws.com\"\n },\n \"Effect\": \"Allow\",\n \"Sid\": \"\"\n }\n ]\n}\n" + }, + "name": { + "constant_value": "Spacelift_Test_Lambda_Function_Role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.iam_policy_for_lambda.arn", + "aws_iam_policy.iam_policy_for_lambda" + ] + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.name", + "aws_iam_role.lambda_role" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_kms_key.a", + "mode": "managed", + "type": "aws_kms_key", + "name": "a", + "provider_config_key": "aws", + "expressions": { + "deletion_window_in_days": { + "constant_value": 10 + }, + "description": { + "constant_value": "KMS key 1" + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_config_key": "aws", + "expressions": { + "environment": [ + { + "variables": { + "constant_value": { + "SECRET_KEY": "Terraform key" + } + } + } + ], + "filename": { + "constant_value": "" + }, + "function_name": { + "constant_value": "Spacelift_Test_Lambda_Function" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "kms_key_arn": { + "constant_value": "arn:aws:signer:us-west-2:123456789012:kms-key-arn" + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.arn", + "aws_iam_role.lambda_role" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0, + "depends_on": [ + "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role" + ] + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_policy.iam_policy_for_lambda", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-04-01T16:15:11Z", + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-env-var-encryption/test/good-test/main.tf b/terraform/plan/lambda-best-practices/check-env-var-encryption/test/good-test/main.tf new file mode 100644 index 00000000..1bd26c25 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-env-var-encryption/test/good-test/main.tf @@ -0,0 +1,84 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + random = { + source = "hashicorp/random" + version = ">= 2.0" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_iam_role" "lambda_role" { +name = "Spacelift_Test_Lambda_Function_Role" +assume_role_policy = < payload.json + ``` +4. Test your payload against the policy using `kyverno-json scan` command + ``` + kyverno-json scan --payload good-payload.json --policy check-function-concurrency.yaml --bindings ./binding.yaml + ``` + Since you have provided a valid non-negative value to the *reserved_concurrent_executions* attribute in the *aws_lambda_function* resource block, the policy will give you passing checks. If you would have specifed an empty string or might have not used the attribute or provided a non-negative value, the Policy will give you failing checks. + + In order to test the policy for bad payload, run the following command: + ``` + kyverno-json scan --payload bad-payload-01.json --policy check-function-concurrency.yaml --bindings ./binding.yaml + ``` \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-function-concurrency/check-function-concurrency.yaml b/terraform/plan/lambda-best-practices/check-function-concurrency/check-function-concurrency.yaml new file mode 100644 index 00000000..c09f7ff6 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-function-concurrency/check-function-concurrency.yaml @@ -0,0 +1,24 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-function-concurrency + annotations: + policies.kyverno.io/title: check-function-concurrency + policies.kyverno.io/category: AWS Lambda Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy checks whether concurrency level config is set for the Lambda function. +spec: + rules: + - name: check-function-concurrency + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_lambda_function'] | length(@) > `0`): true + assert: + all: + - message: Configure the AWS Lambda function for function-level concurrent execution limit using 'reserved_concurrent_execution' attribute + check: + ~.(planned_values.root_module.resources[?type=='aws_lambda_function']): + values: + (reserved_concurrent_executions > `0`): true \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-function-concurrency/test/bad-test/bad-payload-01.json b/terraform/plan/lambda-best-practices/check-function-concurrency/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..1d0a43ab --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-function-concurrency/test/bad-test/bad-payload-01.json @@ -0,0 +1,420 @@ +{ + "format_version": "1.2", + "terraform_version": "1.7.5", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "role_last_used": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "sensitive_values": {} + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": 0, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "sensitive_values": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "after_unknown": { + "arn": true, + "id": true, + "name_prefix": true, + "policy_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "role_last_used": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "role_last_used": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "after_unknown": { + "id": true, + "policy_arn": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": 0, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "after_unknown": { + "architectures": true, + "arn": true, + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": true, + "file_system_config": [], + "id": true, + "image_config": [], + "invoke_arn": true, + "last_modified": true, + "qualified_arn": true, + "qualified_invoke_arn": true, + "role": true, + "signing_job_arn": true, + "signing_profile_version_arn": true, + "snap_start": [], + "source_code_hash": true, + "source_code_size": true, + "tags_all": true, + "tracing_config": true, + "version": true, + "vpc_config": [] + }, + "before_sensitive": false, + "after_sensitive": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": {} + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_config_key": "aws", + "expressions": { + "description": { + "constant_value": "AWS IAM Policy for managing aws lambda role" + }, + "name": { + "constant_value": "aws_iam_policy_for_terraform_aws_lambda_role" + }, + "path": { + "constant_value": "/" + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": [\n \"logs:CreateLogGroup\",\n \"logs:CreateLogStream\",\n \"logs:PutLogEvents\"\n ],\n \"Resource\": \"arn:aws:logs:*:*:*\",\n \"Effect\": \"Allow\"\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"lambda.amazonaws.com\"\n },\n \"Effect\": \"Allow\",\n \"Sid\": \"\"\n }\n ]\n}\n" + }, + "name": { + "constant_value": "Spacelift_Test_Lambda_Function_Role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.iam_policy_for_lambda.arn", + "aws_iam_policy.iam_policy_for_lambda" + ] + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.name", + "aws_iam_role.lambda_role" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_config_key": "aws", + "expressions": { + "filename": { + "constant_value": "" + }, + "function_name": { + "constant_value": "Spacelift_Test_Lambda_Function" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "reserved_concurrent_executions": { + "constant_value": 0 + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.arn", + "aws_iam_role.lambda_role" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0, + "depends_on": [ + "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role" + ] + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_policy.iam_policy_for_lambda", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-04-02T06:20:40Z", + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-function-concurrency/test/bad-test/bad-payload-02.json b/terraform/plan/lambda-best-practices/check-function-concurrency/test/bad-test/bad-payload-02.json new file mode 100644 index 00000000..c2aafd29 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-function-concurrency/test/bad-test/bad-payload-02.json @@ -0,0 +1,421 @@ +{ + "format_version": "1.2", + "terraform_version": "1.7.5", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "role_last_used": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "sensitive_values": {} + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": null, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "sensitive_values": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "after_unknown": { + "arn": true, + "id": true, + "name_prefix": true, + "policy_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "role_last_used": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "role_last_used": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "after_unknown": { + "id": true, + "policy_arn": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": null, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "after_unknown": { + "architectures": true, + "arn": true, + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": true, + "file_system_config": [], + "id": true, + "image_config": [], + "invoke_arn": true, + "last_modified": true, + "qualified_arn": true, + "qualified_invoke_arn": true, + "role": true, + "signing_job_arn": true, + "signing_profile_version_arn": true, + "snap_start": [], + "source_code_hash": true, + "source_code_size": true, + "tags_all": true, + "tracing_config": true, + "version": true, + "vpc_config": [] + }, + "before_sensitive": false, + "after_sensitive": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": {} + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_config_key": "aws", + "expressions": { + "description": { + "constant_value": "AWS IAM Policy for managing aws lambda role" + }, + "name": { + "constant_value": "aws_iam_policy_for_terraform_aws_lambda_role" + }, + "path": { + "constant_value": "/" + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": [\n \"logs:CreateLogGroup\",\n \"logs:CreateLogStream\",\n \"logs:PutLogEvents\"\n ],\n \"Resource\": \"arn:aws:logs:*:*:*\",\n \"Effect\": \"Allow\"\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"lambda.amazonaws.com\"\n },\n \"Effect\": \"Allow\",\n \"Sid\": \"\"\n }\n ]\n}\n" + }, + "name": { + "constant_value": "Spacelift_Test_Lambda_Function_Role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.iam_policy_for_lambda.arn", + "aws_iam_policy.iam_policy_for_lambda" + ] + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.name", + "aws_iam_role.lambda_role" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_config_key": "aws", + "expressions": { + "filename": { + "constant_value": "" + }, + "function_name": { + "constant_value": "Spacelift_Test_Lambda_Function" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "reserved_concurrent_executions": { + "constant_value": null + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.arn", + "aws_iam_role.lambda_role" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0, + "depends_on": [ + "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role" + ] + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_policy.iam_policy_for_lambda", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-04-02T06:20:40Z", + "errored": false + } + \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-function-concurrency/test/bad-test/terraform-01.tf b/terraform/plan/lambda-best-practices/check-function-concurrency/test/bad-test/terraform-01.tf new file mode 100644 index 00000000..ee160256 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-function-concurrency/test/bad-test/terraform-01.tf @@ -0,0 +1,71 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_iam_role" "lambda_role" { +name = "Spacelift_Test_Lambda_Function_Role" +assume_role_policy = < 4.16", + "expressions": {} + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_config_key": "aws", + "expressions": { + "description": { + "constant_value": "AWS IAM Policy for managing aws lambda role" + }, + "name": { + "constant_value": "aws_iam_policy_for_terraform_aws_lambda_role" + }, + "path": { + "constant_value": "/" + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": [\n \"logs:CreateLogGroup\",\n \"logs:CreateLogStream\",\n \"logs:PutLogEvents\"\n ],\n \"Resource\": \"arn:aws:logs:*:*:*\",\n \"Effect\": \"Allow\"\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"lambda.amazonaws.com\"\n },\n \"Effect\": \"Allow\",\n \"Sid\": \"\"\n }\n ]\n}\n" + }, + "name": { + "constant_value": "Spacelift_Test_Lambda_Function_Role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.iam_policy_for_lambda.arn", + "aws_iam_policy.iam_policy_for_lambda" + ] + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.name", + "aws_iam_role.lambda_role" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_config_key": "aws", + "expressions": { + "filename": { + "constant_value": "" + }, + "function_name": { + "constant_value": "Spacelift_Test_Lambda_Function" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "reserved_concurrent_executions": { + "constant_value": 1 + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.arn", + "aws_iam_role.lambda_role" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0, + "depends_on": [ + "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role" + ] + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_policy.iam_policy_for_lambda", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "name" + ] + } + ], + "timestamp": "2024-04-02T06:16:45Z", + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-function-concurrency/test/good-test/terraform.tf b/terraform/plan/lambda-best-practices/check-function-concurrency/test/good-test/terraform.tf new file mode 100644 index 00000000..e1db755c --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-function-concurrency/test/good-test/terraform.tf @@ -0,0 +1,71 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_iam_role" "lambda_role" { +name = "Spacelift_Test_Lambda_Function_Role" +assume_role_policy = < payload.json + ``` +4. Test your payload against the policy using `kyverno-json scan` command + ``` + kyverno-json scan --payload good-payload.json --policy check-lambda-code-signing.yaml --bindings ./binding.yaml + ``` + Since you have provided a valid string value to the *code_signing_config_arn* attribute in the *aws_lambda_function* resource block, the policy will give you passing checks. If you would have specifed an empty string or might have not used the attribute, the Policy will give you failing checks. + + In order to test the policy for bad payload, run the following command: + ``` + kyverno-json scan --payload bad-payload.json --policy check-lambda-code-signing.yaml --bindings ./binding.yaml + ``` diff --git a/terraform/plan/lambda-best-practices/check-lambda-code-signing/check-lambda-code-signing.yaml b/terraform/plan/lambda-best-practices/check-lambda-code-signing/check-lambda-code-signing.yaml new file mode 100644 index 00000000..7388cd30 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-code-signing/check-lambda-code-signing.yaml @@ -0,0 +1,24 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-lambda-code-signing + annotations: + policies.kyverno.io/title: check-lambda-code-signing + policies.kyverno.io/category: AWS Lambda Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy ensures that AWS Lambda function is configured to validate code-signing +spec: + rules: + - name: check-lambda-code-signing + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_lambda_function'] | length(@) > `0`): true + assert: + all: + - message: Enable the code signing for the AWS Lambda function by specifying correct value to 'code_signing_config_arn' attribute in 'aws_lambda_function' resource block + check: + ~.(planned_values.root_module.resources[?type=='aws_lambda_function']): + values: + ((code_signing_config_arn || '') != ''): true diff --git a/terraform/plan/lambda-best-practices/check-lambda-code-signing/test/bad-test/bad-payload-02.json b/terraform/plan/lambda-best-practices/check-lambda-code-signing/test/bad-test/bad-payload-02.json new file mode 100644 index 00000000..4d82b548 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-code-signing/test/bad-test/bad-payload-02.json @@ -0,0 +1,492 @@ +{ + "format_version": "1.2", + "terraform_version": "1.7.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "sensitive_values": {} + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "./python/hello-python.zip", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "sensitive_values": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "after_unknown": { + "arn": true, + "id": true, + "name_prefix": true, + "policy_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "after_unknown": { + "id": true, + "policy_arn": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "./python/hello-python.zip", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "after_unknown": { + "architectures": true, + "arn": true, + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": true, + "file_system_config": [], + "id": true, + "image_config": [], + "invoke_arn": true, + "last_modified": true, + "logging_config": true, + "qualified_arn": true, + "qualified_invoke_arn": true, + "role": true, + "signing_job_arn": true, + "signing_profile_version_arn": true, + "snap_start": [], + "source_code_hash": true, + "source_code_size": true, + "tags_all": true, + "tracing_config": true, + "version": true, + "vpc_config": [] + }, + "before_sensitive": false, + "after_sensitive": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + } + ], + "prior_state": { + "format_version": "1.0", + "terraform_version": "1.7.4", + "values": { + "root_module": { + "resources": [ + { + "address": "data.archive_file.zip_the_python_code", + "mode": "data", + "type": "archive_file", + "name": "zip_the_python_code", + "provider_name": "registry.terraform.io/hashicorp/archive", + "schema_version": 0, + "values": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "a214dde8a12ca94253e6511d64619f0ff9ffee35", + "output_base64sha256": "SFSoo0NG4FG8mNorh4sscOyiKc/kJzFsP8hLOy3Fk3Q=", + "output_base64sha512": "NutLilmFQDdniQXgTqfmvMcu9viZvU9BAyF9ChFwLG2w486kDHCfAyhUXCW4Ggxft6nSFxtN6QGVqRdlzn7WVQ==", + "output_file_mode": null, + "output_md5": "1b85a86b0487bc677393bb5399ab98ff", + "output_path": "./python/hello-python.zip", + "output_sha": "a214dde8a12ca94253e6511d64619f0ff9ffee35", + "output_sha256": "4854a8a34346e051bc98da2b878b2c70eca229cfe427316c3fc84b3b2dc59374", + "output_sha512": "36eb4b8a59854037678905e04ea7e6bcc72ef6f899bd4f4103217d0a11702c6db0e3cea40c709f0328545c25b81a0c5fb7a9d2171b4de90195a91765ce7ed655", + "output_size": 368, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./python/", + "source_file": null, + "type": "zip" + }, + "sensitive_values": { + "source": [] + } + } + ] + } + } + }, + "configuration": { + "provider_config": { + "archive": { + "name": "archive", + "full_name": "registry.terraform.io/hashicorp/archive" + }, + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": ">= 5.32.0", + "expressions": { + } + }, + "random": { + "name": "random", + "full_name": "registry.terraform.io/hashicorp/random", + "version_constraint": ">= 2.0.0" + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_config_key": "aws", + "expressions": { + "description": { + "constant_value": "AWS IAM Policy for managing aws lambda role" + }, + "name": { + "constant_value": "aws_iam_policy_for_terraform_aws_lambda_role" + }, + "path": { + "constant_value": "/" + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": [\n \"logs:CreateLogGroup\",\n \"logs:CreateLogStream\",\n \"logs:PutLogEvents\"\n ],\n \"Resource\": \"arn:aws:logs:*:*:*\",\n \"Effect\": \"Allow\"\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"lambda.amazonaws.com\"\n },\n \"Effect\": \"Allow\",\n \"Sid\": \"\"\n }\n ]\n}\n" + }, + "name": { + "constant_value": "Spacelift_Test_Lambda_Function_Role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.iam_policy_for_lambda.arn", + "aws_iam_policy.iam_policy_for_lambda" + ] + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.name", + "aws_iam_role.lambda_role" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_config_key": "aws", + "expressions": { + "filename": { + "references": [ + "path.module" + ] + }, + "function_name": { + "constant_value": "Spacelift_Test_Lambda_Function" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.arn", + "aws_iam_role.lambda_role" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0, + "depends_on": [ + "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role" + ] + }, + { + "address": "data.archive_file.zip_the_python_code", + "mode": "data", + "type": "archive_file", + "name": "zip_the_python_code", + "provider_config_key": "archive", + "expressions": { + "output_path": { + "references": [ + "path.module" + ] + }, + "source_dir": { + "references": [ + "path.module" + ] + }, + "type": { + "constant_value": "zip" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_policy.iam_policy_for_lambda", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-03-26T05:15:13Z", + "errored": false + } + \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-lambda-code-signing/test/bad-test/bad-payload.json b/terraform/plan/lambda-best-practices/check-lambda-code-signing/test/bad-test/bad-payload.json new file mode 100644 index 00000000..8a5fa13d --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-code-signing/test/bad-test/bad-payload.json @@ -0,0 +1,496 @@ +{ + "format_version": "1.2", + "terraform_version": "1.7.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "sensitive_values": {} + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "code_signing_config_arn": "", + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "./python/hello-python.zip", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "sensitive_values": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "after_unknown": { + "arn": true, + "id": true, + "name_prefix": true, + "policy_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "after_unknown": { + "id": true, + "policy_arn": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "code_signing_config_arn": "", + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "./python/hello-python.zip", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "after_unknown": { + "architectures": true, + "arn": true, + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": true, + "file_system_config": [], + "id": true, + "image_config": [], + "invoke_arn": true, + "last_modified": true, + "logging_config": true, + "qualified_arn": true, + "qualified_invoke_arn": true, + "role": true, + "signing_job_arn": true, + "signing_profile_version_arn": true, + "snap_start": [], + "source_code_hash": true, + "source_code_size": true, + "tags_all": true, + "tracing_config": true, + "version": true, + "vpc_config": [] + }, + "before_sensitive": false, + "after_sensitive": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + } + ], + "prior_state": { + "format_version": "1.0", + "terraform_version": "1.7.4", + "values": { + "root_module": { + "resources": [ + { + "address": "data.archive_file.zip_the_python_code", + "mode": "data", + "type": "archive_file", + "name": "zip_the_python_code", + "provider_name": "registry.terraform.io/hashicorp/archive", + "schema_version": 0, + "values": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "a214dde8a12ca94253e6511d64619f0ff9ffee35", + "output_base64sha256": "SFSoo0NG4FG8mNorh4sscOyiKc/kJzFsP8hLOy3Fk3Q=", + "output_base64sha512": "NutLilmFQDdniQXgTqfmvMcu9viZvU9BAyF9ChFwLG2w486kDHCfAyhUXCW4Ggxft6nSFxtN6QGVqRdlzn7WVQ==", + "output_file_mode": null, + "output_md5": "1b85a86b0487bc677393bb5399ab98ff", + "output_path": "./python/hello-python.zip", + "output_sha": "a214dde8a12ca94253e6511d64619f0ff9ffee35", + "output_sha256": "4854a8a34346e051bc98da2b878b2c70eca229cfe427316c3fc84b3b2dc59374", + "output_sha512": "36eb4b8a59854037678905e04ea7e6bcc72ef6f899bd4f4103217d0a11702c6db0e3cea40c709f0328545c25b81a0c5fb7a9d2171b4de90195a91765ce7ed655", + "output_size": 368, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./python/", + "source_file": null, + "type": "zip" + }, + "sensitive_values": { + "source": [] + } + } + ] + } + } + }, + "configuration": { + "provider_config": { + "archive": { + "name": "archive", + "full_name": "registry.terraform.io/hashicorp/archive" + }, + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": ">= 5.32.0", + "expressions": { + } + }, + "random": { + "name": "random", + "full_name": "registry.terraform.io/hashicorp/random", + "version_constraint": ">= 2.0.0" + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_config_key": "aws", + "expressions": { + "description": { + "constant_value": "AWS IAM Policy for managing aws lambda role" + }, + "name": { + "constant_value": "aws_iam_policy_for_terraform_aws_lambda_role" + }, + "path": { + "constant_value": "/" + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": [\n \"logs:CreateLogGroup\",\n \"logs:CreateLogStream\",\n \"logs:PutLogEvents\"\n ],\n \"Resource\": \"arn:aws:logs:*:*:*\",\n \"Effect\": \"Allow\"\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"lambda.amazonaws.com\"\n },\n \"Effect\": \"Allow\",\n \"Sid\": \"\"\n }\n ]\n}\n" + }, + "name": { + "constant_value": "Spacelift_Test_Lambda_Function_Role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.iam_policy_for_lambda.arn", + "aws_iam_policy.iam_policy_for_lambda" + ] + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.name", + "aws_iam_role.lambda_role" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_config_key": "aws", + "expressions": { + "code_signing_config_arn": { + "constant_value": "" + }, + "filename": { + "references": [ + "path.module" + ] + }, + "function_name": { + "constant_value": "Spacelift_Test_Lambda_Function" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.arn", + "aws_iam_role.lambda_role" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0, + "depends_on": [ + "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role" + ] + }, + { + "address": "data.archive_file.zip_the_python_code", + "mode": "data", + "type": "archive_file", + "name": "zip_the_python_code", + "provider_config_key": "archive", + "expressions": { + "output_path": { + "references": [ + "path.module" + ] + }, + "source_dir": { + "references": [ + "path.module" + ] + }, + "type": { + "constant_value": "zip" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_policy.iam_policy_for_lambda", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-03-26T05:15:13Z", + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-lambda-code-signing/test/bad-test/terraform-01.tf b/terraform/plan/lambda-best-practices/check-lambda-code-signing/test/bad-test/terraform-01.tf new file mode 100644 index 00000000..2f20f97a --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-code-signing/test/bad-test/terraform-01.tf @@ -0,0 +1,80 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + random = { + source = "hashicorp/random" + version = ">= 2.0" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_iam_role" "lambda_role" { +name = "Spacelift_Test_Lambda_Function_Role" +assume_role_policy = <= 5.32.0", + "expressions": { + } + }, + "random": { + "name": "random", + "full_name": "registry.terraform.io/hashicorp/random", + "version_constraint": ">= 2.0.0" + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_config_key": "aws", + "expressions": { + "description": { + "constant_value": "AWS IAM Policy for managing aws lambda role" + }, + "name": { + "constant_value": "aws_iam_policy_for_terraform_aws_lambda_role" + }, + "path": { + "constant_value": "/" + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": [\n \"logs:CreateLogGroup\",\n \"logs:CreateLogStream\",\n \"logs:PutLogEvents\"\n ],\n \"Resource\": \"arn:aws:logs:*:*:*\",\n \"Effect\": \"Allow\"\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"lambda.amazonaws.com\"\n },\n \"Effect\": \"Allow\",\n \"Sid\": \"\"\n }\n ]\n}\n" + }, + "name": { + "constant_value": "Spacelift_Test_Lambda_Function_Role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.iam_policy_for_lambda.arn", + "aws_iam_policy.iam_policy_for_lambda" + ] + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.name", + "aws_iam_role.lambda_role" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_config_key": "aws", + "expressions": { + "code_signing_config_arn": { + "constant_value": "arn:aws:signer:us-west-2:123456789012:signing-profile/example_signing_profile" + }, + "filename": { + "references": [ + "path.module" + ] + }, + "function_name": { + "constant_value": "Spacelift_Test_Lambda_Function" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.arn", + "aws_iam_role.lambda_role" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0, + "depends_on": [ + "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role" + ] + }, + { + "address": "data.archive_file.zip_the_python_code", + "mode": "data", + "type": "archive_file", + "name": "zip_the_python_code", + "provider_config_key": "archive", + "expressions": { + "output_path": { + "references": [ + "path.module" + ] + }, + "source_dir": { + "references": [ + "path.module" + ] + }, + "type": { + "constant_value": "zip" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_policy.iam_policy_for_lambda", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-03-26T05:04:48Z", + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-lambda-code-signing/test/good-test/main.tf b/terraform/plan/lambda-best-practices/check-lambda-code-signing/test/good-test/main.tf new file mode 100644 index 00000000..373a93b1 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-code-signing/test/good-test/main.tf @@ -0,0 +1,80 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + random = { + source = "hashicorp/random" + version = ">= 2.0" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_iam_role" "lambda_role" { +name = "Spacelift_Test_Lambda_Function_Role" +assume_role_policy = < payload.json + ``` + +4. **Test the Policy with Kyverno:** + ``` + kyverno-json scan --payload payload.json --policy policy.yaml + ``` + + a. **Test Policy Against Valid Payload:** + ``` + kyverno-json scan --payload test/good-test/good-payload-01.json --policy check-lambda-public-access.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - check-lambda-public-access / check-lambda-public-access / PASSED + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-lambda-public-access.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - check-lambda-public-access / check-lambda-public-access / FAILED + -> Principal must be set to a specific resource or user account and not '*' + -> all[0].check.~.(planned_values.root_module.resources[?type=='aws_lambda_permission'])[0].values.(principal != '*'): Invalid value: false: Expected value: true + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-lambda-public-access/check-lambda-public-access.yaml b/terraform/plan/lambda-best-practices/check-lambda-public-access/check-lambda-public-access.yaml new file mode 100644 index 00000000..b6681f27 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-public-access/check-lambda-public-access.yaml @@ -0,0 +1,24 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-lambda-public-access + annotations: + policies.kyverno.io/title: check-lambda-public-access + policies.kyverno.io/category: AWS Lambda Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy ensures that AWS Lambda function is not publicly accessible +spec: + rules: + - name: check-lambda-public-access + match: + all: + - (planned_values.root_module.resources[?type=='aws_lambda_function'] | length(@) > `0`): true + assert: + all: + - message: Principal must be set to a specific resource or user account and not '*' + check: + ~.(planned_values.root_module.resources[?type=='aws_lambda_permission']): + values: + (principal != '*'): true + diff --git a/terraform/plan/lambda-best-practices/check-lambda-public-access/test/bad-test/bad-01.tf b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/bad-test/bad-01.tf new file mode 100644 index 00000000..cde0647c --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/bad-test/bad-01.tf @@ -0,0 +1,51 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_lambda_function" "example" { + function_name = "example_lambda" + handler = "index.lambda_handler" + role = aws_iam_role.lambda_exec.arn + runtime = "python3.8" + filename = "" +} + +resource "aws_lambda_permission" "example_permission" { + action = "lambda:InvokeFunction" + function_name = aws_lambda_function.example.function_name + principal = "*" +} + +resource "aws_iam_role" "lambda_exec" { + name = "lambda_exec_role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "lambda.amazonaws.com" + } + }, + ] + }) +} + +resource "aws_iam_role_policy_attachment" "lambda_exec_policy" { + role = aws_iam_role.lambda_exec.name + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" +} + diff --git a/terraform/plan/lambda-best-practices/check-lambda-public-access/test/bad-test/bad-payload-01.json b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..d44f93bc --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/bad-test/bad-payload-01.json @@ -0,0 +1,419 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "lambda_exec_role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "role": "lambda_exec_role" + }, + "sensitive_values": {} + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "", + "function_name": "example_lambda", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "sensitive_values": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + }, + { + "address": "aws_lambda_permission.example_permission", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "action": "lambda:InvokeFunction", + "event_source_token": null, + "function_name": "example_lambda", + "function_url_auth_type": null, + "principal": "*", + "principal_org_id": null, + "qualifier": null, + "source_account": null, + "source_arn": null + }, + "sensitive_values": {} + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "lambda_exec_role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "role": "lambda_exec_role" + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "", + "function_name": "example_lambda", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "after_unknown": { + "architectures": true, + "arn": true, + "code_sha256": true, + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": true, + "file_system_config": [], + "id": true, + "image_config": [], + "invoke_arn": true, + "last_modified": true, + "logging_config": true, + "qualified_arn": true, + "qualified_invoke_arn": true, + "role": true, + "signing_job_arn": true, + "signing_profile_version_arn": true, + "snap_start": [], + "source_code_hash": true, + "source_code_size": true, + "tags_all": true, + "tracing_config": true, + "version": true, + "vpc_config": [] + }, + "before_sensitive": false, + "after_sensitive": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + }, + { + "address": "aws_lambda_permission.example_permission", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "action": "lambda:InvokeFunction", + "event_source_token": null, + "function_name": "example_lambda", + "function_url_auth_type": null, + "principal": "*", + "principal_org_id": null, + "qualifier": null, + "source_account": null, + "source_arn": null + }, + "after_unknown": { + "id": true, + "statement_id": true, + "statement_id_prefix": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "\u003e= 5.32.0", + "expressions": { + "region": { + "constant_value": "us-west-2" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": {}, + "name": { + "constant_value": "lambda_exec_role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "constant_value": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + }, + "role": { + "references": [ + "aws_iam_role.lambda_exec.name", + "aws_iam_role.lambda_exec" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "filename": { + "constant_value": "" + }, + "function_name": { + "constant_value": "example_lambda" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "role": { + "references": [ + "aws_iam_role.lambda_exec.arn", + "aws_iam_role.lambda_exec" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_permission.example_permission", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission", + "provider_config_key": "aws", + "expressions": { + "action": { + "constant_value": "lambda:InvokeFunction" + }, + "function_name": { + "references": [ + "aws_lambda_function.example.function_name", + "aws_lambda_function.example" + ] + }, + "principal": { + "constant_value": "*" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_exec", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_role.lambda_exec", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_lambda_function.example", + "attribute": [ + "function_name" + ] + } + ], + "timestamp": "2024-06-23T15:30:55Z", + "applyable": true, + "complete": true, + "errored": false +} \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-lambda-public-access/test/chainsaw-test.yaml b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/chainsaw-test.yaml new file mode 100644 index 00000000..6927b84e --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/chainsaw-test.yaml @@ -0,0 +1,61 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./good-test/good-payload-01.json --policy ../check-lambda-public-access.yaml --output json + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-lambda-public-access + rules: + - rule: + name: check-lambda-public-access + error: ~ + violations: ~ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./bad-test/bad-payload-01.json --policy ../check-lambda-public-access.yaml --output json + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-lambda-public-access + rules: + - rule: + name: check-lambda-public-access + error: ~ + violations: + - message: "Principal must be set to a specific resource or user account and not '*'" + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' + diff --git a/terraform/plan/lambda-best-practices/check-lambda-public-access/test/good-test/good-01.tf b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/good-test/good-01.tf new file mode 100644 index 00000000..18586e8c --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/good-test/good-01.tf @@ -0,0 +1,51 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_lambda_function" "example" { + function_name = "example_lambda" + handler = "index.lambda_handler" + role = aws_iam_role.lambda_exec.arn + runtime = "python3.8" + filename = "" +} + +resource "aws_lambda_permission" "example_permission" { + action = "lambda:InvokeFunction" + function_name = aws_lambda_function.example.function_name + principal = "events.amazonaws.com" +} + +resource "aws_iam_role" "lambda_exec" { + name = "lambda_exec_role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "lambda.amazonaws.com" + } + }, + ] + }) +} + +resource "aws_iam_role_policy_attachment" "lambda_exec_policy" { + role = aws_iam_role.lambda_exec.name + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" +} + diff --git a/terraform/plan/lambda-best-practices/check-lambda-public-access/test/good-test/good-payload-01.json b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/good-test/good-payload-01.json new file mode 100644 index 00000000..96beb2fd --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/good-test/good-payload-01.json @@ -0,0 +1,419 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "lambda_exec_role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "role": "lambda_exec_role" + }, + "sensitive_values": {} + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "", + "function_name": "example_lambda", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "sensitive_values": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + }, + { + "address": "aws_lambda_permission.example_permission", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "action": "lambda:InvokeFunction", + "event_source_token": null, + "function_name": "example_lambda", + "function_url_auth_type": null, + "principal": "events.amazonaws.com", + "principal_org_id": null, + "qualifier": null, + "source_account": null, + "source_arn": null + }, + "sensitive_values": {} + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "lambda_exec_role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "role": "lambda_exec_role" + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "", + "function_name": "example_lambda", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "after_unknown": { + "architectures": true, + "arn": true, + "code_sha256": true, + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": true, + "file_system_config": [], + "id": true, + "image_config": [], + "invoke_arn": true, + "last_modified": true, + "logging_config": true, + "qualified_arn": true, + "qualified_invoke_arn": true, + "role": true, + "signing_job_arn": true, + "signing_profile_version_arn": true, + "snap_start": [], + "source_code_hash": true, + "source_code_size": true, + "tags_all": true, + "tracing_config": true, + "version": true, + "vpc_config": [] + }, + "before_sensitive": false, + "after_sensitive": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + }, + { + "address": "aws_lambda_permission.example_permission", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "action": "lambda:InvokeFunction", + "event_source_token": null, + "function_name": "example_lambda", + "function_url_auth_type": null, + "principal": "events.amazonaws.com", + "principal_org_id": null, + "qualifier": null, + "source_account": null, + "source_arn": null + }, + "after_unknown": { + "id": true, + "statement_id": true, + "statement_id_prefix": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "\u003e= 5.32.0", + "expressions": { + "region": { + "constant_value": "us-west-2" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": {}, + "name": { + "constant_value": "lambda_exec_role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "constant_value": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + }, + "role": { + "references": [ + "aws_iam_role.lambda_exec.name", + "aws_iam_role.lambda_exec" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "filename": { + "constant_value": "" + }, + "function_name": { + "constant_value": "example_lambda" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "role": { + "references": [ + "aws_iam_role.lambda_exec.arn", + "aws_iam_role.lambda_exec" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_permission.example_permission", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission", + "provider_config_key": "aws", + "expressions": { + "action": { + "constant_value": "lambda:InvokeFunction" + }, + "function_name": { + "references": [ + "aws_lambda_function.example.function_name", + "aws_lambda_function.example" + ] + }, + "principal": { + "constant_value": "events.amazonaws.com" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_exec", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_role.lambda_exec", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_lambda_function.example", + "attribute": [ + "function_name" + ] + } + ], + "timestamp": "2024-06-23T15:31:50Z", + "applyable": true, + "complete": true, + "errored": false +} \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-lambda-runtime/README.md b/terraform/plan/lambda-best-practices/check-lambda-runtime/README.md new file mode 100644 index 00000000..4b27fb06 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-runtime/README.md @@ -0,0 +1,35 @@ +AWS Lambda runtimes are environments in which your Lambda functions execute. They provide the execution environment, including the language runtime, libraries, and dependencies that your function code needs to run. Each runtime is tailored to support a specific programming language, such as Python, Node.js, Java, or C#. AWS Lambda supports a variety of runtimes to accommodate different programming languages and frameworks. + +You can find more information about it [here](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html) + +In order to test this policy, you need set the runtime value in the *aws_lambda_function* block to some value that is not deprecated. If the value is not deprecated, the policy will return you passing checks else failing checks. + +``` +resource "aws_lambda_function" "terraform_lambda_func" { +filename = "${path.module}/python/hello-python.zip" +function_name = "Spacelift_Test_Lambda_Function" +role = aws_iam_role.lambda_role.arn +handler = "index.lambda_handler" +runtime = "python2.7" +depends_on = [aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role] +} +``` + +1. Navigate to the `aws/lambda/terraform/check-lambda-runtime` 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 check-url-auth-type.yaml --bindings ./binding.yaml + ``` + Since you're not using any deprecated runtime for the aws lambda function, the policy will give you passing checks. Run the same command against the bad-paylod present in the *bad-test* directory and you'll get failing checks. This can be done something like: + ``` + kyverno-json scan --payload bad-payload.json --policy check-x-ray-tracing-enabled.yaml --bindings ./binding.yaml + ``` \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-lambda-runtime/check-lambda-runtime.yaml b/terraform/plan/lambda-best-practices/check-lambda-runtime/check-lambda-runtime.yaml new file mode 100644 index 00000000..14ea239c --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-runtime/check-lambda-runtime.yaml @@ -0,0 +1,51 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-deprecated-runtime + annotations: + policies.kyverno.io/title: check-deprecated-runtime + policies.kyverno.io/category: AWS Lambda Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy ensures that Lambda Runtime is not deprecated +spec: + rules: + - name: check-deprecated-runtime + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_lambda_function'] | length(@) > `0`): true + context: + - name: forbidden_values + variable: + - java8 + - go1.x + - provided + - ruby2.7 + - nodejs14.x + - python3.7 + - dotnetcore3.1 + - nodejs12.x + - python3.6 + - dotnet5.0 + - dotnetcore2.1 + - nodejs10.x + - ruby2.5 + - python2.7 + - nodejs8.10 + - ruby2.5 + - python2.7 + - nodejs8.10 + - nodejs4.3 + - nodejs4.3-edge + - nodejs6.10 + - dotnetcore1.0 + - dotnetcore2.0 + - nodejs + assert: + all: + - message: The runtime is deprecated for AWS lambda function, use the another version. + check: + ~.(planned_values.root_module.resources[?type=='aws_lambda_function']): + values: + (contains($forbidden_values, runtime || '')): false \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-lambda-runtime/test/bad-test/bad-payload.json b/terraform/plan/lambda-best-practices/check-lambda-runtime/test/bad-test/bad-payload.json new file mode 100644 index 00000000..d6d40b26 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-runtime/test/bad-test/bad-payload.json @@ -0,0 +1,487 @@ +{ + "format_version": "1.2", + "terraform_version": "1.7.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "role_last_used": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "sensitive_values": {} + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "./python/hello-python.zip", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python2.7", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "sensitive_values": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "after_unknown": { + "arn": true, + "id": true, + "name_prefix": true, + "policy_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "role_last_used": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "role_last_used": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "after_unknown": { + "id": true, + "policy_arn": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "./python/hello-python.zip", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python2.7", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "after_unknown": { + "architectures": true, + "arn": true, + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": true, + "file_system_config": [], + "id": true, + "image_config": [], + "invoke_arn": true, + "last_modified": true, + "qualified_arn": true, + "qualified_invoke_arn": true, + "role": true, + "signing_job_arn": true, + "signing_profile_version_arn": true, + "snap_start": [], + "source_code_hash": true, + "source_code_size": true, + "tags_all": true, + "tracing_config": true, + "version": true, + "vpc_config": [] + }, + "before_sensitive": false, + "after_sensitive": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + } + ], + "prior_state": { + "format_version": "1.0", + "terraform_version": "1.7.4", + "values": { + "root_module": { + "resources": [ + { + "address": "data.archive_file.zip_the_python_code", + "mode": "data", + "type": "archive_file", + "name": "zip_the_python_code", + "provider_name": "registry.terraform.io/hashicorp/archive", + "schema_version": 0, + "values": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "a214dde8a12ca94253e6511d64619f0ff9ffee35", + "output_base64sha256": "SFSoo0NG4FG8mNorh4sscOyiKc/kJzFsP8hLOy3Fk3Q=", + "output_base64sha512": "NutLilmFQDdniQXgTqfmvMcu9viZvU9BAyF9ChFwLG2w486kDHCfAyhUXCW4Ggxft6nSFxtN6QGVqRdlzn7WVQ==", + "output_file_mode": null, + "output_md5": "1b85a86b0487bc677393bb5399ab98ff", + "output_path": "./python/hello-python.zip", + "output_sha": "a214dde8a12ca94253e6511d64619f0ff9ffee35", + "output_sha256": "4854a8a34346e051bc98da2b878b2c70eca229cfe427316c3fc84b3b2dc59374", + "output_sha512": "36eb4b8a59854037678905e04ea7e6bcc72ef6f899bd4f4103217d0a11702c6db0e3cea40c709f0328545c25b81a0c5fb7a9d2171b4de90195a91765ce7ed655", + "output_size": 368, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./python/", + "source_file": null, + "type": "zip" + }, + "sensitive_values": { + "source": [] + } + } + ] + } + } + }, + "configuration": { + "provider_config": { + "archive": { + "name": "archive", + "full_name": "registry.terraform.io/hashicorp/archive" + }, + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": {} + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_config_key": "aws", + "expressions": { + "description": { + "constant_value": "AWS IAM Policy for managing aws lambda role" + }, + "name": { + "constant_value": "aws_iam_policy_for_terraform_aws_lambda_role" + }, + "path": { + "constant_value": "/" + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": [\n \"logs:CreateLogGroup\",\n \"logs:CreateLogStream\",\n \"logs:PutLogEvents\"\n ],\n \"Resource\": \"arn:aws:logs:*:*:*\",\n \"Effect\": \"Allow\"\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"lambda.amazonaws.com\"\n },\n \"Effect\": \"Allow\",\n \"Sid\": \"\"\n }\n ]\n}\n" + }, + "name": { + "constant_value": "Spacelift_Test_Lambda_Function_Role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.iam_policy_for_lambda.arn", + "aws_iam_policy.iam_policy_for_lambda" + ] + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.name", + "aws_iam_role.lambda_role" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_config_key": "aws", + "expressions": { + "filename": { + "references": [ + "path.module" + ] + }, + "function_name": { + "constant_value": "Spacelift_Test_Lambda_Function" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.arn", + "aws_iam_role.lambda_role" + ] + }, + "runtime": { + "constant_value": "python2.7" + } + }, + "schema_version": 0, + "depends_on": [ + "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role" + ] + }, + { + "address": "data.archive_file.zip_the_python_code", + "mode": "data", + "type": "archive_file", + "name": "zip_the_python_code", + "provider_config_key": "archive", + "expressions": { + "output_path": { + "references": [ + "path.module" + ] + }, + "source_dir": { + "references": [ + "path.module" + ] + }, + "type": { + "constant_value": "zip" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_policy.iam_policy_for_lambda", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "name" + ] + } + ], + "timestamp": "2024-03-12T08:59:03Z", + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-lambda-runtime/test/bad-test/terraform.tf b/terraform/plan/lambda-best-practices/check-lambda-runtime/test/bad-test/terraform.tf new file mode 100644 index 00000000..4987ffca --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-runtime/test/bad-test/terraform.tf @@ -0,0 +1,75 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_iam_role" "lambda_role" { +name = "Spacelift_Test_Lambda_Function_Role" +assume_role_policy = < 4.16", + "expressions": {} + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_config_key": "aws", + "expressions": { + "description": { + "constant_value": "AWS IAM Policy for managing aws lambda role" + }, + "name": { + "constant_value": "aws_iam_policy_for_terraform_aws_lambda_role" + }, + "path": { + "constant_value": "/" + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": [\n \"logs:CreateLogGroup\",\n \"logs:CreateLogStream\",\n \"logs:PutLogEvents\"\n ],\n \"Resource\": \"arn:aws:logs:*:*:*\",\n \"Effect\": \"Allow\"\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"lambda.amazonaws.com\"\n },\n \"Effect\": \"Allow\",\n \"Sid\": \"\"\n }\n ]\n}\n" + }, + "name": { + "constant_value": "Spacelift_Test_Lambda_Function_Role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.iam_policy_for_lambda.arn", + "aws_iam_policy.iam_policy_for_lambda" + ] + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.name", + "aws_iam_role.lambda_role" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_config_key": "aws", + "expressions": { + "filename": { + "references": [ + "path.module" + ] + }, + "function_name": { + "constant_value": "Spacelift_Test_Lambda_Function" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.arn", + "aws_iam_role.lambda_role" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0, + "depends_on": [ + "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role" + ] + }, + { + "address": "data.archive_file.zip_the_python_code", + "mode": "data", + "type": "archive_file", + "name": "zip_the_python_code", + "provider_config_key": "archive", + "expressions": { + "output_path": { + "references": [ + "path.module" + ] + }, + "source_dir": { + "references": [ + "path.module" + ] + }, + "type": { + "constant_value": "zip" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_policy.iam_policy_for_lambda", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-03-12T08:53:40Z", + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-lambda-runtime/test/good-test/terraform.tf b/terraform/plan/lambda-best-practices/check-lambda-runtime/test/good-test/terraform.tf new file mode 100644 index 00000000..aa4f58be --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-runtime/test/good-test/terraform.tf @@ -0,0 +1,75 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_iam_role" "lambda_role" { +name = "Spacelift_Test_Lambda_Function_Role" +assume_role_policy = < payload.json + ``` + +4. **Test the Policy with Kyverno:** + ``` + kyverno-json scan --payload payload.json --policy policy.yaml + ``` + + a. **Test Policy Against Valid Payload:** + ``` + kyverno-json scan --payload test/good-test/good-payload-01.json --policy check-source-arn-account.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - check-source-arn-account / check-source-arn-account / PASSED + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-source-arn-account.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - check-source-arn-account / check-source-arn-account / FAILED + -> AWS Lambda function permissions delegated to AWS services should be limited by SourceArn or SourceAccount + -> all[0].check.~.(planned_values.root_module.resources[?type=='aws_lambda_permission'].values[?ends_with(principal, '.amazonaws.com')])[0].(!source_arn == `true` && !source_account == `true`): Invalid value: true: Expected value: false + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-source-arn-account/check-source-arn-account.yaml b/terraform/plan/lambda-best-practices/check-source-arn-account/check-source-arn-account.yaml new file mode 100644 index 00000000..ee436eb4 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-source-arn-account/check-source-arn-account.yaml @@ -0,0 +1,23 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-source-arn-account + annotations: + policies.kyverno.io/title: check-source-arn-account + policies.kyverno.io/category: AWS Lambda Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy ensures that AWS Lambda function permissions delegated to AWS services are limited by SourceArn or SourceAccount +spec: + rules: + - name: check-source-arn-account + match: + all: + - (planned_values.root_module.resources[?type=='aws_lambda_permission'].values[?ends_with(principal, '.amazonaws.com')] | length(@) > `0`): true + assert: + all: + - message: AWS Lambda function permissions delegated to AWS services should be limited by SourceArn or SourceAccount + check: + ~.(planned_values.root_module.resources[?type=='aws_lambda_permission'].values[?ends_with(principal, '.amazonaws.com')]): + (!source_arn == `true` && !source_account == `true`): false + diff --git a/terraform/plan/lambda-best-practices/check-source-arn-account/test/bad-test/bad-01.tf b/terraform/plan/lambda-best-practices/check-source-arn-account/test/bad-test/bad-01.tf new file mode 100644 index 00000000..4e2c4868 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-source-arn-account/test/bad-test/bad-01.tf @@ -0,0 +1,51 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_lambda_function" "example" { + function_name = "example_lambda" + handler = "index.lambda_handler" + role = aws_iam_role.lambda_exec.arn + runtime = "python3.8" + filename = "" +} + +resource "aws_lambda_permission" "example_permission" { + action = "lambda:InvokeFunction" + function_name = aws_lambda_function.example.function_name + principal = "apigateway.amazonaws.com" +} + +resource "aws_iam_role" "lambda_exec" { + name = "lambda_exec_role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "lambda.amazonaws.com" + } + }, + ] + }) +} + +resource "aws_iam_role_policy_attachment" "lambda_exec_policy" { + role = aws_iam_role.lambda_exec.name + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" +} + diff --git a/terraform/plan/lambda-best-practices/check-source-arn-account/test/bad-test/bad-payload-01.json b/terraform/plan/lambda-best-practices/check-source-arn-account/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..be7a575e --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-source-arn-account/test/bad-test/bad-payload-01.json @@ -0,0 +1,419 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "lambda_exec_role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "role": "lambda_exec_role" + }, + "sensitive_values": {} + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "", + "function_name": "example_lambda", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "sensitive_values": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + }, + { + "address": "aws_lambda_permission.example_permission", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "action": "lambda:InvokeFunction", + "event_source_token": null, + "function_name": "example_lambda", + "function_url_auth_type": null, + "principal": "apigateway.amazonaws.com", + "principal_org_id": null, + "qualifier": null, + "source_account": null, + "source_arn": null + }, + "sensitive_values": {} + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "lambda_exec_role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "role": "lambda_exec_role" + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "", + "function_name": "example_lambda", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "after_unknown": { + "architectures": true, + "arn": true, + "code_sha256": true, + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": true, + "file_system_config": [], + "id": true, + "image_config": [], + "invoke_arn": true, + "last_modified": true, + "logging_config": true, + "qualified_arn": true, + "qualified_invoke_arn": true, + "role": true, + "signing_job_arn": true, + "signing_profile_version_arn": true, + "snap_start": [], + "source_code_hash": true, + "source_code_size": true, + "tags_all": true, + "tracing_config": true, + "version": true, + "vpc_config": [] + }, + "before_sensitive": false, + "after_sensitive": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + }, + { + "address": "aws_lambda_permission.example_permission", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "action": "lambda:InvokeFunction", + "event_source_token": null, + "function_name": "example_lambda", + "function_url_auth_type": null, + "principal": "apigateway.amazonaws.com", + "principal_org_id": null, + "qualifier": null, + "source_account": null, + "source_arn": null + }, + "after_unknown": { + "id": true, + "statement_id": true, + "statement_id_prefix": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": ">= 5.32.0", + "expressions": { + "region": { + "constant_value": "us-west-2" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": {}, + "name": { + "constant_value": "lambda_exec_role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "constant_value": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + }, + "role": { + "references": [ + "aws_iam_role.lambda_exec.name", + "aws_iam_role.lambda_exec" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "filename": { + "constant_value": "" + }, + "function_name": { + "constant_value": "example_lambda" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "role": { + "references": [ + "aws_iam_role.lambda_exec.arn", + "aws_iam_role.lambda_exec" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_permission.example_permission", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission", + "provider_config_key": "aws", + "expressions": { + "action": { + "constant_value": "lambda:InvokeFunction" + }, + "function_name": { + "references": [ + "aws_lambda_function.example.function_name", + "aws_lambda_function.example" + ] + }, + "principal": { + "constant_value": "apigateway.amazonaws.com" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_exec", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_role.lambda_exec", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_lambda_function.example", + "attribute": [ + "function_name" + ] + } + ], + "timestamp": "2024-07-04T18:30:59Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-source-arn-account/test/chainsaw-test.yaml b/terraform/plan/lambda-best-practices/check-source-arn-account/test/chainsaw-test.yaml new file mode 100644 index 00000000..b7cbcc06 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-source-arn-account/test/chainsaw-test.yaml @@ -0,0 +1,61 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./good-test/good-payload-01.json --policy ../check-source-arn-account.yaml --output json + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-source-arn-account + rules: + - rule: + name: check-source-arn-account + error: ~ + violations: ~ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./bad-test/bad-payload-01.json --policy ../check-source-arn-account.yaml --output json + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-source-arn-account + rules: + - rule: + name: check-source-arn-account + error: ~ + violations: + - message: AWS Lambda function permissions delegated to AWS services should be limited by SourceArn or SourceAccount + errors: + - type: FieldValueInvalid + value: true + detail: 'Expected value: false' + diff --git a/terraform/plan/lambda-best-practices/check-source-arn-account/test/good-test/good-01.tf b/terraform/plan/lambda-best-practices/check-source-arn-account/test/good-test/good-01.tf new file mode 100644 index 00000000..b192ad6a --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-source-arn-account/test/good-test/good-01.tf @@ -0,0 +1,67 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_lambda_function" "example" { + function_name = "example_lambda" + handler = "index.lambda_handler" + role = aws_iam_role.lambda_exec.arn + runtime = "python3.8" + filename = "" +} + +resource "aws_lambda_permission" "example_permission" { + action = "lambda:InvokeFunction" + function_name = aws_lambda_function.example.function_name + principal = "s3.amazonaws.com" + source_arn = "arn:aws:s3:::example-bucket" +} + +resource "aws_lambda_permission" "example_permission_2" { + action = "lambda:InvokeFunction" + function_name = aws_lambda_function.example.function_name + principal = "s3.amazonaws.com" + source_account = "123456789012" +} + +resource "aws_lambda_permission" "example_permission_3" { + action = "lambda:InvokeFunction" + function_name = aws_lambda_function.example.function_name + principal = "s3.amazonaws.com" + source_arn = "arn:aws:s3:::example-bucket-2" + source_account = "123456789012" +} + +resource "aws_iam_role" "lambda_exec" { + name = "lambda_exec_role" + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "lambda.amazonaws.com" + } + }, + ] + }) +} + +resource "aws_iam_role_policy_attachment" "lambda_exec_policy" { + role = aws_iam_role.lambda_exec.name + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" +} + diff --git a/terraform/plan/lambda-best-practices/check-source-arn-account/test/good-test/good-payload-01.json b/terraform/plan/lambda-best-practices/check-source-arn-account/test/good-test/good-payload-01.json new file mode 100644 index 00000000..4d123f14 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-source-arn-account/test/good-test/good-payload-01.json @@ -0,0 +1,577 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "lambda_exec_role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "role": "lambda_exec_role" + }, + "sensitive_values": {} + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "", + "function_name": "example_lambda", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "sensitive_values": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + }, + { + "address": "aws_lambda_permission.example_permission", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "action": "lambda:InvokeFunction", + "event_source_token": null, + "function_name": "example_lambda", + "function_url_auth_type": null, + "principal": "s3.amazonaws.com", + "principal_org_id": null, + "qualifier": null, + "source_account": null, + "source_arn": "arn:aws:s3:::example-bucket" + }, + "sensitive_values": {} + }, + { + "address": "aws_lambda_permission.example_permission_2", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission_2", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "action": "lambda:InvokeFunction", + "event_source_token": null, + "function_name": "example_lambda", + "function_url_auth_type": null, + "principal": "s3.amazonaws.com", + "principal_org_id": null, + "qualifier": null, + "source_account": "123456789012", + "source_arn": null + }, + "sensitive_values": {} + }, + { + "address": "aws_lambda_permission.example_permission_3", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission_3", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "action": "lambda:InvokeFunction", + "event_source_token": null, + "function_name": "example_lambda", + "function_url_auth_type": null, + "principal": "s3.amazonaws.com", + "principal_org_id": null, + "qualifier": null, + "source_account": "123456789012", + "source_arn": "arn:aws:s3:::example-bucket-2" + }, + "sensitive_values": {} + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "lambda_exec_role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", + "role": "lambda_exec_role" + }, + "after_unknown": { + "id": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "", + "function_name": "example_lambda", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "after_unknown": { + "architectures": true, + "arn": true, + "code_sha256": true, + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": true, + "file_system_config": [], + "id": true, + "image_config": [], + "invoke_arn": true, + "last_modified": true, + "logging_config": true, + "qualified_arn": true, + "qualified_invoke_arn": true, + "role": true, + "signing_job_arn": true, + "signing_profile_version_arn": true, + "snap_start": [], + "source_code_hash": true, + "source_code_size": true, + "tags_all": true, + "tracing_config": true, + "version": true, + "vpc_config": [] + }, + "before_sensitive": false, + "after_sensitive": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + }, + { + "address": "aws_lambda_permission.example_permission", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "action": "lambda:InvokeFunction", + "event_source_token": null, + "function_name": "example_lambda", + "function_url_auth_type": null, + "principal": "s3.amazonaws.com", + "principal_org_id": null, + "qualifier": null, + "source_account": null, + "source_arn": "arn:aws:s3:::example-bucket" + }, + "after_unknown": { + "id": true, + "statement_id": true, + "statement_id_prefix": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_lambda_permission.example_permission_2", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission_2", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "action": "lambda:InvokeFunction", + "event_source_token": null, + "function_name": "example_lambda", + "function_url_auth_type": null, + "principal": "s3.amazonaws.com", + "principal_org_id": null, + "qualifier": null, + "source_account": "123456789012", + "source_arn": null + }, + "after_unknown": { + "id": true, + "statement_id": true, + "statement_id_prefix": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_lambda_permission.example_permission_3", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission_3", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "action": "lambda:InvokeFunction", + "event_source_token": null, + "function_name": "example_lambda", + "function_url_auth_type": null, + "principal": "s3.amazonaws.com", + "principal_org_id": null, + "qualifier": null, + "source_account": "123456789012", + "source_arn": "arn:aws:s3:::example-bucket-2" + }, + "after_unknown": { + "id": true, + "statement_id": true, + "statement_id_prefix": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": ">= 5.32.0", + "expressions": { + "region": { + "constant_value": "us-west-2" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_role.lambda_exec", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_exec", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": {}, + "name": { + "constant_value": "lambda_exec_role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.lambda_exec_policy", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "lambda_exec_policy", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "constant_value": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + }, + "role": { + "references": [ + "aws_iam_role.lambda_exec.name", + "aws_iam_role.lambda_exec" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.example", + "mode": "managed", + "type": "aws_lambda_function", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "filename": { + "constant_value": "" + }, + "function_name": { + "constant_value": "example_lambda" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "role": { + "references": [ + "aws_iam_role.lambda_exec.arn", + "aws_iam_role.lambda_exec" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_permission.example_permission", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission", + "provider_config_key": "aws", + "expressions": { + "action": { + "constant_value": "lambda:InvokeFunction" + }, + "function_name": { + "references": [ + "aws_lambda_function.example.function_name", + "aws_lambda_function.example" + ] + }, + "principal": { + "constant_value": "s3.amazonaws.com" + }, + "source_arn": { + "constant_value": "arn:aws:s3:::example-bucket" + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_permission.example_permission_2", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission_2", + "provider_config_key": "aws", + "expressions": { + "action": { + "constant_value": "lambda:InvokeFunction" + }, + "function_name": { + "references": [ + "aws_lambda_function.example.function_name", + "aws_lambda_function.example" + ] + }, + "principal": { + "constant_value": "s3.amazonaws.com" + }, + "source_account": { + "constant_value": "123456789012" + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_permission.example_permission_3", + "mode": "managed", + "type": "aws_lambda_permission", + "name": "example_permission_3", + "provider_config_key": "aws", + "expressions": { + "action": { + "constant_value": "lambda:InvokeFunction" + }, + "function_name": { + "references": [ + "aws_lambda_function.example.function_name", + "aws_lambda_function.example" + ] + }, + "principal": { + "constant_value": "s3.amazonaws.com" + }, + "source_account": { + "constant_value": "123456789012" + }, + "source_arn": { + "constant_value": "arn:aws:s3:::example-bucket-2" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_exec", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_role.lambda_exec", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_lambda_function.example", + "attribute": [ + "function_name" + ] + } + ], + "timestamp": "2024-07-04T18:39:27Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-url-auth-type/README.md b/terraform/plan/lambda-best-practices/check-url-auth-type/README.md new file mode 100644 index 00000000..a4eb9725 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-url-auth-type/README.md @@ -0,0 +1,54 @@ +You can control access to your Lambda function URLs using the AuthType parameter combined with resource-based policies attached to your specific function. The configuration of these two components determines who can invoke or perform other administrative actions on your function URL. + +The AuthType parameter determines how Lambda authenticates or authorizes requests to your function URL. When you configure your function URL, you must specify one of the following AuthType options: + +- **AWS_IAM** – Lambda uses AWS Identity and Access Management (IAM) to authenticate and authorize requests based on the IAM principal's identity policy and the function's resource-based policy. Choose this option if you want only authenticated users and roles to invoke your function via the function URL. + +- **NONE** – Lambda doesn't perform any authentication before invoking your function. However, your function's resource-based policy is always in effect and must grant public access before your function URL can receive requests. Choose this option to allow public, unauthenticated access to your function URL. + +You can use the [AWS Lambda function URL Block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function_url) to set the Authorization Type. + +``` +resource "aws_lambda_function_url" "test_latest" { + function_name = aws_lambda_function.test.function_name + authorization_type = "NONE" +} + +resource "aws_lambda_function_url" "test_live" { + function_name = aws_lambda_function.test.function_name + qualifier = "my_alias" + authorization_type = "AWS_IAM" + + cors { + allow_credentials = true + allow_origins = ["*"] + allow_methods = ["*"] + allow_headers = ["date", "keep-alive"] + expose_headers = ["keep-alive", "date"] + max_age = 86400 + } +} +``` + +This policy checks whether you've set the authorization type of the AWS Lambda function to NONE. If you've, the policy will give you failing checks else passing checks. + +In order to test this policy, use the following commands: + +1. Navigate to the `aws/lambda/terraform/check-url-auth-type` 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 check-url-auth-type.yaml --bindings ./binding.yaml + ``` + Since you've set the *authorization type* not equal to *NONE*, the policy will give you passing checks. Run the same command against the bad-paylod present in the *bad-test* directory and you'll get failing checks. This can be done something like: + ``` + kyverno-json scan --payload bad-payload.json --policy check-x-ray-tracing-enabled.yaml --bindings ./binding.yaml + ``` \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-url-auth-type/check-url-auth-type.yaml b/terraform/plan/lambda-best-practices/check-url-auth-type/check-url-auth-type.yaml new file mode 100644 index 00000000..6c768bfd --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-url-auth-type/check-url-auth-type.yaml @@ -0,0 +1,25 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-url-auth-type + annotations: + policies.kyverno.io/title: check-url-auth-type + policies.kyverno.io/category: AWS Lambda Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy ensures that Lambda function URLs AuthType is not None. +spec: + rules: + - name: check-url-auth-type + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_lambda_function'] | length(@) > `0`): true + assert: + all: + - message: Set the authoriation type of the aws lambda function url is set to `AWS_IAM` + check: + ~.(planned_values.root_module.resources[?type=='aws_lambda_function_url']): + values: + (authorization_type=='AWS_IAM'): true + diff --git a/terraform/plan/lambda-best-practices/check-url-auth-type/test/bad-test/bad-payload.json b/terraform/plan/lambda-best-practices/check-url-auth-type/test/bad-test/bad-payload.json new file mode 100644 index 00000000..a8130ff4 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-url-auth-type/test/bad-test/bad-payload.json @@ -0,0 +1,687 @@ +{ + "format_version": "1.2", + "terraform_version": "1.7.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "role_last_used": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "sensitive_values": {} + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "./python/hello-python.zip", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "sensitive_values": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + }, + { + "address": "aws_lambda_function_url.test_live", + "mode": "managed", + "type": "aws_lambda_function_url", + "name": "test_live", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "authorization_type": "NONE", + "cors": [ + { + "allow_credentials": true, + "allow_headers": [ + "date", + "keep-alive" + ], + "allow_methods": [ + "*" + ], + "allow_origins": [ + "*" + ], + "expose_headers": [ + "date", + "keep-alive" + ], + "max_age": 86400 + } + ], + "function_name": "Spacelift_Test_Lambda_Function", + "invoke_mode": "BUFFERED", + "qualifier": "my_alias", + "timeouts": null + }, + "sensitive_values": { + "cors": [ + { + "allow_headers": [ + false, + false + ], + "allow_methods": [ + false + ], + "allow_origins": [ + false + ], + "expose_headers": [ + false, + false + ] + } + ] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "after_unknown": { + "arn": true, + "id": true, + "name_prefix": true, + "policy_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "role_last_used": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "role_last_used": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "after_unknown": { + "id": true, + "policy_arn": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "./python/hello-python.zip", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "after_unknown": { + "architectures": true, + "arn": true, + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": true, + "file_system_config": [], + "id": true, + "image_config": [], + "invoke_arn": true, + "last_modified": true, + "qualified_arn": true, + "qualified_invoke_arn": true, + "role": true, + "signing_job_arn": true, + "signing_profile_version_arn": true, + "snap_start": [], + "source_code_hash": true, + "source_code_size": true, + "tags_all": true, + "tracing_config": true, + "version": true, + "vpc_config": [] + }, + "before_sensitive": false, + "after_sensitive": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + }, + { + "address": "aws_lambda_function_url.test_live", + "mode": "managed", + "type": "aws_lambda_function_url", + "name": "test_live", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "authorization_type": "NONE", + "cors": [ + { + "allow_credentials": true, + "allow_headers": [ + "date", + "keep-alive" + ], + "allow_methods": [ + "*" + ], + "allow_origins": [ + "*" + ], + "expose_headers": [ + "date", + "keep-alive" + ], + "max_age": 86400 + } + ], + "function_name": "Spacelift_Test_Lambda_Function", + "invoke_mode": "BUFFERED", + "qualifier": "my_alias", + "timeouts": null + }, + "after_unknown": { + "cors": [ + { + "allow_headers": [ + false, + false + ], + "allow_methods": [ + false + ], + "allow_origins": [ + false + ], + "expose_headers": [ + false, + false + ] + } + ], + "function_arn": true, + "function_url": true, + "id": true, + "url_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "cors": [ + { + "allow_headers": [ + false, + false + ], + "allow_methods": [ + false + ], + "allow_origins": [ + false + ], + "expose_headers": [ + false, + false + ] + } + ] + } + } + } + ], + "prior_state": { + "format_version": "1.0", + "terraform_version": "1.7.4", + "values": { + "root_module": { + "resources": [ + { + "address": "data.archive_file.zip_the_python_code", + "mode": "data", + "type": "archive_file", + "name": "zip_the_python_code", + "provider_name": "registry.terraform.io/hashicorp/archive", + "schema_version": 0, + "values": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "a214dde8a12ca94253e6511d64619f0ff9ffee35", + "output_base64sha256": "SFSoo0NG4FG8mNorh4sscOyiKc/kJzFsP8hLOy3Fk3Q=", + "output_base64sha512": "NutLilmFQDdniQXgTqfmvMcu9viZvU9BAyF9ChFwLG2w486kDHCfAyhUXCW4Ggxft6nSFxtN6QGVqRdlzn7WVQ==", + "output_file_mode": null, + "output_md5": "1b85a86b0487bc677393bb5399ab98ff", + "output_path": "./python/hello-python.zip", + "output_sha": "a214dde8a12ca94253e6511d64619f0ff9ffee35", + "output_sha256": "4854a8a34346e051bc98da2b878b2c70eca229cfe427316c3fc84b3b2dc59374", + "output_sha512": "36eb4b8a59854037678905e04ea7e6bcc72ef6f899bd4f4103217d0a11702c6db0e3cea40c709f0328545c25b81a0c5fb7a9d2171b4de90195a91765ce7ed655", + "output_size": 368, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./python/", + "source_file": null, + "type": "zip" + }, + "sensitive_values": { + "source": [] + } + } + ] + } + } + }, + "configuration": { + "provider_config": { + "archive": { + "name": "archive", + "full_name": "registry.terraform.io/hashicorp/archive" + }, + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": {} + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_config_key": "aws", + "expressions": { + "description": { + "constant_value": "AWS IAM Policy for managing aws lambda role" + }, + "name": { + "constant_value": "aws_iam_policy_for_terraform_aws_lambda_role" + }, + "path": { + "constant_value": "/" + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": [\n \"logs:CreateLogGroup\",\n \"logs:CreateLogStream\",\n \"logs:PutLogEvents\"\n ],\n \"Resource\": \"arn:aws:logs:*:*:*\",\n \"Effect\": \"Allow\"\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"lambda.amazonaws.com\"\n },\n \"Effect\": \"Allow\",\n \"Sid\": \"\"\n }\n ]\n}\n" + }, + "name": { + "constant_value": "Spacelift_Test_Lambda_Function_Role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.iam_policy_for_lambda.arn", + "aws_iam_policy.iam_policy_for_lambda" + ] + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.name", + "aws_iam_role.lambda_role" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_config_key": "aws", + "expressions": { + "filename": { + "references": [ + "path.module" + ] + }, + "function_name": { + "constant_value": "Spacelift_Test_Lambda_Function" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.arn", + "aws_iam_role.lambda_role" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0, + "depends_on": [ + "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role" + ] + }, + { + "address": "aws_lambda_function_url.test_live", + "mode": "managed", + "type": "aws_lambda_function_url", + "name": "test_live", + "provider_config_key": "aws", + "expressions": { + "authorization_type": { + "constant_value": "NONE" + }, + "cors": [ + { + "allow_credentials": { + "constant_value": true + }, + "allow_headers": { + "constant_value": [ + "date", + "keep-alive" + ] + }, + "allow_methods": { + "constant_value": [ + "*" + ] + }, + "allow_origins": { + "constant_value": [ + "*" + ] + }, + "expose_headers": { + "constant_value": [ + "keep-alive", + "date" + ] + }, + "max_age": { + "constant_value": 86400 + } + } + ], + "function_name": { + "references": [ + "aws_lambda_function.terraform_lambda_func.function_name", + "aws_lambda_function.terraform_lambda_func" + ] + }, + "qualifier": { + "constant_value": "my_alias" + } + }, + "schema_version": 0 + }, + { + "address": "data.archive_file.zip_the_python_code", + "mode": "data", + "type": "archive_file", + "name": "zip_the_python_code", + "provider_config_key": "archive", + "expressions": { + "output_path": { + "references": [ + "path.module" + ] + }, + "source_dir": { + "references": [ + "path.module" + ] + }, + "type": { + "constant_value": "zip" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_lambda_function.terraform_lambda_func", + "attribute": [ + "function_name" + ] + }, + { + "resource": "aws_iam_policy.iam_policy_for_lambda", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "name" + ] + } + ], + "timestamp": "2024-03-12T05:38:02Z", + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-url-auth-type/test/bad-test/terraform.tf b/terraform/plan/lambda-best-practices/check-url-auth-type/test/bad-test/terraform.tf new file mode 100644 index 00000000..18404d47 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-url-auth-type/test/bad-test/terraform.tf @@ -0,0 +1,91 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_iam_role" "lambda_role" { +name = "Spacelift_Test_Lambda_Function_Role" +assume_role_policy = < 4.16", + "expressions": {} + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_config_key": "aws", + "expressions": { + "description": { + "constant_value": "AWS IAM Policy for managing aws lambda role" + }, + "name": { + "constant_value": "aws_iam_policy_for_terraform_aws_lambda_role" + }, + "path": { + "constant_value": "/" + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": [\n \"logs:CreateLogGroup\",\n \"logs:CreateLogStream\",\n \"logs:PutLogEvents\"\n ],\n \"Resource\": \"arn:aws:logs:*:*:*\",\n \"Effect\": \"Allow\"\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"lambda.amazonaws.com\"\n },\n \"Effect\": \"Allow\",\n \"Sid\": \"\"\n }\n ]\n}\n" + }, + "name": { + "constant_value": "Spacelift_Test_Lambda_Function_Role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.iam_policy_for_lambda.arn", + "aws_iam_policy.iam_policy_for_lambda" + ] + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.name", + "aws_iam_role.lambda_role" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_config_key": "aws", + "expressions": { + "filename": { + "references": [ + "path.module" + ] + }, + "function_name": { + "constant_value": "Spacelift_Test_Lambda_Function" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.arn", + "aws_iam_role.lambda_role" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0, + "depends_on": [ + "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role" + ] + }, + { + "address": "aws_lambda_function_url.test_live", + "mode": "managed", + "type": "aws_lambda_function_url", + "name": "test_live", + "provider_config_key": "aws", + "expressions": { + "authorization_type": { + "constant_value": "AWS_IAM" + }, + "cors": [ + { + "allow_credentials": { + "constant_value": true + }, + "allow_headers": { + "constant_value": [ + "date", + "keep-alive" + ] + }, + "allow_methods": { + "constant_value": [ + "*" + ] + }, + "allow_origins": { + "constant_value": [ + "*" + ] + }, + "expose_headers": { + "constant_value": [ + "keep-alive", + "date" + ] + }, + "max_age": { + "constant_value": 86400 + } + } + ], + "function_name": { + "references": [ + "aws_lambda_function.terraform_lambda_func.function_name", + "aws_lambda_function.terraform_lambda_func" + ] + }, + "qualifier": { + "constant_value": "my_alias" + } + }, + "schema_version": 0 + }, + { + "address": "data.archive_file.zip_the_python_code", + "mode": "data", + "type": "archive_file", + "name": "zip_the_python_code", + "provider_config_key": "archive", + "expressions": { + "output_path": { + "references": [ + "path.module" + ] + }, + "source_dir": { + "references": [ + "path.module" + ] + }, + "type": { + "constant_value": "zip" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_policy.iam_policy_for_lambda", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_lambda_function.terraform_lambda_func", + "attribute": [ + "function_name" + ] + } + ], + "timestamp": "2024-03-12T05:34:31Z", + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-url-auth-type/test/good-test/terraform.tf b/terraform/plan/lambda-best-practices/check-url-auth-type/test/good-test/terraform.tf new file mode 100644 index 00000000..d129c2e8 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-url-auth-type/test/good-test/terraform.tf @@ -0,0 +1,90 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_iam_role" "lambda_role" { +name = "Spacelift_Test_Lambda_Function_Role" +assume_role_policy = < payload.json + ``` +4. Test your payload against the policy using `kyverno-json scan` command + ``` + kyverno-json scan --payload good-payload.json --policy check-x-ray-tracing-enabled.yaml --bindings ./binding.yaml + ``` + Since you've set the *mode* in the *aws_lambda_function* resource block to *Active*, the policy will give you passing checks. Run the same command against the bad-paylod present in the *bad-test* directory and you'll get failing checks. This can be done something like: + ``` + kyverno-json scan --payload bad-payload.json --policy check-x-ray-tracing-enabled.yaml --bindings ./binding.yaml + ``` diff --git a/terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/check-x-ray-tracing-enabled.yaml b/terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/check-x-ray-tracing-enabled.yaml new file mode 100644 index 00000000..13fca3c8 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/check-x-ray-tracing-enabled.yaml @@ -0,0 +1,28 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: enable-x-ray-tracing + annotations: + policies.kyverno.io/title: enable-x-ray-tracing + policies.kyverno.io/category: AWS Lambda Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + AWS X-Ray to visualize the components of your application, + identify performance bottlenecks, and troubleshoot requests that + resulted in an error. This policy checks whether X-Ray is enabled + for Labmda function. +spec: + rules: + - name: check-x-ray-tracing-enabled + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_lambda_function'] | length(@) > `0`): true + assert: + all: + - message: Use the `tracing_config` block in the `aws_lambda_function` resource to set the mode to `Active` or `PassThrough` + check: + ~.(planned_values.root_module.resources[?type=='aws_lambda_function']): + (values.tracing_config[?mode=='Active' || mode=='PassThrough'] || `[]` | length(@) > `0`): true + + diff --git a/terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/test/bad-test/bad-payload.json b/terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/test/bad-test/bad-payload.json new file mode 100644 index 00000000..8be34b2a --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/test/bad-test/bad-payload.json @@ -0,0 +1,487 @@ +{ + "format_version": "1.2", + "terraform_version": "1.7.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "sensitive_values": { + "tags_all": {} + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "sensitive_values": { + "inline_policy": [], + "managed_policy_arns": [], + "role_last_used": [], + "tags_all": {} + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "sensitive_values": {} + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "./python/hello-python.zip", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "sensitive_values": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": "AWS IAM Policy for managing aws lambda role", + "name": "aws_iam_policy_for_terraform_aws_lambda_role", + "path": "/", + "policy": "{\"Statement\":[{\"Action\":[\"logs:CreateLogGroup\",\"logs:CreateLogStream\",\"logs:PutLogEvents\"],\"Effect\":\"Allow\",\"Resource\":\"arn:aws:logs:*:*:*\"}],\"Version\":\"2012-10-17\"}", + "tags": null + }, + "after_unknown": { + "arn": true, + "id": true, + "name_prefix": true, + "policy_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"},\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}", + "description": null, + "force_detach_policies": false, + "max_session_duration": 3600, + "name": "Spacelift_Test_Lambda_Function_Role", + "path": "/", + "permissions_boundary": null, + "tags": null + }, + "after_unknown": { + "arn": true, + "create_date": true, + "id": true, + "inline_policy": true, + "managed_policy_arns": true, + "name_prefix": true, + "role_last_used": true, + "tags_all": true, + "unique_id": true + }, + "before_sensitive": false, + "after_sensitive": { + "inline_policy": [], + "managed_policy_arns": [], + "role_last_used": [], + "tags_all": {} + } + } + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "role": "Spacelift_Test_Lambda_Function_Role" + }, + "after_unknown": { + "id": true, + "policy_arn": true + }, + "before_sensitive": false, + "after_sensitive": {} + } + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "code_signing_config_arn": null, + "dead_letter_config": [], + "description": null, + "environment": [], + "file_system_config": [], + "filename": "./python/hello-python.zip", + "function_name": "Spacelift_Test_Lambda_Function", + "handler": "index.lambda_handler", + "image_config": [], + "image_uri": null, + "kms_key_arn": null, + "layers": null, + "memory_size": 128, + "package_type": "Zip", + "publish": false, + "replace_security_groups_on_destroy": null, + "replacement_security_group_ids": null, + "reserved_concurrent_executions": -1, + "runtime": "python3.8", + "s3_bucket": null, + "s3_key": null, + "s3_object_version": null, + "skip_destroy": false, + "snap_start": [], + "tags": null, + "timeout": 3, + "timeouts": null, + "vpc_config": [] + }, + "after_unknown": { + "architectures": true, + "arn": true, + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": true, + "file_system_config": [], + "id": true, + "image_config": [], + "invoke_arn": true, + "last_modified": true, + "qualified_arn": true, + "qualified_invoke_arn": true, + "role": true, + "signing_job_arn": true, + "signing_profile_version_arn": true, + "snap_start": [], + "source_code_hash": true, + "source_code_size": true, + "tags_all": true, + "tracing_config": true, + "version": true, + "vpc_config": [] + }, + "before_sensitive": false, + "after_sensitive": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [] + } + } + } + ], + "prior_state": { + "format_version": "1.0", + "terraform_version": "1.7.4", + "values": { + "root_module": { + "resources": [ + { + "address": "data.archive_file.zip_the_python_code", + "mode": "data", + "type": "archive_file", + "name": "zip_the_python_code", + "provider_name": "registry.terraform.io/hashicorp/archive", + "schema_version": 0, + "values": { + "exclude_symlink_directories": null, + "excludes": null, + "id": "bff9551d27784d38fc02eba7a2117d5237944797", + "output_base64sha256": "HtYeQBTx8d+YMSa31gZS/P85fZHhQNBJzzE0s+IaSTA=", + "output_base64sha512": "fbSSLKmSixIurBEohYIXSOd6R+BuVtKudu2CU7PZhh5saNR4EfzmL95F03s/0nO0lnFn1HbGUkOocJ8B5gZ+DA==", + "output_file_mode": null, + "output_md5": "6446e24063bd14d74694e010b85e4c8b", + "output_path": "./python/hello-python.zip", + "output_sha": "bff9551d27784d38fc02eba7a2117d5237944797", + "output_sha256": "1ed61e4014f1f1df983126b7d60652fcff397d91e140d049cf3134b3e21a4930", + "output_sha512": "7db4922ca9928b122eac112885821748e77a47e06e56d2ae76ed8253b3d9861e6c68d47811fce62fde45d37b3fd273b4967167d476c65243a8709f01e6067e0c", + "output_size": 369, + "source": [], + "source_content": null, + "source_content_filename": null, + "source_dir": "./python/", + "source_file": null, + "type": "zip" + }, + "sensitive_values": { + "source": [] + } + } + ] + } + } + }, + "configuration": { + "provider_config": { + "archive": { + "name": "archive", + "full_name": "registry.terraform.io/hashicorp/archive" + }, + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": "~> 4.16", + "expressions": {} + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_config_key": "aws", + "expressions": { + "description": { + "constant_value": "AWS IAM Policy for managing aws lambda role" + }, + "name": { + "constant_value": "aws_iam_policy_for_terraform_aws_lambda_role" + }, + "path": { + "constant_value": "/" + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": [\n \"logs:CreateLogGroup\",\n \"logs:CreateLogStream\",\n \"logs:PutLogEvents\"\n ],\n \"Resource\": \"arn:aws:logs:*:*:*\",\n \"Effect\": \"Allow\"\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"lambda.amazonaws.com\"\n },\n \"Effect\": \"Allow\",\n \"Sid\": \"\"\n }\n ]\n}\n" + }, + "name": { + "constant_value": "Spacelift_Test_Lambda_Function_Role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.iam_policy_for_lambda.arn", + "aws_iam_policy.iam_policy_for_lambda" + ] + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.name", + "aws_iam_role.lambda_role" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_config_key": "aws", + "expressions": { + "filename": { + "references": [ + "path.module" + ] + }, + "function_name": { + "constant_value": "Spacelift_Test_Lambda_Function" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.arn", + "aws_iam_role.lambda_role" + ] + }, + "runtime": { + "constant_value": "python3.8" + } + }, + "schema_version": 0, + "depends_on": [ + "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role" + ] + }, + { + "address": "data.archive_file.zip_the_python_code", + "mode": "data", + "type": "archive_file", + "name": "zip_the_python_code", + "provider_config_key": "archive", + "expressions": { + "output_path": { + "references": [ + "path.module" + ] + }, + "source_dir": { + "references": [ + "path.module" + ] + }, + "type": { + "constant_value": "zip" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_policy.iam_policy_for_lambda", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "name" + ] + } + ], + "timestamp": "2024-03-05T06:55:02Z", + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/test/bad-test/bad-terraform.tf b/terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/test/bad-test/bad-terraform.tf new file mode 100644 index 00000000..4bc429c3 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/test/bad-test/bad-terraform.tf @@ -0,0 +1,80 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_iam_role" "lambda_role" { +name = "Spacelift_Test_Lambda_Function_Role" +assume_role_policy = < 4.16", + "expressions": {} + } + }, + "root_module": { + "resources": [ + { + "address": "aws_iam_policy.iam_policy_for_lambda", + "mode": "managed", + "type": "aws_iam_policy", + "name": "iam_policy_for_lambda", + "provider_config_key": "aws", + "expressions": { + "description": { + "constant_value": "AWS IAM Policy for managing aws lambda role" + }, + "name": { + "constant_value": "aws_iam_policy_for_terraform_aws_lambda_role" + }, + "path": { + "constant_value": "/" + }, + "policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": [\n \"logs:CreateLogGroup\",\n \"logs:CreateLogStream\",\n \"logs:PutLogEvents\"\n ],\n \"Resource\": \"arn:aws:logs:*:*:*\",\n \"Effect\": \"Allow\"\n }\n ]\n}\n" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role.lambda_role", + "mode": "managed", + "type": "aws_iam_role", + "name": "lambda_role", + "provider_config_key": "aws", + "expressions": { + "assume_role_policy": { + "constant_value": "{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Action\": \"sts:AssumeRole\",\n \"Principal\": {\n \"Service\": \"lambda.amazonaws.com\"\n },\n \"Effect\": \"Allow\",\n \"Sid\": \"\"\n }\n ]\n}\n" + }, + "name": { + "constant_value": "Spacelift_Test_Lambda_Function_Role" + } + }, + "schema_version": 0 + }, + { + "address": "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role", + "mode": "managed", + "type": "aws_iam_role_policy_attachment", + "name": "attach_iam_policy_to_iam_role", + "provider_config_key": "aws", + "expressions": { + "policy_arn": { + "references": [ + "aws_iam_policy.iam_policy_for_lambda.arn", + "aws_iam_policy.iam_policy_for_lambda" + ] + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.name", + "aws_iam_role.lambda_role" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_lambda_function.terraform_lambda_func", + "mode": "managed", + "type": "aws_lambda_function", + "name": "terraform_lambda_func", + "provider_config_key": "aws", + "expressions": { + "filename": { + "references": [ + "path.module" + ] + }, + "function_name": { + "constant_value": "Spacelift_Test_Lambda_Function" + }, + "handler": { + "constant_value": "index.lambda_handler" + }, + "role": { + "references": [ + "aws_iam_role.lambda_role.arn", + "aws_iam_role.lambda_role" + ] + }, + "runtime": { + "constant_value": "python3.8" + }, + "tracing_config": [ + { + "mode": { + "constant_value": "Active" + } + } + ] + }, + "schema_version": 0, + "depends_on": [ + "aws_iam_role_policy_attachment.attach_iam_policy_to_iam_role" + ] + }, + { + "address": "data.archive_file.zip_the_python_code", + "mode": "data", + "type": "archive_file", + "name": "zip_the_python_code", + "provider_config_key": "archive", + "expressions": { + "output_path": { + "references": [ + "path.module" + ] + }, + "source_dir": { + "references": [ + "path.module" + ] + }, + "type": { + "constant_value": "zip" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_policy.iam_policy_for_lambda", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "name" + ] + }, + { + "resource": "aws_iam_role.lambda_role", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-03-05T06:33:33Z", + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/test/good-test/good-terraform.tf b/terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/test/good-test/good-terraform.tf new file mode 100644 index 00000000..eee5e048 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-x-ray-tracing-enabled/test/good-test/good-terraform.tf @@ -0,0 +1,80 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4.16" + } + } + + required_version = ">= 1.2.0" +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_iam_role" "lambda_role" { +name = "Spacelift_Test_Lambda_Function_Role" +assume_role_policy = < Date: Thu, 25 Jul 2024 15:30:56 +0000 Subject: [PATCH 3/3] remove lambda policies that do not have bindings Signed-off-by: Chandan-DK --- .../check-dead-letter-queue-config/README.md | 69 --- .../check-dead-letter-queue-config.yaml | 24 - .../test/bad-test/bad-01.tf | 45 -- .../test/bad-test/bad-payload-01.json | 340 ----------- .../test/chainsaw-test.yaml | 61 -- .../test/good-test/good-01.tf | 48 -- .../test/good-test/good-payload-01.json | 361 ----------- .../check-lambda-public-access/README.md | 71 --- .../check-lambda-public-access.yaml | 24 - .../test/bad-test/bad-01.tf | 51 -- .../test/bad-test/bad-payload-01.json | 419 ------------- .../test/chainsaw-test.yaml | 61 -- .../test/good-test/good-01.tf | 51 -- .../test/good-test/good-payload-01.json | 419 ------------- .../check-source-arn-account/README.md | 69 --- .../check-source-arn-account.yaml | 23 - .../test/bad-test/bad-01.tf | 51 -- .../test/bad-test/bad-payload-01.json | 419 ------------- .../test/chainsaw-test.yaml | 61 -- .../test/good-test/good-01.tf | 67 -- .../test/good-test/good-payload-01.json | 577 ------------------ 21 files changed, 3311 deletions(-) delete mode 100644 terraform/plan/lambda-best-practices/check-dead-letter-queue-config/README.md delete mode 100644 terraform/plan/lambda-best-practices/check-dead-letter-queue-config/check-dead-letter-queue-config.yaml delete mode 100644 terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/bad-test/bad-01.tf delete mode 100644 terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/bad-test/bad-payload-01.json delete mode 100644 terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/chainsaw-test.yaml delete mode 100644 terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/good-test/good-01.tf delete mode 100644 terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/good-test/good-payload-01.json delete mode 100644 terraform/plan/lambda-best-practices/check-lambda-public-access/README.md delete mode 100644 terraform/plan/lambda-best-practices/check-lambda-public-access/check-lambda-public-access.yaml delete mode 100644 terraform/plan/lambda-best-practices/check-lambda-public-access/test/bad-test/bad-01.tf delete mode 100644 terraform/plan/lambda-best-practices/check-lambda-public-access/test/bad-test/bad-payload-01.json delete mode 100644 terraform/plan/lambda-best-practices/check-lambda-public-access/test/chainsaw-test.yaml delete mode 100644 terraform/plan/lambda-best-practices/check-lambda-public-access/test/good-test/good-01.tf delete mode 100644 terraform/plan/lambda-best-practices/check-lambda-public-access/test/good-test/good-payload-01.json delete mode 100644 terraform/plan/lambda-best-practices/check-source-arn-account/README.md delete mode 100644 terraform/plan/lambda-best-practices/check-source-arn-account/check-source-arn-account.yaml delete mode 100644 terraform/plan/lambda-best-practices/check-source-arn-account/test/bad-test/bad-01.tf delete mode 100644 terraform/plan/lambda-best-practices/check-source-arn-account/test/bad-test/bad-payload-01.json delete mode 100644 terraform/plan/lambda-best-practices/check-source-arn-account/test/chainsaw-test.yaml delete mode 100644 terraform/plan/lambda-best-practices/check-source-arn-account/test/good-test/good-01.tf delete mode 100644 terraform/plan/lambda-best-practices/check-source-arn-account/test/good-test/good-payload-01.json diff --git a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/README.md b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/README.md deleted file mode 100644 index ddff17ed..00000000 --- a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# Check Dead Letter Queue Config - -Dead Letter Queues (DLQs) allow Lambda functions to be set up with an SQS queue or SNS topic to capture information about failed asynchronous requests. When a Lambda function's processing fails and the request has exhausted its retries, the Lambda service can store details of the failed request to the configured DLQ. These failed messages can then be examined to determine the cause of failures. - -## Policy Details: - -- **Policy Name:** check-dead-letter-queue-config -- **Check Description:** This policy ensures that AWS Lambda function is configured for a Dead Letter Queue(DLQ) -- **Policy Category:** AWS Lambda Best Practices - -### Policy Validation Testing Instructions - -For testing this policy you will need to: -- Make sure you have `kyverno-json` installed on the machine -- Properly authenticate with AWS - -1. **Initialize Terraform:** - ```bash - terraform init - ``` - -2. **Create Binary Terraform Plan:** - ```bash - terraform plan -out tfplan.binary - ``` - -3. **Convert Binary to JSON Payload:** - ```bash - terraform show -json tfplan.binary | jq > payload.json - ``` - -4. **Test the Policy with Kyverno:** - ``` - kyverno-json scan --payload payload.json --policy policy.yaml - ``` - - a. **Test Policy Against Valid Payload:** - ``` - kyverno-json scan --payload test/good-test/good-payload-01.json --policy check-dead-letter-queue-config.yaml - ``` - - This produces the output: - ``` - Loading policies ... - Loading payload ... - Pre processing ... - Running ( evaluating 1 resource against 1 policy ) ... - - check-dead-letter-queue-config / check-dead-letter-queue-config / PASSED - Done - ``` - - b. **Test Against Invalid Payload:** - ``` - kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-dead-letter-queue-config.yaml - ``` - - This produces the output: - ``` - Loading policies ... - Loading payload ... - Pre processing ... - Running ( evaluating 1 resource against 1 policy ) ... - - check-dead-letter-queue-config / check-dead-letter-queue-config / FAILED - -> AWS Lambda function should be configured for a Dead Letter Queue(DLQ) - -> all[0].check.~.(planned_values.root_module.resources[?type=='aws_lambda_function'])[0].values.(dead_letter_config != `[]`): Invalid value: false: Expected value: true - Done - ``` - ---- \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/check-dead-letter-queue-config.yaml b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/check-dead-letter-queue-config.yaml deleted file mode 100644 index 3f10f69a..00000000 --- a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/check-dead-letter-queue-config.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: json.kyverno.io/v1alpha1 -kind: ValidatingPolicy -metadata: - name: check-dead-letter-queue-config - annotations: - policies.kyverno.io/title: check-dead-letter-queue-config - policies.kyverno.io/category: AWS Lambda Best Practices - policies.kyverno.io/severity: medium - policies.kyverno.io/description: >- - Ensure that AWS Lambda function is configured for a Dead Letter Queue(DLQ) -spec: - rules: - - name: check-dead-letter-queue-config - match: - all: - - (planned_values.root_module.resources[?type=='aws_lambda_function'] | length(@) > `0`): true - assert: - all: - - message: AWS Lambda function should be configured for a Dead Letter Queue(DLQ) - check: - ~.(planned_values.root_module.resources[?type=='aws_lambda_function']): - values: - (dead_letter_config != `[]`): true - diff --git a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/bad-test/bad-01.tf b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/bad-test/bad-01.tf deleted file mode 100644 index 90ef5ad6..00000000 --- a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/bad-test/bad-01.tf +++ /dev/null @@ -1,45 +0,0 @@ -terraform { - required_version = ">= 1.0" - - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 5.32" - } - } -} - -provider "aws" { - region = "us-west-2" -} - -resource "aws_lambda_function" "example" { - function_name = "example_lambda" - handler = "index.lambda_handler" - role = aws_iam_role.lambda_exec.arn - runtime = "python3.8" - filename = "" -} - -resource "aws_iam_role" "lambda_exec" { - name = "lambda_exec_role" - - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Action = "sts:AssumeRole" - Effect = "Allow" - Principal = { - Service = "lambda.amazonaws.com" - } - }, - ] - }) -} - -resource "aws_iam_role_policy_attachment" "lambda_exec_policy" { - role = aws_iam_role.lambda_exec.name - policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" -} - diff --git a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/bad-test/bad-payload-01.json b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/bad-test/bad-payload-01.json deleted file mode 100644 index 48e0ddd8..00000000 --- a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/bad-test/bad-payload-01.json +++ /dev/null @@ -1,340 +0,0 @@ -{ - "format_version": "1.2", - "terraform_version": "1.8.4", - "planned_values": { - "root_module": { - "resources": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", - "description": null, - "force_detach_policies": false, - "max_session_duration": 3600, - "name": "lambda_exec_role", - "path": "/", - "permissions_boundary": null, - "tags": null - }, - "sensitive_values": { - "inline_policy": [], - "managed_policy_arns": [], - "tags_all": {} - } - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - "role": "lambda_exec_role" - }, - "sensitive_values": {} - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "code_signing_config_arn": null, - "dead_letter_config": [], - "description": null, - "environment": [], - "file_system_config": [], - "filename": "", - "function_name": "example_lambda", - "handler": "index.lambda_handler", - "image_config": [], - "image_uri": null, - "kms_key_arn": null, - "layers": null, - "memory_size": 128, - "package_type": "Zip", - "publish": false, - "replace_security_groups_on_destroy": null, - "replacement_security_group_ids": null, - "reserved_concurrent_executions": -1, - "runtime": "python3.8", - "s3_bucket": null, - "s3_key": null, - "s3_object_version": null, - "skip_destroy": false, - "snap_start": [], - "tags": null, - "timeout": 3, - "timeouts": null, - "vpc_config": [] - }, - "sensitive_values": { - "architectures": [], - "dead_letter_config": [], - "environment": [], - "ephemeral_storage": [], - "file_system_config": [], - "image_config": [], - "logging_config": [], - "snap_start": [], - "tags_all": {}, - "tracing_config": [], - "vpc_config": [] - } - } - ] - } - }, - "resource_changes": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", - "description": null, - "force_detach_policies": false, - "max_session_duration": 3600, - "name": "lambda_exec_role", - "path": "/", - "permissions_boundary": null, - "tags": null - }, - "after_unknown": { - "arn": true, - "create_date": true, - "id": true, - "inline_policy": true, - "managed_policy_arns": true, - "name_prefix": true, - "tags_all": true, - "unique_id": true - }, - "before_sensitive": false, - "after_sensitive": { - "inline_policy": [], - "managed_policy_arns": [], - "tags_all": {} - } - } - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - "role": "lambda_exec_role" - }, - "after_unknown": { - "id": true - }, - "before_sensitive": false, - "after_sensitive": {} - } - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "code_signing_config_arn": null, - "dead_letter_config": [], - "description": null, - "environment": [], - "file_system_config": [], - "filename": "", - "function_name": "example_lambda", - "handler": "index.lambda_handler", - "image_config": [], - "image_uri": null, - "kms_key_arn": null, - "layers": null, - "memory_size": 128, - "package_type": "Zip", - "publish": false, - "replace_security_groups_on_destroy": null, - "replacement_security_group_ids": null, - "reserved_concurrent_executions": -1, - "runtime": "python3.8", - "s3_bucket": null, - "s3_key": null, - "s3_object_version": null, - "skip_destroy": false, - "snap_start": [], - "tags": null, - "timeout": 3, - "timeouts": null, - "vpc_config": [] - }, - "after_unknown": { - "architectures": true, - "arn": true, - "code_sha256": true, - "dead_letter_config": [], - "environment": [], - "ephemeral_storage": true, - "file_system_config": [], - "id": true, - "image_config": [], - "invoke_arn": true, - "last_modified": true, - "logging_config": true, - "qualified_arn": true, - "qualified_invoke_arn": true, - "role": true, - "signing_job_arn": true, - "signing_profile_version_arn": true, - "snap_start": [], - "source_code_hash": true, - "source_code_size": true, - "tags_all": true, - "tracing_config": true, - "version": true, - "vpc_config": [] - }, - "before_sensitive": false, - "after_sensitive": { - "architectures": [], - "dead_letter_config": [], - "environment": [], - "ephemeral_storage": [], - "file_system_config": [], - "image_config": [], - "logging_config": [], - "snap_start": [], - "tags_all": {}, - "tracing_config": [], - "vpc_config": [] - } - } - } - ], - "configuration": { - "provider_config": { - "aws": { - "name": "aws", - "full_name": "registry.terraform.io/hashicorp/aws", - "version_constraint": ">= 5.32.0", - "expressions": { - "region": { - "constant_value": "us-west-2" - } - } - } - }, - "root_module": { - "resources": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_config_key": "aws", - "expressions": { - "assume_role_policy": {}, - "name": { - "constant_value": "lambda_exec_role" - } - }, - "schema_version": 0 - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_config_key": "aws", - "expressions": { - "policy_arn": { - "constant_value": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - }, - "role": { - "references": [ - "aws_iam_role.lambda_exec.name", - "aws_iam_role.lambda_exec" - ] - } - }, - "schema_version": 0 - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_config_key": "aws", - "expressions": { - "filename": { - "constant_value": "" - }, - "function_name": { - "constant_value": "example_lambda" - }, - "handler": { - "constant_value": "index.lambda_handler" - }, - "role": { - "references": [ - "aws_iam_role.lambda_exec.arn", - "aws_iam_role.lambda_exec" - ] - }, - "runtime": { - "constant_value": "python3.8" - } - }, - "schema_version": 0 - } - ] - } - }, - "relevant_attributes": [ - { - "resource": "aws_iam_role.lambda_exec", - "attribute": [ - "name" - ] - }, - { - "resource": "aws_iam_role.lambda_exec", - "attribute": [ - "arn" - ] - } - ], - "timestamp": "2024-07-03T18:08:59Z", - "applyable": true, - "complete": true, - "errored": false -} diff --git a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/chainsaw-test.yaml b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/chainsaw-test.yaml deleted file mode 100644 index 6daeffb8..00000000 --- a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/chainsaw-test.yaml +++ /dev/null @@ -1,61 +0,0 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json -apiVersion: chainsaw.kyverno.io/v1alpha1 -kind: Test -metadata: - name: good-test-01 -spec: - steps: - - name: kyverno-json - try: - - script: - content: | - set -e - kyverno-json scan --payload ./good-test/good-payload-01.json --policy ../check-dead-letter-queue-config.yaml --output json - check: - ($error): ~ - (json_parse($stdout)): - - results: - - policy: - apiVersion: json.kyverno.io/v1alpha1 - kind: ValidatingPolicy - metadata: - name: check-dead-letter-queue-config - rules: - - rule: - name: check-dead-letter-queue-config - error: ~ - violations: ~ ---- -# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json -apiVersion: chainsaw.kyverno.io/v1alpha1 -kind: Test -metadata: - name: bad-test-01 -spec: - steps: - - name: kyverno-json - try: - - script: - content: | - set -e - kyverno-json scan --payload ./bad-test/bad-payload-01.json --policy ../check-dead-letter-queue-config.yaml --output json - check: - ($error): ~ - (json_parse($stdout)): - - results: - - policy: - apiVersion: json.kyverno.io/v1alpha1 - kind: ValidatingPolicy - metadata: - name: check-dead-letter-queue-config - rules: - - rule: - name: check-dead-letter-queue-config - error: ~ - violations: - - message: AWS Lambda function should be configured for a Dead Letter Queue(DLQ) - errors: - - type: FieldValueInvalid - value: false - detail: 'Expected value: true' - diff --git a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/good-test/good-01.tf b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/good-test/good-01.tf deleted file mode 100644 index e71b5080..00000000 --- a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/good-test/good-01.tf +++ /dev/null @@ -1,48 +0,0 @@ -terraform { - required_version = ">= 1.0" - - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 5.32" - } - } -} - -provider "aws" { - region = "us-west-2" -} - -resource "aws_lambda_function" "example" { - function_name = "example_lambda" - handler = "index.lambda_handler" - role = aws_iam_role.lambda_exec.arn - runtime = "python3.8" - filename = "" - dead_letter_config { - target_arn = "arn:aws:sqs:us-west-2:123456789012:example_queue" - } -} - -resource "aws_iam_role" "lambda_exec" { - name = "lambda_exec_role" - - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Action = "sts:AssumeRole" - Effect = "Allow" - Principal = { - Service = "lambda.amazonaws.com" - } - }, - ] - }) -} - -resource "aws_iam_role_policy_attachment" "lambda_exec_policy" { - role = aws_iam_role.lambda_exec.name - policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" -} - diff --git a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/good-test/good-payload-01.json b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/good-test/good-payload-01.json deleted file mode 100644 index ac24f302..00000000 --- a/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/good-test/good-payload-01.json +++ /dev/null @@ -1,361 +0,0 @@ -{ - "format_version": "1.2", - "terraform_version": "1.8.4", - "planned_values": { - "root_module": { - "resources": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", - "description": null, - "force_detach_policies": false, - "max_session_duration": 3600, - "name": "lambda_exec_role", - "path": "/", - "permissions_boundary": null, - "tags": null - }, - "sensitive_values": { - "inline_policy": [], - "managed_policy_arns": [], - "tags_all": {} - } - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - "role": "lambda_exec_role" - }, - "sensitive_values": {} - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "code_signing_config_arn": null, - "dead_letter_config": [ - { - "target_arn": "arn:aws:sqs:us-west-2:123456789012:example_queue" - } - ], - "description": null, - "environment": [], - "file_system_config": [], - "filename": "", - "function_name": "example_lambda", - "handler": "index.lambda_handler", - "image_config": [], - "image_uri": null, - "kms_key_arn": null, - "layers": null, - "memory_size": 128, - "package_type": "Zip", - "publish": false, - "replace_security_groups_on_destroy": null, - "replacement_security_group_ids": null, - "reserved_concurrent_executions": -1, - "runtime": "python3.8", - "s3_bucket": null, - "s3_key": null, - "s3_object_version": null, - "skip_destroy": false, - "snap_start": [], - "tags": null, - "timeout": 3, - "timeouts": null, - "vpc_config": [] - }, - "sensitive_values": { - "architectures": [], - "dead_letter_config": [ - {} - ], - "environment": [], - "ephemeral_storage": [], - "file_system_config": [], - "image_config": [], - "logging_config": [], - "snap_start": [], - "tags_all": {}, - "tracing_config": [], - "vpc_config": [] - } - } - ] - } - }, - "resource_changes": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", - "description": null, - "force_detach_policies": false, - "max_session_duration": 3600, - "name": "lambda_exec_role", - "path": "/", - "permissions_boundary": null, - "tags": null - }, - "after_unknown": { - "arn": true, - "create_date": true, - "id": true, - "inline_policy": true, - "managed_policy_arns": true, - "name_prefix": true, - "tags_all": true, - "unique_id": true - }, - "before_sensitive": false, - "after_sensitive": { - "inline_policy": [], - "managed_policy_arns": [], - "tags_all": {} - } - } - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - "role": "lambda_exec_role" - }, - "after_unknown": { - "id": true - }, - "before_sensitive": false, - "after_sensitive": {} - } - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "code_signing_config_arn": null, - "dead_letter_config": [ - { - "target_arn": "arn:aws:sqs:us-west-2:123456789012:example_queue" - } - ], - "description": null, - "environment": [], - "file_system_config": [], - "filename": "", - "function_name": "example_lambda", - "handler": "index.lambda_handler", - "image_config": [], - "image_uri": null, - "kms_key_arn": null, - "layers": null, - "memory_size": 128, - "package_type": "Zip", - "publish": false, - "replace_security_groups_on_destroy": null, - "replacement_security_group_ids": null, - "reserved_concurrent_executions": -1, - "runtime": "python3.8", - "s3_bucket": null, - "s3_key": null, - "s3_object_version": null, - "skip_destroy": false, - "snap_start": [], - "tags": null, - "timeout": 3, - "timeouts": null, - "vpc_config": [] - }, - "after_unknown": { - "architectures": true, - "arn": true, - "code_sha256": true, - "dead_letter_config": [ - {} - ], - "environment": [], - "ephemeral_storage": true, - "file_system_config": [], - "id": true, - "image_config": [], - "invoke_arn": true, - "last_modified": true, - "logging_config": true, - "qualified_arn": true, - "qualified_invoke_arn": true, - "role": true, - "signing_job_arn": true, - "signing_profile_version_arn": true, - "snap_start": [], - "source_code_hash": true, - "source_code_size": true, - "tags_all": true, - "tracing_config": true, - "version": true, - "vpc_config": [] - }, - "before_sensitive": false, - "after_sensitive": { - "architectures": [], - "dead_letter_config": [ - {} - ], - "environment": [], - "ephemeral_storage": [], - "file_system_config": [], - "image_config": [], - "logging_config": [], - "snap_start": [], - "tags_all": {}, - "tracing_config": [], - "vpc_config": [] - } - } - } - ], - "configuration": { - "provider_config": { - "aws": { - "name": "aws", - "full_name": "registry.terraform.io/hashicorp/aws", - "version_constraint": ">= 5.32.0", - "expressions": { - "region": { - "constant_value": "us-west-2" - } - } - } - }, - "root_module": { - "resources": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_config_key": "aws", - "expressions": { - "assume_role_policy": {}, - "name": { - "constant_value": "lambda_exec_role" - } - }, - "schema_version": 0 - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_config_key": "aws", - "expressions": { - "policy_arn": { - "constant_value": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - }, - "role": { - "references": [ - "aws_iam_role.lambda_exec.name", - "aws_iam_role.lambda_exec" - ] - } - }, - "schema_version": 0 - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_config_key": "aws", - "expressions": { - "dead_letter_config": [ - { - "target_arn": { - "constant_value": "arn:aws:sqs:us-west-2:123456789012:example_queue" - } - } - ], - "filename": { - "constant_value": "" - }, - "function_name": { - "constant_value": "example_lambda" - }, - "handler": { - "constant_value": "index.lambda_handler" - }, - "role": { - "references": [ - "aws_iam_role.lambda_exec.arn", - "aws_iam_role.lambda_exec" - ] - }, - "runtime": { - "constant_value": "python3.8" - } - }, - "schema_version": 0 - } - ] - } - }, - "relevant_attributes": [ - { - "resource": "aws_iam_role.lambda_exec", - "attribute": [ - "name" - ] - }, - { - "resource": "aws_iam_role.lambda_exec", - "attribute": [ - "arn" - ] - } - ], - "timestamp": "2024-07-03T18:11:12Z", - "applyable": true, - "complete": true, - "errored": false -} diff --git a/terraform/plan/lambda-best-practices/check-lambda-public-access/README.md b/terraform/plan/lambda-best-practices/check-lambda-public-access/README.md deleted file mode 100644 index 9dd2807d..00000000 --- a/terraform/plan/lambda-best-practices/check-lambda-public-access/README.md +++ /dev/null @@ -1,71 +0,0 @@ -# Check Lambda Public Access - -Granting public access to AWS Lambda functions is not recommended for security reasons. Restricting public access can help you prevent unauthorized invocations, which could compromise your data or incur unwanted costs. - -To restrict access to your Lambda functions, specify the AWS account IDs or the Amazon Resource Names (ARNs) of the IAM users, roles, or services explicitly in the `principal` attribute instead of using `*`. This ensures that only trusted entities can invoke your Lambda functions, enhancing your security posture. - -## Policy Details: - -- **Policy Name:** check-lambda-public-access -- **Check Description:** This policy ensures that AWS Lambda function is not publicly accessible -- **Policy Category:** AWS Lambda Best Practices - -### Policy Validation Testing Instructions - -For testing this policy you will need to: -- Make sure you have `kyverno-json` installed on the machine -- Properly authenticate with AWS - -1. **Initialize Terraform:** - ```bash - terraform init - ``` - -2. **Create Binary Terraform Plan:** - ```bash - terraform plan -out tfplan.binary - ``` - -3. **Convert Binary to JSON Payload:** - ```bash - terraform show -json tfplan.binary | jq > payload.json - ``` - -4. **Test the Policy with Kyverno:** - ``` - kyverno-json scan --payload payload.json --policy policy.yaml - ``` - - a. **Test Policy Against Valid Payload:** - ``` - kyverno-json scan --payload test/good-test/good-payload-01.json --policy check-lambda-public-access.yaml - ``` - - This produces the output: - ``` - Loading policies ... - Loading payload ... - Pre processing ... - Running ( evaluating 1 resource against 1 policy ) ... - - check-lambda-public-access / check-lambda-public-access / PASSED - Done - ``` - - b. **Test Against Invalid Payload:** - ``` - kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-lambda-public-access.yaml - ``` - - This produces the output: - ``` - Loading policies ... - Loading payload ... - Pre processing ... - Running ( evaluating 1 resource against 1 policy ) ... - - check-lambda-public-access / check-lambda-public-access / FAILED - -> Principal must be set to a specific resource or user account and not '*' - -> all[0].check.~.(planned_values.root_module.resources[?type=='aws_lambda_permission'])[0].values.(principal != '*'): Invalid value: false: Expected value: true - Done - ``` - ---- \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-lambda-public-access/check-lambda-public-access.yaml b/terraform/plan/lambda-best-practices/check-lambda-public-access/check-lambda-public-access.yaml deleted file mode 100644 index b6681f27..00000000 --- a/terraform/plan/lambda-best-practices/check-lambda-public-access/check-lambda-public-access.yaml +++ /dev/null @@ -1,24 +0,0 @@ -apiVersion: json.kyverno.io/v1alpha1 -kind: ValidatingPolicy -metadata: - name: check-lambda-public-access - annotations: - policies.kyverno.io/title: check-lambda-public-access - policies.kyverno.io/category: AWS Lambda Best Practices - policies.kyverno.io/severity: medium - policies.kyverno.io/description: >- - This policy ensures that AWS Lambda function is not publicly accessible -spec: - rules: - - name: check-lambda-public-access - match: - all: - - (planned_values.root_module.resources[?type=='aws_lambda_function'] | length(@) > `0`): true - assert: - all: - - message: Principal must be set to a specific resource or user account and not '*' - check: - ~.(planned_values.root_module.resources[?type=='aws_lambda_permission']): - values: - (principal != '*'): true - diff --git a/terraform/plan/lambda-best-practices/check-lambda-public-access/test/bad-test/bad-01.tf b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/bad-test/bad-01.tf deleted file mode 100644 index cde0647c..00000000 --- a/terraform/plan/lambda-best-practices/check-lambda-public-access/test/bad-test/bad-01.tf +++ /dev/null @@ -1,51 +0,0 @@ -terraform { - required_version = ">= 1.0" - - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 5.32" - } - } -} - -provider "aws" { - region = "us-west-2" -} - -resource "aws_lambda_function" "example" { - function_name = "example_lambda" - handler = "index.lambda_handler" - role = aws_iam_role.lambda_exec.arn - runtime = "python3.8" - filename = "" -} - -resource "aws_lambda_permission" "example_permission" { - action = "lambda:InvokeFunction" - function_name = aws_lambda_function.example.function_name - principal = "*" -} - -resource "aws_iam_role" "lambda_exec" { - name = "lambda_exec_role" - - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Action = "sts:AssumeRole" - Effect = "Allow" - Principal = { - Service = "lambda.amazonaws.com" - } - }, - ] - }) -} - -resource "aws_iam_role_policy_attachment" "lambda_exec_policy" { - role = aws_iam_role.lambda_exec.name - policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" -} - diff --git a/terraform/plan/lambda-best-practices/check-lambda-public-access/test/bad-test/bad-payload-01.json b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/bad-test/bad-payload-01.json deleted file mode 100644 index d44f93bc..00000000 --- a/terraform/plan/lambda-best-practices/check-lambda-public-access/test/bad-test/bad-payload-01.json +++ /dev/null @@ -1,419 +0,0 @@ -{ - "format_version": "1.2", - "terraform_version": "1.8.4", - "planned_values": { - "root_module": { - "resources": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", - "description": null, - "force_detach_policies": false, - "max_session_duration": 3600, - "name": "lambda_exec_role", - "path": "/", - "permissions_boundary": null, - "tags": null - }, - "sensitive_values": { - "inline_policy": [], - "managed_policy_arns": [], - "tags_all": {} - } - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - "role": "lambda_exec_role" - }, - "sensitive_values": {} - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "code_signing_config_arn": null, - "dead_letter_config": [], - "description": null, - "environment": [], - "file_system_config": [], - "filename": "", - "function_name": "example_lambda", - "handler": "index.lambda_handler", - "image_config": [], - "image_uri": null, - "kms_key_arn": null, - "layers": null, - "memory_size": 128, - "package_type": "Zip", - "publish": false, - "replace_security_groups_on_destroy": null, - "replacement_security_group_ids": null, - "reserved_concurrent_executions": -1, - "runtime": "python3.8", - "s3_bucket": null, - "s3_key": null, - "s3_object_version": null, - "skip_destroy": false, - "snap_start": [], - "tags": null, - "timeout": 3, - "timeouts": null, - "vpc_config": [] - }, - "sensitive_values": { - "architectures": [], - "dead_letter_config": [], - "environment": [], - "ephemeral_storage": [], - "file_system_config": [], - "image_config": [], - "logging_config": [], - "snap_start": [], - "tags_all": {}, - "tracing_config": [], - "vpc_config": [] - } - }, - { - "address": "aws_lambda_permission.example_permission", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "action": "lambda:InvokeFunction", - "event_source_token": null, - "function_name": "example_lambda", - "function_url_auth_type": null, - "principal": "*", - "principal_org_id": null, - "qualifier": null, - "source_account": null, - "source_arn": null - }, - "sensitive_values": {} - } - ] - } - }, - "resource_changes": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", - "description": null, - "force_detach_policies": false, - "max_session_duration": 3600, - "name": "lambda_exec_role", - "path": "/", - "permissions_boundary": null, - "tags": null - }, - "after_unknown": { - "arn": true, - "create_date": true, - "id": true, - "inline_policy": true, - "managed_policy_arns": true, - "name_prefix": true, - "tags_all": true, - "unique_id": true - }, - "before_sensitive": false, - "after_sensitive": { - "inline_policy": [], - "managed_policy_arns": [], - "tags_all": {} - } - } - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - "role": "lambda_exec_role" - }, - "after_unknown": { - "id": true - }, - "before_sensitive": false, - "after_sensitive": {} - } - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "code_signing_config_arn": null, - "dead_letter_config": [], - "description": null, - "environment": [], - "file_system_config": [], - "filename": "", - "function_name": "example_lambda", - "handler": "index.lambda_handler", - "image_config": [], - "image_uri": null, - "kms_key_arn": null, - "layers": null, - "memory_size": 128, - "package_type": "Zip", - "publish": false, - "replace_security_groups_on_destroy": null, - "replacement_security_group_ids": null, - "reserved_concurrent_executions": -1, - "runtime": "python3.8", - "s3_bucket": null, - "s3_key": null, - "s3_object_version": null, - "skip_destroy": false, - "snap_start": [], - "tags": null, - "timeout": 3, - "timeouts": null, - "vpc_config": [] - }, - "after_unknown": { - "architectures": true, - "arn": true, - "code_sha256": true, - "dead_letter_config": [], - "environment": [], - "ephemeral_storage": true, - "file_system_config": [], - "id": true, - "image_config": [], - "invoke_arn": true, - "last_modified": true, - "logging_config": true, - "qualified_arn": true, - "qualified_invoke_arn": true, - "role": true, - "signing_job_arn": true, - "signing_profile_version_arn": true, - "snap_start": [], - "source_code_hash": true, - "source_code_size": true, - "tags_all": true, - "tracing_config": true, - "version": true, - "vpc_config": [] - }, - "before_sensitive": false, - "after_sensitive": { - "architectures": [], - "dead_letter_config": [], - "environment": [], - "ephemeral_storage": [], - "file_system_config": [], - "image_config": [], - "logging_config": [], - "snap_start": [], - "tags_all": {}, - "tracing_config": [], - "vpc_config": [] - } - } - }, - { - "address": "aws_lambda_permission.example_permission", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "action": "lambda:InvokeFunction", - "event_source_token": null, - "function_name": "example_lambda", - "function_url_auth_type": null, - "principal": "*", - "principal_org_id": null, - "qualifier": null, - "source_account": null, - "source_arn": null - }, - "after_unknown": { - "id": true, - "statement_id": true, - "statement_id_prefix": true - }, - "before_sensitive": false, - "after_sensitive": {} - } - } - ], - "configuration": { - "provider_config": { - "aws": { - "name": "aws", - "full_name": "registry.terraform.io/hashicorp/aws", - "version_constraint": "\u003e= 5.32.0", - "expressions": { - "region": { - "constant_value": "us-west-2" - } - } - } - }, - "root_module": { - "resources": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_config_key": "aws", - "expressions": { - "assume_role_policy": {}, - "name": { - "constant_value": "lambda_exec_role" - } - }, - "schema_version": 0 - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_config_key": "aws", - "expressions": { - "policy_arn": { - "constant_value": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - }, - "role": { - "references": [ - "aws_iam_role.lambda_exec.name", - "aws_iam_role.lambda_exec" - ] - } - }, - "schema_version": 0 - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_config_key": "aws", - "expressions": { - "filename": { - "constant_value": "" - }, - "function_name": { - "constant_value": "example_lambda" - }, - "handler": { - "constant_value": "index.lambda_handler" - }, - "role": { - "references": [ - "aws_iam_role.lambda_exec.arn", - "aws_iam_role.lambda_exec" - ] - }, - "runtime": { - "constant_value": "python3.8" - } - }, - "schema_version": 0 - }, - { - "address": "aws_lambda_permission.example_permission", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission", - "provider_config_key": "aws", - "expressions": { - "action": { - "constant_value": "lambda:InvokeFunction" - }, - "function_name": { - "references": [ - "aws_lambda_function.example.function_name", - "aws_lambda_function.example" - ] - }, - "principal": { - "constant_value": "*" - } - }, - "schema_version": 0 - } - ] - } - }, - "relevant_attributes": [ - { - "resource": "aws_iam_role.lambda_exec", - "attribute": [ - "name" - ] - }, - { - "resource": "aws_iam_role.lambda_exec", - "attribute": [ - "arn" - ] - }, - { - "resource": "aws_lambda_function.example", - "attribute": [ - "function_name" - ] - } - ], - "timestamp": "2024-06-23T15:30:55Z", - "applyable": true, - "complete": true, - "errored": false -} \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-lambda-public-access/test/chainsaw-test.yaml b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/chainsaw-test.yaml deleted file mode 100644 index 6927b84e..00000000 --- a/terraform/plan/lambda-best-practices/check-lambda-public-access/test/chainsaw-test.yaml +++ /dev/null @@ -1,61 +0,0 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json -apiVersion: chainsaw.kyverno.io/v1alpha1 -kind: Test -metadata: - name: good-test-01 -spec: - steps: - - name: kyverno-json - try: - - script: - content: | - set -e - kyverno-json scan --payload ./good-test/good-payload-01.json --policy ../check-lambda-public-access.yaml --output json - check: - ($error): ~ - (json_parse($stdout)): - - results: - - policy: - apiVersion: json.kyverno.io/v1alpha1 - kind: ValidatingPolicy - metadata: - name: check-lambda-public-access - rules: - - rule: - name: check-lambda-public-access - error: ~ - violations: ~ ---- -# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json -apiVersion: chainsaw.kyverno.io/v1alpha1 -kind: Test -metadata: - name: bad-test-01 -spec: - steps: - - name: kyverno-json - try: - - script: - content: | - set -e - kyverno-json scan --payload ./bad-test/bad-payload-01.json --policy ../check-lambda-public-access.yaml --output json - check: - ($error): ~ - (json_parse($stdout)): - - results: - - policy: - apiVersion: json.kyverno.io/v1alpha1 - kind: ValidatingPolicy - metadata: - name: check-lambda-public-access - rules: - - rule: - name: check-lambda-public-access - error: ~ - violations: - - message: "Principal must be set to a specific resource or user account and not '*'" - errors: - - type: FieldValueInvalid - value: false - detail: 'Expected value: true' - diff --git a/terraform/plan/lambda-best-practices/check-lambda-public-access/test/good-test/good-01.tf b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/good-test/good-01.tf deleted file mode 100644 index 18586e8c..00000000 --- a/terraform/plan/lambda-best-practices/check-lambda-public-access/test/good-test/good-01.tf +++ /dev/null @@ -1,51 +0,0 @@ -terraform { - required_version = ">= 1.0" - - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 5.32" - } - } -} - -provider "aws" { - region = "us-west-2" -} - -resource "aws_lambda_function" "example" { - function_name = "example_lambda" - handler = "index.lambda_handler" - role = aws_iam_role.lambda_exec.arn - runtime = "python3.8" - filename = "" -} - -resource "aws_lambda_permission" "example_permission" { - action = "lambda:InvokeFunction" - function_name = aws_lambda_function.example.function_name - principal = "events.amazonaws.com" -} - -resource "aws_iam_role" "lambda_exec" { - name = "lambda_exec_role" - - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Action = "sts:AssumeRole" - Effect = "Allow" - Principal = { - Service = "lambda.amazonaws.com" - } - }, - ] - }) -} - -resource "aws_iam_role_policy_attachment" "lambda_exec_policy" { - role = aws_iam_role.lambda_exec.name - policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" -} - diff --git a/terraform/plan/lambda-best-practices/check-lambda-public-access/test/good-test/good-payload-01.json b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/good-test/good-payload-01.json deleted file mode 100644 index 96beb2fd..00000000 --- a/terraform/plan/lambda-best-practices/check-lambda-public-access/test/good-test/good-payload-01.json +++ /dev/null @@ -1,419 +0,0 @@ -{ - "format_version": "1.2", - "terraform_version": "1.8.4", - "planned_values": { - "root_module": { - "resources": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", - "description": null, - "force_detach_policies": false, - "max_session_duration": 3600, - "name": "lambda_exec_role", - "path": "/", - "permissions_boundary": null, - "tags": null - }, - "sensitive_values": { - "inline_policy": [], - "managed_policy_arns": [], - "tags_all": {} - } - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - "role": "lambda_exec_role" - }, - "sensitive_values": {} - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "code_signing_config_arn": null, - "dead_letter_config": [], - "description": null, - "environment": [], - "file_system_config": [], - "filename": "", - "function_name": "example_lambda", - "handler": "index.lambda_handler", - "image_config": [], - "image_uri": null, - "kms_key_arn": null, - "layers": null, - "memory_size": 128, - "package_type": "Zip", - "publish": false, - "replace_security_groups_on_destroy": null, - "replacement_security_group_ids": null, - "reserved_concurrent_executions": -1, - "runtime": "python3.8", - "s3_bucket": null, - "s3_key": null, - "s3_object_version": null, - "skip_destroy": false, - "snap_start": [], - "tags": null, - "timeout": 3, - "timeouts": null, - "vpc_config": [] - }, - "sensitive_values": { - "architectures": [], - "dead_letter_config": [], - "environment": [], - "ephemeral_storage": [], - "file_system_config": [], - "image_config": [], - "logging_config": [], - "snap_start": [], - "tags_all": {}, - "tracing_config": [], - "vpc_config": [] - } - }, - { - "address": "aws_lambda_permission.example_permission", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "action": "lambda:InvokeFunction", - "event_source_token": null, - "function_name": "example_lambda", - "function_url_auth_type": null, - "principal": "events.amazonaws.com", - "principal_org_id": null, - "qualifier": null, - "source_account": null, - "source_arn": null - }, - "sensitive_values": {} - } - ] - } - }, - "resource_changes": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", - "description": null, - "force_detach_policies": false, - "max_session_duration": 3600, - "name": "lambda_exec_role", - "path": "/", - "permissions_boundary": null, - "tags": null - }, - "after_unknown": { - "arn": true, - "create_date": true, - "id": true, - "inline_policy": true, - "managed_policy_arns": true, - "name_prefix": true, - "tags_all": true, - "unique_id": true - }, - "before_sensitive": false, - "after_sensitive": { - "inline_policy": [], - "managed_policy_arns": [], - "tags_all": {} - } - } - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - "role": "lambda_exec_role" - }, - "after_unknown": { - "id": true - }, - "before_sensitive": false, - "after_sensitive": {} - } - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "code_signing_config_arn": null, - "dead_letter_config": [], - "description": null, - "environment": [], - "file_system_config": [], - "filename": "", - "function_name": "example_lambda", - "handler": "index.lambda_handler", - "image_config": [], - "image_uri": null, - "kms_key_arn": null, - "layers": null, - "memory_size": 128, - "package_type": "Zip", - "publish": false, - "replace_security_groups_on_destroy": null, - "replacement_security_group_ids": null, - "reserved_concurrent_executions": -1, - "runtime": "python3.8", - "s3_bucket": null, - "s3_key": null, - "s3_object_version": null, - "skip_destroy": false, - "snap_start": [], - "tags": null, - "timeout": 3, - "timeouts": null, - "vpc_config": [] - }, - "after_unknown": { - "architectures": true, - "arn": true, - "code_sha256": true, - "dead_letter_config": [], - "environment": [], - "ephemeral_storage": true, - "file_system_config": [], - "id": true, - "image_config": [], - "invoke_arn": true, - "last_modified": true, - "logging_config": true, - "qualified_arn": true, - "qualified_invoke_arn": true, - "role": true, - "signing_job_arn": true, - "signing_profile_version_arn": true, - "snap_start": [], - "source_code_hash": true, - "source_code_size": true, - "tags_all": true, - "tracing_config": true, - "version": true, - "vpc_config": [] - }, - "before_sensitive": false, - "after_sensitive": { - "architectures": [], - "dead_letter_config": [], - "environment": [], - "ephemeral_storage": [], - "file_system_config": [], - "image_config": [], - "logging_config": [], - "snap_start": [], - "tags_all": {}, - "tracing_config": [], - "vpc_config": [] - } - } - }, - { - "address": "aws_lambda_permission.example_permission", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "action": "lambda:InvokeFunction", - "event_source_token": null, - "function_name": "example_lambda", - "function_url_auth_type": null, - "principal": "events.amazonaws.com", - "principal_org_id": null, - "qualifier": null, - "source_account": null, - "source_arn": null - }, - "after_unknown": { - "id": true, - "statement_id": true, - "statement_id_prefix": true - }, - "before_sensitive": false, - "after_sensitive": {} - } - } - ], - "configuration": { - "provider_config": { - "aws": { - "name": "aws", - "full_name": "registry.terraform.io/hashicorp/aws", - "version_constraint": "\u003e= 5.32.0", - "expressions": { - "region": { - "constant_value": "us-west-2" - } - } - } - }, - "root_module": { - "resources": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_config_key": "aws", - "expressions": { - "assume_role_policy": {}, - "name": { - "constant_value": "lambda_exec_role" - } - }, - "schema_version": 0 - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_config_key": "aws", - "expressions": { - "policy_arn": { - "constant_value": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - }, - "role": { - "references": [ - "aws_iam_role.lambda_exec.name", - "aws_iam_role.lambda_exec" - ] - } - }, - "schema_version": 0 - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_config_key": "aws", - "expressions": { - "filename": { - "constant_value": "" - }, - "function_name": { - "constant_value": "example_lambda" - }, - "handler": { - "constant_value": "index.lambda_handler" - }, - "role": { - "references": [ - "aws_iam_role.lambda_exec.arn", - "aws_iam_role.lambda_exec" - ] - }, - "runtime": { - "constant_value": "python3.8" - } - }, - "schema_version": 0 - }, - { - "address": "aws_lambda_permission.example_permission", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission", - "provider_config_key": "aws", - "expressions": { - "action": { - "constant_value": "lambda:InvokeFunction" - }, - "function_name": { - "references": [ - "aws_lambda_function.example.function_name", - "aws_lambda_function.example" - ] - }, - "principal": { - "constant_value": "events.amazonaws.com" - } - }, - "schema_version": 0 - } - ] - } - }, - "relevant_attributes": [ - { - "resource": "aws_iam_role.lambda_exec", - "attribute": [ - "name" - ] - }, - { - "resource": "aws_iam_role.lambda_exec", - "attribute": [ - "arn" - ] - }, - { - "resource": "aws_lambda_function.example", - "attribute": [ - "function_name" - ] - } - ], - "timestamp": "2024-06-23T15:31:50Z", - "applyable": true, - "complete": true, - "errored": false -} \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-source-arn-account/README.md b/terraform/plan/lambda-best-practices/check-source-arn-account/README.md deleted file mode 100644 index 01a96a0f..00000000 --- a/terraform/plan/lambda-best-practices/check-source-arn-account/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# Check Source Arn Account - -Granting unrestricted access to Lambda functions from other AWS services can compromise the security of your system. To mitigate this risk, it is essential to restrict access by using the `source_arn` or `source_account` parameters. By doing so, you ensure that access is only allowed from specific resources and accounts, respectively, thereby enhancing the security of your applications and data within AWS. - -## Policy Details: - -- **Policy Name:** check-source-arn-account -- **Check Description:** This policy ensures that AWS Lambda function permissions delegated to AWS services are limited by SourceArn or SourceAccount -- **Policy Category:** AWS Lambda Best Practices - -### Policy Validation Testing Instructions - -For testing this policy you will need to: -- Make sure you have `kyverno-json` installed on the machine -- Properly authenticate with AWS - -1. **Initialize Terraform:** - ```bash - terraform init - ``` - -2. **Create Binary Terraform Plan:** - ```bash - terraform plan -out tfplan.binary - ``` - -3. **Convert Binary to JSON Payload:** - ```bash - terraform show -json tfplan.binary | jq > payload.json - ``` - -4. **Test the Policy with Kyverno:** - ``` - kyverno-json scan --payload payload.json --policy policy.yaml - ``` - - a. **Test Policy Against Valid Payload:** - ``` - kyverno-json scan --payload test/good-test/good-payload-01.json --policy check-source-arn-account.yaml - ``` - - This produces the output: - ``` - Loading policies ... - Loading payload ... - Pre processing ... - Running ( evaluating 1 resource against 1 policy ) ... - - check-source-arn-account / check-source-arn-account / PASSED - Done - ``` - - b. **Test Against Invalid Payload:** - ``` - kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-source-arn-account.yaml - ``` - - This produces the output: - ``` - Loading policies ... - Loading payload ... - Pre processing ... - Running ( evaluating 1 resource against 1 policy ) ... - - check-source-arn-account / check-source-arn-account / FAILED - -> AWS Lambda function permissions delegated to AWS services should be limited by SourceArn or SourceAccount - -> all[0].check.~.(planned_values.root_module.resources[?type=='aws_lambda_permission'].values[?ends_with(principal, '.amazonaws.com')])[0].(!source_arn == `true` && !source_account == `true`): Invalid value: true: Expected value: false - Done - ``` - ---- \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-source-arn-account/check-source-arn-account.yaml b/terraform/plan/lambda-best-practices/check-source-arn-account/check-source-arn-account.yaml deleted file mode 100644 index ee436eb4..00000000 --- a/terraform/plan/lambda-best-practices/check-source-arn-account/check-source-arn-account.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: json.kyverno.io/v1alpha1 -kind: ValidatingPolicy -metadata: - name: check-source-arn-account - annotations: - policies.kyverno.io/title: check-source-arn-account - policies.kyverno.io/category: AWS Lambda Best Practices - policies.kyverno.io/severity: medium - policies.kyverno.io/description: >- - This policy ensures that AWS Lambda function permissions delegated to AWS services are limited by SourceArn or SourceAccount -spec: - rules: - - name: check-source-arn-account - match: - all: - - (planned_values.root_module.resources[?type=='aws_lambda_permission'].values[?ends_with(principal, '.amazonaws.com')] | length(@) > `0`): true - assert: - all: - - message: AWS Lambda function permissions delegated to AWS services should be limited by SourceArn or SourceAccount - check: - ~.(planned_values.root_module.resources[?type=='aws_lambda_permission'].values[?ends_with(principal, '.amazonaws.com')]): - (!source_arn == `true` && !source_account == `true`): false - diff --git a/terraform/plan/lambda-best-practices/check-source-arn-account/test/bad-test/bad-01.tf b/terraform/plan/lambda-best-practices/check-source-arn-account/test/bad-test/bad-01.tf deleted file mode 100644 index 4e2c4868..00000000 --- a/terraform/plan/lambda-best-practices/check-source-arn-account/test/bad-test/bad-01.tf +++ /dev/null @@ -1,51 +0,0 @@ -terraform { - required_version = ">= 1.0" - - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 5.32" - } - } -} - -provider "aws" { - region = "us-west-2" -} - -resource "aws_lambda_function" "example" { - function_name = "example_lambda" - handler = "index.lambda_handler" - role = aws_iam_role.lambda_exec.arn - runtime = "python3.8" - filename = "" -} - -resource "aws_lambda_permission" "example_permission" { - action = "lambda:InvokeFunction" - function_name = aws_lambda_function.example.function_name - principal = "apigateway.amazonaws.com" -} - -resource "aws_iam_role" "lambda_exec" { - name = "lambda_exec_role" - - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Action = "sts:AssumeRole" - Effect = "Allow" - Principal = { - Service = "lambda.amazonaws.com" - } - }, - ] - }) -} - -resource "aws_iam_role_policy_attachment" "lambda_exec_policy" { - role = aws_iam_role.lambda_exec.name - policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" -} - diff --git a/terraform/plan/lambda-best-practices/check-source-arn-account/test/bad-test/bad-payload-01.json b/terraform/plan/lambda-best-practices/check-source-arn-account/test/bad-test/bad-payload-01.json deleted file mode 100644 index be7a575e..00000000 --- a/terraform/plan/lambda-best-practices/check-source-arn-account/test/bad-test/bad-payload-01.json +++ /dev/null @@ -1,419 +0,0 @@ -{ - "format_version": "1.2", - "terraform_version": "1.8.4", - "planned_values": { - "root_module": { - "resources": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", - "description": null, - "force_detach_policies": false, - "max_session_duration": 3600, - "name": "lambda_exec_role", - "path": "/", - "permissions_boundary": null, - "tags": null - }, - "sensitive_values": { - "inline_policy": [], - "managed_policy_arns": [], - "tags_all": {} - } - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - "role": "lambda_exec_role" - }, - "sensitive_values": {} - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "code_signing_config_arn": null, - "dead_letter_config": [], - "description": null, - "environment": [], - "file_system_config": [], - "filename": "", - "function_name": "example_lambda", - "handler": "index.lambda_handler", - "image_config": [], - "image_uri": null, - "kms_key_arn": null, - "layers": null, - "memory_size": 128, - "package_type": "Zip", - "publish": false, - "replace_security_groups_on_destroy": null, - "replacement_security_group_ids": null, - "reserved_concurrent_executions": -1, - "runtime": "python3.8", - "s3_bucket": null, - "s3_key": null, - "s3_object_version": null, - "skip_destroy": false, - "snap_start": [], - "tags": null, - "timeout": 3, - "timeouts": null, - "vpc_config": [] - }, - "sensitive_values": { - "architectures": [], - "dead_letter_config": [], - "environment": [], - "ephemeral_storage": [], - "file_system_config": [], - "image_config": [], - "logging_config": [], - "snap_start": [], - "tags_all": {}, - "tracing_config": [], - "vpc_config": [] - } - }, - { - "address": "aws_lambda_permission.example_permission", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "action": "lambda:InvokeFunction", - "event_source_token": null, - "function_name": "example_lambda", - "function_url_auth_type": null, - "principal": "apigateway.amazonaws.com", - "principal_org_id": null, - "qualifier": null, - "source_account": null, - "source_arn": null - }, - "sensitive_values": {} - } - ] - } - }, - "resource_changes": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", - "description": null, - "force_detach_policies": false, - "max_session_duration": 3600, - "name": "lambda_exec_role", - "path": "/", - "permissions_boundary": null, - "tags": null - }, - "after_unknown": { - "arn": true, - "create_date": true, - "id": true, - "inline_policy": true, - "managed_policy_arns": true, - "name_prefix": true, - "tags_all": true, - "unique_id": true - }, - "before_sensitive": false, - "after_sensitive": { - "inline_policy": [], - "managed_policy_arns": [], - "tags_all": {} - } - } - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - "role": "lambda_exec_role" - }, - "after_unknown": { - "id": true - }, - "before_sensitive": false, - "after_sensitive": {} - } - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "code_signing_config_arn": null, - "dead_letter_config": [], - "description": null, - "environment": [], - "file_system_config": [], - "filename": "", - "function_name": "example_lambda", - "handler": "index.lambda_handler", - "image_config": [], - "image_uri": null, - "kms_key_arn": null, - "layers": null, - "memory_size": 128, - "package_type": "Zip", - "publish": false, - "replace_security_groups_on_destroy": null, - "replacement_security_group_ids": null, - "reserved_concurrent_executions": -1, - "runtime": "python3.8", - "s3_bucket": null, - "s3_key": null, - "s3_object_version": null, - "skip_destroy": false, - "snap_start": [], - "tags": null, - "timeout": 3, - "timeouts": null, - "vpc_config": [] - }, - "after_unknown": { - "architectures": true, - "arn": true, - "code_sha256": true, - "dead_letter_config": [], - "environment": [], - "ephemeral_storage": true, - "file_system_config": [], - "id": true, - "image_config": [], - "invoke_arn": true, - "last_modified": true, - "logging_config": true, - "qualified_arn": true, - "qualified_invoke_arn": true, - "role": true, - "signing_job_arn": true, - "signing_profile_version_arn": true, - "snap_start": [], - "source_code_hash": true, - "source_code_size": true, - "tags_all": true, - "tracing_config": true, - "version": true, - "vpc_config": [] - }, - "before_sensitive": false, - "after_sensitive": { - "architectures": [], - "dead_letter_config": [], - "environment": [], - "ephemeral_storage": [], - "file_system_config": [], - "image_config": [], - "logging_config": [], - "snap_start": [], - "tags_all": {}, - "tracing_config": [], - "vpc_config": [] - } - } - }, - { - "address": "aws_lambda_permission.example_permission", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "action": "lambda:InvokeFunction", - "event_source_token": null, - "function_name": "example_lambda", - "function_url_auth_type": null, - "principal": "apigateway.amazonaws.com", - "principal_org_id": null, - "qualifier": null, - "source_account": null, - "source_arn": null - }, - "after_unknown": { - "id": true, - "statement_id": true, - "statement_id_prefix": true - }, - "before_sensitive": false, - "after_sensitive": {} - } - } - ], - "configuration": { - "provider_config": { - "aws": { - "name": "aws", - "full_name": "registry.terraform.io/hashicorp/aws", - "version_constraint": ">= 5.32.0", - "expressions": { - "region": { - "constant_value": "us-west-2" - } - } - } - }, - "root_module": { - "resources": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_config_key": "aws", - "expressions": { - "assume_role_policy": {}, - "name": { - "constant_value": "lambda_exec_role" - } - }, - "schema_version": 0 - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_config_key": "aws", - "expressions": { - "policy_arn": { - "constant_value": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - }, - "role": { - "references": [ - "aws_iam_role.lambda_exec.name", - "aws_iam_role.lambda_exec" - ] - } - }, - "schema_version": 0 - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_config_key": "aws", - "expressions": { - "filename": { - "constant_value": "" - }, - "function_name": { - "constant_value": "example_lambda" - }, - "handler": { - "constant_value": "index.lambda_handler" - }, - "role": { - "references": [ - "aws_iam_role.lambda_exec.arn", - "aws_iam_role.lambda_exec" - ] - }, - "runtime": { - "constant_value": "python3.8" - } - }, - "schema_version": 0 - }, - { - "address": "aws_lambda_permission.example_permission", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission", - "provider_config_key": "aws", - "expressions": { - "action": { - "constant_value": "lambda:InvokeFunction" - }, - "function_name": { - "references": [ - "aws_lambda_function.example.function_name", - "aws_lambda_function.example" - ] - }, - "principal": { - "constant_value": "apigateway.amazonaws.com" - } - }, - "schema_version": 0 - } - ] - } - }, - "relevant_attributes": [ - { - "resource": "aws_iam_role.lambda_exec", - "attribute": [ - "name" - ] - }, - { - "resource": "aws_iam_role.lambda_exec", - "attribute": [ - "arn" - ] - }, - { - "resource": "aws_lambda_function.example", - "attribute": [ - "function_name" - ] - } - ], - "timestamp": "2024-07-04T18:30:59Z", - "applyable": true, - "complete": true, - "errored": false -} diff --git a/terraform/plan/lambda-best-practices/check-source-arn-account/test/chainsaw-test.yaml b/terraform/plan/lambda-best-practices/check-source-arn-account/test/chainsaw-test.yaml deleted file mode 100644 index b7cbcc06..00000000 --- a/terraform/plan/lambda-best-practices/check-source-arn-account/test/chainsaw-test.yaml +++ /dev/null @@ -1,61 +0,0 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json -apiVersion: chainsaw.kyverno.io/v1alpha1 -kind: Test -metadata: - name: good-test-01 -spec: - steps: - - name: kyverno-json - try: - - script: - content: | - set -e - kyverno-json scan --payload ./good-test/good-payload-01.json --policy ../check-source-arn-account.yaml --output json - check: - ($error): ~ - (json_parse($stdout)): - - results: - - policy: - apiVersion: json.kyverno.io/v1alpha1 - kind: ValidatingPolicy - metadata: - name: check-source-arn-account - rules: - - rule: - name: check-source-arn-account - error: ~ - violations: ~ ---- -# yaml-language-server: $schema=https://raw.githubusercontent.com/kyverno/chainsaw/main/.schemas/json/test-chainsaw-v1alpha1.json -apiVersion: chainsaw.kyverno.io/v1alpha1 -kind: Test -metadata: - name: bad-test-01 -spec: - steps: - - name: kyverno-json - try: - - script: - content: | - set -e - kyverno-json scan --payload ./bad-test/bad-payload-01.json --policy ../check-source-arn-account.yaml --output json - check: - ($error): ~ - (json_parse($stdout)): - - results: - - policy: - apiVersion: json.kyverno.io/v1alpha1 - kind: ValidatingPolicy - metadata: - name: check-source-arn-account - rules: - - rule: - name: check-source-arn-account - error: ~ - violations: - - message: AWS Lambda function permissions delegated to AWS services should be limited by SourceArn or SourceAccount - errors: - - type: FieldValueInvalid - value: true - detail: 'Expected value: false' - diff --git a/terraform/plan/lambda-best-practices/check-source-arn-account/test/good-test/good-01.tf b/terraform/plan/lambda-best-practices/check-source-arn-account/test/good-test/good-01.tf deleted file mode 100644 index b192ad6a..00000000 --- a/terraform/plan/lambda-best-practices/check-source-arn-account/test/good-test/good-01.tf +++ /dev/null @@ -1,67 +0,0 @@ -terraform { - required_version = ">= 1.0" - - required_providers { - aws = { - source = "hashicorp/aws" - version = ">= 5.32" - } - } -} - -provider "aws" { - region = "us-west-2" -} - -resource "aws_lambda_function" "example" { - function_name = "example_lambda" - handler = "index.lambda_handler" - role = aws_iam_role.lambda_exec.arn - runtime = "python3.8" - filename = "" -} - -resource "aws_lambda_permission" "example_permission" { - action = "lambda:InvokeFunction" - function_name = aws_lambda_function.example.function_name - principal = "s3.amazonaws.com" - source_arn = "arn:aws:s3:::example-bucket" -} - -resource "aws_lambda_permission" "example_permission_2" { - action = "lambda:InvokeFunction" - function_name = aws_lambda_function.example.function_name - principal = "s3.amazonaws.com" - source_account = "123456789012" -} - -resource "aws_lambda_permission" "example_permission_3" { - action = "lambda:InvokeFunction" - function_name = aws_lambda_function.example.function_name - principal = "s3.amazonaws.com" - source_arn = "arn:aws:s3:::example-bucket-2" - source_account = "123456789012" -} - -resource "aws_iam_role" "lambda_exec" { - name = "lambda_exec_role" - - assume_role_policy = jsonencode({ - Version = "2012-10-17" - Statement = [ - { - Action = "sts:AssumeRole" - Effect = "Allow" - Principal = { - Service = "lambda.amazonaws.com" - } - }, - ] - }) -} - -resource "aws_iam_role_policy_attachment" "lambda_exec_policy" { - role = aws_iam_role.lambda_exec.name - policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" -} - diff --git a/terraform/plan/lambda-best-practices/check-source-arn-account/test/good-test/good-payload-01.json b/terraform/plan/lambda-best-practices/check-source-arn-account/test/good-test/good-payload-01.json deleted file mode 100644 index 4d123f14..00000000 --- a/terraform/plan/lambda-best-practices/check-source-arn-account/test/good-test/good-payload-01.json +++ /dev/null @@ -1,577 +0,0 @@ -{ - "format_version": "1.2", - "terraform_version": "1.8.4", - "planned_values": { - "root_module": { - "resources": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", - "description": null, - "force_detach_policies": false, - "max_session_duration": 3600, - "name": "lambda_exec_role", - "path": "/", - "permissions_boundary": null, - "tags": null - }, - "sensitive_values": { - "inline_policy": [], - "managed_policy_arns": [], - "tags_all": {} - } - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - "role": "lambda_exec_role" - }, - "sensitive_values": {} - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "code_signing_config_arn": null, - "dead_letter_config": [], - "description": null, - "environment": [], - "file_system_config": [], - "filename": "", - "function_name": "example_lambda", - "handler": "index.lambda_handler", - "image_config": [], - "image_uri": null, - "kms_key_arn": null, - "layers": null, - "memory_size": 128, - "package_type": "Zip", - "publish": false, - "replace_security_groups_on_destroy": null, - "replacement_security_group_ids": null, - "reserved_concurrent_executions": -1, - "runtime": "python3.8", - "s3_bucket": null, - "s3_key": null, - "s3_object_version": null, - "skip_destroy": false, - "snap_start": [], - "tags": null, - "timeout": 3, - "timeouts": null, - "vpc_config": [] - }, - "sensitive_values": { - "architectures": [], - "dead_letter_config": [], - "environment": [], - "ephemeral_storage": [], - "file_system_config": [], - "image_config": [], - "logging_config": [], - "snap_start": [], - "tags_all": {}, - "tracing_config": [], - "vpc_config": [] - } - }, - { - "address": "aws_lambda_permission.example_permission", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "action": "lambda:InvokeFunction", - "event_source_token": null, - "function_name": "example_lambda", - "function_url_auth_type": null, - "principal": "s3.amazonaws.com", - "principal_org_id": null, - "qualifier": null, - "source_account": null, - "source_arn": "arn:aws:s3:::example-bucket" - }, - "sensitive_values": {} - }, - { - "address": "aws_lambda_permission.example_permission_2", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission_2", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "action": "lambda:InvokeFunction", - "event_source_token": null, - "function_name": "example_lambda", - "function_url_auth_type": null, - "principal": "s3.amazonaws.com", - "principal_org_id": null, - "qualifier": null, - "source_account": "123456789012", - "source_arn": null - }, - "sensitive_values": {} - }, - { - "address": "aws_lambda_permission.example_permission_3", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission_3", - "provider_name": "registry.terraform.io/hashicorp/aws", - "schema_version": 0, - "values": { - "action": "lambda:InvokeFunction", - "event_source_token": null, - "function_name": "example_lambda", - "function_url_auth_type": null, - "principal": "s3.amazonaws.com", - "principal_org_id": null, - "qualifier": null, - "source_account": "123456789012", - "source_arn": "arn:aws:s3:::example-bucket-2" - }, - "sensitive_values": {} - } - ] - } - }, - "resource_changes": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "assume_role_policy": "{\"Statement\":[{\"Action\":\"sts:AssumeRole\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"lambda.amazonaws.com\"}}],\"Version\":\"2012-10-17\"}", - "description": null, - "force_detach_policies": false, - "max_session_duration": 3600, - "name": "lambda_exec_role", - "path": "/", - "permissions_boundary": null, - "tags": null - }, - "after_unknown": { - "arn": true, - "create_date": true, - "id": true, - "inline_policy": true, - "managed_policy_arns": true, - "name_prefix": true, - "tags_all": true, - "unique_id": true - }, - "before_sensitive": false, - "after_sensitive": { - "inline_policy": [], - "managed_policy_arns": [], - "tags_all": {} - } - } - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "policy_arn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole", - "role": "lambda_exec_role" - }, - "after_unknown": { - "id": true - }, - "before_sensitive": false, - "after_sensitive": {} - } - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "code_signing_config_arn": null, - "dead_letter_config": [], - "description": null, - "environment": [], - "file_system_config": [], - "filename": "", - "function_name": "example_lambda", - "handler": "index.lambda_handler", - "image_config": [], - "image_uri": null, - "kms_key_arn": null, - "layers": null, - "memory_size": 128, - "package_type": "Zip", - "publish": false, - "replace_security_groups_on_destroy": null, - "replacement_security_group_ids": null, - "reserved_concurrent_executions": -1, - "runtime": "python3.8", - "s3_bucket": null, - "s3_key": null, - "s3_object_version": null, - "skip_destroy": false, - "snap_start": [], - "tags": null, - "timeout": 3, - "timeouts": null, - "vpc_config": [] - }, - "after_unknown": { - "architectures": true, - "arn": true, - "code_sha256": true, - "dead_letter_config": [], - "environment": [], - "ephemeral_storage": true, - "file_system_config": [], - "id": true, - "image_config": [], - "invoke_arn": true, - "last_modified": true, - "logging_config": true, - "qualified_arn": true, - "qualified_invoke_arn": true, - "role": true, - "signing_job_arn": true, - "signing_profile_version_arn": true, - "snap_start": [], - "source_code_hash": true, - "source_code_size": true, - "tags_all": true, - "tracing_config": true, - "version": true, - "vpc_config": [] - }, - "before_sensitive": false, - "after_sensitive": { - "architectures": [], - "dead_letter_config": [], - "environment": [], - "ephemeral_storage": [], - "file_system_config": [], - "image_config": [], - "logging_config": [], - "snap_start": [], - "tags_all": {}, - "tracing_config": [], - "vpc_config": [] - } - } - }, - { - "address": "aws_lambda_permission.example_permission", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "action": "lambda:InvokeFunction", - "event_source_token": null, - "function_name": "example_lambda", - "function_url_auth_type": null, - "principal": "s3.amazonaws.com", - "principal_org_id": null, - "qualifier": null, - "source_account": null, - "source_arn": "arn:aws:s3:::example-bucket" - }, - "after_unknown": { - "id": true, - "statement_id": true, - "statement_id_prefix": true - }, - "before_sensitive": false, - "after_sensitive": {} - } - }, - { - "address": "aws_lambda_permission.example_permission_2", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission_2", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "action": "lambda:InvokeFunction", - "event_source_token": null, - "function_name": "example_lambda", - "function_url_auth_type": null, - "principal": "s3.amazonaws.com", - "principal_org_id": null, - "qualifier": null, - "source_account": "123456789012", - "source_arn": null - }, - "after_unknown": { - "id": true, - "statement_id": true, - "statement_id_prefix": true - }, - "before_sensitive": false, - "after_sensitive": {} - } - }, - { - "address": "aws_lambda_permission.example_permission_3", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission_3", - "provider_name": "registry.terraform.io/hashicorp/aws", - "change": { - "actions": [ - "create" - ], - "before": null, - "after": { - "action": "lambda:InvokeFunction", - "event_source_token": null, - "function_name": "example_lambda", - "function_url_auth_type": null, - "principal": "s3.amazonaws.com", - "principal_org_id": null, - "qualifier": null, - "source_account": "123456789012", - "source_arn": "arn:aws:s3:::example-bucket-2" - }, - "after_unknown": { - "id": true, - "statement_id": true, - "statement_id_prefix": true - }, - "before_sensitive": false, - "after_sensitive": {} - } - } - ], - "configuration": { - "provider_config": { - "aws": { - "name": "aws", - "full_name": "registry.terraform.io/hashicorp/aws", - "version_constraint": ">= 5.32.0", - "expressions": { - "region": { - "constant_value": "us-west-2" - } - } - } - }, - "root_module": { - "resources": [ - { - "address": "aws_iam_role.lambda_exec", - "mode": "managed", - "type": "aws_iam_role", - "name": "lambda_exec", - "provider_config_key": "aws", - "expressions": { - "assume_role_policy": {}, - "name": { - "constant_value": "lambda_exec_role" - } - }, - "schema_version": 0 - }, - { - "address": "aws_iam_role_policy_attachment.lambda_exec_policy", - "mode": "managed", - "type": "aws_iam_role_policy_attachment", - "name": "lambda_exec_policy", - "provider_config_key": "aws", - "expressions": { - "policy_arn": { - "constant_value": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" - }, - "role": { - "references": [ - "aws_iam_role.lambda_exec.name", - "aws_iam_role.lambda_exec" - ] - } - }, - "schema_version": 0 - }, - { - "address": "aws_lambda_function.example", - "mode": "managed", - "type": "aws_lambda_function", - "name": "example", - "provider_config_key": "aws", - "expressions": { - "filename": { - "constant_value": "" - }, - "function_name": { - "constant_value": "example_lambda" - }, - "handler": { - "constant_value": "index.lambda_handler" - }, - "role": { - "references": [ - "aws_iam_role.lambda_exec.arn", - "aws_iam_role.lambda_exec" - ] - }, - "runtime": { - "constant_value": "python3.8" - } - }, - "schema_version": 0 - }, - { - "address": "aws_lambda_permission.example_permission", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission", - "provider_config_key": "aws", - "expressions": { - "action": { - "constant_value": "lambda:InvokeFunction" - }, - "function_name": { - "references": [ - "aws_lambda_function.example.function_name", - "aws_lambda_function.example" - ] - }, - "principal": { - "constant_value": "s3.amazonaws.com" - }, - "source_arn": { - "constant_value": "arn:aws:s3:::example-bucket" - } - }, - "schema_version": 0 - }, - { - "address": "aws_lambda_permission.example_permission_2", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission_2", - "provider_config_key": "aws", - "expressions": { - "action": { - "constant_value": "lambda:InvokeFunction" - }, - "function_name": { - "references": [ - "aws_lambda_function.example.function_name", - "aws_lambda_function.example" - ] - }, - "principal": { - "constant_value": "s3.amazonaws.com" - }, - "source_account": { - "constant_value": "123456789012" - } - }, - "schema_version": 0 - }, - { - "address": "aws_lambda_permission.example_permission_3", - "mode": "managed", - "type": "aws_lambda_permission", - "name": "example_permission_3", - "provider_config_key": "aws", - "expressions": { - "action": { - "constant_value": "lambda:InvokeFunction" - }, - "function_name": { - "references": [ - "aws_lambda_function.example.function_name", - "aws_lambda_function.example" - ] - }, - "principal": { - "constant_value": "s3.amazonaws.com" - }, - "source_account": { - "constant_value": "123456789012" - }, - "source_arn": { - "constant_value": "arn:aws:s3:::example-bucket-2" - } - }, - "schema_version": 0 - } - ] - } - }, - "relevant_attributes": [ - { - "resource": "aws_iam_role.lambda_exec", - "attribute": [ - "name" - ] - }, - { - "resource": "aws_iam_role.lambda_exec", - "attribute": [ - "arn" - ] - }, - { - "resource": "aws_lambda_function.example", - "attribute": [ - "function_name" - ] - } - ], - "timestamp": "2024-07-04T18:39:27Z", - "applyable": true, - "complete": true, - "errored": false -}