From 8c717a08ba08e425b5fb29da8a378eb7e39a4ea4 Mon Sep 17 00:00:00 2001 From: Chandan-DK Date: Wed, 2 Oct 2024 22:12:08 +0000 Subject: [PATCH 1/3] add ec2 best practices terraform plan policies Signed-off-by: Chandan-DK --- .../check-ec2-auto-scaling-groups/README.md | 81 +++ .../check-ec2-auto-scaling-groups.yaml | 25 + .../test/bad-test/bad-01.tf | 27 + .../test/bad-test/bad-payload-01.json | 287 ++++++++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 59 ++ .../test/good-test/good-01.tf | 29 + .../test/good-test/good-payload-01.json | 400 +++++++++++ .../check-ec2-detailed-monitoring/README.md | 76 ++ .../check-ec2-detailed-monitoring.yaml | 35 + .../test/bad-test/bad-01.tf | 21 + .../test/bad-test/bad-02.tf | 20 + .../test/bad-test/bad-03.tf | 33 + .../test/bad-test/bad-04.tf | 30 + .../test/bad-test/bad-05.tf | 29 + .../test/bad-test/bad-payload-01.json | 194 +++++ .../test/bad-test/bad-payload-02.json | 190 +++++ .../test/bad-test/bad-payload-03.json | 438 ++++++++++++ .../test/bad-test/bad-payload-04.json | 417 +++++++++++ .../test/bad-test/bad-payload-05.json | 307 ++++++++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 241 +++++++ .../test/good-test/good-01.tf | 21 + .../test/good-test/good-02.tf | 33 + .../test/good-test/good-03.tf | 43 ++ .../test/good-test/good-payload-01.json | 194 +++++ .../test/good-test/good-payload-02.json | 438 ++++++++++++ .../test/good-test/good-payload-03.json | 569 +++++++++++++++ .../check-ec2-iam-role/README.md | 73 ++ .../check-ec2-iam-role.yaml | 25 + .../test/bad-test/bad-01.tf | 24 + .../test/bad-test/bad-payload-01.json | 208 ++++++ .../check-ec2-iam-role/test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 59 ++ .../test/good-test/good-01.tf | 25 + .../test/good-test/good-payload-01.json | 212 ++++++ .../check-ec2-public-ip/README.md | 73 ++ .../check-ec2-public-ip.yaml | 31 + .../test/bad-test/bad-01.tf | 22 + .../test/bad-test/bad-02.tf | 20 + .../test/bad-test/bad-03.tf | 24 + .../test/bad-test/bad-04.tf | 24 + .../test/bad-test/bad-05.tf | 20 + .../test/bad-test/bad-06.tf | 20 + .../test/bad-test/bad-07.tf | 22 + .../test/bad-test/bad-payload-01.json | 194 +++++ .../test/bad-test/bad-payload-02.json | 190 +++++ .../test/bad-test/bad-payload-03.json | 271 +++++++ .../test/bad-test/bad-payload-04.json | 267 +++++++ .../test/bad-test/bad-payload-05.json | 214 ++++++ .../test/bad-test/bad-payload-06.json | 121 ++++ .../test/bad-test/bad-payload-07.json | 125 ++++ .../check-ec2-public-ip/test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 306 ++++++++ .../test/good-test/good-01.tf | 21 + .../test/good-test/good-02.tf | 23 + .../test/good-test/good-03.tf | 21 + .../test/good-test/good-payload-01.json | 194 +++++ .../test/good-test/good-payload-02.json | 271 +++++++ .../test/good-test/good-payload-03.json | 125 ++++ .../check-imds-v1/README.md | 84 +++ .../check-imds-v1/check-imds-v1.yaml | 25 + .../check-imds-v1/test/bad-test/bad-01.tf | 19 + .../check-imds-v1/test/bad-test/bad-02.tf | 23 + .../check-imds-v1/test/bad-test/bad-03.tf | 24 + .../check-imds-v1/test/bad-test/bad-04.tf | 24 + .../check-imds-v1/test/bad-test/bad-05.tf | 20 + .../check-imds-v1/test/bad-test/bad-06.tf | 20 + .../test/bad-test/bad-payload-01.json | 190 +++++ .../test/bad-test/bad-payload-02.json | 215 ++++++ .../test/bad-test/bad-payload-03.json | 223 ++++++ .../test/bad-test/bad-payload-04.json | 151 ++++ .../test/bad-test/bad-payload-05.json | 236 +++++++ .../test/bad-test/bad-payload-06.json | 236 +++++++ .../check-imds-v1/test/binding.yaml | 3 + .../check-imds-v1/test/chainsaw-test.yaml | 273 ++++++++ .../check-imds-v1/test/good-test/good-01.tf | 42 ++ .../check-imds-v1/test/good-test/good-02.tf | 43 ++ .../check-imds-v1/test/good-test/good-03.tf | 42 ++ .../test/good-test/good-payload-01.json | 594 ++++++++++++++++ .../test/good-test/good-payload-02.json | 662 ++++++++++++++++++ .../test/good-test/good-payload-03.json | 377 ++++++++++ .../README.md | 75 ++ .../check-transit-gateways-vpc-request.yaml | 27 + .../test/bad-test/bad-01.tf | 19 + .../test/bad-test/bad-payload-01.json | 112 +++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 86 +++ .../test/good-test/good-01.tf | 19 + .../test/good-test/good-02.tf | 19 + .../test/good-test/good-payload-01.json | 109 +++ .../test/good-test/good-payload-02.json | 112 +++ 92 files changed, 11581 insertions(+) create mode 100644 terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/README.md create mode 100644 terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/check-ec2-auto-scaling-groups.yaml create mode 100644 terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/bad-test/bad-01.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/binding.yaml create mode 100644 terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/chainsaw-test.yaml create mode 100644 terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/good-test/good-01.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/good-test/good-payload-01.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/README.md create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/check-ec2-detailed-monitoring.yaml create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-01.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-02.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-03.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-04.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-05.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-02.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-03.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-04.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-05.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/binding.yaml create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/chainsaw-test.yaml create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-01.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-02.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-03.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-payload-01.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-payload-02.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-payload-03.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-iam-role/README.md create mode 100644 terraform/plan/ec2-best-practices/check-ec2-iam-role/check-ec2-iam-role.yaml create mode 100644 terraform/plan/ec2-best-practices/check-ec2-iam-role/test/bad-test/bad-01.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-iam-role/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-iam-role/test/binding.yaml create mode 100644 terraform/plan/ec2-best-practices/check-ec2-iam-role/test/chainsaw-test.yaml create mode 100644 terraform/plan/ec2-best-practices/check-ec2-iam-role/test/good-test/good-01.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-iam-role/test/good-test/good-payload-01.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/README.md create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/check-ec2-public-ip.yaml create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-01.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-02.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-03.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-04.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-05.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-06.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-07.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-02.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-03.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-04.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-05.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-06.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-07.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/binding.yaml create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/chainsaw-test.yaml create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-01.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-02.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-03.tf create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-payload-01.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-payload-02.json create mode 100644 terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-payload-03.json create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/README.md create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/check-imds-v1.yaml create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-01.tf create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-02.tf create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-03.tf create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-04.tf create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-05.tf create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-06.tf create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-02.json create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-03.json create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-04.json create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-05.json create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-06.json create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/binding.yaml create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/chainsaw-test.yaml create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-01.tf create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-02.tf create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-03.tf create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-payload-01.json create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-payload-02.json create mode 100644 terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-payload-03.json create mode 100644 terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/README.md create mode 100644 terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/check-transit-gateways-vpc-request.yaml create mode 100644 terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/bad-test/bad-01.tf create mode 100644 terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/binding.yaml create mode 100644 terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/chainsaw-test.yaml create mode 100644 terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/good-test/good-01.tf create mode 100644 terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/good-test/good-02.tf create mode 100644 terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/good-test/good-payload-01.json create mode 100644 terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/good-test/good-payload-02.json diff --git a/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/README.md b/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/README.md new file mode 100644 index 00000000..0bbba4a9 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/README.md @@ -0,0 +1,81 @@ +# Check EC2 Auto Scaling Groups + +Launch Templates is a capability that enables to templatize your launch requests. Launch Templates can help simplify and streamline the launch process for Auto Scaling. Launch Templates reduce the number of steps required to create an instance by capturing all launch parameters within one resource. This makes the process easy to reproduce. Launch Templates make it easier to implement standards and best practices, helping you to better manage costs, improve your security posture, and minimize the risk of deployment errors. + +A launch template is similar to a launch configuration, in that it specifies instance configuration information. It includes the ID of the Amazon Machine Image (AMI), the instance type, a key pair, security groups, and other parameters used to launch EC2 instances. However, defining a launch template instead of a launch configuration allows you to have multiple versions of a launch template. + +It is recommended that you use migrate to launch templates to ensure that you're accessing the latest features and improvements. Not all Amazon EC2 Auto Scaling features are available when you use launch configurations. + +You can read more about it from the following links: +[Auto Scaling launch templates](https://docs.aws.amazon.com/autoscaling/ec2/userguide/launch-templates.html) +[Auto Scaling launch configurations](https://docs.aws.amazon.com/autoscaling/ec2/userguide/launch-configurations.html) + +## Policy Details: + +- **Policy Name:** check-ec2-auto-scaling-groups +- **Check Description:** This policy ensures that EC2 Auto Scaling Groups use launch templates instead of launch configurations +- **Policy Category:** AWS EC2 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-ec2-auto-scaling-groups.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=check-ec2-auto-scaling-groups, RULE=check-ec2-auto-scaling-groups) + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-ec2-auto-scaling-groups.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=check-ec2-auto-scaling-groups, RULE=check-ec2-auto-scaling-groups) + -> Auto Scaling Groups should use EC2 launch templates instead of launch configurations (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: true: Expected value: false (PATH=~.(planned_values.root_module.resources[?type=='aws_autoscaling_group'])[0].values.(!launch_template)) + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/check-ec2-auto-scaling-groups.yaml b/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/check-ec2-auto-scaling-groups.yaml new file mode 100644 index 00000000..fb516074 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/check-ec2-auto-scaling-groups.yaml @@ -0,0 +1,25 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-ec2-auto-scaling-groups + annotations: + policies.kyverno.io/title: check-ec2-auto-scaling-groups + policies.kyverno.io/category: AWS EC2 Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + Using EC2 launch templates in EC2 Auto Scaling groups provides standardization, + simplified management, versioning, customization, integration with AWS services, enhanced security, and cost optimization benefits. +spec: + rules: + - name: check-ec2-auto-scaling-groups + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_autoscaling_group'] | length(@) > `0`): true + assert: + all: + - message: Auto Scaling Groups should use EC2 launch templates instead of launch configurations + check: + ~.(planned_values.root_module.resources[?type=='aws_autoscaling_group']): + values: + (!launch_template): false \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/bad-test/bad-01.tf b/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/bad-test/bad-01.tf new file mode 100644 index 00000000..8d1c7e78 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/bad-test/bad-01.tf @@ -0,0 +1,27 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_launch_configuration" "example" { + name = "test-launch-configuration" + image_id = "ami-12345678" + instance_type = "t2.micro" +} + +resource "aws_autoscaling_group" "example" { + max_size = 3 + min_size = 1 + + launch_configuration = aws_launch_configuration.example.name +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/bad-test/bad-payload-01.json b/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..37b23603 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/bad-test/bad-payload-01.json @@ -0,0 +1,287 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "capacity_rebalance": null, + "context": null, + "default_instance_warmup": null, + "desired_capacity_type": null, + "enabled_metrics": null, + "force_delete": false, + "force_delete_warm_pool": false, + "health_check_grace_period": 300, + "ignore_failed_scaling_activities": false, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_configuration": "test-launch-configuration", + "max_instance_lifetime": null, + "max_size": 3, + "metrics_granularity": "1Minute", + "min_elb_capacity": null, + "min_size": 1, + "placement_group": null, + "protect_from_scale_in": false, + "suspended_processes": null, + "tag": [], + "termination_policies": null, + "timeouts": null, + "wait_for_capacity_timeout": "10m", + "wait_for_elb_capacity": null, + "warm_pool": [] + }, + "sensitive_values": { + "availability_zones": [], + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [], + "load_balancers": [], + "mixed_instances_policy": [], + "tag": [], + "target_group_arns": [], + "traffic_source": [], + "vpc_zone_identifier": [], + "warm_pool": [] + } + }, + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "ami-12345678", + "instance_type": "t2.micro", + "name": "test-launch-configuration", + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "sensitive_values": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [], + "root_block_device": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "capacity_rebalance": null, + "context": null, + "default_instance_warmup": null, + "desired_capacity_type": null, + "enabled_metrics": null, + "force_delete": false, + "force_delete_warm_pool": false, + "health_check_grace_period": 300, + "ignore_failed_scaling_activities": false, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_configuration": "test-launch-configuration", + "max_instance_lifetime": null, + "max_size": 3, + "metrics_granularity": "1Minute", + "min_elb_capacity": null, + "min_size": 1, + "placement_group": null, + "protect_from_scale_in": false, + "suspended_processes": null, + "tag": [], + "termination_policies": null, + "timeouts": null, + "wait_for_capacity_timeout": "10m", + "wait_for_elb_capacity": null, + "warm_pool": [] + }, + "after_unknown": { + "arn": true, + "availability_zones": true, + "default_cooldown": true, + "desired_capacity": true, + "health_check_type": true, + "id": true, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": true, + "load_balancers": true, + "mixed_instances_policy": true, + "name": true, + "name_prefix": true, + "predicted_capacity": true, + "service_linked_role_arn": true, + "tag": [], + "target_group_arns": true, + "traffic_source": true, + "vpc_zone_identifier": true, + "warm_pool": [], + "warm_pool_size": true + }, + "before_sensitive": false, + "after_sensitive": { + "availability_zones": [], + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [], + "load_balancers": [], + "mixed_instances_policy": [], + "tag": [], + "target_group_arns": [], + "traffic_source": [], + "vpc_zone_identifier": [], + "warm_pool": [] + } + } + }, + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "ami-12345678", + "instance_type": "t2.micro", + "name": "test-launch-configuration", + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "ebs_block_device": true, + "ebs_optimized": true, + "ephemeral_block_device": [], + "id": true, + "key_name": true, + "metadata_options": true, + "name_prefix": true, + "root_block_device": true + }, + "before_sensitive": false, + "after_sensitive": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [], + "root_block_device": [] + } + } + } + ], + "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_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "launch_configuration": { + "references": [ + "aws_launch_configuration.example.name", + "aws_launch_configuration.example" + ] + }, + "max_size": { + "constant_value": 3 + }, + "min_size": { + "constant_value": 1 + } + }, + "schema_version": 1 + }, + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "ami-12345678" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "name": { + "constant_value": "test-launch-configuration" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_launch_configuration.example", + "attribute": [ + "name" + ] + } + ], + "timestamp": "2024-07-09T06:27:26Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/binding.yaml b/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/chainsaw-test.yaml b/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/chainsaw-test.yaml new file mode 100644 index 00000000..11f23d13 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/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-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./good-test/good-payload-01.json --policy ../check-ec2-auto-scaling-groups.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-auto-scaling-groups + rules: + - rule: + name: check-ec2-auto-scaling-groups + 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 ../check-ec2-auto-scaling-groups.yaml --payload ./bad-test/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: check-ec2-auto-scaling-groups + rules: + - rule: + name: check-ec2-auto-scaling-groups + error: ~ + violations: + - (contains(message, 'Auto Scaling Groups should use EC2 launch templates instead of launch configurations')): true + errors: + - type: FieldValueInvalid + value: true + detail: 'Expected value: false' \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/good-test/good-01.tf b/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/good-test/good-01.tf new file mode 100644 index 00000000..2fabc482 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/good-test/good-01.tf @@ -0,0 +1,29 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_launch_template" "example" { + name_prefix = "example" + image_id = "ami-775287582" + instance_type = "t2.micro" +} + +resource "aws_autoscaling_group" "example" { + max_size = 3 + min_size = 1 + + launch_template { + id = aws_launch_template.example.id + } +} \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/good-test/good-payload-01.json b/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/good-test/good-payload-01.json new file mode 100644 index 00000000..ea0fc25b --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-auto-scaling-groups/test/good-test/good-payload-01.json @@ -0,0 +1,400 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "capacity_rebalance": null, + "context": null, + "default_instance_warmup": null, + "desired_capacity_type": null, + "enabled_metrics": null, + "force_delete": false, + "force_delete_warm_pool": false, + "health_check_grace_period": 300, + "ignore_failed_scaling_activities": false, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_configuration": null, + "launch_template": [ + {} + ], + "max_instance_lifetime": null, + "max_size": 3, + "metrics_granularity": "1Minute", + "min_elb_capacity": null, + "min_size": 1, + "placement_group": null, + "protect_from_scale_in": false, + "suspended_processes": null, + "tag": [], + "termination_policies": null, + "timeouts": null, + "wait_for_capacity_timeout": "10m", + "wait_for_elb_capacity": null, + "warm_pool": [] + }, + "sensitive_values": { + "availability_zones": [], + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [ + {} + ], + "load_balancers": [], + "mixed_instances_policy": [], + "tag": [], + "target_group_arns": [], + "traffic_source": [], + "vpc_zone_identifier": [], + "warm_pool": [] + } + }, + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "ami-775287582", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "monitoring": [], + "name_prefix": "example", + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "sensitive_values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "capacity_rebalance": null, + "context": null, + "default_instance_warmup": null, + "desired_capacity_type": null, + "enabled_metrics": null, + "force_delete": false, + "force_delete_warm_pool": false, + "health_check_grace_period": 300, + "ignore_failed_scaling_activities": false, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_configuration": null, + "launch_template": [ + {} + ], + "max_instance_lifetime": null, + "max_size": 3, + "metrics_granularity": "1Minute", + "min_elb_capacity": null, + "min_size": 1, + "placement_group": null, + "protect_from_scale_in": false, + "suspended_processes": null, + "tag": [], + "termination_policies": null, + "timeouts": null, + "wait_for_capacity_timeout": "10m", + "wait_for_elb_capacity": null, + "warm_pool": [] + }, + "after_unknown": { + "arn": true, + "availability_zones": true, + "default_cooldown": true, + "desired_capacity": true, + "health_check_type": true, + "id": true, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [ + { + "id": true, + "name": true, + "version": true + } + ], + "load_balancers": true, + "mixed_instances_policy": true, + "name": true, + "name_prefix": true, + "predicted_capacity": true, + "service_linked_role_arn": true, + "tag": [], + "target_group_arns": true, + "traffic_source": true, + "vpc_zone_identifier": true, + "warm_pool": [], + "warm_pool_size": true + }, + "before_sensitive": false, + "after_sensitive": { + "availability_zones": [], + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [ + {} + ], + "load_balancers": [], + "mixed_instances_policy": [], + "tag": [], + "target_group_arns": [], + "traffic_source": [], + "vpc_zone_identifier": [], + "warm_pool": [] + } + } + }, + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "ami-775287582", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "monitoring": [], + "name_prefix": "example", + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "after_unknown": { + "arn": true, + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "default_version": true, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "id": true, + "instance_market_options": [], + "instance_requirements": [], + "latest_version": true, + "license_specification": [], + "maintenance_options": [], + "metadata_options": true, + "monitoring": [], + "name": true, + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + } + ], + "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_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "launch_template": [ + { + "id": { + "references": [ + "aws_launch_template.example.id", + "aws_launch_template.example" + ] + } + } + ], + "max_size": { + "constant_value": 3 + }, + "min_size": { + "constant_value": 1 + } + }, + "schema_version": 1 + }, + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "ami-775287582" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "name_prefix": { + "constant_value": "example" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_launch_template.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-07-09T06:23:26Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/README.md b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/README.md new file mode 100644 index 00000000..a2b7b7d6 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/README.md @@ -0,0 +1,76 @@ +# Check EC2 Detailed Monitoring + +CloudWatch provides two categories of monitoring: basic monitoring and detailed monitoring. +By default, an instance is enabled for basic monitoring and metrics is published at five-minute intervals. Amazon EC2 detailed monitoring provides more frequent metrics, published at one-minute intervals. Using detailed monitoring for Amazon EC2 helps you better manage your Amazon EC2 resources, so that you can find trends and take action faster. However, enabling detailed monitoring incurs additional [charges](https://aws.amazon.com/cloudwatch/pricing/). + +You can read more about it [here](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-cloudwatch-new.html) + +## Policy Details: + +- **Policy Name:** check-ec2-detailed-monitoring +- **Check Description:** This policy ensures that detailed monitoring is enabled for the EC2 instance +- **Policy Category:** AWS EC2 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-ec2-detailed-monitoring.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=check-ec2-detailed-monitoring, RULE=check-ec2-detailed-monitoring) + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-ec2-detailed-monitoring.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=check-ec2-detailed-monitoring, RULE=check-ec2-detailed-monitoring) + -> Detailed monitoring must be enabled for the EC2 instance (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: false: Expected value: true (PATH=~.(planned_values.root_module.resources[?type=='aws_instance'])[0].values.monitoring) + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/check-ec2-detailed-monitoring.yaml b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/check-ec2-detailed-monitoring.yaml new file mode 100644 index 00000000..a31db360 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/check-ec2-detailed-monitoring.yaml @@ -0,0 +1,35 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-ec2-detailed-monitoring + annotations: + policies.kyverno.io/title: check-ec2-detailed-monitoring + policies.kyverno.io/category: AWS EC2 Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy ensures that detailed monitoring is enabled for the AWS EC2 instance +spec: + rules: + - name: check-ec2-detailed-monitoring + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_instance' || type=='aws_launch_configuration' || type=='aws_launch_template'] | length(@) > `0`): true + assert: + all: + - message: Detailed monitoring must be enabled for the EC2 instance + check: + ~.(planned_values.root_module.resources[?type=='aws_instance']): + values: + monitoring: true + - message: Detailed monitoring must be enabled in EC2 launch configuration + check: + ~.(planned_values.root_module.resources[?type=='aws_launch_configuration']): + values: + enable_monitoring: true + - message: Detailed monitoring must be enabled in EC2 launch template + check: + ~.(planned_values.root_module.resources[?type=='aws_launch_template']): + values: + ~.(monitoring || `[{}]`): + enabled: true \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-01.tf b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-01.tf new file mode 100644 index 00000000..26518fb3 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-01.tf @@ -0,0 +1,21 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_instance" "example" { + ami = "ami-0604d81f2fd264c7b" + instance_type = "t2.micro" + monitoring = false +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-02.tf b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-02.tf new file mode 100644 index 00000000..cba6fd92 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-02.tf @@ -0,0 +1,20 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_instance" "example" { + ami = "ami-0604d81f2fd264c7b" + instance_type = "t2.micro" +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-03.tf b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-03.tf new file mode 100644 index 00000000..8e359f37 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-03.tf @@ -0,0 +1,33 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "ap-south-1" +} + +resource "aws_launch_template" "example" { + name_prefix = "example-lc" + image_id = "ami-01376101673c89611" + instance_type = "t2.micro" + monitoring { + enabled = false + } +} + +resource "aws_autoscaling_group" "example" { + max_size = 3 + min_size = 1 + availability_zones = ["ap-south-1a"] + launch_template { + id = aws_launch_template.example.id + } +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-04.tf b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-04.tf new file mode 100644 index 00000000..4b112a92 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-04.tf @@ -0,0 +1,30 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "ap-south-1" +} + +resource "aws_launch_template" "example" { + name_prefix = "example-lc" + image_id = "ami-01376101673c89611" + instance_type = "t2.micro" +} + +resource "aws_autoscaling_group" "example" { + max_size = 3 + min_size = 1 + availability_zones = ["ap-south-1a"] + launch_template { + id = aws_launch_template.example.id + } +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-05.tf b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-05.tf new file mode 100644 index 00000000..38e452be --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-05.tf @@ -0,0 +1,29 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "ap-south-1" +} + +resource "aws_launch_configuration" "example" { + name = "example-lc" + image_id = "ami-01376101673c89611" + instance_type = "t2.micro" + enable_monitoring = false +} + +resource "aws_autoscaling_group" "example" { + max_size = 3 + min_size = 1 + availability_zones = ["ap-south-1a"] + launch_configuration = aws_launch_configuration.example.name +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-01.json b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..6a853742 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-01.json @@ -0,0 +1,194 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "ami": "ami-0604d81f2fd264c7b", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "monitoring": false, + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "sensitive_values": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "ami-0604d81f2fd264c7b", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "monitoring": false, + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "availability_zone": true, + "capacity_reservation_specification": true, + "cpu_core_count": true, + "cpu_options": true, + "cpu_threads_per_core": true, + "credit_specification": [], + "disable_api_stop": true, + "disable_api_termination": true, + "ebs_block_device": true, + "ebs_optimized": true, + "enclave_options": true, + "ephemeral_block_device": true, + "host_id": true, + "host_resource_group_arn": true, + "iam_instance_profile": true, + "id": true, + "instance_initiated_shutdown_behavior": true, + "instance_lifecycle": true, + "instance_market_options": true, + "instance_state": true, + "ipv6_address_count": true, + "ipv6_addresses": true, + "key_name": true, + "launch_template": [], + "maintenance_options": true, + "metadata_options": true, + "network_interface": true, + "outpost_arn": true, + "password_data": true, + "placement_group": true, + "placement_partition_number": true, + "primary_network_interface_id": true, + "private_dns": true, + "private_dns_name_options": true, + "private_ip": true, + "public_dns": true, + "public_ip": true, + "root_block_device": true, + "secondary_private_ips": true, + "security_groups": true, + "spot_instance_request_id": true, + "subnet_id": true, + "tags_all": true, + "tenancy": true, + "user_data": true, + "user_data_base64": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "ami": { + "constant_value": "ami-0604d81f2fd264c7b" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "monitoring": { + "constant_value": false + } + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-07-09T09:11:33Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-02.json b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-02.json new file mode 100644 index 00000000..c6d5c76c --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-02.json @@ -0,0 +1,190 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "ami": "ami-0604d81f2fd264c7b", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "sensitive_values": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "ami-0604d81f2fd264c7b", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "availability_zone": true, + "capacity_reservation_specification": true, + "cpu_core_count": true, + "cpu_options": true, + "cpu_threads_per_core": true, + "credit_specification": [], + "disable_api_stop": true, + "disable_api_termination": true, + "ebs_block_device": true, + "ebs_optimized": true, + "enclave_options": true, + "ephemeral_block_device": true, + "host_id": true, + "host_resource_group_arn": true, + "iam_instance_profile": true, + "id": true, + "instance_initiated_shutdown_behavior": true, + "instance_lifecycle": true, + "instance_market_options": true, + "instance_state": true, + "ipv6_address_count": true, + "ipv6_addresses": true, + "key_name": true, + "launch_template": [], + "maintenance_options": true, + "metadata_options": true, + "monitoring": true, + "network_interface": true, + "outpost_arn": true, + "password_data": true, + "placement_group": true, + "placement_partition_number": true, + "primary_network_interface_id": true, + "private_dns": true, + "private_dns_name_options": true, + "private_ip": true, + "public_dns": true, + "public_ip": true, + "root_block_device": true, + "secondary_private_ips": true, + "security_groups": true, + "spot_instance_request_id": true, + "subnet_id": true, + "tags_all": true, + "tenancy": true, + "user_data": true, + "user_data_base64": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "ami": { + "constant_value": "ami-0604d81f2fd264c7b" + }, + "instance_type": { + "constant_value": "t2.micro" + } + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-07-09T09:09:14Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-03.json b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-03.json new file mode 100644 index 00000000..d155f414 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-03.json @@ -0,0 +1,438 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "availability_zones": [ + "ap-south-1a" + ], + "capacity_rebalance": null, + "context": null, + "default_instance_warmup": null, + "desired_capacity_type": null, + "enabled_metrics": null, + "force_delete": false, + "force_delete_warm_pool": false, + "health_check_grace_period": 300, + "ignore_failed_scaling_activities": false, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_configuration": null, + "launch_template": [ + {} + ], + "max_instance_lifetime": null, + "max_size": 3, + "metrics_granularity": "1Minute", + "min_elb_capacity": null, + "min_size": 1, + "placement_group": null, + "protect_from_scale_in": false, + "suspended_processes": null, + "tag": [], + "termination_policies": null, + "timeouts": null, + "wait_for_capacity_timeout": "10m", + "wait_for_elb_capacity": null, + "warm_pool": [] + }, + "sensitive_values": { + "availability_zones": [ + false + ], + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [ + {} + ], + "load_balancers": [], + "mixed_instances_policy": [], + "tag": [], + "target_group_arns": [], + "traffic_source": [], + "vpc_zone_identifier": [], + "warm_pool": [] + } + }, + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "ami-01376101673c89611", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "monitoring": [ + { + "enabled": false + } + ], + "name_prefix": "example-lc", + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "sensitive_values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [], + "monitoring": [ + {} + ], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "availability_zones": [ + "ap-south-1a" + ], + "capacity_rebalance": null, + "context": null, + "default_instance_warmup": null, + "desired_capacity_type": null, + "enabled_metrics": null, + "force_delete": false, + "force_delete_warm_pool": false, + "health_check_grace_period": 300, + "ignore_failed_scaling_activities": false, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_configuration": null, + "launch_template": [ + {} + ], + "max_instance_lifetime": null, + "max_size": 3, + "metrics_granularity": "1Minute", + "min_elb_capacity": null, + "min_size": 1, + "placement_group": null, + "protect_from_scale_in": false, + "suspended_processes": null, + "tag": [], + "termination_policies": null, + "timeouts": null, + "wait_for_capacity_timeout": "10m", + "wait_for_elb_capacity": null, + "warm_pool": [] + }, + "after_unknown": { + "arn": true, + "availability_zones": [ + false + ], + "default_cooldown": true, + "desired_capacity": true, + "health_check_type": true, + "id": true, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [ + { + "id": true, + "name": true, + "version": true + } + ], + "load_balancers": true, + "mixed_instances_policy": true, + "name": true, + "name_prefix": true, + "predicted_capacity": true, + "service_linked_role_arn": true, + "tag": [], + "target_group_arns": true, + "traffic_source": true, + "vpc_zone_identifier": true, + "warm_pool": [], + "warm_pool_size": true + }, + "before_sensitive": false, + "after_sensitive": { + "availability_zones": [ + false + ], + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [ + {} + ], + "load_balancers": [], + "mixed_instances_policy": [], + "tag": [], + "target_group_arns": [], + "traffic_source": [], + "vpc_zone_identifier": [], + "warm_pool": [] + } + } + }, + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "ami-01376101673c89611", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "monitoring": [ + { + "enabled": false + } + ], + "name_prefix": "example-lc", + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "after_unknown": { + "arn": true, + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "default_version": true, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "id": true, + "instance_market_options": [], + "instance_requirements": [], + "latest_version": true, + "license_specification": [], + "maintenance_options": [], + "metadata_options": true, + "monitoring": [ + {} + ], + "name": true, + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [], + "monitoring": [ + {} + ], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": ">= 5.32.0", + "expressions": { + "region": { + "constant_value": "ap-south-1" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "availability_zones": { + "constant_value": [ + "ap-south-1a" + ] + }, + "launch_template": [ + { + "id": { + "references": [ + "aws_launch_template.example.id", + "aws_launch_template.example" + ] + } + } + ], + "max_size": { + "constant_value": 3 + }, + "min_size": { + "constant_value": 1 + } + }, + "schema_version": 1 + }, + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "ami-01376101673c89611" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "monitoring": [ + { + "enabled": { + "constant_value": false + } + } + ], + "name_prefix": { + "constant_value": "example-lc" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_launch_template.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-07-09T19:24:36Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-04.json b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-04.json new file mode 100644 index 00000000..53a88546 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-04.json @@ -0,0 +1,417 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "availability_zones": [ + "ap-south-1a" + ], + "capacity_rebalance": null, + "context": null, + "default_instance_warmup": null, + "desired_capacity_type": null, + "enabled_metrics": null, + "force_delete": false, + "force_delete_warm_pool": false, + "health_check_grace_period": 300, + "ignore_failed_scaling_activities": false, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_configuration": null, + "launch_template": [ + {} + ], + "max_instance_lifetime": null, + "max_size": 3, + "metrics_granularity": "1Minute", + "min_elb_capacity": null, + "min_size": 1, + "placement_group": null, + "protect_from_scale_in": false, + "suspended_processes": null, + "tag": [], + "termination_policies": null, + "timeouts": null, + "wait_for_capacity_timeout": "10m", + "wait_for_elb_capacity": null, + "warm_pool": [] + }, + "sensitive_values": { + "availability_zones": [ + false + ], + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [ + {} + ], + "load_balancers": [], + "mixed_instances_policy": [], + "tag": [], + "target_group_arns": [], + "traffic_source": [], + "vpc_zone_identifier": [], + "warm_pool": [] + } + }, + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "ami-01376101673c89611", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "monitoring": [], + "name_prefix": "example-lc", + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "sensitive_values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "availability_zones": [ + "ap-south-1a" + ], + "capacity_rebalance": null, + "context": null, + "default_instance_warmup": null, + "desired_capacity_type": null, + "enabled_metrics": null, + "force_delete": false, + "force_delete_warm_pool": false, + "health_check_grace_period": 300, + "ignore_failed_scaling_activities": false, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_configuration": null, + "launch_template": [ + {} + ], + "max_instance_lifetime": null, + "max_size": 3, + "metrics_granularity": "1Minute", + "min_elb_capacity": null, + "min_size": 1, + "placement_group": null, + "protect_from_scale_in": false, + "suspended_processes": null, + "tag": [], + "termination_policies": null, + "timeouts": null, + "wait_for_capacity_timeout": "10m", + "wait_for_elb_capacity": null, + "warm_pool": [] + }, + "after_unknown": { + "arn": true, + "availability_zones": [ + false + ], + "default_cooldown": true, + "desired_capacity": true, + "health_check_type": true, + "id": true, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [ + { + "id": true, + "name": true, + "version": true + } + ], + "load_balancers": true, + "mixed_instances_policy": true, + "name": true, + "name_prefix": true, + "predicted_capacity": true, + "service_linked_role_arn": true, + "tag": [], + "target_group_arns": true, + "traffic_source": true, + "vpc_zone_identifier": true, + "warm_pool": [], + "warm_pool_size": true + }, + "before_sensitive": false, + "after_sensitive": { + "availability_zones": [ + false + ], + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [ + {} + ], + "load_balancers": [], + "mixed_instances_policy": [], + "tag": [], + "target_group_arns": [], + "traffic_source": [], + "vpc_zone_identifier": [], + "warm_pool": [] + } + } + }, + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "ami-01376101673c89611", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "monitoring": [], + "name_prefix": "example-lc", + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "after_unknown": { + "arn": true, + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "default_version": true, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "id": true, + "instance_market_options": [], + "instance_requirements": [], + "latest_version": true, + "license_specification": [], + "maintenance_options": [], + "metadata_options": true, + "monitoring": [], + "name": true, + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": ">= 5.32.0", + "expressions": { + "region": { + "constant_value": "ap-south-1" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "availability_zones": { + "constant_value": [ + "ap-south-1a" + ] + }, + "launch_template": [ + { + "id": { + "references": [ + "aws_launch_template.example.id", + "aws_launch_template.example" + ] + } + } + ], + "max_size": { + "constant_value": 3 + }, + "min_size": { + "constant_value": 1 + } + }, + "schema_version": 1 + }, + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "ami-01376101673c89611" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "name_prefix": { + "constant_value": "example-lc" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_launch_template.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-07-09T19:21:42Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-05.json b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-05.json new file mode 100644 index 00000000..e917b576 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/bad-test/bad-payload-05.json @@ -0,0 +1,307 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "availability_zones": [ + "ap-south-1a" + ], + "capacity_rebalance": null, + "context": null, + "default_instance_warmup": null, + "desired_capacity_type": null, + "enabled_metrics": null, + "force_delete": false, + "force_delete_warm_pool": false, + "health_check_grace_period": 300, + "ignore_failed_scaling_activities": false, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_configuration": "example-lc", + "max_instance_lifetime": null, + "max_size": 3, + "metrics_granularity": "1Minute", + "min_elb_capacity": null, + "min_size": 1, + "placement_group": null, + "protect_from_scale_in": false, + "suspended_processes": null, + "tag": [], + "termination_policies": null, + "timeouts": null, + "wait_for_capacity_timeout": "10m", + "wait_for_elb_capacity": null, + "warm_pool": [] + }, + "sensitive_values": { + "availability_zones": [ + false + ], + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [], + "load_balancers": [], + "mixed_instances_policy": [], + "tag": [], + "target_group_arns": [], + "traffic_source": [], + "vpc_zone_identifier": [], + "warm_pool": [] + } + }, + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "enable_monitoring": false, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "ami-01376101673c89611", + "instance_type": "t2.micro", + "name": "example-lc", + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "sensitive_values": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [], + "root_block_device": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "availability_zones": [ + "ap-south-1a" + ], + "capacity_rebalance": null, + "context": null, + "default_instance_warmup": null, + "desired_capacity_type": null, + "enabled_metrics": null, + "force_delete": false, + "force_delete_warm_pool": false, + "health_check_grace_period": 300, + "ignore_failed_scaling_activities": false, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_configuration": "example-lc", + "max_instance_lifetime": null, + "max_size": 3, + "metrics_granularity": "1Minute", + "min_elb_capacity": null, + "min_size": 1, + "placement_group": null, + "protect_from_scale_in": false, + "suspended_processes": null, + "tag": [], + "termination_policies": null, + "timeouts": null, + "wait_for_capacity_timeout": "10m", + "wait_for_elb_capacity": null, + "warm_pool": [] + }, + "after_unknown": { + "arn": true, + "availability_zones": [ + false + ], + "default_cooldown": true, + "desired_capacity": true, + "health_check_type": true, + "id": true, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": true, + "load_balancers": true, + "mixed_instances_policy": true, + "name": true, + "name_prefix": true, + "predicted_capacity": true, + "service_linked_role_arn": true, + "tag": [], + "target_group_arns": true, + "traffic_source": true, + "vpc_zone_identifier": true, + "warm_pool": [], + "warm_pool_size": true + }, + "before_sensitive": false, + "after_sensitive": { + "availability_zones": [ + false + ], + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [], + "load_balancers": [], + "mixed_instances_policy": [], + "tag": [], + "target_group_arns": [], + "traffic_source": [], + "vpc_zone_identifier": [], + "warm_pool": [] + } + } + }, + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "enable_monitoring": false, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "ami-01376101673c89611", + "instance_type": "t2.micro", + "name": "example-lc", + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "ebs_block_device": true, + "ebs_optimized": true, + "ephemeral_block_device": [], + "id": true, + "key_name": true, + "metadata_options": true, + "name_prefix": true, + "root_block_device": true + }, + "before_sensitive": false, + "after_sensitive": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [], + "root_block_device": [] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": ">= 5.32.0", + "expressions": { + "region": { + "constant_value": "ap-south-1" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "availability_zones": { + "constant_value": [ + "ap-south-1a" + ] + }, + "launch_configuration": { + "references": [ + "aws_launch_configuration.example.name", + "aws_launch_configuration.example" + ] + }, + "max_size": { + "constant_value": 3 + }, + "min_size": { + "constant_value": 1 + } + }, + "schema_version": 1 + }, + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "enable_monitoring": { + "constant_value": false + }, + "image_id": { + "constant_value": "ami-01376101673c89611" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "name": { + "constant_value": "example-lc" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_launch_configuration.example", + "attribute": [ + "name" + ] + } + ], + "timestamp": "2024-07-09T19:25:30Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/binding.yaml b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/chainsaw-test.yaml b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/chainsaw-test.yaml new file mode 100644 index 00000000..a272024a --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/chainsaw-test.yaml @@ -0,0 +1,241 @@ +# 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-ec2-detailed-monitoring.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-detailed-monitoring + rules: + - rule: + name: check-ec2-detailed-monitoring + 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 --payload ./good-test/good-payload-02.json --policy ../check-ec2-detailed-monitoring.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-detailed-monitoring + rules: + - rule: + name: check-ec2-detailed-monitoring + error: ~ + violations: ~ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test-03 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./good-test/good-payload-03.json --policy ../check-ec2-detailed-monitoring.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-detailed-monitoring + rules: + - rule: + name: check-ec2-detailed-monitoring + 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 --payload ./bad-test/bad-payload-01.json --policy ../check-ec2-detailed-monitoring.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-detailed-monitoring + rules: + - rule: + name: check-ec2-detailed-monitoring + error: ~ + violations: + - (contains(message, 'Detailed monitoring must be enabled for the EC2 instance')): 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 --payload ./bad-test/bad-payload-02.json --policy ../check-ec2-detailed-monitoring.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-detailed-monitoring + rules: + - rule: + name: check-ec2-detailed-monitoring + error: ~ + violations: + - (contains(message, 'Detailed monitoring must be enabled for the EC2 instance')): true + errors: + - type: FieldValueRequired + value: "" + detail: 'field not found in the input object' +--- +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 --payload ./bad-test/bad-payload-03.json --policy ../check-ec2-detailed-monitoring.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-detailed-monitoring + rules: + - rule: + name: check-ec2-detailed-monitoring + error: ~ + violations: + - (contains(message, 'Detailed monitoring must be enabled in EC2 launch template')): 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 --payload ./bad-test/bad-payload-04.json --policy ../check-ec2-detailed-monitoring.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-detailed-monitoring + rules: + - rule: + name: check-ec2-detailed-monitoring + error: ~ + violations: + - (contains(message, 'Detailed monitoring must be enabled in EC2 launch template')): true + errors: + - type: FieldValueRequired + value: "" + detail: 'field not found in the input object' +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-05 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./bad-test/bad-payload-05.json --policy ../check-ec2-detailed-monitoring.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-detailed-monitoring + rules: + - rule: + name: check-ec2-detailed-monitoring + error: ~ + violations: + - (contains(message, 'Detailed monitoring must be enabled in EC2 launch configuration')): true + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-01.tf b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-01.tf new file mode 100644 index 00000000..4ee59012 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-01.tf @@ -0,0 +1,21 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_instance" "example" { + ami = "ami-0604d81f2fd264c7b" + instance_type = "t2.micro" + monitoring = true +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-02.tf b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-02.tf new file mode 100644 index 00000000..cc5e58a5 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-02.tf @@ -0,0 +1,33 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "ap-south-1" +} + +resource "aws_launch_template" "example" { + name_prefix = "example" + image_id = "ami-01376101673c89611" + instance_type = "t2.micro" + monitoring { + enabled = true + } +} + +resource "aws_autoscaling_group" "example" { + max_size = 3 + min_size = 1 + availability_zones = ["ap-south-1a"] + launch_template { + id = aws_launch_template.example.id + } +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-03.tf b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-03.tf new file mode 100644 index 00000000..156aaf42 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-03.tf @@ -0,0 +1,43 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "ap-south-1" +} + +resource "aws_launch_configuration" "example" { + name = "example-lc" + image_id = "ami-01376101673c89611" + instance_type = "t2.micro" + enable_monitoring = true +} + +resource "aws_autoscaling_group" "example" { + max_size = 3 + min_size = 1 + availability_zones = ["ap-south-1a"] + launch_configuration = aws_launch_configuration.example.name +} + +# enable_monitoring = true by default +resource "aws_launch_configuration" "example_2" { + name = "example-lc-2" + image_id = "ami-01376101673c89611" + instance_type = "t2.micro" +} + +resource "aws_autoscaling_group" "example_2" { + max_size = 3 + min_size = 1 + availability_zones = ["ap-south-1a"] + launch_configuration = aws_launch_configuration.example.name +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-payload-01.json b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-payload-01.json new file mode 100644 index 00000000..63b57c5d --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-payload-01.json @@ -0,0 +1,194 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "ami": "ami-0604d81f2fd264c7b", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "monitoring": true, + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "sensitive_values": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "ami-0604d81f2fd264c7b", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "monitoring": true, + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "availability_zone": true, + "capacity_reservation_specification": true, + "cpu_core_count": true, + "cpu_options": true, + "cpu_threads_per_core": true, + "credit_specification": [], + "disable_api_stop": true, + "disable_api_termination": true, + "ebs_block_device": true, + "ebs_optimized": true, + "enclave_options": true, + "ephemeral_block_device": true, + "host_id": true, + "host_resource_group_arn": true, + "iam_instance_profile": true, + "id": true, + "instance_initiated_shutdown_behavior": true, + "instance_lifecycle": true, + "instance_market_options": true, + "instance_state": true, + "ipv6_address_count": true, + "ipv6_addresses": true, + "key_name": true, + "launch_template": [], + "maintenance_options": true, + "metadata_options": true, + "network_interface": true, + "outpost_arn": true, + "password_data": true, + "placement_group": true, + "placement_partition_number": true, + "primary_network_interface_id": true, + "private_dns": true, + "private_dns_name_options": true, + "private_ip": true, + "public_dns": true, + "public_ip": true, + "root_block_device": true, + "secondary_private_ips": true, + "security_groups": true, + "spot_instance_request_id": true, + "subnet_id": true, + "tags_all": true, + "tenancy": true, + "user_data": true, + "user_data_base64": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "ami": { + "constant_value": "ami-0604d81f2fd264c7b" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "monitoring": { + "constant_value": true + } + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-07-09T09:14:08Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-payload-02.json b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-payload-02.json new file mode 100644 index 00000000..fdbd1f58 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-payload-02.json @@ -0,0 +1,438 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "availability_zones": [ + "ap-south-1a" + ], + "capacity_rebalance": null, + "context": null, + "default_instance_warmup": null, + "desired_capacity_type": null, + "enabled_metrics": null, + "force_delete": false, + "force_delete_warm_pool": false, + "health_check_grace_period": 300, + "ignore_failed_scaling_activities": false, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_configuration": null, + "launch_template": [ + {} + ], + "max_instance_lifetime": null, + "max_size": 3, + "metrics_granularity": "1Minute", + "min_elb_capacity": null, + "min_size": 1, + "placement_group": null, + "protect_from_scale_in": false, + "suspended_processes": null, + "tag": [], + "termination_policies": null, + "timeouts": null, + "wait_for_capacity_timeout": "10m", + "wait_for_elb_capacity": null, + "warm_pool": [] + }, + "sensitive_values": { + "availability_zones": [ + false + ], + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [ + {} + ], + "load_balancers": [], + "mixed_instances_policy": [], + "tag": [], + "target_group_arns": [], + "traffic_source": [], + "vpc_zone_identifier": [], + "warm_pool": [] + } + }, + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "ami-01376101673c89611", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "monitoring": [ + { + "enabled": true + } + ], + "name_prefix": "example", + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "sensitive_values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [], + "monitoring": [ + {} + ], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "availability_zones": [ + "ap-south-1a" + ], + "capacity_rebalance": null, + "context": null, + "default_instance_warmup": null, + "desired_capacity_type": null, + "enabled_metrics": null, + "force_delete": false, + "force_delete_warm_pool": false, + "health_check_grace_period": 300, + "ignore_failed_scaling_activities": false, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_configuration": null, + "launch_template": [ + {} + ], + "max_instance_lifetime": null, + "max_size": 3, + "metrics_granularity": "1Minute", + "min_elb_capacity": null, + "min_size": 1, + "placement_group": null, + "protect_from_scale_in": false, + "suspended_processes": null, + "tag": [], + "termination_policies": null, + "timeouts": null, + "wait_for_capacity_timeout": "10m", + "wait_for_elb_capacity": null, + "warm_pool": [] + }, + "after_unknown": { + "arn": true, + "availability_zones": [ + false + ], + "default_cooldown": true, + "desired_capacity": true, + "health_check_type": true, + "id": true, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [ + { + "id": true, + "name": true, + "version": true + } + ], + "load_balancers": true, + "mixed_instances_policy": true, + "name": true, + "name_prefix": true, + "predicted_capacity": true, + "service_linked_role_arn": true, + "tag": [], + "target_group_arns": true, + "traffic_source": true, + "vpc_zone_identifier": true, + "warm_pool": [], + "warm_pool_size": true + }, + "before_sensitive": false, + "after_sensitive": { + "availability_zones": [ + false + ], + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [ + {} + ], + "load_balancers": [], + "mixed_instances_policy": [], + "tag": [], + "target_group_arns": [], + "traffic_source": [], + "vpc_zone_identifier": [], + "warm_pool": [] + } + } + }, + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "ami-01376101673c89611", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "monitoring": [ + { + "enabled": true + } + ], + "name_prefix": "example", + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "after_unknown": { + "arn": true, + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "default_version": true, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "id": true, + "instance_market_options": [], + "instance_requirements": [], + "latest_version": true, + "license_specification": [], + "maintenance_options": [], + "metadata_options": true, + "monitoring": [ + {} + ], + "name": true, + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [], + "monitoring": [ + {} + ], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": ">= 5.32.0", + "expressions": { + "region": { + "constant_value": "ap-south-1" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "availability_zones": { + "constant_value": [ + "ap-south-1a" + ] + }, + "launch_template": [ + { + "id": { + "references": [ + "aws_launch_template.example.id", + "aws_launch_template.example" + ] + } + } + ], + "max_size": { + "constant_value": 3 + }, + "min_size": { + "constant_value": 1 + } + }, + "schema_version": 1 + }, + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "ami-01376101673c89611" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "monitoring": [ + { + "enabled": { + "constant_value": true + } + } + ], + "name_prefix": { + "constant_value": "example" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_launch_template.example", + "attribute": [ + "id" + ] + } + ], + "timestamp": "2024-07-09T19:06:28Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-payload-03.json b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-payload-03.json new file mode 100644 index 00000000..c8e5e2c4 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-detailed-monitoring/test/good-test/good-payload-03.json @@ -0,0 +1,569 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "availability_zones": [ + "ap-south-1a" + ], + "capacity_rebalance": null, + "context": null, + "default_instance_warmup": null, + "desired_capacity_type": null, + "enabled_metrics": null, + "force_delete": false, + "force_delete_warm_pool": false, + "health_check_grace_period": 300, + "ignore_failed_scaling_activities": false, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_configuration": "example-lc", + "max_instance_lifetime": null, + "max_size": 3, + "metrics_granularity": "1Minute", + "min_elb_capacity": null, + "min_size": 1, + "placement_group": null, + "protect_from_scale_in": false, + "suspended_processes": null, + "tag": [], + "termination_policies": null, + "timeouts": null, + "wait_for_capacity_timeout": "10m", + "wait_for_elb_capacity": null, + "warm_pool": [] + }, + "sensitive_values": { + "availability_zones": [ + false + ], + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [], + "load_balancers": [], + "mixed_instances_policy": [], + "tag": [], + "target_group_arns": [], + "traffic_source": [], + "vpc_zone_identifier": [], + "warm_pool": [] + } + }, + { + "address": "aws_autoscaling_group.example_2", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example_2", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "availability_zones": [ + "ap-south-1a" + ], + "capacity_rebalance": null, + "context": null, + "default_instance_warmup": null, + "desired_capacity_type": null, + "enabled_metrics": null, + "force_delete": false, + "force_delete_warm_pool": false, + "health_check_grace_period": 300, + "ignore_failed_scaling_activities": false, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_configuration": "example-lc", + "max_instance_lifetime": null, + "max_size": 3, + "metrics_granularity": "1Minute", + "min_elb_capacity": null, + "min_size": 1, + "placement_group": null, + "protect_from_scale_in": false, + "suspended_processes": null, + "tag": [], + "termination_policies": null, + "timeouts": null, + "wait_for_capacity_timeout": "10m", + "wait_for_elb_capacity": null, + "warm_pool": [] + }, + "sensitive_values": { + "availability_zones": [ + false + ], + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [], + "load_balancers": [], + "mixed_instances_policy": [], + "tag": [], + "target_group_arns": [], + "traffic_source": [], + "vpc_zone_identifier": [], + "warm_pool": [] + } + }, + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "ami-01376101673c89611", + "instance_type": "t2.micro", + "name": "example-lc", + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "sensitive_values": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [], + "root_block_device": [] + } + }, + { + "address": "aws_launch_configuration.example_2", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example_2", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "ami-01376101673c89611", + "instance_type": "t2.micro", + "name": "example-lc-2", + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "sensitive_values": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [], + "root_block_device": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "availability_zones": [ + "ap-south-1a" + ], + "capacity_rebalance": null, + "context": null, + "default_instance_warmup": null, + "desired_capacity_type": null, + "enabled_metrics": null, + "force_delete": false, + "force_delete_warm_pool": false, + "health_check_grace_period": 300, + "ignore_failed_scaling_activities": false, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_configuration": "example-lc", + "max_instance_lifetime": null, + "max_size": 3, + "metrics_granularity": "1Minute", + "min_elb_capacity": null, + "min_size": 1, + "placement_group": null, + "protect_from_scale_in": false, + "suspended_processes": null, + "tag": [], + "termination_policies": null, + "timeouts": null, + "wait_for_capacity_timeout": "10m", + "wait_for_elb_capacity": null, + "warm_pool": [] + }, + "after_unknown": { + "arn": true, + "availability_zones": [ + false + ], + "default_cooldown": true, + "desired_capacity": true, + "health_check_type": true, + "id": true, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": true, + "load_balancers": true, + "mixed_instances_policy": true, + "name": true, + "name_prefix": true, + "predicted_capacity": true, + "service_linked_role_arn": true, + "tag": [], + "target_group_arns": true, + "traffic_source": true, + "vpc_zone_identifier": true, + "warm_pool": [], + "warm_pool_size": true + }, + "before_sensitive": false, + "after_sensitive": { + "availability_zones": [ + false + ], + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [], + "load_balancers": [], + "mixed_instances_policy": [], + "tag": [], + "target_group_arns": [], + "traffic_source": [], + "vpc_zone_identifier": [], + "warm_pool": [] + } + } + }, + { + "address": "aws_autoscaling_group.example_2", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example_2", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "availability_zones": [ + "ap-south-1a" + ], + "capacity_rebalance": null, + "context": null, + "default_instance_warmup": null, + "desired_capacity_type": null, + "enabled_metrics": null, + "force_delete": false, + "force_delete_warm_pool": false, + "health_check_grace_period": 300, + "ignore_failed_scaling_activities": false, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_configuration": "example-lc", + "max_instance_lifetime": null, + "max_size": 3, + "metrics_granularity": "1Minute", + "min_elb_capacity": null, + "min_size": 1, + "placement_group": null, + "protect_from_scale_in": false, + "suspended_processes": null, + "tag": [], + "termination_policies": null, + "timeouts": null, + "wait_for_capacity_timeout": "10m", + "wait_for_elb_capacity": null, + "warm_pool": [] + }, + "after_unknown": { + "arn": true, + "availability_zones": [ + false + ], + "default_cooldown": true, + "desired_capacity": true, + "health_check_type": true, + "id": true, + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": true, + "load_balancers": true, + "mixed_instances_policy": true, + "name": true, + "name_prefix": true, + "predicted_capacity": true, + "service_linked_role_arn": true, + "tag": [], + "target_group_arns": true, + "traffic_source": true, + "vpc_zone_identifier": true, + "warm_pool": [], + "warm_pool_size": true + }, + "before_sensitive": false, + "after_sensitive": { + "availability_zones": [ + false + ], + "initial_lifecycle_hook": [], + "instance_maintenance_policy": [], + "instance_refresh": [], + "launch_template": [], + "load_balancers": [], + "mixed_instances_policy": [], + "tag": [], + "target_group_arns": [], + "traffic_source": [], + "vpc_zone_identifier": [], + "warm_pool": [] + } + } + }, + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "ami-01376101673c89611", + "instance_type": "t2.micro", + "name": "example-lc", + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "ebs_block_device": true, + "ebs_optimized": true, + "ephemeral_block_device": [], + "id": true, + "key_name": true, + "metadata_options": true, + "name_prefix": true, + "root_block_device": true + }, + "before_sensitive": false, + "after_sensitive": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [], + "root_block_device": [] + } + } + }, + { + "address": "aws_launch_configuration.example_2", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example_2", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "ami-01376101673c89611", + "instance_type": "t2.micro", + "name": "example-lc-2", + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "ebs_block_device": true, + "ebs_optimized": true, + "ephemeral_block_device": [], + "id": true, + "key_name": true, + "metadata_options": true, + "name_prefix": true, + "root_block_device": true + }, + "before_sensitive": false, + "after_sensitive": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [], + "root_block_device": [] + } + } + } + ], + "configuration": { + "provider_config": { + "aws": { + "name": "aws", + "full_name": "registry.terraform.io/hashicorp/aws", + "version_constraint": ">= 5.32.0", + "expressions": { + "region": { + "constant_value": "ap-south-1" + } + } + } + }, + "root_module": { + "resources": [ + { + "address": "aws_autoscaling_group.example", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "availability_zones": { + "constant_value": [ + "ap-south-1a" + ] + }, + "launch_configuration": { + "references": [ + "aws_launch_configuration.example.name", + "aws_launch_configuration.example" + ] + }, + "max_size": { + "constant_value": 3 + }, + "min_size": { + "constant_value": 1 + } + }, + "schema_version": 1 + }, + { + "address": "aws_autoscaling_group.example_2", + "mode": "managed", + "type": "aws_autoscaling_group", + "name": "example_2", + "provider_config_key": "aws", + "expressions": { + "availability_zones": { + "constant_value": [ + "ap-south-1a" + ] + }, + "launch_configuration": { + "references": [ + "aws_launch_configuration.example.name", + "aws_launch_configuration.example" + ] + }, + "max_size": { + "constant_value": 3 + }, + "min_size": { + "constant_value": 1 + } + }, + "schema_version": 1 + }, + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "enable_monitoring": { + "constant_value": true + }, + "image_id": { + "constant_value": "ami-01376101673c89611" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "name": { + "constant_value": "example-lc" + } + }, + "schema_version": 0 + }, + { + "address": "aws_launch_configuration.example_2", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example_2", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "ami-01376101673c89611" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "name": { + "constant_value": "example-lc-2" + } + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_launch_configuration.example", + "attribute": [ + "name" + ] + } + ], + "timestamp": "2024-07-09T19:07:34Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-iam-role/README.md b/terraform/plan/ec2-best-practices/check-ec2-iam-role/README.md new file mode 100644 index 00000000..21379172 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-iam-role/README.md @@ -0,0 +1,73 @@ +# Check EC2 IAM Role + +An IAM role acts as an identity with specific permission policies that determine the allowed and disallowed actions within AWS. Creating IAM roles and attaching them to manage permissions for EC2 instances ensures that access is controlled and temporary credentials are used, enhancing security. + +## Policy Details: + +- **Policy Name:** check-ec2-iam-role +- **Check Description:** This policy ensures that an IAM role is attached to an EC2 instance +- **Policy Category:** AWS EC2 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-ec2-iam-role.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=check-ec2-iam-role, RULE=check-ec2-iam-role) + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-ec2-iam-role.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=check-ec2-iam-role, RULE=check-ec2-iam-role) + -> 'iam_instance_profile' must be present for the EC2 instance (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: true: Expected value: false (PATH=~.(planned_values.root_module.resources[?type=='aws_instance'])[0].values.(!iam_instance_profile)) + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-ec2-iam-role/check-ec2-iam-role.yaml b/terraform/plan/ec2-best-practices/check-ec2-iam-role/check-ec2-iam-role.yaml new file mode 100644 index 00000000..0c0768be --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-iam-role/check-ec2-iam-role.yaml @@ -0,0 +1,25 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-ec2-iam-role + annotations: + policies.kyverno.io/title: check-ec2-iam-role + policies.kyverno.io/category: AWS EC2 Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy ensures that an IAM role is attached to an EC2 instance +spec: + rules: + - name: check-ec2-iam-role + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_instance'] | length(@) > `0`): true + assert: + all: + - message: "'iam_instance_profile' must be present for the EC2 instance" + check: + ~.(planned_values.root_module.resources[?type=='aws_instance']): + values: + (!iam_instance_profile): false + diff --git a/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/bad-test/bad-01.tf b/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/bad-test/bad-01.tf new file mode 100644 index 00000000..25039d52 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/bad-test/bad-01.tf @@ -0,0 +1,24 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_instance" "example" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t2.micro" + + tags = { + Name = "example_ec2" + } +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/bad-test/bad-payload-01.json b/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..cf3bf5fd --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/bad-test/bad-payload-01.json @@ -0,0 +1,208 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "ami": "ami-0c55b159cbfafe1f0", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "source_dest_check": true, + "tags": { + "Name": "example_ec2" + }, + "tags_all": { + "Name": "example_ec2" + }, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "sensitive_values": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags": {}, + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "ami-0c55b159cbfafe1f0", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "source_dest_check": true, + "tags": { + "Name": "example_ec2" + }, + "tags_all": { + "Name": "example_ec2" + }, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "availability_zone": true, + "capacity_reservation_specification": true, + "cpu_core_count": true, + "cpu_options": true, + "cpu_threads_per_core": true, + "credit_specification": [], + "disable_api_stop": true, + "disable_api_termination": true, + "ebs_block_device": true, + "ebs_optimized": true, + "enclave_options": true, + "ephemeral_block_device": true, + "host_id": true, + "host_resource_group_arn": true, + "iam_instance_profile": true, + "id": true, + "instance_initiated_shutdown_behavior": true, + "instance_lifecycle": true, + "instance_market_options": true, + "instance_state": true, + "ipv6_address_count": true, + "ipv6_addresses": true, + "key_name": true, + "launch_template": [], + "maintenance_options": true, + "metadata_options": true, + "monitoring": true, + "network_interface": true, + "outpost_arn": true, + "password_data": true, + "placement_group": true, + "placement_partition_number": true, + "primary_network_interface_id": true, + "private_dns": true, + "private_dns_name_options": true, + "private_ip": true, + "public_dns": true, + "public_ip": true, + "root_block_device": true, + "secondary_private_ips": true, + "security_groups": true, + "spot_instance_request_id": true, + "subnet_id": true, + "tags": {}, + "tags_all": {}, + "tenancy": true, + "user_data": true, + "user_data_base64": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags": {}, + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "ami": { + "constant_value": "ami-0c55b159cbfafe1f0" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "tags": { + "constant_value": { + "Name": "example_ec2" + } + } + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-06-28T04:33:41Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/binding.yaml b/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/chainsaw-test.yaml b/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/chainsaw-test.yaml new file mode 100644 index 00000000..a31c1cfe --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-iam-role/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-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./good-test/good-payload-01.json --policy ../check-ec2-iam-role.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-iam-role + rules: + - rule: + name: check-ec2-iam-role + 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 ../check-ec2-iam-role.yaml --payload ./bad-test/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: check-ec2-iam-role + rules: + - rule: + name: check-ec2-iam-role + error: ~ + violations: + - (contains(message, '\'iam_instance_profile\' must be present for the EC2 instance')): true + errors: + - type: FieldValueInvalid + value: true + detail: 'Expected value: false' diff --git a/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/good-test/good-01.tf b/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/good-test/good-01.tf new file mode 100644 index 00000000..ca485764 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/good-test/good-01.tf @@ -0,0 +1,25 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_instance" "example" { + ami = "ami-01572eda7c4411960" + instance_type = "t2.micro" + iam_instance_profile = "example_iam_instance_profile" + + tags = { + Name = "example_ec2" + } +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/good-test/good-payload-01.json b/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/good-test/good-payload-01.json new file mode 100644 index 00000000..4158f9b4 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-iam-role/test/good-test/good-payload-01.json @@ -0,0 +1,212 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "ami": "ami-01572eda7c4411960", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "iam_instance_profile": "example_iam_instance_profile", + "instance_type": "t2.micro", + "launch_template": [], + "source_dest_check": true, + "tags": { + "Name": "example_ec2" + }, + "tags_all": { + "Name": "example_ec2" + }, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "sensitive_values": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags": {}, + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "ami-01572eda7c4411960", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "iam_instance_profile": "example_iam_instance_profile", + "instance_type": "t2.micro", + "launch_template": [], + "source_dest_check": true, + "tags": { + "Name": "example_ec2" + }, + "tags_all": { + "Name": "example_ec2" + }, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "availability_zone": true, + "capacity_reservation_specification": true, + "cpu_core_count": true, + "cpu_options": true, + "cpu_threads_per_core": true, + "credit_specification": [], + "disable_api_stop": true, + "disable_api_termination": true, + "ebs_block_device": true, + "ebs_optimized": true, + "enclave_options": true, + "ephemeral_block_device": true, + "host_id": true, + "host_resource_group_arn": true, + "id": true, + "instance_initiated_shutdown_behavior": true, + "instance_lifecycle": true, + "instance_market_options": true, + "instance_state": true, + "ipv6_address_count": true, + "ipv6_addresses": true, + "key_name": true, + "launch_template": [], + "maintenance_options": true, + "metadata_options": true, + "monitoring": true, + "network_interface": true, + "outpost_arn": true, + "password_data": true, + "placement_group": true, + "placement_partition_number": true, + "primary_network_interface_id": true, + "private_dns": true, + "private_dns_name_options": true, + "private_ip": true, + "public_dns": true, + "public_ip": true, + "root_block_device": true, + "secondary_private_ips": true, + "security_groups": true, + "spot_instance_request_id": true, + "subnet_id": true, + "tags": {}, + "tags_all": {}, + "tenancy": true, + "user_data": true, + "user_data_base64": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags": {}, + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "ami": { + "constant_value": "ami-01572eda7c4411960" + }, + "iam_instance_profile": { + "constant_value": "example_iam_instance_profile" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "tags": { + "constant_value": { + "Name": "example_ec2" + } + } + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-06-28T04:42:02Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/README.md b/terraform/plan/ec2-best-practices/check-ec2-public-ip/README.md new file mode 100644 index 00000000..becf9ae0 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/README.md @@ -0,0 +1,73 @@ +# Check EC2 Public IP + +Public IP addresses can make EC2 instances directly accessible from the internet, which might not always be desirable from a security or compliance standpoint. In many cases, you might not want your EC2 instances to have public IP addresses unless they need to be publicly accessible. Having a public IP address can expose your EC2 instance to potential security risks, such as unauthorized access or attacks. + +## Policy Details: + +- **Policy Name:** check-ec2-public-ip +- **Check Description:** This policy ensures that the EC2 instance is not assigned a public IP address +- **Policy Category:** AWS EC2 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-ec2-public-ip.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - check-ec2-public-ip / check-ec2-public-ip / PASSED + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-ec2-public-ip.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - check-ec2-public-ip / check-ec2-public-ip / FAILED + -> EC2 instance should not be created or launched with a public IP address to avoid exposing it to the internet + -> all[0].check.~.(planned_values.root_module.resources[?type=='aws_instance' || type=='aws_launch_configuration'])[0].values.associate_public_ip_address: Invalid value: true: Expected value: false + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/check-ec2-public-ip.yaml b/terraform/plan/ec2-best-practices/check-ec2-public-ip/check-ec2-public-ip.yaml new file mode 100644 index 00000000..83e04ff5 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/check-ec2-public-ip.yaml @@ -0,0 +1,31 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-ec2-public-ip + annotations: + policies.kyverno.io/title: check-ec2-public-ip + policies.kyverno.io/category: AWS EC2 Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy ensures that the EC2 instance is not assigned a public IP address +spec: + rules: + - name: check-ec2-public-ip + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_instance' || type=='aws_launch_template' || type=='aws_launch_configuration'] | length(@) > `0`): true + assert: + all: + - message: EC2 instance should not be created or launched with a public IP address to avoid exposing it to the internet + check: + ~.(planned_values.root_module.resources[?type=='aws_instance' || type=='aws_launch_configuration']): + values: + associate_public_ip_address: false + - message: EC2 launch templates should not assign a public IP address to EC2 instances to avoid exposing them to the internet + check: + ~.(planned_values.root_module.resources[?type=='aws_launch_template']): + values: + ~.(network_interfaces || `[{}]`): + associate_public_ip_address: 'false' + diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-01.tf b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-01.tf new file mode 100644 index 00000000..cac333c7 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-01.tf @@ -0,0 +1,22 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_instance" "example" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t2.micro" + + associate_public_ip_address = true +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-02.tf b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-02.tf new file mode 100644 index 00000000..367ac8cb --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-02.tf @@ -0,0 +1,20 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_instance" "example" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t2.micro" +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-03.tf b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-03.tf new file mode 100644 index 00000000..2d3c3632 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-03.tf @@ -0,0 +1,24 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_launch_template" "example" { + instance_type = "t2.micro" + image_id = "" + + network_interfaces { + associate_public_ip_address = true + } +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-04.tf b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-04.tf new file mode 100644 index 00000000..53a54530 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-04.tf @@ -0,0 +1,24 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_launch_template" "example" { + instance_type = "c6a.large" + image_id = "ami-02d3f9239f16d5514" + + network_interfaces { + + } +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-05.tf b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-05.tf new file mode 100644 index 00000000..6f3fed88 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-05.tf @@ -0,0 +1,20 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_launch_template" "example" { + instance_type = "t2.micro" + image_id = "" +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-06.tf b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-06.tf new file mode 100644 index 00000000..42028c6c --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-06.tf @@ -0,0 +1,20 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_launch_configuration" "example" { + instance_type = "t2.micro" + image_id = "" +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-07.tf b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-07.tf new file mode 100644 index 00000000..88989978 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-07.tf @@ -0,0 +1,22 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_launch_configuration" "example" { + instance_type = "t2.micro" + image_id = "" + + associate_public_ip_address = true +} + diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-01.json b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..57d45d59 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-01.json @@ -0,0 +1,194 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "ami": "ami-0c55b159cbfafe1f0", + "associate_public_ip_address": true, + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "sensitive_values": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "ami-0c55b159cbfafe1f0", + "associate_public_ip_address": true, + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "after_unknown": { + "arn": true, + "availability_zone": true, + "capacity_reservation_specification": true, + "cpu_core_count": true, + "cpu_options": true, + "cpu_threads_per_core": true, + "credit_specification": [], + "disable_api_stop": true, + "disable_api_termination": true, + "ebs_block_device": true, + "ebs_optimized": true, + "enclave_options": true, + "ephemeral_block_device": true, + "host_id": true, + "host_resource_group_arn": true, + "iam_instance_profile": true, + "id": true, + "instance_initiated_shutdown_behavior": true, + "instance_lifecycle": true, + "instance_market_options": true, + "instance_state": true, + "ipv6_address_count": true, + "ipv6_addresses": true, + "key_name": true, + "launch_template": [], + "maintenance_options": true, + "metadata_options": true, + "monitoring": true, + "network_interface": true, + "outpost_arn": true, + "password_data": true, + "placement_group": true, + "placement_partition_number": true, + "primary_network_interface_id": true, + "private_dns": true, + "private_dns_name_options": true, + "private_ip": true, + "public_dns": true, + "public_ip": true, + "root_block_device": true, + "secondary_private_ips": true, + "security_groups": true, + "spot_instance_request_id": true, + "subnet_id": true, + "tags_all": true, + "tenancy": true, + "user_data": true, + "user_data_base64": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "ami": { + "constant_value": "ami-0c55b159cbfafe1f0" + }, + "associate_public_ip_address": { + "constant_value": true + }, + "instance_type": { + "constant_value": "t2.micro" + } + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-07-11T14:46:17Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-02.json b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-02.json new file mode 100644 index 00000000..0d852d99 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-02.json @@ -0,0 +1,190 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "ami": "ami-0c55b159cbfafe1f0", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "sensitive_values": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "ami-0c55b159cbfafe1f0", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "availability_zone": true, + "capacity_reservation_specification": true, + "cpu_core_count": true, + "cpu_options": true, + "cpu_threads_per_core": true, + "credit_specification": [], + "disable_api_stop": true, + "disable_api_termination": true, + "ebs_block_device": true, + "ebs_optimized": true, + "enclave_options": true, + "ephemeral_block_device": true, + "host_id": true, + "host_resource_group_arn": true, + "iam_instance_profile": true, + "id": true, + "instance_initiated_shutdown_behavior": true, + "instance_lifecycle": true, + "instance_market_options": true, + "instance_state": true, + "ipv6_address_count": true, + "ipv6_addresses": true, + "key_name": true, + "launch_template": [], + "maintenance_options": true, + "metadata_options": true, + "monitoring": true, + "network_interface": true, + "outpost_arn": true, + "password_data": true, + "placement_group": true, + "placement_partition_number": true, + "primary_network_interface_id": true, + "private_dns": true, + "private_dns_name_options": true, + "private_ip": true, + "public_dns": true, + "public_ip": true, + "root_block_device": true, + "secondary_private_ips": true, + "security_groups": true, + "spot_instance_request_id": true, + "subnet_id": true, + "tags_all": true, + "tenancy": true, + "user_data": true, + "user_data_base64": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "ami": { + "constant_value": "ami-0c55b159cbfafe1f0" + }, + "instance_type": { + "constant_value": "t2.micro" + } + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-07-11T14:46:47Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-03.json b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-03.json new file mode 100644 index 00000000..af12937b --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-03.json @@ -0,0 +1,271 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "monitoring": [], + "network_interfaces": [ + { + "associate_carrier_ip_address": null, + "associate_public_ip_address": "true", + "delete_on_termination": null, + "description": null, + "device_index": null, + "interface_type": null, + "ipv4_address_count": null, + "ipv4_addresses": null, + "ipv4_prefix_count": null, + "ipv4_prefixes": null, + "ipv6_address_count": null, + "ipv6_addresses": null, + "ipv6_prefix_count": null, + "ipv6_prefixes": null, + "network_card_index": null, + "network_interface_id": null, + "private_ip_address": null, + "security_groups": null, + "subnet_id": null + } + ], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "sensitive_values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [], + "monitoring": [], + "network_interfaces": [ + {} + ], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "monitoring": [], + "network_interfaces": [ + { + "associate_carrier_ip_address": null, + "associate_public_ip_address": "true", + "delete_on_termination": null, + "description": null, + "device_index": null, + "interface_type": null, + "ipv4_address_count": null, + "ipv4_addresses": null, + "ipv4_prefix_count": null, + "ipv4_prefixes": null, + "ipv6_address_count": null, + "ipv6_addresses": null, + "ipv6_prefix_count": null, + "ipv6_prefixes": null, + "network_card_index": null, + "network_interface_id": null, + "private_ip_address": null, + "security_groups": null, + "subnet_id": null + } + ], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "after_unknown": { + "arn": true, + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "default_version": true, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "id": true, + "instance_market_options": [], + "instance_requirements": [], + "latest_version": true, + "license_specification": [], + "maintenance_options": [], + "metadata_options": true, + "monitoring": [], + "name": true, + "name_prefix": true, + "network_interfaces": [ + {} + ], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [], + "monitoring": [], + "network_interfaces": [ + {} + ], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + } + ], + "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_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "network_interfaces": [ + { + "associate_public_ip_address": { + "constant_value": true + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "timestamp": "2024-07-11T14:47:14Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-04.json b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-04.json new file mode 100644 index 00000000..9b1dc8d3 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-04.json @@ -0,0 +1,267 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "monitoring": [], + "network_interfaces": [ + { + "associate_carrier_ip_address": null, + "associate_public_ip_address": null, + "delete_on_termination": null, + "description": null, + "device_index": null, + "interface_type": null, + "ipv4_address_count": null, + "ipv4_addresses": null, + "ipv4_prefix_count": null, + "ipv4_prefixes": null, + "ipv6_address_count": null, + "ipv6_addresses": null, + "ipv6_prefix_count": null, + "ipv6_prefixes": null, + "network_card_index": null, + "network_interface_id": null, + "private_ip_address": null, + "security_groups": null, + "subnet_id": null + } + ], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "sensitive_values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [], + "monitoring": [], + "network_interfaces": [ + {} + ], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "monitoring": [], + "network_interfaces": [ + { + "associate_carrier_ip_address": null, + "associate_public_ip_address": null, + "delete_on_termination": null, + "description": null, + "device_index": null, + "interface_type": null, + "ipv4_address_count": null, + "ipv4_addresses": null, + "ipv4_prefix_count": null, + "ipv4_prefixes": null, + "ipv6_address_count": null, + "ipv6_addresses": null, + "ipv6_prefix_count": null, + "ipv6_prefixes": null, + "network_card_index": null, + "network_interface_id": null, + "private_ip_address": null, + "security_groups": null, + "subnet_id": null + } + ], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "after_unknown": { + "arn": true, + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "default_version": true, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "id": true, + "instance_market_options": [], + "instance_requirements": [], + "latest_version": true, + "license_specification": [], + "maintenance_options": [], + "metadata_options": true, + "monitoring": [], + "name": true, + "name_prefix": true, + "network_interfaces": [ + {} + ], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [], + "monitoring": [], + "network_interfaces": [ + {} + ], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + } + ], + "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_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "network_interfaces": [ + {} + ] + }, + "schema_version": 0 + } + ] + } + }, + "timestamp": "2024-07-11T14:47:42Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-05.json b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-05.json new file mode 100644 index 00000000..e5aa2a35 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-05.json @@ -0,0 +1,214 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "sensitive_values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "after_unknown": { + "arn": true, + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "default_version": true, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "id": true, + "instance_market_options": [], + "instance_requirements": [], + "latest_version": true, + "license_specification": [], + "maintenance_options": [], + "metadata_options": true, + "monitoring": [], + "name": true, + "name_prefix": true, + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + } + ], + "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_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "" + }, + "instance_type": { + "constant_value": "t2.micro" + } + }, + "schema_version": 0 + } + ] + } + }, + "timestamp": "2024-07-11T14:48:16Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-06.json b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-06.json new file mode 100644 index 00000000..cc746104 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-06.json @@ -0,0 +1,121 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "", + "instance_type": "t2.micro", + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "sensitive_values": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [], + "root_block_device": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "", + "instance_type": "t2.micro", + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "ebs_block_device": true, + "ebs_optimized": true, + "ephemeral_block_device": [], + "id": true, + "key_name": true, + "metadata_options": true, + "name": true, + "name_prefix": true, + "root_block_device": true + }, + "before_sensitive": false, + "after_sensitive": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [], + "root_block_device": [] + } + } + } + ], + "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_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "" + }, + "instance_type": { + "constant_value": "t2.micro" + } + }, + "schema_version": 0 + } + ] + } + }, + "timestamp": "2024-07-11T14:48:42Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-07.json b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-07.json new file mode 100644 index 00000000..5afc4b66 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/bad-test/bad-payload-07.json @@ -0,0 +1,125 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "associate_public_ip_address": true, + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "", + "instance_type": "t2.micro", + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "sensitive_values": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [], + "root_block_device": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "associate_public_ip_address": true, + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "", + "instance_type": "t2.micro", + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "after_unknown": { + "arn": true, + "ebs_block_device": true, + "ebs_optimized": true, + "ephemeral_block_device": [], + "id": true, + "key_name": true, + "metadata_options": true, + "name": true, + "name_prefix": true, + "root_block_device": true + }, + "before_sensitive": false, + "after_sensitive": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [], + "root_block_device": [] + } + } + } + ], + "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_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "associate_public_ip_address": { + "constant_value": true + }, + "image_id": { + "constant_value": "" + }, + "instance_type": { + "constant_value": "t2.micro" + } + }, + "schema_version": 0 + } + ] + } + }, + "timestamp": "2024-07-11T14:49:07Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/binding.yaml b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/chainsaw-test.yaml b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/chainsaw-test.yaml new file mode 100644 index 00000000..b7880c9d --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/chainsaw-test.yaml @@ -0,0 +1,306 @@ +# 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-ec2-public-ip.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-public-ip + rules: + - rule: + name: check-ec2-public-ip + 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 --payload ./good-test/good-payload-02.json --policy ../check-ec2-public-ip.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-public-ip + rules: + - rule: + name: check-ec2-public-ip + error: ~ + violations: ~ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test-03 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./good-test/good-payload-03.json --policy ../check-ec2-public-ip.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-public-ip + rules: + - rule: + name: check-ec2-public-ip + 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 --payload ./bad-test/bad-payload-01.json --policy ../check-ec2-public-ip.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-public-ip + rules: + - rule: + name: check-ec2-public-ip + error: ~ + violations: + - (contains(message, 'EC2 instance should not be created or launched with a public IP address to avoid exposing it to the internet')): true + errors: + - type: FieldValueInvalid + (value != `false`): true + detail: 'Expected value: false' +--- +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 --payload ./bad-test/bad-payload-02.json --policy ../check-ec2-public-ip.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-public-ip + rules: + - rule: + name: check-ec2-public-ip + error: ~ + violations: + - (contains(message, 'EC2 instance should not be created or launched with a public IP address to avoid exposing it to the internet')): true + errors: + - type: FieldValueRequired + (value != `false`): true + detail: 'field not found in the input object' +--- +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 --payload ./bad-test/bad-payload-03.json --policy ../check-ec2-public-ip.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-public-ip + rules: + - rule: + name: check-ec2-public-ip + error: ~ + violations: + - (contains(message, 'EC2 launch templates should not assign a public IP address to EC2 instances to avoid exposing them to the internet')): true + errors: + - type: FieldValueInvalid + (value != 'false'): true + detail: "Expected value: \"false\"" +--- +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 --payload ./bad-test/bad-payload-04.json --policy ../check-ec2-public-ip.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-public-ip + rules: + - rule: + name: check-ec2-public-ip + error: ~ + violations: + - (contains(message, 'EC2 launch templates should not assign a public IP address to EC2 instances to avoid exposing them to the internet')): true + errors: + - type: FieldValueInvalid + (value != 'false'): true + detail: "Expected value: \"false\"" +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-05 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./bad-test/bad-payload-05.json --policy ../check-ec2-public-ip.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-public-ip + rules: + - rule: + name: check-ec2-public-ip + error: ~ + violations: + - (contains(message, 'EC2 launch templates should not assign a public IP address to EC2 instances to avoid exposing them to the internet')): true + errors: + - type: FieldValueRequired + (value != 'false'): true + detail: "field not found in the input object" +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-06 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./bad-test/bad-payload-06.json --policy ../check-ec2-public-ip.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-public-ip + rules: + - rule: + name: check-ec2-public-ip + error: ~ + violations: + - (contains(message, 'EC2 instance should not be created or launched with a public IP address to avoid exposing it to the internet')): true + errors: + - type: FieldValueRequired + (value != `false`): true + detail: 'field not found in the input object' +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-07 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./bad-test/bad-payload-07.json --policy ../check-ec2-public-ip.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-ec2-public-ip + rules: + - rule: + name: check-ec2-public-ip + error: ~ + violations: + - (contains(message, 'EC2 instance should not be created or launched with a public IP address to avoid exposing it to the internet')): true + errors: + - type: FieldValueInvalid + (value != `false`): true + detail: 'Expected value: false' + diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-01.tf b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-01.tf new file mode 100644 index 00000000..2c9d96a3 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-01.tf @@ -0,0 +1,21 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_instance" "example" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t2.micro" + + associate_public_ip_address = false +} \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-02.tf b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-02.tf new file mode 100644 index 00000000..23abb505 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-02.tf @@ -0,0 +1,23 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_launch_template" "example" { + instance_type = "t2.micro" + image_id = "" + + network_interfaces { + associate_public_ip_address = false + } +} \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-03.tf b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-03.tf new file mode 100644 index 00000000..23d6e053 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-03.tf @@ -0,0 +1,21 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_launch_configuration" "example" { + instance_type = "t2.micro" + image_id = "" + + associate_public_ip_address = false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-payload-01.json b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-payload-01.json new file mode 100644 index 00000000..10715378 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-payload-01.json @@ -0,0 +1,194 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "ami": "ami-0c55b159cbfafe1f0", + "associate_public_ip_address": false, + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "sensitive_values": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "ami-0c55b159cbfafe1f0", + "associate_public_ip_address": false, + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "after_unknown": { + "arn": true, + "availability_zone": true, + "capacity_reservation_specification": true, + "cpu_core_count": true, + "cpu_options": true, + "cpu_threads_per_core": true, + "credit_specification": [], + "disable_api_stop": true, + "disable_api_termination": true, + "ebs_block_device": true, + "ebs_optimized": true, + "enclave_options": true, + "ephemeral_block_device": true, + "host_id": true, + "host_resource_group_arn": true, + "iam_instance_profile": true, + "id": true, + "instance_initiated_shutdown_behavior": true, + "instance_lifecycle": true, + "instance_market_options": true, + "instance_state": true, + "ipv6_address_count": true, + "ipv6_addresses": true, + "key_name": true, + "launch_template": [], + "maintenance_options": true, + "metadata_options": true, + "monitoring": true, + "network_interface": true, + "outpost_arn": true, + "password_data": true, + "placement_group": true, + "placement_partition_number": true, + "primary_network_interface_id": true, + "private_dns": true, + "private_dns_name_options": true, + "private_ip": true, + "public_dns": true, + "public_ip": true, + "root_block_device": true, + "secondary_private_ips": true, + "security_groups": true, + "spot_instance_request_id": true, + "subnet_id": true, + "tags_all": true, + "tenancy": true, + "user_data": true, + "user_data_base64": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "ami": { + "constant_value": "ami-0c55b159cbfafe1f0" + }, + "associate_public_ip_address": { + "constant_value": false + }, + "instance_type": { + "constant_value": "t2.micro" + } + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-07-11T14:43:07Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-payload-02.json b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-payload-02.json new file mode 100644 index 00000000..d2118d17 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-payload-02.json @@ -0,0 +1,271 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "monitoring": [], + "network_interfaces": [ + { + "associate_carrier_ip_address": null, + "associate_public_ip_address": "false", + "delete_on_termination": null, + "description": null, + "device_index": null, + "interface_type": null, + "ipv4_address_count": null, + "ipv4_addresses": null, + "ipv4_prefix_count": null, + "ipv4_prefixes": null, + "ipv6_address_count": null, + "ipv6_addresses": null, + "ipv6_prefix_count": null, + "ipv6_prefixes": null, + "network_card_index": null, + "network_interface_id": null, + "private_ip_address": null, + "security_groups": null, + "subnet_id": null + } + ], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "sensitive_values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [], + "monitoring": [], + "network_interfaces": [ + {} + ], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "monitoring": [], + "network_interfaces": [ + { + "associate_carrier_ip_address": null, + "associate_public_ip_address": "false", + "delete_on_termination": null, + "description": null, + "device_index": null, + "interface_type": null, + "ipv4_address_count": null, + "ipv4_addresses": null, + "ipv4_prefix_count": null, + "ipv4_prefixes": null, + "ipv6_address_count": null, + "ipv6_addresses": null, + "ipv6_prefix_count": null, + "ipv6_prefixes": null, + "network_card_index": null, + "network_interface_id": null, + "private_ip_address": null, + "security_groups": null, + "subnet_id": null + } + ], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "after_unknown": { + "arn": true, + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "default_version": true, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "id": true, + "instance_market_options": [], + "instance_requirements": [], + "latest_version": true, + "license_specification": [], + "maintenance_options": [], + "metadata_options": true, + "monitoring": [], + "name": true, + "name_prefix": true, + "network_interfaces": [ + {} + ], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [], + "monitoring": [], + "network_interfaces": [ + {} + ], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + } + ], + "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_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "network_interfaces": [ + { + "associate_public_ip_address": { + "constant_value": false + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "timestamp": "2024-07-11T14:43:43Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-payload-03.json b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-payload-03.json new file mode 100644 index 00000000..0d495efc --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-ec2-public-ip/test/good-test/good-payload-03.json @@ -0,0 +1,125 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "associate_public_ip_address": false, + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "", + "instance_type": "t2.micro", + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "sensitive_values": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [], + "root_block_device": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "associate_public_ip_address": false, + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "", + "instance_type": "t2.micro", + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "after_unknown": { + "arn": true, + "ebs_block_device": true, + "ebs_optimized": true, + "ephemeral_block_device": [], + "id": true, + "key_name": true, + "metadata_options": true, + "name": true, + "name_prefix": true, + "root_block_device": true + }, + "before_sensitive": false, + "after_sensitive": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [], + "root_block_device": [] + } + } + } + ], + "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_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "associate_public_ip_address": { + "constant_value": false + }, + "image_id": { + "constant_value": "" + }, + "instance_type": { + "constant_value": "t2.micro" + } + }, + "schema_version": 0 + } + ] + } + }, + "timestamp": "2024-07-11T14:44:06Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/README.md b/terraform/plan/ec2-best-practices/check-imds-v1/README.md new file mode 100644 index 00000000..2374a64d --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/README.md @@ -0,0 +1,84 @@ +# Check EC2 IMDSv1 + +The Instance Metadata Service (IMDS) is a feature provided by AWS that allows applications running on an EC2 instance to get information about the instance. This service is attached locally to every EC2 instance, the IMDS runs on a special “link local” IP address of 169.254.169.254 that means only software running on the instance can access it. For applications with access to IMDS, it makes available metadata about the instance, its network, storage and other information. The IMDS also makes the AWS credentials available for any IAM role that is attached to the instance. + +You can access instance metadata from a running instance using one of the following methods: + +- Instance Metadata Service Version 1 (IMDSv1) – a request/response method +- Instance Metadata Service Version 2 (IMDSv2) – a session-oriented method + +IMDSv2 adds an authentication step, making it harder for unauthorized users or attackers to access instance metadata. This feature helps protect against various vulnerabilities, such as misconfigured firewalls and SSRF attacks, making your EC2 instances more secure. + +You can read more about it from the following links: +[Add defense in depth against open firewalls, reverse proxies, and SSRF vulnerabilities with enhancements to the EC2 Instance Metadata Service](https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service/) +[Use IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html) + +## Policy Details: + +- **Policy Name:** check-imds-v1 +- **Check Description:** This policy ensures that EC2 instances make use of IMDSv2 instead of IMDSv1 +- **Policy Category:** AWS EC2 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-imds-v1.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=check-imds-v1, RULE=check-imds-v1) + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-imds-v1.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=check-imds-v1, RULE=check-imds-v1) + -> IMDSv1 should not be enabled, use IMDSv2 instead (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: false: Expected value: true (PATH=~.(planned_values.root_module.resources[?type=='aws_instance' || type=='aws_launch_template' || type=='aws_launch_configuration'])[0].values.~.(metadata_options || `[{}]`)[0].(http_endpoint == 'disabled' || http_tokens == 'required')) + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/check-imds-v1.yaml b/terraform/plan/ec2-best-practices/check-imds-v1/check-imds-v1.yaml new file mode 100644 index 00000000..dc9f2b49 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/check-imds-v1.yaml @@ -0,0 +1,25 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-imds-v1 + annotations: + policies.kyverno.io/title: check-imds-v1 + policies.kyverno.io/category: AWS EC2 Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + Enabling IMDSv1 exposes cloud environments to significant security risks, and it is recommended to disable it in favor of more secure alternatives such as IMDSv2. +spec: + rules: + - name: check-imds-v1 + match: + any: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_instance' || type=='aws_launch_template' || type=='aws_launch_configuration'] | length(@) > `0`): true + assert: + all: + - message: "IMDSv1 should not be enabled, use IMDSv2 instead" + check: + ~.(planned_values.root_module.resources[?type=='aws_instance' || type=='aws_launch_template' || type=='aws_launch_configuration']): + values: + ~.(metadata_options || `[{}]`): + (http_endpoint == 'disabled' || http_tokens == 'required'): true diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-01.tf b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-01.tf new file mode 100644 index 00000000..a12dc986 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-01.tf @@ -0,0 +1,19 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_instance" "example" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t2.micro" +} \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-02.tf b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-02.tf new file mode 100644 index 00000000..23e60a56 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-02.tf @@ -0,0 +1,23 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_instance" "example" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t2.micro" + + metadata_options { + + } +} \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-03.tf b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-03.tf new file mode 100644 index 00000000..62f2012b --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-03.tf @@ -0,0 +1,24 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_instance" "example" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t2.micro" + + metadata_options { + http_endpoint = "enabled" + http_tokens = "optional" + } +} \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-04.tf b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-04.tf new file mode 100644 index 00000000..e55e3e19 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-04.tf @@ -0,0 +1,24 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_launch_configuration" "example" { + instance_type = "t2.micro" + image_id = "" + + metadata_options { + http_endpoint = "enabled" + http_tokens = "optional" + } +} \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-05.tf b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-05.tf new file mode 100644 index 00000000..ce76812f --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-05.tf @@ -0,0 +1,20 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_launch_template" "example" { + metadata_options { + http_tokens = "optional" + } +} \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-06.tf b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-06.tf new file mode 100644 index 00000000..977c6f75 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-06.tf @@ -0,0 +1,20 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_launch_template" "example" { + metadata_options { + http_endpoint = "enabled" + } +} \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-01.json b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..900f03bc --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-01.json @@ -0,0 +1,190 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "ami": "ami-0c55b159cbfafe1f0", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "sensitive_values": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "ami-0c55b159cbfafe1f0", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "availability_zone": true, + "capacity_reservation_specification": true, + "cpu_core_count": true, + "cpu_options": true, + "cpu_threads_per_core": true, + "credit_specification": [], + "disable_api_stop": true, + "disable_api_termination": true, + "ebs_block_device": true, + "ebs_optimized": true, + "enclave_options": true, + "ephemeral_block_device": true, + "host_id": true, + "host_resource_group_arn": true, + "iam_instance_profile": true, + "id": true, + "instance_initiated_shutdown_behavior": true, + "instance_lifecycle": true, + "instance_market_options": true, + "instance_state": true, + "ipv6_address_count": true, + "ipv6_addresses": true, + "key_name": true, + "launch_template": [], + "maintenance_options": true, + "metadata_options": true, + "monitoring": true, + "network_interface": true, + "outpost_arn": true, + "password_data": true, + "placement_group": true, + "placement_partition_number": true, + "primary_network_interface_id": true, + "private_dns": true, + "private_dns_name_options": true, + "private_ip": true, + "public_dns": true, + "public_ip": true, + "root_block_device": true, + "secondary_private_ips": true, + "security_groups": true, + "spot_instance_request_id": true, + "subnet_id": true, + "tags_all": true, + "tenancy": true, + "user_data": true, + "user_data_base64": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "ami": { + "constant_value": "ami-0c55b159cbfafe1f0" + }, + "instance_type": { + "constant_value": "t2.micro" + } + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-07-02T17:55:24Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-02.json b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-02.json new file mode 100644 index 00000000..958013f8 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-02.json @@ -0,0 +1,215 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "ami": "ami-0c55b159cbfafe1f0", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "metadata_options": [ + { + "http_endpoint": "enabled", + "http_protocol_ipv6": "disabled" + } + ], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "sensitive_values": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "ami-0c55b159cbfafe1f0", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "metadata_options": [ + { + "http_endpoint": "enabled", + "http_protocol_ipv6": "disabled" + } + ], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "availability_zone": true, + "capacity_reservation_specification": true, + "cpu_core_count": true, + "cpu_options": true, + "cpu_threads_per_core": true, + "credit_specification": [], + "disable_api_stop": true, + "disable_api_termination": true, + "ebs_block_device": true, + "ebs_optimized": true, + "enclave_options": true, + "ephemeral_block_device": true, + "host_id": true, + "host_resource_group_arn": true, + "iam_instance_profile": true, + "id": true, + "instance_initiated_shutdown_behavior": true, + "instance_lifecycle": true, + "instance_market_options": true, + "instance_state": true, + "ipv6_address_count": true, + "ipv6_addresses": true, + "key_name": true, + "launch_template": [], + "maintenance_options": true, + "metadata_options": [ + { + "http_put_response_hop_limit": true, + "http_tokens": true, + "instance_metadata_tags": true + } + ], + "monitoring": true, + "network_interface": true, + "outpost_arn": true, + "password_data": true, + "placement_group": true, + "placement_partition_number": true, + "primary_network_interface_id": true, + "private_dns": true, + "private_dns_name_options": true, + "private_ip": true, + "public_dns": true, + "public_ip": true, + "root_block_device": true, + "secondary_private_ips": true, + "security_groups": true, + "spot_instance_request_id": true, + "subnet_id": true, + "tags_all": true, + "tenancy": true, + "user_data": true, + "user_data_base64": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "ami": { + "constant_value": "ami-0c55b159cbfafe1f0" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "metadata_options": [ + {} + ] + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-07-02T17:58:22Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-03.json b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-03.json new file mode 100644 index 00000000..01895331 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-03.json @@ -0,0 +1,223 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "ami": "ami-0c55b159cbfafe1f0", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "metadata_options": [ + { + "http_endpoint": "enabled", + "http_protocol_ipv6": "disabled", + "http_tokens": "optional" + } + ], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "sensitive_values": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "ami-0c55b159cbfafe1f0", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "metadata_options": [ + { + "http_endpoint": "enabled", + "http_protocol_ipv6": "disabled", + "http_tokens": "optional" + } + ], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "availability_zone": true, + "capacity_reservation_specification": true, + "cpu_core_count": true, + "cpu_options": true, + "cpu_threads_per_core": true, + "credit_specification": [], + "disable_api_stop": true, + "disable_api_termination": true, + "ebs_block_device": true, + "ebs_optimized": true, + "enclave_options": true, + "ephemeral_block_device": true, + "host_id": true, + "host_resource_group_arn": true, + "iam_instance_profile": true, + "id": true, + "instance_initiated_shutdown_behavior": true, + "instance_lifecycle": true, + "instance_market_options": true, + "instance_state": true, + "ipv6_address_count": true, + "ipv6_addresses": true, + "key_name": true, + "launch_template": [], + "maintenance_options": true, + "metadata_options": [ + { + "http_put_response_hop_limit": true, + "instance_metadata_tags": true + } + ], + "monitoring": true, + "network_interface": true, + "outpost_arn": true, + "password_data": true, + "placement_group": true, + "placement_partition_number": true, + "primary_network_interface_id": true, + "private_dns": true, + "private_dns_name_options": true, + "private_ip": true, + "public_dns": true, + "public_ip": true, + "root_block_device": true, + "secondary_private_ips": true, + "security_groups": true, + "spot_instance_request_id": true, + "subnet_id": true, + "tags_all": true, + "tenancy": true, + "user_data": true, + "user_data_base64": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_instance.example", + "mode": "managed", + "type": "aws_instance", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "ami": { + "constant_value": "ami-0c55b159cbfafe1f0" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "metadata_options": [ + { + "http_endpoint": { + "constant_value": "enabled" + }, + "http_tokens": { + "constant_value": "optional" + } + } + ] + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-07-02T18:02:22Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-04.json b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-04.json new file mode 100644 index 00000000..5e496a08 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-04.json @@ -0,0 +1,151 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "", + "instance_type": "t2.micro", + "metadata_options": [ + { + "http_endpoint": "enabled", + "http_tokens": "optional" + } + ], + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "sensitive_values": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [ + {} + ], + "root_block_device": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "", + "instance_type": "t2.micro", + "metadata_options": [ + { + "http_endpoint": "enabled", + "http_tokens": "optional" + } + ], + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "ebs_block_device": true, + "ebs_optimized": true, + "ephemeral_block_device": [], + "id": true, + "key_name": true, + "metadata_options": [ + { + "http_put_response_hop_limit": true + } + ], + "name": true, + "name_prefix": true, + "root_block_device": true + }, + "before_sensitive": false, + "after_sensitive": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [ + {} + ], + "root_block_device": [] + } + } + } + ], + "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_launch_configuration.example", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "metadata_options": [ + { + "http_endpoint": { + "constant_value": "enabled" + }, + "http_tokens": { + "constant_value": "optional" + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "timestamp": "2024-07-02T18:06:23Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-05.json b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-05.json new file mode 100644 index 00000000..5cf0c302 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-05.json @@ -0,0 +1,236 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": null, + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": null, + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + { + "http_tokens": "optional" + } + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "sensitive_values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": null, + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": null, + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + { + "http_tokens": "optional" + } + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "after_unknown": { + "arn": true, + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "default_version": true, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "id": true, + "instance_market_options": [], + "instance_requirements": [], + "latest_version": true, + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + { + "http_endpoint": true, + "http_protocol_ipv6": true, + "http_put_response_hop_limit": true, + "instance_metadata_tags": true + } + ], + "monitoring": [], + "name": true, + "name_prefix": true, + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + } + ], + "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_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "metadata_options": [ + { + "http_tokens": { + "constant_value": "optional" + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "timestamp": "2024-07-02T18:08:06Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-06.json b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-06.json new file mode 100644 index 00000000..7240940f --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/bad-test/bad-payload-06.json @@ -0,0 +1,236 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": null, + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": null, + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + { + "http_endpoint": "enabled" + } + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "sensitive_values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": null, + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": null, + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + { + "http_endpoint": "enabled" + } + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "after_unknown": { + "arn": true, + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "default_version": true, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "id": true, + "instance_market_options": [], + "instance_requirements": [], + "latest_version": true, + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + { + "http_protocol_ipv6": true, + "http_put_response_hop_limit": true, + "http_tokens": true, + "instance_metadata_tags": true + } + ], + "monitoring": [], + "name": true, + "name_prefix": true, + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + } + ], + "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_launch_template.example", + "mode": "managed", + "type": "aws_launch_template", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "metadata_options": [ + { + "http_endpoint": { + "constant_value": "enabled" + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "timestamp": "2024-07-02T18:09:11Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/binding.yaml b/terraform/plan/ec2-best-practices/check-imds-v1/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/chainsaw-test.yaml b/terraform/plan/ec2-best-practices/check-imds-v1/test/chainsaw-test.yaml new file mode 100644 index 00000000..ac638025 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/chainsaw-test.yaml @@ -0,0 +1,273 @@ +# 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-imds-v1.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-imds-v1 + rules: + - rule: + name: check-imds-v1 + 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 --payload ./good-test/good-payload-02.json --policy ../check-imds-v1.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-imds-v1 + rules: + - rule: + name: check-imds-v1 + error: ~ + violations: ~ +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: good-test-03 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./good-test/good-payload-03.json --policy ../check-imds-v1.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-imds-v1 + rules: + - rule: + name: check-imds-v1 + 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 --payload ./bad-test/bad-payload-01.json --policy ../check-imds-v1.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-imds-v1 + rules: + - rule: + name: check-imds-v1 + error: ~ + violations: + - (contains(message, 'IMDSv1 should not be enabled, use IMDSv2 instead')): 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 --payload ./bad-test/bad-payload-02.json --policy ../check-imds-v1.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-imds-v1 + rules: + - rule: + name: check-imds-v1 + error: ~ + violations: + - (contains(message, 'IMDSv1 should not be enabled, use IMDSv2 instead')): 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 --payload ./bad-test/bad-payload-03.json --policy ../check-imds-v1.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-imds-v1 + rules: + - rule: + name: check-imds-v1 + error: ~ + violations: + - (contains(message, 'IMDSv1 should not be enabled, use IMDSv2 instead')): 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 --payload ./bad-test/bad-payload-04.json --policy ../check-imds-v1.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-imds-v1 + rules: + - rule: + name: check-imds-v1 + error: ~ + violations: + - (contains(message, 'IMDSv1 should not be enabled, use IMDSv2 instead')): true + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-05 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./bad-test/bad-payload-05.json --policy ../check-imds-v1.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-imds-v1 + rules: + - rule: + name: check-imds-v1 + error: ~ + violations: + - (contains(message, 'IMDSv1 should not be enabled, use IMDSv2 instead')): true + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: bad-test-06 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./bad-test/bad-payload-06.json --policy ../check-imds-v1.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-imds-v1 + rules: + - rule: + name: check-imds-v1 + error: ~ + violations: + - (contains(message, 'IMDSv1 should not be enabled, use IMDSv2 instead')): true + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-01.tf b/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-01.tf new file mode 100644 index 00000000..2da72cc3 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-01.tf @@ -0,0 +1,42 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_instance" "example_1" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t2.micro" + + metadata_options { + http_endpoint = "disabled" + } +} + +resource "aws_instance" "example_2" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t2.micro" + + metadata_options { + http_tokens = "required" + } +} + +resource "aws_instance" "example_3" { + ami = "ami-0c55b159cbfafe1f0" + instance_type = "t2.micro" + + metadata_options { + http_endpoint = "enabled" + http_tokens = "required" + } +} diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-02.tf b/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-02.tf new file mode 100644 index 00000000..086e3283 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-02.tf @@ -0,0 +1,43 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_launch_template" "example_1" { + instance_type = "t2.micro" + image_id = "" + + metadata_options { + http_endpoint = "disabled" + } +} + +resource "aws_launch_template" "example_2" { + instance_type = "t2.micro" + image_id = "" + + metadata_options { + http_tokens = "required" + } +} + +resource "aws_launch_template" "example_3" { + instance_type = "t2.micro" + image_id = "" + + metadata_options { + http_endpoint = "enabled" + http_tokens = "required" + } +} + diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-03.tf b/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-03.tf new file mode 100644 index 00000000..ef56a50b --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-03.tf @@ -0,0 +1,42 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_launch_configuration" "example_1" { + instance_type = "t2.micro" + image_id = "" + + metadata_options { + http_endpoint = "disabled" + } +} + +resource "aws_launch_configuration" "example_2" { + instance_type = "t2.micro" + image_id = "" + + metadata_options { + http_tokens = "required" + } +} + +resource "aws_launch_configuration" "example_3" { + instance_type = "t2.micro" + image_id = "" + + metadata_options { + http_endpoint = "enabled" + http_tokens = "required" + } +} diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-payload-01.json b/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-payload-01.json new file mode 100644 index 00000000..b231295a --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-payload-01.json @@ -0,0 +1,594 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_instance.example_1", + "mode": "managed", + "type": "aws_instance", + "name": "example_1", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "ami": "ami-0c55b159cbfafe1f0", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "metadata_options": [ + { + "http_endpoint": "disabled", + "http_protocol_ipv6": "disabled" + } + ], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "sensitive_values": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + }, + { + "address": "aws_instance.example_2", + "mode": "managed", + "type": "aws_instance", + "name": "example_2", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "ami": "ami-0c55b159cbfafe1f0", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "metadata_options": [ + { + "http_endpoint": "enabled", + "http_protocol_ipv6": "disabled", + "http_tokens": "required" + } + ], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "sensitive_values": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + }, + { + "address": "aws_instance.example_3", + "mode": "managed", + "type": "aws_instance", + "name": "example_3", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "ami": "ami-0c55b159cbfafe1f0", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "metadata_options": [ + { + "http_endpoint": "enabled", + "http_protocol_ipv6": "disabled", + "http_tokens": "required" + } + ], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "sensitive_values": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_instance.example_1", + "mode": "managed", + "type": "aws_instance", + "name": "example_1", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "ami-0c55b159cbfafe1f0", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "metadata_options": [ + { + "http_endpoint": "disabled", + "http_protocol_ipv6": "disabled" + } + ], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "availability_zone": true, + "capacity_reservation_specification": true, + "cpu_core_count": true, + "cpu_options": true, + "cpu_threads_per_core": true, + "credit_specification": [], + "disable_api_stop": true, + "disable_api_termination": true, + "ebs_block_device": true, + "ebs_optimized": true, + "enclave_options": true, + "ephemeral_block_device": true, + "host_id": true, + "host_resource_group_arn": true, + "iam_instance_profile": true, + "id": true, + "instance_initiated_shutdown_behavior": true, + "instance_lifecycle": true, + "instance_market_options": true, + "instance_state": true, + "ipv6_address_count": true, + "ipv6_addresses": true, + "key_name": true, + "launch_template": [], + "maintenance_options": true, + "metadata_options": [ + { + "http_put_response_hop_limit": true, + "http_tokens": true, + "instance_metadata_tags": true + } + ], + "monitoring": true, + "network_interface": true, + "outpost_arn": true, + "password_data": true, + "placement_group": true, + "placement_partition_number": true, + "primary_network_interface_id": true, + "private_dns": true, + "private_dns_name_options": true, + "private_ip": true, + "public_dns": true, + "public_ip": true, + "root_block_device": true, + "secondary_private_ips": true, + "security_groups": true, + "spot_instance_request_id": true, + "subnet_id": true, + "tags_all": true, + "tenancy": true, + "user_data": true, + "user_data_base64": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + }, + { + "address": "aws_instance.example_2", + "mode": "managed", + "type": "aws_instance", + "name": "example_2", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "ami-0c55b159cbfafe1f0", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "metadata_options": [ + { + "http_endpoint": "enabled", + "http_protocol_ipv6": "disabled", + "http_tokens": "required" + } + ], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "availability_zone": true, + "capacity_reservation_specification": true, + "cpu_core_count": true, + "cpu_options": true, + "cpu_threads_per_core": true, + "credit_specification": [], + "disable_api_stop": true, + "disable_api_termination": true, + "ebs_block_device": true, + "ebs_optimized": true, + "enclave_options": true, + "ephemeral_block_device": true, + "host_id": true, + "host_resource_group_arn": true, + "iam_instance_profile": true, + "id": true, + "instance_initiated_shutdown_behavior": true, + "instance_lifecycle": true, + "instance_market_options": true, + "instance_state": true, + "ipv6_address_count": true, + "ipv6_addresses": true, + "key_name": true, + "launch_template": [], + "maintenance_options": true, + "metadata_options": [ + { + "http_put_response_hop_limit": true, + "instance_metadata_tags": true + } + ], + "monitoring": true, + "network_interface": true, + "outpost_arn": true, + "password_data": true, + "placement_group": true, + "placement_partition_number": true, + "primary_network_interface_id": true, + "private_dns": true, + "private_dns_name_options": true, + "private_ip": true, + "public_dns": true, + "public_ip": true, + "root_block_device": true, + "secondary_private_ips": true, + "security_groups": true, + "spot_instance_request_id": true, + "subnet_id": true, + "tags_all": true, + "tenancy": true, + "user_data": true, + "user_data_base64": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + }, + { + "address": "aws_instance.example_3", + "mode": "managed", + "type": "aws_instance", + "name": "example_3", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "ami": "ami-0c55b159cbfafe1f0", + "credit_specification": [], + "get_password_data": false, + "hibernation": null, + "instance_type": "t2.micro", + "launch_template": [], + "metadata_options": [ + { + "http_endpoint": "enabled", + "http_protocol_ipv6": "disabled", + "http_tokens": "required" + } + ], + "source_dest_check": true, + "tags": null, + "timeouts": null, + "user_data_replace_on_change": false, + "volume_tags": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "availability_zone": true, + "capacity_reservation_specification": true, + "cpu_core_count": true, + "cpu_options": true, + "cpu_threads_per_core": true, + "credit_specification": [], + "disable_api_stop": true, + "disable_api_termination": true, + "ebs_block_device": true, + "ebs_optimized": true, + "enclave_options": true, + "ephemeral_block_device": true, + "host_id": true, + "host_resource_group_arn": true, + "iam_instance_profile": true, + "id": true, + "instance_initiated_shutdown_behavior": true, + "instance_lifecycle": true, + "instance_market_options": true, + "instance_state": true, + "ipv6_address_count": true, + "ipv6_addresses": true, + "key_name": true, + "launch_template": [], + "maintenance_options": true, + "metadata_options": [ + { + "http_put_response_hop_limit": true, + "instance_metadata_tags": true + } + ], + "monitoring": true, + "network_interface": true, + "outpost_arn": true, + "password_data": true, + "placement_group": true, + "placement_partition_number": true, + "primary_network_interface_id": true, + "private_dns": true, + "private_dns_name_options": true, + "private_ip": true, + "public_dns": true, + "public_ip": true, + "root_block_device": true, + "secondary_private_ips": true, + "security_groups": true, + "spot_instance_request_id": true, + "subnet_id": true, + "tags_all": true, + "tenancy": true, + "user_data": true, + "user_data_base64": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "ebs_block_device": [], + "enclave_options": [], + "ephemeral_block_device": [], + "instance_market_options": [], + "ipv6_addresses": [], + "launch_template": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "network_interface": [], + "private_dns_name_options": [], + "root_block_device": [], + "secondary_private_ips": [], + "security_groups": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_instance.example_1", + "mode": "managed", + "type": "aws_instance", + "name": "example_1", + "provider_config_key": "aws", + "expressions": { + "ami": { + "constant_value": "ami-0c55b159cbfafe1f0" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "metadata_options": [ + { + "http_endpoint": { + "constant_value": "disabled" + } + } + ] + }, + "schema_version": 1 + }, + { + "address": "aws_instance.example_2", + "mode": "managed", + "type": "aws_instance", + "name": "example_2", + "provider_config_key": "aws", + "expressions": { + "ami": { + "constant_value": "ami-0c55b159cbfafe1f0" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "metadata_options": [ + { + "http_tokens": { + "constant_value": "required" + } + } + ] + }, + "schema_version": 1 + }, + { + "address": "aws_instance.example_3", + "mode": "managed", + "type": "aws_instance", + "name": "example_3", + "provider_config_key": "aws", + "expressions": { + "ami": { + "constant_value": "ami-0c55b159cbfafe1f0" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "metadata_options": [ + { + "http_endpoint": { + "constant_value": "enabled" + }, + "http_tokens": { + "constant_value": "required" + } + } + ] + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-07-10T08:30:40Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-payload-02.json b/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-payload-02.json new file mode 100644 index 00000000..8442fac6 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-payload-02.json @@ -0,0 +1,662 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_launch_template.example_1", + "mode": "managed", + "type": "aws_launch_template", + "name": "example_1", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + { + "http_endpoint": "disabled" + } + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "sensitive_values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + }, + { + "address": "aws_launch_template.example_2", + "mode": "managed", + "type": "aws_launch_template", + "name": "example_2", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + { + "http_tokens": "required" + } + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "sensitive_values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + }, + { + "address": "aws_launch_template.example_3", + "mode": "managed", + "type": "aws_launch_template", + "name": "example_3", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + { + "http_endpoint": "enabled", + "http_tokens": "required" + } + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "sensitive_values": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_launch_template.example_1", + "mode": "managed", + "type": "aws_launch_template", + "name": "example_1", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + { + "http_endpoint": "disabled" + } + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "after_unknown": { + "arn": true, + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "default_version": true, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "id": true, + "instance_market_options": [], + "instance_requirements": [], + "latest_version": true, + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + { + "http_protocol_ipv6": true, + "http_put_response_hop_limit": true, + "http_tokens": true, + "instance_metadata_tags": true + } + ], + "monitoring": [], + "name": true, + "name_prefix": true, + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + }, + { + "address": "aws_launch_template.example_2", + "mode": "managed", + "type": "aws_launch_template", + "name": "example_2", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + { + "http_tokens": "required" + } + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "after_unknown": { + "arn": true, + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "default_version": true, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "id": true, + "instance_market_options": [], + "instance_requirements": [], + "latest_version": true, + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + { + "http_endpoint": true, + "http_protocol_ipv6": true, + "http_put_response_hop_limit": true, + "instance_metadata_tags": true + } + ], + "monitoring": [], + "name": true, + "name_prefix": true, + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + }, + { + "address": "aws_launch_template.example_3", + "mode": "managed", + "type": "aws_launch_template", + "name": "example_3", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "description": null, + "disable_api_stop": null, + "disable_api_termination": null, + "ebs_optimized": null, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "image_id": "", + "instance_initiated_shutdown_behavior": null, + "instance_market_options": [], + "instance_requirements": [], + "instance_type": "t2.micro", + "kernel_id": null, + "key_name": null, + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + { + "http_endpoint": "enabled", + "http_tokens": "required" + } + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "ram_disk_id": null, + "security_group_names": null, + "tag_specifications": [], + "tags": null, + "update_default_version": null, + "user_data": null, + "vpc_security_group_ids": null + }, + "after_unknown": { + "arn": true, + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "default_version": true, + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "id": true, + "instance_market_options": [], + "instance_requirements": [], + "latest_version": true, + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + { + "http_protocol_ipv6": true, + "http_put_response_hop_limit": true, + "instance_metadata_tags": true + } + ], + "monitoring": [], + "name": true, + "name_prefix": true, + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "block_device_mappings": [], + "capacity_reservation_specification": [], + "cpu_options": [], + "credit_specification": [], + "elastic_gpu_specifications": [], + "elastic_inference_accelerator": [], + "enclave_options": [], + "hibernation_options": [], + "iam_instance_profile": [], + "instance_market_options": [], + "instance_requirements": [], + "license_specification": [], + "maintenance_options": [], + "metadata_options": [ + {} + ], + "monitoring": [], + "network_interfaces": [], + "placement": [], + "private_dns_name_options": [], + "tag_specifications": [], + "tags_all": {} + } + } + } + ], + "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_launch_template.example_1", + "mode": "managed", + "type": "aws_launch_template", + "name": "example_1", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "metadata_options": [ + { + "http_endpoint": { + "constant_value": "disabled" + } + } + ] + }, + "schema_version": 0 + }, + { + "address": "aws_launch_template.example_2", + "mode": "managed", + "type": "aws_launch_template", + "name": "example_2", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "metadata_options": [ + { + "http_tokens": { + "constant_value": "required" + } + } + ] + }, + "schema_version": 0 + }, + { + "address": "aws_launch_template.example_3", + "mode": "managed", + "type": "aws_launch_template", + "name": "example_3", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "metadata_options": [ + { + "http_endpoint": { + "constant_value": "enabled" + }, + "http_tokens": { + "constant_value": "required" + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "timestamp": "2024-07-10T08:31:16Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-payload-03.json b/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-payload-03.json new file mode 100644 index 00000000..29dd022c --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-imds-v1/test/good-test/good-payload-03.json @@ -0,0 +1,377 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_launch_configuration.example_1", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example_1", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "", + "instance_type": "t2.micro", + "metadata_options": [ + { + "http_endpoint": "disabled" + } + ], + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "sensitive_values": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [ + {} + ], + "root_block_device": [] + } + }, + { + "address": "aws_launch_configuration.example_2", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example_2", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "", + "instance_type": "t2.micro", + "metadata_options": [ + { + "http_tokens": "required" + } + ], + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "sensitive_values": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [ + {} + ], + "root_block_device": [] + } + }, + { + "address": "aws_launch_configuration.example_3", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example_3", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "", + "instance_type": "t2.micro", + "metadata_options": [ + { + "http_endpoint": "enabled", + "http_tokens": "required" + } + ], + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "sensitive_values": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [ + {} + ], + "root_block_device": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_launch_configuration.example_1", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example_1", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "", + "instance_type": "t2.micro", + "metadata_options": [ + { + "http_endpoint": "disabled" + } + ], + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "ebs_block_device": true, + "ebs_optimized": true, + "ephemeral_block_device": [], + "id": true, + "key_name": true, + "metadata_options": [ + { + "http_put_response_hop_limit": true, + "http_tokens": true + } + ], + "name": true, + "name_prefix": true, + "root_block_device": true + }, + "before_sensitive": false, + "after_sensitive": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [ + {} + ], + "root_block_device": [] + } + } + }, + { + "address": "aws_launch_configuration.example_2", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example_2", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "", + "instance_type": "t2.micro", + "metadata_options": [ + { + "http_tokens": "required" + } + ], + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "ebs_block_device": true, + "ebs_optimized": true, + "ephemeral_block_device": [], + "id": true, + "key_name": true, + "metadata_options": [ + { + "http_endpoint": true, + "http_put_response_hop_limit": true + } + ], + "name": true, + "name_prefix": true, + "root_block_device": true + }, + "before_sensitive": false, + "after_sensitive": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [ + {} + ], + "root_block_device": [] + } + } + }, + { + "address": "aws_launch_configuration.example_3", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example_3", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "enable_monitoring": true, + "ephemeral_block_device": [], + "iam_instance_profile": null, + "image_id": "", + "instance_type": "t2.micro", + "metadata_options": [ + { + "http_endpoint": "enabled", + "http_tokens": "required" + } + ], + "placement_tenancy": null, + "security_groups": null, + "spot_price": null, + "user_data": null, + "user_data_base64": null + }, + "after_unknown": { + "arn": true, + "associate_public_ip_address": true, + "ebs_block_device": true, + "ebs_optimized": true, + "ephemeral_block_device": [], + "id": true, + "key_name": true, + "metadata_options": [ + { + "http_put_response_hop_limit": true + } + ], + "name": true, + "name_prefix": true, + "root_block_device": true + }, + "before_sensitive": false, + "after_sensitive": { + "ebs_block_device": [], + "ephemeral_block_device": [], + "metadata_options": [ + {} + ], + "root_block_device": [] + } + } + } + ], + "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_launch_configuration.example_1", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example_1", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "metadata_options": [ + { + "http_endpoint": { + "constant_value": "disabled" + } + } + ] + }, + "schema_version": 0 + }, + { + "address": "aws_launch_configuration.example_2", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example_2", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "metadata_options": [ + { + "http_tokens": { + "constant_value": "required" + } + } + ] + }, + "schema_version": 0 + }, + { + "address": "aws_launch_configuration.example_3", + "mode": "managed", + "type": "aws_launch_configuration", + "name": "example_3", + "provider_config_key": "aws", + "expressions": { + "image_id": { + "constant_value": "" + }, + "instance_type": { + "constant_value": "t2.micro" + }, + "metadata_options": [ + { + "http_endpoint": { + "constant_value": "enabled" + }, + "http_tokens": { + "constant_value": "required" + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "timestamp": "2024-07-10T09:36:01Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/README.md b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/README.md new file mode 100644 index 00000000..3c54c87f --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/README.md @@ -0,0 +1,75 @@ +# Check EC2 Transit Gateways VPC Request + +A Transit Gateway serves as a central network hub, connecting multiple VPCs and on-premises networks. When configured to automatically accept VPC attachment requests, there is a risk of unauthorized or unintended networks gaining access, potentially compromising security and leading to data breaches. + +"Auto Accept Shared Attachments" feature can pose a security risk by automatically accepting cross-account attachments. Disabling this feature is a recommended best practice to maintain control over which accounts are allowed to connect, ensuring only trusted and authorized requests are approved. + +## Policy Details: + +- **Policy Name:** check-transit-gateways-vpc-request +- **Check Description:** This policy ensures that an EC2 Transit Gateway does not automatically accept VPC attachment requests +- **Policy Category:** AWS EC2 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-transit-gateways-vpc-request.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=check-transit-gateways-vpc-request, RULE=check-transit-gateways-vpc-request) + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-transit-gateways-vpc-request.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=check-transit-gateways-vpc-request, RULE=check-transit-gateways-vpc-request) + -> 'auto_accept_shared_attachments' should either be omitted or set to 'disable' (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: false: Expected value: true (PATH=~.(planned_values.root_module.resources[?type=='aws_ec2_transit_gateway'])[0].values.(auto_accept_shared_attachments != 'enable')) + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/check-transit-gateways-vpc-request.yaml b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/check-transit-gateways-vpc-request.yaml new file mode 100644 index 00000000..4aa5e74e --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/check-transit-gateways-vpc-request.yaml @@ -0,0 +1,27 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-transit-gateways-vpc-request + annotations: + policies.kyverno.io/title: check-transit-gateways-vpc-request + policies.kyverno.io/category: AWS EC2 Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + Transit Gateways should not automatically accept VPC attachment requests to maintain control over network access, mitigate security risks, + comply with governance requirements, prevent resource exhaustion, ensure visibility and accountability, + avoid misconfigurations, and adhere to best practices for network security. +spec: + rules: + - name: check-transit-gateways-vpc-request + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_ec2_transit_gateway'] | length(@) > `0`): true + assert: + all: + - message: "'auto_accept_shared_attachments' should either be omitted or set to 'disable'" + check: + ~.(planned_values.root_module.resources[?type=='aws_ec2_transit_gateway']): + values: + (auto_accept_shared_attachments != 'enable'): true + diff --git a/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/bad-test/bad-01.tf b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/bad-test/bad-01.tf new file mode 100644 index 00000000..40432bad --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/bad-test/bad-01.tf @@ -0,0 +1,19 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_ec2_transit_gateway" "example" { + description = "example" + auto_accept_shared_attachments = "enable" +} diff --git a/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/bad-test/bad-payload-01.json b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..caf3f31c --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/bad-test/bad-payload-01.json @@ -0,0 +1,112 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_ec2_transit_gateway.example", + "mode": "managed", + "type": "aws_ec2_transit_gateway", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "amazon_side_asn": 64512, + "auto_accept_shared_attachments": "enable", + "default_route_table_association": "enable", + "default_route_table_propagation": "enable", + "description": "example", + "dns_support": "enable", + "multicast_support": "disable", + "tags": null, + "timeouts": null, + "transit_gateway_cidr_blocks": null, + "vpn_ecmp_support": "enable" + }, + "sensitive_values": { + "tags_all": {} + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_ec2_transit_gateway.example", + "mode": "managed", + "type": "aws_ec2_transit_gateway", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "amazon_side_asn": 64512, + "auto_accept_shared_attachments": "enable", + "default_route_table_association": "enable", + "default_route_table_propagation": "enable", + "description": "example", + "dns_support": "enable", + "multicast_support": "disable", + "tags": null, + "timeouts": null, + "transit_gateway_cidr_blocks": null, + "vpn_ecmp_support": "enable" + }, + "after_unknown": { + "arn": true, + "association_default_route_table_id": true, + "id": true, + "owner_id": true, + "propagation_default_route_table_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + } + ], + "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_ec2_transit_gateway.example", + "mode": "managed", + "type": "aws_ec2_transit_gateway", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "auto_accept_shared_attachments": { + "constant_value": "enable" + }, + "description": { + "constant_value": "example" + } + }, + "schema_version": 0 + } + ] + } + }, + "timestamp": "2024-06-28T08:02:00Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/binding.yaml b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/chainsaw-test.yaml b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/chainsaw-test.yaml new file mode 100644 index 00000000..bc7b2750 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/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 --payload ./good-test/good-payload-01.json --policy ../check-transit-gateways-vpc-request.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-transit-gateways-vpc-request + rules: + - rule: + name: check-transit-gateways-vpc-request + 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 --payload ./good-test/good-payload-02.json --policy ../check-transit-gateways-vpc-request.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-transit-gateways-vpc-request + rules: + - rule: + name: check-transit-gateways-vpc-request + 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 ../check-transit-gateways-vpc-request.yaml --payload ./bad-test/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: check-transit-gateways-vpc-request + rules: + - rule: + name: check-transit-gateways-vpc-request + error: ~ + violations: + - (contains(message, '\'auto_accept_shared_attachments\' should either be omitted or set to \'disable\'')): true + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' diff --git a/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/good-test/good-01.tf b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/good-test/good-01.tf new file mode 100644 index 00000000..a21ef89d --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/good-test/good-01.tf @@ -0,0 +1,19 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_ec2_transit_gateway" "example" { + description = "example" +} + diff --git a/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/good-test/good-02.tf b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/good-test/good-02.tf new file mode 100644 index 00000000..86e6d676 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/good-test/good-02.tf @@ -0,0 +1,19 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_ec2_transit_gateway" "example" { + description = "example" + auto_accept_shared_attachments = "disable" +} diff --git a/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/good-test/good-payload-01.json b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/good-test/good-payload-01.json new file mode 100644 index 00000000..b911f97a --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/good-test/good-payload-01.json @@ -0,0 +1,109 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_ec2_transit_gateway.example", + "mode": "managed", + "type": "aws_ec2_transit_gateway", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "amazon_side_asn": 64512, + "auto_accept_shared_attachments": "disable", + "default_route_table_association": "enable", + "default_route_table_propagation": "enable", + "description": "example", + "dns_support": "enable", + "multicast_support": "disable", + "tags": null, + "timeouts": null, + "transit_gateway_cidr_blocks": null, + "vpn_ecmp_support": "enable" + }, + "sensitive_values": { + "tags_all": {} + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_ec2_transit_gateway.example", + "mode": "managed", + "type": "aws_ec2_transit_gateway", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "amazon_side_asn": 64512, + "auto_accept_shared_attachments": "disable", + "default_route_table_association": "enable", + "default_route_table_propagation": "enable", + "description": "example", + "dns_support": "enable", + "multicast_support": "disable", + "tags": null, + "timeouts": null, + "transit_gateway_cidr_blocks": null, + "vpn_ecmp_support": "enable" + }, + "after_unknown": { + "arn": true, + "association_default_route_table_id": true, + "id": true, + "owner_id": true, + "propagation_default_route_table_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + } + ], + "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_ec2_transit_gateway.example", + "mode": "managed", + "type": "aws_ec2_transit_gateway", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "description": { + "constant_value": "example" + } + }, + "schema_version": 0 + } + ] + } + }, + "timestamp": "2024-06-28T08:04:49Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/good-test/good-payload-02.json b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/good-test/good-payload-02.json new file mode 100644 index 00000000..ad524b37 --- /dev/null +++ b/terraform/plan/ec2-best-practices/check-transit-gateways-vpc-request/test/good-test/good-payload-02.json @@ -0,0 +1,112 @@ +{ + "format_version": "1.2", + "terraform_version": "1.8.4", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_ec2_transit_gateway.example", + "mode": "managed", + "type": "aws_ec2_transit_gateway", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "amazon_side_asn": 64512, + "auto_accept_shared_attachments": "disable", + "default_route_table_association": "enable", + "default_route_table_propagation": "enable", + "description": "example", + "dns_support": "enable", + "multicast_support": "disable", + "tags": null, + "timeouts": null, + "transit_gateway_cidr_blocks": null, + "vpn_ecmp_support": "enable" + }, + "sensitive_values": { + "tags_all": {} + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_ec2_transit_gateway.example", + "mode": "managed", + "type": "aws_ec2_transit_gateway", + "name": "example", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "amazon_side_asn": 64512, + "auto_accept_shared_attachments": "disable", + "default_route_table_association": "enable", + "default_route_table_propagation": "enable", + "description": "example", + "dns_support": "enable", + "multicast_support": "disable", + "tags": null, + "timeouts": null, + "transit_gateway_cidr_blocks": null, + "vpn_ecmp_support": "enable" + }, + "after_unknown": { + "arn": true, + "association_default_route_table_id": true, + "id": true, + "owner_id": true, + "propagation_default_route_table_id": true, + "tags_all": true + }, + "before_sensitive": false, + "after_sensitive": { + "tags_all": {} + } + } + } + ], + "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_ec2_transit_gateway.example", + "mode": "managed", + "type": "aws_ec2_transit_gateway", + "name": "example", + "provider_config_key": "aws", + "expressions": { + "auto_accept_shared_attachments": { + "constant_value": "disable" + }, + "description": { + "constant_value": "example" + } + }, + "schema_version": 0 + } + ] + } + }, + "timestamp": "2024-06-28T08:07:03Z", + "applyable": true, + "complete": true, + "errored": false +} From 0f21f1133864dae856019b49a27538d43920d6f3 Mon Sep 17 00:00:00 2001 From: Chandan-DK Date: Wed, 2 Oct 2024 22:13:40 +0000 Subject: [PATCH 2/3] add lambda best practices terraform plan policies Signed-off-by: Chandan-DK --- .../check-dead-letter-queue-config/README.md | 73 +++ .../check-dead-letter-queue-config.yaml | 25 + .../test/bad-test/bad-01.tf | 45 ++ .../test/bad-test/bad-payload-01.json | 340 +++++++++++ .../test/binding.yaml | 3 + .../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 | 75 +++ .../check-lambda-public-access.yaml | 25 + .../test/bad-test/bad-01.tf | 51 ++ .../test/bad-test/bad-payload-01.json | 419 +++++++++++++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 61 ++ .../test/good-test/good-01.tf | 51 ++ .../test/good-test/good-payload-01.json | 419 +++++++++++++ .../check-lambda-vpc/README.md | 73 +++ .../check-lambda-vpc/check-lambda-vpc.yaml | 26 + .../check-lambda-vpc/test/bad-test/bad-01.tf | 46 ++ .../test/bad-test/bad-payload-01.json | 340 +++++++++++ .../check-lambda-vpc/test/binding.yaml | 3 + .../check-lambda-vpc/test/chainsaw-test.yaml | 60 ++ .../test/good-test/good-01.tf | 50 ++ .../test/good-test/good-payload-01.json | 408 +++++++++++++ .../check-source-arn-account/README.md | 73 +++ .../check-source-arn-account.yaml | 24 + .../test/bad-test/bad-01.tf | 51 ++ .../test/bad-test/bad-payload-01.json | 419 +++++++++++++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 61 ++ .../test/good-test/good-01.tf | 67 ++ .../test/good-test/good-payload-01.json | 577 ++++++++++++++++++ 32 files changed, 4341 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/binding.yaml 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-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/binding.yaml 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-vpc/README.md create mode 100644 terraform/plan/lambda-best-practices/check-lambda-vpc/check-lambda-vpc.yaml create mode 100644 terraform/plan/lambda-best-practices/check-lambda-vpc/test/bad-test/bad-01.tf create mode 100644 terraform/plan/lambda-best-practices/check-lambda-vpc/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/lambda-best-practices/check-lambda-vpc/test/binding.yaml create mode 100644 terraform/plan/lambda-best-practices/check-lambda-vpc/test/chainsaw-test.yaml create mode 100644 terraform/plan/lambda-best-practices/check-lambda-vpc/test/good-test/good-01.tf create mode 100644 terraform/plan/lambda-best-practices/check-lambda-vpc/test/good-test/good-payload-01.json 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/binding.yaml 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 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..e02c32be --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/README.md @@ -0,0 +1,73 @@ +# 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 --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=check-dead-letter-queue-config, RULE=check-dead-letter-queue-config) + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-dead-letter-queue-config.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=check-dead-letter-queue-config, RULE=check-dead-letter-queue-config) + -> AWS Lambda function should be configured for a Dead Letter Queue(DLQ) (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: false: Expected value: true (PATH=~.(planned_values.root_module.resources[?type=='aws_lambda_function'])[0].values.(dead_letter_config != `[]`)) + 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..c1a8d192 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/check-dead-letter-queue-config.yaml @@ -0,0 +1,25 @@ +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: + - ($analyzer.resource.type): terraform-plan + - (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/binding.yaml b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-dead-letter-queue-config/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file 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..5b79c48f --- /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 --bindings ./binding.yaml + 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 --bindings ./binding.yaml + 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: + - (contains(message, 'AWS Lambda function should be configured for a Dead Letter Queue(DLQ)')): true + 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-lambda-public-access/README.md b/terraform/plan/lambda-best-practices/check-lambda-public-access/README.md new file mode 100644 index 00000000..1f3c29ea --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-public-access/README.md @@ -0,0 +1,75 @@ +# 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 --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=check-lambda-public-access, RULE=check-lambda-public-access) + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-lambda-public-access.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=check-lambda-public-access, RULE=check-lambda-public-access) + -> Principal must be set to a specific resource or user account and not '*' (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: false: Expected value: true (PATH=~.(planned_values.root_module.resources[?type=='aws_lambda_permission'])[0].values.(principal != '*')) + 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..339f86f6 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-public-access/check-lambda-public-access.yaml @@ -0,0 +1,25 @@ +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: + - ($analyzer.resource.type): terraform-plan + - (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/binding.yaml b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-public-access/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ 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..03f46edf --- /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 --bindings ./binding.yaml + 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 --bindings ./binding.yaml + 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: + - (contains(message, 'Principal must be set to a specific resource or user account and not \'*\'')): true + 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-vpc/README.md b/terraform/plan/lambda-best-practices/check-lambda-vpc/README.md new file mode 100644 index 00000000..fe5964d6 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-vpc/README.md @@ -0,0 +1,73 @@ +# Check Lambda VPC + +By default, Lambda functions run in a Lambda-managed VPC that has internet access. To access resources in a VPC in your account, you can add a VPC configuration to a function. This restricts the function to resources within that VPC, unless the VPC has internet access. Running Lambda functions within a VPC provides better isolation and control over network access. + +## Policy Details: + +- **Policy Name:** check-lambda-vpc +- **Check Description:** This policy validates whether vpc_config is specified for the Lambda function. +- **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-vpc.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=check-lambda-vpc, RULE=check-lambda-vpc) + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-lambda-vpc.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=check-lambda-vpc, RULE=check-lambda-vpc) + -> 'vpc_config' must be present for the Lambda function (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: false: Expected value: true (PATH=~.(planned_values.root_module.resources[?type=='aws_lambda_function'])[0].values.(vpc_config != `[]`)) + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-lambda-vpc/check-lambda-vpc.yaml b/terraform/plan/lambda-best-practices/check-lambda-vpc/check-lambda-vpc.yaml new file mode 100644 index 00000000..5d25ce44 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-vpc/check-lambda-vpc.yaml @@ -0,0 +1,26 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-lambda-vpc + annotations: + policies.kyverno.io/title: check-lambda-vpc + policies.kyverno.io/category: AWS Lambda Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + VPC provides isolation and enhanced security to Lambda functions. + This policy validates whether vpc_config is specified for the Lambda function. +spec: + rules: + - name: check-lambda-vpc + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_lambda_function'] | length(@) > `0`): true + assert: + all: + - message: "'vpc_config' must be present for the Lambda function" + check: + ~.(planned_values.root_module.resources[?type=='aws_lambda_function']): + values: + (vpc_config != `[]`): true + diff --git a/terraform/plan/lambda-best-practices/check-lambda-vpc/test/bad-test/bad-01.tf b/terraform/plan/lambda-best-practices/check-lambda-vpc/test/bad-test/bad-01.tf new file mode 100644 index 00000000..e0a91671 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-vpc/test/bad-test/bad-01.tf @@ -0,0 +1,46 @@ +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-lambda-vpc/test/bad-test/bad-payload-01.json b/terraform/plan/lambda-best-practices/check-lambda-vpc/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..95452faa --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-vpc/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-06-26T17:14:11Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/lambda-best-practices/check-lambda-vpc/test/binding.yaml b/terraform/plan/lambda-best-practices/check-lambda-vpc/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-vpc/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/lambda-best-practices/check-lambda-vpc/test/chainsaw-test.yaml b/terraform/plan/lambda-best-practices/check-lambda-vpc/test/chainsaw-test.yaml new file mode 100644 index 00000000..780925f4 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-vpc/test/chainsaw-test.yaml @@ -0,0 +1,60 @@ +# 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-vpc.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-lambda-vpc + rules: + - rule: + name: check-lambda-vpc + 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-vpc.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-lambda-vpc + rules: + - rule: + name: check-lambda-vpc + error: ~ + violations: + - (contains(message, '\'vpc_config\' must be present for the Lambda function')): true + errors: + - type: FieldValueInvalid + value: false + detail: 'Expected value: true' diff --git a/terraform/plan/lambda-best-practices/check-lambda-vpc/test/good-test/good-01.tf b/terraform/plan/lambda-best-practices/check-lambda-vpc/test/good-test/good-01.tf new file mode 100644 index 00000000..0b4c998a --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-vpc/test/good-test/good-01.tf @@ -0,0 +1,50 @@ +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 = "" + + vpc_config { + subnet_ids = ["subnet-12345678", "subnet-87654321"] + security_group_ids = ["sg-abcdef12"] + } +} + +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-vpc/test/good-test/good-payload-01.json b/terraform/plan/lambda-best-practices/check-lambda-vpc/test/good-test/good-payload-01.json new file mode 100644 index 00000000..2770dcc6 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-lambda-vpc/test/good-test/good-payload-01.json @@ -0,0 +1,408 @@ +{ + "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": [ + { + "ipv6_allowed_for_dual_stack": false, + "security_group_ids": [ + "sg-abcdef12" + ], + "subnet_ids": [ + "subnet-12345678", + "subnet-87654321" + ] + } + ] + }, + "sensitive_values": { + "architectures": [], + "dead_letter_config": [], + "environment": [], + "ephemeral_storage": [], + "file_system_config": [], + "image_config": [], + "logging_config": [], + "snap_start": [], + "tags_all": {}, + "tracing_config": [], + "vpc_config": [ + { + "security_group_ids": [ + false + ], + "subnet_ids": [ + false, + false + ] + } + ] + } + } + ] + } + }, + "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": [ + { + "ipv6_allowed_for_dual_stack": false, + "security_group_ids": [ + "sg-abcdef12" + ], + "subnet_ids": [ + "subnet-12345678", + "subnet-87654321" + ] + } + ] + }, + "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": [ + { + "security_group_ids": [ + false + ], + "subnet_ids": [ + false, + false + ], + "vpc_id": true + } + ] + }, + "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": [ + { + "security_group_ids": [ + false + ], + "subnet_ids": [ + false, + false + ] + } + ] + } + } + } + ], + "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" + }, + "vpc_config": [ + { + "security_group_ids": { + "constant_value": [ + "sg-abcdef12" + ] + }, + "subnet_ids": { + "constant_value": [ + "subnet-12345678", + "subnet-87654321" + ] + } + } + ] + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_iam_role.lambda_exec", + "attribute": [ + "arn" + ] + }, + { + "resource": "aws_iam_role.lambda_exec", + "attribute": [ + "name" + ] + } + ], + "timestamp": "2024-06-26T17:17:12Z", + "applyable": true, + "complete": true, + "errored": false +} 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 new file mode 100644 index 00000000..4fcd41b2 --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-source-arn-account/README.md @@ -0,0 +1,73 @@ +# 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 --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=check-source-arn-account, RULE=check-source-arn-account) + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-source-arn-account.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ``` + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=check-source-arn-account, RULE=check-source-arn-account) + -> AWS Lambda function permissions delegated to AWS services should be limited by SourceArn or SourceAccount (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: true: Expected value: false (PATH=~.(planned_values.root_module.resources[?type=='aws_lambda_permission'].values[?ends_with(principal, '.amazonaws.com')])[0].(!source_arn == `true` && !source_account == `true`)) + 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..0213179f --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-source-arn-account/check-source-arn-account.yaml @@ -0,0 +1,24 @@ +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: + - ($analyzer.resource.type): terraform-plan + - (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/binding.yaml b/terraform/plan/lambda-best-practices/check-source-arn-account/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/lambda-best-practices/check-source-arn-account/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file 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..ad86581f --- /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 --bindings ./binding.yaml + 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 --bindings ./binding.yaml + 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: + - (contains(message, 'AWS Lambda function permissions delegated to AWS services should be limited by SourceArn or SourceAccount')): true + 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 +} From cfa4d2ce2b18ae87d817939d9e72791d4cb79008 Mon Sep 17 00:00:00 2001 From: Chandan-DK Date: Wed, 2 Oct 2024 22:14:48 +0000 Subject: [PATCH 3/3] add rds best practices terraform plan policies Signed-off-by: Chandan-DK --- .../README.md | 76 ++++ ...ds-aurora-mysql-audit-logging-enabled.yaml | 29 ++ .../test/bad-test/bad-01.tf | 24 ++ .../test/bad-test/bad-payload-01.json | 224 ++++++++++++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 82 +++++ .../test/good-test/good-01.tf | 24 ++ .../test/good-test/good-payload-01.json | 242 +++++++++++++ .../test/skip-test/skip-01.tf | 24 ++ .../test/skip-test/skip-payload-01.json | 227 ++++++++++++ .../README.md | 76 ++++ ...tomatic-minor-version-upgrade-enabled.yaml | 27 ++ .../test/bad-test/bad-01.tf | 25 ++ .../test/bad-test/bad-payload-01.json | 240 ++++++++++++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 86 +++++ .../test/good-test/good-01.tf | 25 ++ .../test/good-test/good-02.tf | 26 ++ .../test/good-test/good-payload-01.json | 240 ++++++++++++ .../test/good-test/good-payload-02.json | 237 ++++++++++++ .../README.md | 76 ++++ ...s-cluster-deletion-protection-enabled.yaml | 27 ++ .../test/bad-test/bad-01.tf | 22 ++ .../test/bad-test/bad-02.tf | 23 ++ .../test/bad-test/bad-payload-01.json | 220 +++++++++++ .../test/bad-test/bad-payload-02.json | 217 +++++++++++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 91 +++++ .../test/good-test/good-01.tf | 22 ++ .../test/good-test/good-payload-01.json | 220 +++++++++++ .../check-rds-db-proxy-tls/README.md | 76 ++++ .../check-rds-db-proxy-tls.yaml | 27 ++ .../test/bad-test/bad-01.tf | 43 +++ .../test/bad-test/bad-02.tf | 42 +++ .../test/bad-test/bad-payload-01.json | 342 ++++++++++++++++++ .../test/bad-test/bad-payload-02.json | 339 +++++++++++++++++ .../check-rds-db-proxy-tls/test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 91 +++++ .../test/good-test/good-01.tf | 43 +++ .../test/good-test/good-payload-01.json | 342 ++++++++++++++++++ .../README.md | 78 ++++ ...stance-copy-tags-to-snapshots-enabled.yaml | 28 ++ .../test/bad-test/bad-01.tf | 25 ++ .../test/bad-test/bad-02.tf | 26 ++ .../test/bad-test/bad-payload-01.json | 240 ++++++++++++ .../test/bad-test/bad-payload-02.json | 237 ++++++++++++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 92 +++++ .../test/good-test/good-01.tf | 25 ++ .../test/good-test/good-payload-01.json | 240 ++++++++++++ .../README.md | 75 ++++ .../check-rds-instance-public-access.yaml | 28 ++ .../test/bad-test/bad-01.tf | 26 ++ .../test/bad-test/bad-payload-01.json | 244 +++++++++++++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 86 +++++ .../test/good-test/good-01.tf | 26 ++ .../test/good-test/good-02.tf | 27 ++ .../test/good-test/good-payload-01.json | 244 +++++++++++++ .../test/good-test/good-payload-02.json | 241 ++++++++++++ .../check-rds-multi-az-support/README.md | 77 ++++ .../check-rds-multi-az-support.yaml | 27 ++ .../test/bad-test/bad-01.tf | 25 ++ .../test/bad-test/bad-02.tf | 24 ++ .../test/bad-test/bad-payload-01.json | 241 ++++++++++++ .../test/bad-test/bad-payload-02.json | 237 ++++++++++++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 92 +++++ .../test/good-test/good-01.tf | 25 ++ .../test/good-test/good-payload-01.json | 241 ++++++++++++ .../check-rds-storage-encrypted.yaml | 31 ++ .../test/README.md | 110 ++++++ .../test/bad-test/bad-01.tf | 25 ++ .../test/bad-test/bad-02.tf | 24 ++ .../test/bad-test/bad-payload-01.json | 240 ++++++++++++ .../test/bad-test/bad-payload-02.json | 237 ++++++++++++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 91 +++++ .../test/good-test/good-01.tf | 25 ++ .../test/good-test/good-payload-01.json | 240 ++++++++++++ .../README.md | 89 +++++ ...s-instance-iam-authentication-enabled.yaml | 37 ++ .../test/bad-test/bad-01.tf | 25 ++ .../test/bad-test/bad-02.tf | 24 ++ .../test/bad-test/bad-payload-01.json | 240 ++++++++++++ .../test/bad-test/bad-payload-02.json | 237 ++++++++++++ .../test/binding.yaml | 3 + .../test/chainsaw-test.yaml | 114 ++++++ .../test/good-test/good-01.tf | 25 ++ .../test/good-test/good-payload-01.json | 240 ++++++++++++ .../test/skip-test/skip-01.tf | 24 ++ .../test/skip-test/skip-payload-01.json | 237 ++++++++++++ 92 files changed, 9516 insertions(+) create mode 100644 terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/README.md create mode 100644 terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/check-rds-aurora-mysql-audit-logging-enabled.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/bad-test/bad-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/binding.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/chainsaw-test.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/good-test/good-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/good-test/good-payload-01.json create mode 100644 terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/skip-test/skip-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/skip-test/skip-payload-01.json create mode 100644 terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/README.md create mode 100644 terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/check-rds-automatic-minor-version-upgrade-enabled.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/bad-test/bad-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/binding.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/chainsaw-test.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/good-test/good-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/good-test/good-02.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/good-test/good-payload-01.json create mode 100644 terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/good-test/good-payload-02.json create mode 100644 terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/README.md create mode 100644 terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/check-rds-cluster-deletion-protection-enabled.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/bad-test/bad-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/bad-test/bad-02.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/bad-test/bad-payload-02.json create mode 100644 terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/binding.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/chainsaw-test.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/good-test/good-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/good-test/good-payload-01.json create mode 100644 terraform/plan/rds-best-practices/check-rds-db-proxy-tls/README.md create mode 100644 terraform/plan/rds-best-practices/check-rds-db-proxy-tls/check-rds-db-proxy-tls.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/bad-test/bad-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/bad-test/bad-02.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/bad-test/bad-payload-02.json create mode 100644 terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/binding.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/chainsaw-test.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/good-test/good-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/good-test/good-payload-01.json create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/README.md create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/check-rds-instance-copy-tags-to-snapshots-enabled.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/bad-test/bad-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/bad-test/bad-02.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/bad-test/bad-payload-02.json create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/binding.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/chainsaw-test.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/good-test/good-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/good-test/good-payload-01.json create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-public-access/README.md create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-public-access/check-rds-instance-public-access.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-public-access/test/bad-test/bad-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-public-access/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-public-access/test/binding.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-public-access/test/chainsaw-test.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-public-access/test/good-test/good-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-public-access/test/good-test/good-02.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-public-access/test/good-test/good-payload-01.json create mode 100644 terraform/plan/rds-best-practices/check-rds-instance-public-access/test/good-test/good-payload-02.json create mode 100644 terraform/plan/rds-best-practices/check-rds-multi-az-support/README.md create mode 100644 terraform/plan/rds-best-practices/check-rds-multi-az-support/check-rds-multi-az-support.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-multi-az-support/test/bad-test/bad-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-multi-az-support/test/bad-test/bad-02.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-multi-az-support/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/rds-best-practices/check-rds-multi-az-support/test/bad-test/bad-payload-02.json create mode 100644 terraform/plan/rds-best-practices/check-rds-multi-az-support/test/binding.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-multi-az-support/test/chainsaw-test.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-multi-az-support/test/good-test/good-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-multi-az-support/test/good-test/good-payload-01.json create mode 100644 terraform/plan/rds-best-practices/check-rds-storage-encrypted/check-rds-storage-encrypted.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/README.md create mode 100644 terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/bad-test/bad-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/bad-test/bad-02.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/bad-test/bad-payload-02.json create mode 100644 terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/binding.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/chainsaw-test.yaml create mode 100644 terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/good-test/good-01.tf create mode 100644 terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/good-test/good-payload-01.json create mode 100644 terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/README.md create mode 100644 terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/rds-instance-iam-authentication-enabled.yaml create mode 100644 terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/bad-test/bad-01.tf create mode 100644 terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/bad-test/bad-02.tf create mode 100644 terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/bad-test/bad-payload-01.json create mode 100644 terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/bad-test/bad-payload-02.json create mode 100644 terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/binding.yaml create mode 100644 terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/chainsaw-test.yaml create mode 100644 terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/good-test/good-01.tf create mode 100644 terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/good-test/good-payload-01.json create mode 100644 terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/skip-test/skip-01.tf create mode 100644 terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/skip-test/skip-payload-01.json diff --git a/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/README.md b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/README.md new file mode 100644 index 00000000..9af4059a --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/README.md @@ -0,0 +1,76 @@ +# Check RDS Aurora Mysql Audit Logging Enabled + +This policy checks whether an Amazon Aurora MySQL DB cluster is configured to publish audit logs to Amazon CloudWatch Logs. +The policy fails if the cluster isn't configured to publish audit logs to CloudWatch Logs. The policy doesn't generate findings foAurora Serverless v1 DB clusters. Audit logs capture a record of database activity, including login attempts, data modifications, schema changes, and other events that can be audited for security and compliance purposes. +When you configure an Aurora MySQL DB cluster to publish audit logs to a log group in Amazon CloudWatch Logs, you can perform real-time analysis of the log data. +CloudWatch Logs retains logs in highly durable storage. You can also create alarms and view metrics in CloudWatch. + +## Policy Details: + +- **Policy Name:** check-rds-aurora-mysql-audit-logging-enabled +- **Check Description:** This policy checks whether Aurora MySQL DB clusters publish audit logs to CloudWatch Logs +- **Policy Category:** AWS RDS 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:** + ```bash + kyverno-json scan --payload payload.json --policy policy.yaml + ``` + + a. **Test Policy Against Valid Payload:** + ```bash + kyverno-json scan --payload test/good-test/good-payload-01.json --policy check-rds-aurora-mysql-audit-logging-enabled.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=check-rds-aurora-mysql-audit-logging-enabled, RULE=check-rds-aurora-mysql-audit-logging-enabled) + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-rds-aurora-mysql-audit-logging-enabled.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=check-rds-aurora-mysql-audit-logging-enabled, RULE=check-rds-aurora-mysql-audit-logging-enabled) + -> Aurora MySQL DB clusters should publish audit logs to CloudWatch Logs (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: false: Expected value: true (PATH=~.(planned_values.root_module.resources[?type=='aws_rds_cluster' && contains('aurora-mysql', values.engine) && !contains('serverless', values.engine_mode)])[0].values.(enabled_cloudwatch_logs_exports != `null` && length(enabled_cloudwatch_logs_exports) > `0`)) + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/check-rds-aurora-mysql-audit-logging-enabled.yaml b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/check-rds-aurora-mysql-audit-logging-enabled.yaml new file mode 100644 index 00000000..dfe498c7 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/check-rds-aurora-mysql-audit-logging-enabled.yaml @@ -0,0 +1,29 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-rds-aurora-mysql-audit-logging-enabled + annotations: + policies.kyverno.io/title: Check RDS Aurora Mysql Audit Logging Enabled + policies.kyverno.io/category: AWS RDS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy checks whether an Amazon Aurora MySQL DB cluster is configured to publish audit logs to Amazon CloudWatch Logs. + The policy fails if the cluster isn't configured to publish audit logs to CloudWatch Logs. The policy doesn't generate findings for Aurora Serverless v1 DB clusters. + Audit logs capture a record of database activity, including login attempts, data modifications, schema changes, and other events + that can be audited for security and compliance purposes. When you configure an Aurora MySQL DB cluster to publish + audit logs to a log group in Amazon CloudWatch Logs, you can perform real-time analysis of the log data. + CloudWatch Logs retains logs in highly durable storage. You can also create alarms and view metrics in CloudWatch. +spec: + rules: + - name: check-rds-aurora-mysql-audit-logging-enabled + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_rds_cluster' && contains('aurora-mysql', values.engine) && !contains('serverless', values.engine_mode)] || `[]` | length(@) > `0`): true + assert: + all: + - message: Aurora MySQL DB clusters should publish audit logs to CloudWatch Logs + check: + ~.(planned_values.root_module.resources[?type=='aws_rds_cluster' && contains('aurora-mysql', values.engine) && !contains('serverless', values.engine_mode)]): + values: + (enabled_cloudwatch_logs_exports != `null` && length(enabled_cloudwatch_logs_exports) > `0`): true \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/bad-test/bad-01.tf b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/bad-test/bad-01.tf new file mode 100644 index 00000000..2c767af2 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/bad-test/bad-01.tf @@ -0,0 +1,24 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" # Updated region +} + +# No audit log publication to CloudWatch Logs +resource "aws_rds_cluster" "bad_aurora_mysql_cluster" { + cluster_identifier = "bad-aurora-mysql-cluster" + engine = "aurora-mysql" + master_username = "admin" + master_password = "secret99" + backup_retention_period = 7 + skip_final_snapshot = true +} diff --git a/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/bad-test/bad-payload-01.json b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..76eea0ce --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/bad-test/bad-payload-01.json @@ -0,0 +1,224 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_rds_cluster.bad_aurora_mysql_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "bad_aurora_mysql_cluster", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "allow_major_version_upgrade": null, + "backtrack_window": null, + "backup_retention_period": 7, + "cluster_identifier": "bad-aurora-mysql-cluster", + "copy_tags_to_snapshot": false, + "db_cluster_instance_class": null, + "db_instance_parameter_group_name": null, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_iam_role_name": null, + "enable_global_write_forwarding": false, + "enable_http_endpoint": false, + "enable_local_write_forwarding": false, + "enabled_cloudwatch_logs_exports": null, + "engine": "aurora-mysql", + "engine_mode": "provisioned", + "final_snapshot_identifier": null, + "global_cluster_identifier": null, + "iam_database_authentication_enabled": null, + "iops": null, + "manage_master_user_password": null, + "master_password": "secret99", + "master_username": "admin", + "performance_insights_enabled": null, + "replication_source_identifier": null, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "skip_final_snapshot": true, + "snapshot_identifier": null, + "source_region": null, + "tags": null, + "timeouts": null + }, + "sensitive_values": { + "availability_zones": [], + "cluster_members": [], + "iam_roles": [], + "master_password": true, + "master_user_secret": [], + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_rds_cluster.bad_aurora_mysql_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "bad_aurora_mysql_cluster", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allow_major_version_upgrade": null, + "backtrack_window": null, + "backup_retention_period": 7, + "cluster_identifier": "bad-aurora-mysql-cluster", + "copy_tags_to_snapshot": false, + "db_cluster_instance_class": null, + "db_instance_parameter_group_name": null, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_iam_role_name": null, + "enable_global_write_forwarding": false, + "enable_http_endpoint": false, + "enable_local_write_forwarding": false, + "enabled_cloudwatch_logs_exports": null, + "engine": "aurora-mysql", + "engine_mode": "provisioned", + "final_snapshot_identifier": null, + "global_cluster_identifier": null, + "iam_database_authentication_enabled": null, + "iops": null, + "manage_master_user_password": null, + "master_password": "secret99", + "master_username": "admin", + "performance_insights_enabled": null, + "replication_source_identifier": null, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "skip_final_snapshot": true, + "snapshot_identifier": null, + "source_region": null, + "tags": null, + "timeouts": null + }, + "after_unknown": { + "allocated_storage": true, + "apply_immediately": true, + "arn": true, + "availability_zones": true, + "ca_certificate_identifier": true, + "ca_certificate_valid_till": true, + "cluster_identifier_prefix": true, + "cluster_members": true, + "cluster_resource_id": true, + "database_name": true, + "db_cluster_parameter_group_name": true, + "db_subnet_group_name": true, + "db_system_id": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "iam_roles": true, + "id": true, + "kms_key_id": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "network_type": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "preferred_backup_window": true, + "preferred_maintenance_window": true, + "reader_endpoint": true, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "storage_encrypted": true, + "storage_type": true, + "tags_all": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "availability_zones": [], + "cluster_members": [], + "iam_roles": [], + "master_password": true, + "master_user_secret": [], + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_rds_cluster.bad_aurora_mysql_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "bad_aurora_mysql_cluster", + "provider_config_key": "aws", + "expressions": { + "backup_retention_period": { + "constant_value": 7 + }, + "cluster_identifier": { + "constant_value": "bad-aurora-mysql-cluster" + }, + "engine": { + "constant_value": "aurora-mysql" + }, + "master_password": { + "constant_value": "secret99" + }, + "master_username": { + "constant_value": "admin" + }, + "skip_final_snapshot": { + "constant_value": true + } + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-10-01T13:07:17Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/binding.yaml b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/chainsaw-test.yaml b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/chainsaw-test.yaml new file mode 100644 index 00000000..3a8acc88 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/chainsaw-test.yaml @@ -0,0 +1,82 @@ +# 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-rds-aurora-mysql-audit-logging-enabled.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-aurora-mysql-audit-logging-enabled + rules: + - rule: + name: check-rds-aurora-mysql-audit-logging-enabled + 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 --payload ./bad-test/bad-payload-01.json --policy ../check-rds-aurora-mysql-audit-logging-enabled.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-aurora-mysql-audit-logging-enabled + rules: + - rule: + name: check-rds-aurora-mysql-audit-logging-enabled + error: ~ + violations: + - message: Aurora MySQL DB clusters should publish audit logs to CloudWatch Logs (CHECK=spec.rules[0].assert.all[0]) + errors: + - type: FieldValueInvalid + value: false + detail: "Expected value: true" +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: skip-test-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./skip-test/skip-payload-01.json --policy ../check-rds-aurora-mysql-audit-logging-enabled.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-aurora-mysql-audit-logging-enabled + rules: ~ \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/good-test/good-01.tf b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/good-test/good-01.tf new file mode 100644 index 00000000..e4f71b95 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/good-test/good-01.tf @@ -0,0 +1,24 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_rds_cluster" "good_aurora_mysql_cluster" { + cluster_identifier = "good-aurora-mysql-cluster" + engine = "aurora-mysql" + master_username = "admin" + master_password = "secret99" + backup_retention_period = 7 + enabled_cloudwatch_logs_exports = ["audit"] + skip_final_snapshot = true +} diff --git a/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/good-test/good-payload-01.json b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/good-test/good-payload-01.json new file mode 100644 index 00000000..a611dc20 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/good-test/good-payload-01.json @@ -0,0 +1,242 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_rds_cluster.good_aurora_mysql_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "good_aurora_mysql_cluster", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "allow_major_version_upgrade": null, + "backtrack_window": null, + "backup_retention_period": 7, + "cluster_identifier": "good-aurora-mysql-cluster", + "copy_tags_to_snapshot": false, + "db_cluster_instance_class": null, + "db_instance_parameter_group_name": null, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_iam_role_name": null, + "enable_global_write_forwarding": false, + "enable_http_endpoint": false, + "enable_local_write_forwarding": false, + "enabled_cloudwatch_logs_exports": [ + "audit" + ], + "engine": "aurora-mysql", + "engine_mode": "provisioned", + "final_snapshot_identifier": null, + "global_cluster_identifier": null, + "iam_database_authentication_enabled": null, + "iops": null, + "manage_master_user_password": null, + "master_password": "secret99", + "master_username": "admin", + "performance_insights_enabled": null, + "replication_source_identifier": null, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "skip_final_snapshot": true, + "snapshot_identifier": null, + "source_region": null, + "tags": null, + "timeouts": null + }, + "sensitive_values": { + "availability_zones": [], + "cluster_members": [], + "enabled_cloudwatch_logs_exports": [ + false + ], + "iam_roles": [], + "master_password": true, + "master_user_secret": [], + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_rds_cluster.good_aurora_mysql_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "good_aurora_mysql_cluster", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allow_major_version_upgrade": null, + "backtrack_window": null, + "backup_retention_period": 7, + "cluster_identifier": "good-aurora-mysql-cluster", + "copy_tags_to_snapshot": false, + "db_cluster_instance_class": null, + "db_instance_parameter_group_name": null, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_iam_role_name": null, + "enable_global_write_forwarding": false, + "enable_http_endpoint": false, + "enable_local_write_forwarding": false, + "enabled_cloudwatch_logs_exports": [ + "audit" + ], + "engine": "aurora-mysql", + "engine_mode": "provisioned", + "final_snapshot_identifier": null, + "global_cluster_identifier": null, + "iam_database_authentication_enabled": null, + "iops": null, + "manage_master_user_password": null, + "master_password": "secret99", + "master_username": "admin", + "performance_insights_enabled": null, + "replication_source_identifier": null, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "skip_final_snapshot": true, + "snapshot_identifier": null, + "source_region": null, + "tags": null, + "timeouts": null + }, + "after_unknown": { + "allocated_storage": true, + "apply_immediately": true, + "arn": true, + "availability_zones": true, + "ca_certificate_identifier": true, + "ca_certificate_valid_till": true, + "cluster_identifier_prefix": true, + "cluster_members": true, + "cluster_resource_id": true, + "database_name": true, + "db_cluster_parameter_group_name": true, + "db_subnet_group_name": true, + "db_system_id": true, + "enabled_cloudwatch_logs_exports": [ + false + ], + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "iam_roles": true, + "id": true, + "kms_key_id": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "network_type": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "preferred_backup_window": true, + "preferred_maintenance_window": true, + "reader_endpoint": true, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "storage_encrypted": true, + "storage_type": true, + "tags_all": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "availability_zones": [], + "cluster_members": [], + "enabled_cloudwatch_logs_exports": [ + false + ], + "iam_roles": [], + "master_password": true, + "master_user_secret": [], + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_rds_cluster.good_aurora_mysql_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "good_aurora_mysql_cluster", + "provider_config_key": "aws", + "expressions": { + "backup_retention_period": { + "constant_value": 7 + }, + "cluster_identifier": { + "constant_value": "good-aurora-mysql-cluster" + }, + "enabled_cloudwatch_logs_exports": { + "constant_value": [ + "audit" + ] + }, + "engine": { + "constant_value": "aurora-mysql" + }, + "master_password": { + "constant_value": "secret99" + }, + "master_username": { + "constant_value": "admin" + }, + "skip_final_snapshot": { + "constant_value": true + } + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-10-01T13:07:19Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/skip-test/skip-01.tf b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/skip-test/skip-01.tf new file mode 100644 index 00000000..3fb261ce --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/skip-test/skip-01.tf @@ -0,0 +1,24 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" # Updated region +} + +resource "aws_rds_cluster" "skip_serverless_aurora_cluster" { + cluster_identifier = "skip-serverless-aurora-cluster" + engine = "aurora-mysql" + engine_mode = "serverless" # Aurora Serverless v1 is skipped + master_username = "admin" + master_password = "secret99" + backup_retention_period = 7 + skip_final_snapshot = true +} diff --git a/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/skip-test/skip-payload-01.json b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/skip-test/skip-payload-01.json new file mode 100644 index 00000000..59b565bb --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-aurora-mysql-audit-logging-enabled/test/skip-test/skip-payload-01.json @@ -0,0 +1,227 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_rds_cluster.skip_serverless_aurora_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "skip_serverless_aurora_cluster", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "allow_major_version_upgrade": null, + "backtrack_window": null, + "backup_retention_period": 7, + "cluster_identifier": "skip-serverless-aurora-cluster", + "copy_tags_to_snapshot": false, + "db_cluster_instance_class": null, + "db_instance_parameter_group_name": null, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_iam_role_name": null, + "enable_global_write_forwarding": false, + "enable_http_endpoint": false, + "enable_local_write_forwarding": false, + "enabled_cloudwatch_logs_exports": null, + "engine": "aurora-mysql", + "engine_mode": "serverless", + "final_snapshot_identifier": null, + "global_cluster_identifier": null, + "iam_database_authentication_enabled": null, + "iops": null, + "manage_master_user_password": null, + "master_password": "secret99", + "master_username": "admin", + "performance_insights_enabled": null, + "replication_source_identifier": null, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "skip_final_snapshot": true, + "snapshot_identifier": null, + "source_region": null, + "tags": null, + "timeouts": null + }, + "sensitive_values": { + "availability_zones": [], + "cluster_members": [], + "iam_roles": [], + "master_password": true, + "master_user_secret": [], + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_rds_cluster.skip_serverless_aurora_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "skip_serverless_aurora_cluster", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allow_major_version_upgrade": null, + "backtrack_window": null, + "backup_retention_period": 7, + "cluster_identifier": "skip-serverless-aurora-cluster", + "copy_tags_to_snapshot": false, + "db_cluster_instance_class": null, + "db_instance_parameter_group_name": null, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_iam_role_name": null, + "enable_global_write_forwarding": false, + "enable_http_endpoint": false, + "enable_local_write_forwarding": false, + "enabled_cloudwatch_logs_exports": null, + "engine": "aurora-mysql", + "engine_mode": "serverless", + "final_snapshot_identifier": null, + "global_cluster_identifier": null, + "iam_database_authentication_enabled": null, + "iops": null, + "manage_master_user_password": null, + "master_password": "secret99", + "master_username": "admin", + "performance_insights_enabled": null, + "replication_source_identifier": null, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "skip_final_snapshot": true, + "snapshot_identifier": null, + "source_region": null, + "tags": null, + "timeouts": null + }, + "after_unknown": { + "allocated_storage": true, + "apply_immediately": true, + "arn": true, + "availability_zones": true, + "ca_certificate_identifier": true, + "ca_certificate_valid_till": true, + "cluster_identifier_prefix": true, + "cluster_members": true, + "cluster_resource_id": true, + "database_name": true, + "db_cluster_parameter_group_name": true, + "db_subnet_group_name": true, + "db_system_id": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "iam_roles": true, + "id": true, + "kms_key_id": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "network_type": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "preferred_backup_window": true, + "preferred_maintenance_window": true, + "reader_endpoint": true, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "storage_encrypted": true, + "storage_type": true, + "tags_all": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "availability_zones": [], + "cluster_members": [], + "iam_roles": [], + "master_password": true, + "master_user_secret": [], + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_rds_cluster.skip_serverless_aurora_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "skip_serverless_aurora_cluster", + "provider_config_key": "aws", + "expressions": { + "backup_retention_period": { + "constant_value": 7 + }, + "cluster_identifier": { + "constant_value": "skip-serverless-aurora-cluster" + }, + "engine": { + "constant_value": "aurora-mysql" + }, + "engine_mode": { + "constant_value": "serverless" + }, + "master_password": { + "constant_value": "secret99" + }, + "master_username": { + "constant_value": "admin" + }, + "skip_final_snapshot": { + "constant_value": true + } + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-10-01T13:07:16Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/README.md b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/README.md new file mode 100644 index 00000000..de161017 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/README.md @@ -0,0 +1,76 @@ +# Check RDS Automatic Minor Version Upgrade Enabled + +This policy checks whether automatic minor version upgrades are enabled for the RDS database instance. +Enabling automatic minor version upgrades ensures that the latest minor version updates to the +relational database management system (RDBMS) are installed. These upgrades might include security patches and bug fixes. +Keeping up to date with patch installation is an important step in securing systems. + +## Policy Details: + +- **Policy Name:** check-rds-automatic-minor-version-upgrade-enabled +- **Check Description:** This policy checks whether automatic minor version upgrades are enabled for the RDS database instance. +- **Policy Category:** AWS RDS 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:** + ```bash + kyverno-json scan --payload payload.json --policy policy.yaml + ``` + + a. **Test Policy Against Valid Payload:** + ```bash + kyverno-json scan --payload test/good-test/good-payload-01.json --policy check-rds-automatic-minor-version-upgrade-enabled.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=check-rds-automatic-minor-version-upgrade-enabled, RULE=check-rds-automatic-minor-version-upgrade-enabled) + Done + ``` + + b. **Test Against Invalid Payload:** + ```bash + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-rds-automatic-minor-version-upgrade-enabled.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=check-rds-automatic-minor-version-upgrade-enabled, RULE=check-rds-automatic-minor-version-upgrade-enabled) + -> RDS instances should have automatic minor version upgrades enabled (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: false: Expected value: true (PATH=~.(planned_values.root_module.resources[?type=='aws_db_instance'])[0].values.(auto_minor_version_upgrade)) + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/check-rds-automatic-minor-version-upgrade-enabled.yaml b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/check-rds-automatic-minor-version-upgrade-enabled.yaml new file mode 100644 index 00000000..ca787019 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/check-rds-automatic-minor-version-upgrade-enabled.yaml @@ -0,0 +1,27 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-rds-automatic-minor-version-upgrade-enabled + annotations: + policies.kyverno.io/title: Check RDS Automatic Minor Version Upgrade Enabled + policies.kyverno.io/category: AWS RDS Best Practices + policies.kyverno.io/severity: high + policies.kyverno.io/description: >- + This policy checks whether automatic minor version upgrades are enabled for the RDS database instance. + Enabling automatic minor version upgrades ensures that the latest minor version updates to the + relational database management system (RDBMS) are installed. These upgrades might include security patches and bug fixes. + Keeping up to date with patch installation is an important step in securing systems. +spec: + rules: + - name: check-rds-automatic-minor-version-upgrade-enabled + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_db_instance'] || `[]` | length(@) > `0`): true + assert: + all: + - message: RDS instances should have automatic minor version upgrades enabled + check: + ~.(planned_values.root_module.resources[?type=='aws_db_instance']): + values: + (auto_minor_version_upgrade): true diff --git a/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/bad-test/bad-01.tf b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/bad-test/bad-01.tf new file mode 100644 index 00000000..b1219f96 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/bad-test/bad-01.tf @@ -0,0 +1,25 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "bad_mysql_instance" { + identifier = "bad-mysql-instance-01" + instance_class = "db.t3.micro" + engine = "mysql" + username = "admin" + password = "secret99" + allocated_storage = 5 + skip_final_snapshot = true + auto_minor_version_upgrade = false +} diff --git a/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/bad-test/bad-payload-01.json b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..d7560ad1 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/bad-test/bad-payload-01.json @@ -0,0 +1,240 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": false, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "bad-mysql-instance-01", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": false, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "bad-mysql-instance-01", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 5 + }, + "auto_minor_version_upgrade": { + "constant_value": false + }, + "engine": { + "constant_value": "mysql" + }, + "identifier": { + "constant_value": "bad-mysql-instance-01" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "password": { + "constant_value": "secret99" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "admin" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T12:34:22Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/binding.yaml b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/chainsaw-test.yaml b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/chainsaw-test.yaml new file mode 100644 index 00000000..406393dd --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/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 --payload ./good-test/good-payload-01.json --policy ../check-rds-automatic-minor-version-upgrade-enabled.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-automatic-minor-version-upgrade-enabled + rules: + - rule: + name: check-rds-automatic-minor-version-upgrade-enabled + 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 --payload ./good-test/good-payload-02.json --policy ../check-rds-automatic-minor-version-upgrade-enabled.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-automatic-minor-version-upgrade-enabled + rules: + - rule: + name: check-rds-automatic-minor-version-upgrade-enabled + 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 --payload ./bad-test/bad-payload-01.json --policy ../check-rds-automatic-minor-version-upgrade-enabled.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-automatic-minor-version-upgrade-enabled + rules: + - rule: + name: check-rds-automatic-minor-version-upgrade-enabled + error: ~ + violations: + - message: RDS instances should have automatic minor version upgrades enabled (CHECK=spec.rules[0].assert.all[0]) + errors: + - type: FieldValueInvalid + value: false + detail: "Expected value: true" diff --git a/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/good-test/good-01.tf b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/good-test/good-01.tf new file mode 100644 index 00000000..39f1bf99 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/good-test/good-01.tf @@ -0,0 +1,25 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "good_mysql_instance" { + identifier = "good-mysql-instance-01" + instance_class = "db.t3.micro" + engine = "mysql" + username = "admin" + password = "secret99" + allocated_storage = 5 + skip_final_snapshot = true + auto_minor_version_upgrade = true +} diff --git a/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/good-test/good-02.tf b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/good-test/good-02.tf new file mode 100644 index 00000000..e36d1c25 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/good-test/good-02.tf @@ -0,0 +1,26 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "good_mysql_instance" { + identifier = "good-mysql-instance-01" + instance_class = "db.t3.micro" + engine = "mysql" + username = "admin" + password = "secret99" + allocated_storage = 5 + skip_final_snapshot = true +# auto_minor_version_upgrade defaults to true +# auto_minor_version_upgrade = true +} diff --git a/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/good-test/good-payload-01.json b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/good-test/good-payload-01.json new file mode 100644 index 00000000..85d35cd7 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/good-test/good-payload-01.json @@ -0,0 +1,240 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "good-mysql-instance-01", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "good-mysql-instance-01", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 5 + }, + "auto_minor_version_upgrade": { + "constant_value": true + }, + "engine": { + "constant_value": "mysql" + }, + "identifier": { + "constant_value": "good-mysql-instance-01" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "password": { + "constant_value": "secret99" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "admin" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T12:34:55Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/good-test/good-payload-02.json b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/good-test/good-payload-02.json new file mode 100644 index 00000000..a1b0e8a2 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-automatic-minor-version-upgrade-enabled/test/good-test/good-payload-02.json @@ -0,0 +1,237 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "good-mysql-instance-01", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "good-mysql-instance-01", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 5 + }, + "engine": { + "constant_value": "mysql" + }, + "identifier": { + "constant_value": "good-mysql-instance-01" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "password": { + "constant_value": "secret99" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "admin" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T12:35:25Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/README.md b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/README.md new file mode 100644 index 00000000..ae7e5bbd --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/README.md @@ -0,0 +1,76 @@ +# Check RDS Cluster Deletion Protection Enabled + +Preventing accidental deletion of an RDS database through the AWS Management Console, AWS CLI, or the RDS API is essential for avoiding data loss. +The database can't be deleted when deletion protection is enabled. This ensures an extra layer of protection for your data, preventing +unintended actions from impacting availability or causing data loss. By enabling deletion protection, you ensure that the database +remains intact until deliberate action is taken to disable this setting. + +## Policy Details: + +- **Policy Name:** check-rds-cluster-deletion-protection-enabled +- **Check Description:** This policy ensures that deletion protection is enabled for RDS databases +- **Policy Category:** AWS RDS 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:** + ```bash + kyverno-json scan --payload payload.json --policy policy.yaml + ``` + + a. **Test Policy Against Valid Payload:** + ```bash + kyverno-json scan --payload test/good-test/good-payload-01.json --policy check-rds-cluster-deletion-protection-enabled.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=check-rds-cluster-deletion-protection-enabled, RULE=check-rds-cluster-deletion-protection-enabled) + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-rds-cluster-deletion-protection-enabled.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=check-rds-cluster-deletion-protection-enabled, RULE=check-rds-cluster-deletion-protection-enabled) + -> RDS Database Deletion Protection must be enabled (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: false: Expected value: true (PATH=~.(planned_values.root_module.resources[?type=='aws_rds_cluster'])[0].values.(!!deletion_protection)) + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/check-rds-cluster-deletion-protection-enabled.yaml b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/check-rds-cluster-deletion-protection-enabled.yaml new file mode 100644 index 00000000..b3e56f59 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/check-rds-cluster-deletion-protection-enabled.yaml @@ -0,0 +1,27 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-rds-cluster-deletion-protection-enabled + annotations: + policies.kyverno.io/title: Check RDS Cluster Deletion Protection Enabled + policies.kyverno.io/category: AWS RDS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + Preventing accidental deletion of an RDS database through the AWS Management Console, AWS CLI, or the RDS API is essential for avoiding data loss. + The database can't be deleted when deletion protection is enabled. This ensures an extra layer of protection for your data, preventing + unintended actions from impacting availability or causing data loss. By enabling deletion protection, you ensure that the database + remains intact until deliberate action is taken to disable this setting. +spec: + rules: + - name: check-rds-cluster-deletion-protection-enabled + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_rds_cluster'] || `[]` | length(@) > `0`): true + assert: + all: + - message: RDS Database Deletion Protection must be enabled + check: + ~.(planned_values.root_module.resources[?type=='aws_rds_cluster']): + values: + (!!deletion_protection): true diff --git a/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/bad-test/bad-01.tf b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/bad-test/bad-01.tf new file mode 100644 index 00000000..87a5fa34 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/bad-test/bad-01.tf @@ -0,0 +1,22 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_rds_cluster" "bad_rds_db_cluster" { + cluster_identifier = "bad-rds-db-cluster-01" + engine = "aurora-mysql" + master_username = "admin" + master_password = "admin123" + deletion_protection = false +} diff --git a/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/bad-test/bad-02.tf b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/bad-test/bad-02.tf new file mode 100644 index 00000000..de95fc5b --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/bad-test/bad-02.tf @@ -0,0 +1,23 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_rds_cluster" "bad_rds_db_cluster" { + cluster_identifier = "bad-rds-db-cluster-01" + engine = "aurora-mysql" + master_username = "admin" + master_password = "admin123" + # deletion_protection defaults to false + # deletion_protection = false +} diff --git a/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/bad-test/bad-payload-01.json b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..40c2c65b --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/bad-test/bad-payload-01.json @@ -0,0 +1,220 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_rds_cluster.bad_rds_db_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "bad_rds_db_cluster", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "allow_major_version_upgrade": null, + "backtrack_window": null, + "cluster_identifier": "bad-rds-db-cluster-01", + "copy_tags_to_snapshot": false, + "db_cluster_instance_class": null, + "db_instance_parameter_group_name": null, + "delete_automated_backups": true, + "deletion_protection": false, + "domain": null, + "domain_iam_role_name": null, + "enable_global_write_forwarding": false, + "enable_http_endpoint": false, + "enable_local_write_forwarding": false, + "enabled_cloudwatch_logs_exports": null, + "engine": "aurora-mysql", + "engine_mode": "provisioned", + "final_snapshot_identifier": null, + "global_cluster_identifier": null, + "iam_database_authentication_enabled": null, + "iops": null, + "manage_master_user_password": null, + "master_password": "admin123", + "master_username": "admin", + "performance_insights_enabled": null, + "replication_source_identifier": null, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "skip_final_snapshot": false, + "snapshot_identifier": null, + "source_region": null, + "tags": null, + "timeouts": null + }, + "sensitive_values": { + "availability_zones": [], + "cluster_members": [], + "iam_roles": [], + "master_password": true, + "master_user_secret": [], + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_rds_cluster.bad_rds_db_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "bad_rds_db_cluster", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allow_major_version_upgrade": null, + "backtrack_window": null, + "cluster_identifier": "bad-rds-db-cluster-01", + "copy_tags_to_snapshot": false, + "db_cluster_instance_class": null, + "db_instance_parameter_group_name": null, + "delete_automated_backups": true, + "deletion_protection": false, + "domain": null, + "domain_iam_role_name": null, + "enable_global_write_forwarding": false, + "enable_http_endpoint": false, + "enable_local_write_forwarding": false, + "enabled_cloudwatch_logs_exports": null, + "engine": "aurora-mysql", + "engine_mode": "provisioned", + "final_snapshot_identifier": null, + "global_cluster_identifier": null, + "iam_database_authentication_enabled": null, + "iops": null, + "manage_master_user_password": null, + "master_password": "admin123", + "master_username": "admin", + "performance_insights_enabled": null, + "replication_source_identifier": null, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "skip_final_snapshot": false, + "snapshot_identifier": null, + "source_region": null, + "tags": null, + "timeouts": null + }, + "after_unknown": { + "allocated_storage": true, + "apply_immediately": true, + "arn": true, + "availability_zones": true, + "backup_retention_period": true, + "ca_certificate_identifier": true, + "ca_certificate_valid_till": true, + "cluster_identifier_prefix": true, + "cluster_members": true, + "cluster_resource_id": true, + "database_name": true, + "db_cluster_parameter_group_name": true, + "db_subnet_group_name": true, + "db_system_id": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "iam_roles": true, + "id": true, + "kms_key_id": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "network_type": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "preferred_backup_window": true, + "preferred_maintenance_window": true, + "reader_endpoint": true, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "storage_encrypted": true, + "storage_type": true, + "tags_all": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "availability_zones": [], + "cluster_members": [], + "iam_roles": [], + "master_password": true, + "master_user_secret": [], + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_rds_cluster.bad_rds_db_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "bad_rds_db_cluster", + "provider_config_key": "aws", + "expressions": { + "cluster_identifier": { + "constant_value": "bad-rds-db-cluster-01" + }, + "deletion_protection": { + "constant_value": false + }, + "engine": { + "constant_value": "aurora-mysql" + }, + "master_password": { + "constant_value": "admin123" + }, + "master_username": { + "constant_value": "admin" + } + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-10-01T05:47:19Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/bad-test/bad-payload-02.json b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/bad-test/bad-payload-02.json new file mode 100644 index 00000000..90874ffa --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/bad-test/bad-payload-02.json @@ -0,0 +1,217 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_rds_cluster.bad_rds_db_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "bad_rds_db_cluster", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "allow_major_version_upgrade": null, + "backtrack_window": null, + "cluster_identifier": "bad-rds-db-cluster-01", + "copy_tags_to_snapshot": false, + "db_cluster_instance_class": null, + "db_instance_parameter_group_name": null, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_iam_role_name": null, + "enable_global_write_forwarding": false, + "enable_http_endpoint": false, + "enable_local_write_forwarding": false, + "enabled_cloudwatch_logs_exports": null, + "engine": "aurora-mysql", + "engine_mode": "provisioned", + "final_snapshot_identifier": null, + "global_cluster_identifier": null, + "iam_database_authentication_enabled": null, + "iops": null, + "manage_master_user_password": null, + "master_password": "admin123", + "master_username": "admin", + "performance_insights_enabled": null, + "replication_source_identifier": null, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "skip_final_snapshot": false, + "snapshot_identifier": null, + "source_region": null, + "tags": null, + "timeouts": null + }, + "sensitive_values": { + "availability_zones": [], + "cluster_members": [], + "iam_roles": [], + "master_password": true, + "master_user_secret": [], + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_rds_cluster.bad_rds_db_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "bad_rds_db_cluster", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allow_major_version_upgrade": null, + "backtrack_window": null, + "cluster_identifier": "bad-rds-db-cluster-01", + "copy_tags_to_snapshot": false, + "db_cluster_instance_class": null, + "db_instance_parameter_group_name": null, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_iam_role_name": null, + "enable_global_write_forwarding": false, + "enable_http_endpoint": false, + "enable_local_write_forwarding": false, + "enabled_cloudwatch_logs_exports": null, + "engine": "aurora-mysql", + "engine_mode": "provisioned", + "final_snapshot_identifier": null, + "global_cluster_identifier": null, + "iam_database_authentication_enabled": null, + "iops": null, + "manage_master_user_password": null, + "master_password": "admin123", + "master_username": "admin", + "performance_insights_enabled": null, + "replication_source_identifier": null, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "skip_final_snapshot": false, + "snapshot_identifier": null, + "source_region": null, + "tags": null, + "timeouts": null + }, + "after_unknown": { + "allocated_storage": true, + "apply_immediately": true, + "arn": true, + "availability_zones": true, + "backup_retention_period": true, + "ca_certificate_identifier": true, + "ca_certificate_valid_till": true, + "cluster_identifier_prefix": true, + "cluster_members": true, + "cluster_resource_id": true, + "database_name": true, + "db_cluster_parameter_group_name": true, + "db_subnet_group_name": true, + "db_system_id": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "iam_roles": true, + "id": true, + "kms_key_id": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "network_type": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "preferred_backup_window": true, + "preferred_maintenance_window": true, + "reader_endpoint": true, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "storage_encrypted": true, + "storage_type": true, + "tags_all": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "availability_zones": [], + "cluster_members": [], + "iam_roles": [], + "master_password": true, + "master_user_secret": [], + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_rds_cluster.bad_rds_db_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "bad_rds_db_cluster", + "provider_config_key": "aws", + "expressions": { + "cluster_identifier": { + "constant_value": "bad-rds-db-cluster-01" + }, + "engine": { + "constant_value": "aurora-mysql" + }, + "master_password": { + "constant_value": "admin123" + }, + "master_username": { + "constant_value": "admin" + } + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-10-01T05:48:12Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/binding.yaml b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/chainsaw-test.yaml b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/chainsaw-test.yaml new file mode 100644 index 00000000..74250dec --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/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-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./good-test/good-payload-01.json --policy ../check-rds-cluster-deletion-protection-enabled.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-cluster-deletion-protection-enabled + rules: + - rule: + name: check-rds-cluster-deletion-protection-enabled + 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 --payload ./bad-test/bad-payload-01.json --policy ../check-rds-cluster-deletion-protection-enabled.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-cluster-deletion-protection-enabled + rules: + - rule: + name: check-rds-cluster-deletion-protection-enabled + error: ~ + violations: + - message: RDS Database Deletion Protection must be enabled (CHECK=spec.rules[0].assert.all[0]) + 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 --payload ./bad-test/bad-payload-02.json --policy ../check-rds-cluster-deletion-protection-enabled.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-cluster-deletion-protection-enabled + rules: + - rule: + name: check-rds-cluster-deletion-protection-enabled + error: ~ + violations: + - message: RDS Database Deletion Protection must be enabled (CHECK=spec.rules[0].assert.all[0]) + errors: + - type: FieldValueInvalid + value: false + detail: "Expected value: true" \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/good-test/good-01.tf b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/good-test/good-01.tf new file mode 100644 index 00000000..3efe74f4 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/good-test/good-01.tf @@ -0,0 +1,22 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_rds_cluster" "good_rds_db_cluster" { + cluster_identifier = "good-rds-db-cluster-01" + engine = "aurora-mysql" + master_username = "admin" + master_password = "admin123" + deletion_protection = true +} diff --git a/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/good-test/good-payload-01.json b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/good-test/good-payload-01.json new file mode 100644 index 00000000..a470e611 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-cluster-deletion-protection-enabled/test/good-test/good-payload-01.json @@ -0,0 +1,220 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_rds_cluster.good_rds_db_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "good_rds_db_cluster", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 1, + "values": { + "allow_major_version_upgrade": null, + "backtrack_window": null, + "cluster_identifier": "good-rds-db-cluster-01", + "copy_tags_to_snapshot": false, + "db_cluster_instance_class": null, + "db_instance_parameter_group_name": null, + "delete_automated_backups": true, + "deletion_protection": true, + "domain": null, + "domain_iam_role_name": null, + "enable_global_write_forwarding": false, + "enable_http_endpoint": false, + "enable_local_write_forwarding": false, + "enabled_cloudwatch_logs_exports": null, + "engine": "aurora-mysql", + "engine_mode": "provisioned", + "final_snapshot_identifier": null, + "global_cluster_identifier": null, + "iam_database_authentication_enabled": null, + "iops": null, + "manage_master_user_password": null, + "master_password": "admin123", + "master_username": "admin", + "performance_insights_enabled": null, + "replication_source_identifier": null, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "skip_final_snapshot": false, + "snapshot_identifier": null, + "source_region": null, + "tags": null, + "timeouts": null + }, + "sensitive_values": { + "availability_zones": [], + "cluster_members": [], + "iam_roles": [], + "master_password": true, + "master_user_secret": [], + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_rds_cluster.good_rds_db_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "good_rds_db_cluster", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allow_major_version_upgrade": null, + "backtrack_window": null, + "cluster_identifier": "good-rds-db-cluster-01", + "copy_tags_to_snapshot": false, + "db_cluster_instance_class": null, + "db_instance_parameter_group_name": null, + "delete_automated_backups": true, + "deletion_protection": true, + "domain": null, + "domain_iam_role_name": null, + "enable_global_write_forwarding": false, + "enable_http_endpoint": false, + "enable_local_write_forwarding": false, + "enabled_cloudwatch_logs_exports": null, + "engine": "aurora-mysql", + "engine_mode": "provisioned", + "final_snapshot_identifier": null, + "global_cluster_identifier": null, + "iam_database_authentication_enabled": null, + "iops": null, + "manage_master_user_password": null, + "master_password": "admin123", + "master_username": "admin", + "performance_insights_enabled": null, + "replication_source_identifier": null, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "skip_final_snapshot": false, + "snapshot_identifier": null, + "source_region": null, + "tags": null, + "timeouts": null + }, + "after_unknown": { + "allocated_storage": true, + "apply_immediately": true, + "arn": true, + "availability_zones": true, + "backup_retention_period": true, + "ca_certificate_identifier": true, + "ca_certificate_valid_till": true, + "cluster_identifier_prefix": true, + "cluster_members": true, + "cluster_resource_id": true, + "database_name": true, + "db_cluster_parameter_group_name": true, + "db_subnet_group_name": true, + "db_system_id": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "iam_roles": true, + "id": true, + "kms_key_id": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "network_type": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "preferred_backup_window": true, + "preferred_maintenance_window": true, + "reader_endpoint": true, + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "storage_encrypted": true, + "storage_type": true, + "tags_all": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "availability_zones": [], + "cluster_members": [], + "iam_roles": [], + "master_password": true, + "master_user_secret": [], + "restore_to_point_in_time": [], + "s3_import": [], + "scaling_configuration": [], + "serverlessv2_scaling_configuration": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_rds_cluster.good_rds_db_cluster", + "mode": "managed", + "type": "aws_rds_cluster", + "name": "good_rds_db_cluster", + "provider_config_key": "aws", + "expressions": { + "cluster_identifier": { + "constant_value": "good-rds-db-cluster-01" + }, + "deletion_protection": { + "constant_value": true + }, + "engine": { + "constant_value": "aurora-mysql" + }, + "master_password": { + "constant_value": "admin123" + }, + "master_username": { + "constant_value": "admin" + } + }, + "schema_version": 1 + } + ] + } + }, + "timestamp": "2024-10-01T05:48:45Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/README.md b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/README.md new file mode 100644 index 00000000..619cbaa3 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/README.md @@ -0,0 +1,76 @@ +# Check RDS DB Proxy TLS + +RDS Proxy can use security mechanisms such as TLS to add an additional layer of security between client applications and the underlying database. +Database connections often involve sensitive information, such as personally identifiable information (PII), financial data, or confidential business data. +Protecting this data in transit is important to maintain security of the data. +This policy checks if the RDS Proxy is using TLS. + +## Policy Details: + +- **Policy Name:** check-rds-db-proxy-tls +- **Check Description:** This policy ensures that RDS Proxies use TLS +- **Policy Category:** AWS RDS 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:** + ```bash + kyverno-json scan --payload payload.json --policy policy.yaml + ``` + + a. **Test Policy Against Valid Payload:** + ```bash + kyverno-json scan --payload test/good-test/good-payload-01.json --policy check-rds-db-proxy-tls.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=check-rds-db-proxy-tls, RULE=check-rds-db-proxy-tls) + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-rds-db-proxy-tls.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=check-rds-db-proxy-tls, RULE=check-rds-db-proxy-tls) + -> RDS Database Proxy should use TLS (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: false: Expected value: true (PATH=~.(planned_values.root_module.resources[?type=='aws_db_proxy'])[0].values.(!!require_tls)) + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/check-rds-db-proxy-tls.yaml b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/check-rds-db-proxy-tls.yaml new file mode 100644 index 00000000..b920f911 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/check-rds-db-proxy-tls.yaml @@ -0,0 +1,27 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-rds-db-proxy-tls + annotations: + policies.kyverno.io/title: Check RDS DB Proxy TLS + policies.kyverno.io/category: AWS RDS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + RDS Proxy can use security mechanisms such as TLS to add an additional layer of security between client applications and the underlying database. + Database connections often involve sensitive information, such as personally identifiable information (PII), financial data, or confidential business data. + Protecting this data in transit is important to maintain security of the data. + This policy checks if the RDS Proxy is using TLS. +spec: + rules: + - name: check-rds-db-proxy-tls + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_db_proxy'] || `[]` | length(@) > `0`): true + assert: + all: + - message: RDS Database Proxy should use TLS + check: + ~.(planned_values.root_module.resources[?type=='aws_db_proxy']): + values: + (!!require_tls): true \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/bad-test/bad-01.tf b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/bad-test/bad-01.tf new file mode 100644 index 00000000..9e533349 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/bad-test/bad-01.tf @@ -0,0 +1,43 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_secretsmanager_secret" "rds_secret" { + name = "rds-db-secret" + + tags = { + Name = "rds-db-secret" + } +} + +resource "aws_secretsmanager_secret_version" "rds_secret_version" { + secret_id = aws_secretsmanager_secret.rds_secret.id + secret_string = jsonencode({ + username = "admin" + password = "admin1234" + }) +} + +resource "aws_db_proxy" "bad_db_proxy" { + name = "bad-db-proxy-01" + engine_family = "POSTGRESQL" + role_arn = "arn:aws:iam::xxxx:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS" + vpc_subnet_ids = ["subnet-id-1", "subnet-id-2"] + require_tls = false + + auth { + auth_scheme = "SECRETS" + secret_arn = aws_secretsmanager_secret.rds_secret.arn + } +} diff --git a/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/bad-test/bad-02.tf b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/bad-test/bad-02.tf new file mode 100644 index 00000000..f1386050 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/bad-test/bad-02.tf @@ -0,0 +1,42 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_secretsmanager_secret" "rds_secret" { + name = "rds-db-secret" + + tags = { + Name = "rds-db-secret" + } +} + +resource "aws_secretsmanager_secret_version" "rds_secret_version" { + secret_id = aws_secretsmanager_secret.rds_secret.id + secret_string = jsonencode({ + username = "admin" + password = "admin1234" + }) +} + +resource "aws_db_proxy" "bad_db_proxy" { + name = "bad-db-proxy-02" + engine_family = "POSTGRESQL" + role_arn = "arn:aws:iam::xxxx:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS" + vpc_subnet_ids = ["subnet-id-1", "subnet-id-2"] + + auth { + auth_scheme = "SECRETS" + secret_arn = aws_secretsmanager_secret.rds_secret.arn + } +} diff --git a/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/bad-test/bad-payload-01.json b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..bec146f9 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/bad-test/bad-payload-01.json @@ -0,0 +1,342 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_proxy.bad_db_proxy", + "mode": "managed", + "type": "aws_db_proxy", + "name": "bad_db_proxy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "auth": [ + { + "auth_scheme": "SECRETS", + "description": "", + "iam_auth": "", + "username": "" + } + ], + "debug_logging": null, + "engine_family": "POSTGRESQL", + "name": "bad-db-proxy-01", + "require_tls": false, + "role_arn": "arn:aws:iam::xxxx:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS", + "tags": null, + "timeouts": null, + "vpc_subnet_ids": [ + "subnet-id-1", + "subnet-id-2" + ] + }, + "sensitive_values": { + "auth": [ + {} + ], + "tags_all": {}, + "vpc_security_group_ids": [], + "vpc_subnet_ids": [ + false, + false + ] + } + }, + { + "address": "aws_secretsmanager_secret.rds_secret", + "mode": "managed", + "type": "aws_secretsmanager_secret", + "name": "rds_secret", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": null, + "force_overwrite_replica_secret": false, + "kms_key_id": null, + "name": "rds-db-secret", + "recovery_window_in_days": 30, + "tags": { + "Name": "rds-db-secret" + }, + "tags_all": { + "Name": "rds-db-secret" + } + }, + "sensitive_values": { + "replica": [], + "tags": {}, + "tags_all": {} + } + }, + { + "address": "aws_secretsmanager_secret_version.rds_secret_version", + "mode": "managed", + "type": "aws_secretsmanager_secret_version", + "name": "rds_secret_version", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "secret_binary": null, + "secret_string": "{\"password\":\"admin1234\",\"username\":\"admin\"}" + }, + "sensitive_values": { + "secret_binary": true, + "secret_string": true, + "version_stages": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_proxy.bad_db_proxy", + "mode": "managed", + "type": "aws_db_proxy", + "name": "bad_db_proxy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "auth": [ + { + "auth_scheme": "SECRETS", + "description": "", + "iam_auth": "", + "username": "" + } + ], + "debug_logging": null, + "engine_family": "POSTGRESQL", + "name": "bad-db-proxy-01", + "require_tls": false, + "role_arn": "arn:aws:iam::xxxx:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS", + "tags": null, + "timeouts": null, + "vpc_subnet_ids": [ + "subnet-id-1", + "subnet-id-2" + ] + }, + "after_unknown": { + "arn": true, + "auth": [ + { + "client_password_auth_type": true, + "secret_arn": true + } + ], + "endpoint": true, + "id": true, + "idle_client_timeout": true, + "tags_all": true, + "vpc_security_group_ids": true, + "vpc_subnet_ids": [ + false, + false + ] + }, + "before_sensitive": false, + "after_sensitive": { + "auth": [ + {} + ], + "tags_all": {}, + "vpc_security_group_ids": [], + "vpc_subnet_ids": [ + false, + false + ] + } + } + }, + { + "address": "aws_secretsmanager_secret.rds_secret", + "mode": "managed", + "type": "aws_secretsmanager_secret", + "name": "rds_secret", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": null, + "force_overwrite_replica_secret": false, + "kms_key_id": null, + "name": "rds-db-secret", + "recovery_window_in_days": 30, + "tags": { + "Name": "rds-db-secret" + }, + "tags_all": { + "Name": "rds-db-secret" + } + }, + "after_unknown": { + "arn": true, + "id": true, + "name_prefix": true, + "policy": true, + "replica": true, + "tags": {}, + "tags_all": {} + }, + "before_sensitive": false, + "after_sensitive": { + "replica": [], + "tags": {}, + "tags_all": {} + } + } + }, + { + "address": "aws_secretsmanager_secret_version.rds_secret_version", + "mode": "managed", + "type": "aws_secretsmanager_secret_version", + "name": "rds_secret_version", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "secret_binary": null, + "secret_string": "{\"password\":\"admin1234\",\"username\":\"admin\"}" + }, + "after_unknown": { + "arn": true, + "id": true, + "secret_id": true, + "version_id": true, + "version_stages": true + }, + "before_sensitive": false, + "after_sensitive": { + "secret_binary": true, + "secret_string": true, + "version_stages": [] + } + } + } + ], + "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_db_proxy.bad_db_proxy", + "mode": "managed", + "type": "aws_db_proxy", + "name": "bad_db_proxy", + "provider_config_key": "aws", + "expressions": { + "auth": [ + { + "auth_scheme": { + "constant_value": "SECRETS" + }, + "secret_arn": { + "references": [ + "aws_secretsmanager_secret.rds_secret.arn", + "aws_secretsmanager_secret.rds_secret" + ] + } + } + ], + "engine_family": { + "constant_value": "POSTGRESQL" + }, + "name": { + "constant_value": "bad-db-proxy-01" + }, + "require_tls": { + "constant_value": false + }, + "role_arn": { + "constant_value": "arn:aws:iam::xxxx:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS" + }, + "vpc_subnet_ids": { + "constant_value": [ + "subnet-id-1", + "subnet-id-2" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_secretsmanager_secret.rds_secret", + "mode": "managed", + "type": "aws_secretsmanager_secret", + "name": "rds_secret", + "provider_config_key": "aws", + "expressions": { + "name": { + "constant_value": "rds-db-secret" + }, + "tags": { + "constant_value": { + "Name": "rds-db-secret" + } + } + }, + "schema_version": 0 + }, + { + "address": "aws_secretsmanager_secret_version.rds_secret_version", + "mode": "managed", + "type": "aws_secretsmanager_secret_version", + "name": "rds_secret_version", + "provider_config_key": "aws", + "expressions": { + "secret_id": { + "references": [ + "aws_secretsmanager_secret.rds_secret.id", + "aws_secretsmanager_secret.rds_secret" + ] + }, + "secret_string": {} + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_secretsmanager_secret.rds_secret", + "attribute": [ + "id" + ] + }, + { + "resource": "aws_secretsmanager_secret.rds_secret", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-10-01T07:48:25Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/bad-test/bad-payload-02.json b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/bad-test/bad-payload-02.json new file mode 100644 index 00000000..5a74cd92 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/bad-test/bad-payload-02.json @@ -0,0 +1,339 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_proxy.bad_db_proxy", + "mode": "managed", + "type": "aws_db_proxy", + "name": "bad_db_proxy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "auth": [ + { + "auth_scheme": "SECRETS", + "description": "", + "iam_auth": "", + "username": "" + } + ], + "debug_logging": null, + "engine_family": "POSTGRESQL", + "name": "bad-db-proxy-02", + "require_tls": null, + "role_arn": "arn:aws:iam::xxxx:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS", + "tags": null, + "timeouts": null, + "vpc_subnet_ids": [ + "subnet-03c8d8c9fc4dc6c23", + "subnet-0a3043a2ad9bd85a7" + ] + }, + "sensitive_values": { + "auth": [ + {} + ], + "tags_all": {}, + "vpc_security_group_ids": [], + "vpc_subnet_ids": [ + false, + false + ] + } + }, + { + "address": "aws_secretsmanager_secret.rds_secret", + "mode": "managed", + "type": "aws_secretsmanager_secret", + "name": "rds_secret", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": null, + "force_overwrite_replica_secret": false, + "kms_key_id": null, + "name": "rds-db-secret", + "recovery_window_in_days": 30, + "tags": { + "Name": "rds-db-secret" + }, + "tags_all": { + "Name": "rds-db-secret" + } + }, + "sensitive_values": { + "replica": [], + "tags": {}, + "tags_all": {} + } + }, + { + "address": "aws_secretsmanager_secret_version.rds_secret_version", + "mode": "managed", + "type": "aws_secretsmanager_secret_version", + "name": "rds_secret_version", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "secret_binary": null, + "secret_string": "{\"password\":\"admin1234\",\"username\":\"admin\"}" + }, + "sensitive_values": { + "secret_binary": true, + "secret_string": true, + "version_stages": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_proxy.bad_db_proxy", + "mode": "managed", + "type": "aws_db_proxy", + "name": "bad_db_proxy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "auth": [ + { + "auth_scheme": "SECRETS", + "description": "", + "iam_auth": "", + "username": "" + } + ], + "debug_logging": null, + "engine_family": "POSTGRESQL", + "name": "bad-db-proxy-02", + "require_tls": null, + "role_arn": "arn:aws:iam::xxxx:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS", + "tags": null, + "timeouts": null, + "vpc_subnet_ids": [ + "subnet-03c8d8c9fc4dc6c23", + "subnet-0a3043a2ad9bd85a7" + ] + }, + "after_unknown": { + "arn": true, + "auth": [ + { + "client_password_auth_type": true, + "secret_arn": true + } + ], + "endpoint": true, + "id": true, + "idle_client_timeout": true, + "tags_all": true, + "vpc_security_group_ids": true, + "vpc_subnet_ids": [ + false, + false + ] + }, + "before_sensitive": false, + "after_sensitive": { + "auth": [ + {} + ], + "tags_all": {}, + "vpc_security_group_ids": [], + "vpc_subnet_ids": [ + false, + false + ] + } + } + }, + { + "address": "aws_secretsmanager_secret.rds_secret", + "mode": "managed", + "type": "aws_secretsmanager_secret", + "name": "rds_secret", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": null, + "force_overwrite_replica_secret": false, + "kms_key_id": null, + "name": "rds-db-secret", + "recovery_window_in_days": 30, + "tags": { + "Name": "rds-db-secret" + }, + "tags_all": { + "Name": "rds-db-secret" + } + }, + "after_unknown": { + "arn": true, + "id": true, + "name_prefix": true, + "policy": true, + "replica": true, + "tags": {}, + "tags_all": {} + }, + "before_sensitive": false, + "after_sensitive": { + "replica": [], + "tags": {}, + "tags_all": {} + } + } + }, + { + "address": "aws_secretsmanager_secret_version.rds_secret_version", + "mode": "managed", + "type": "aws_secretsmanager_secret_version", + "name": "rds_secret_version", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "secret_binary": null, + "secret_string": "{\"password\":\"admin1234\",\"username\":\"admin\"}" + }, + "after_unknown": { + "arn": true, + "id": true, + "secret_id": true, + "version_id": true, + "version_stages": true + }, + "before_sensitive": false, + "after_sensitive": { + "secret_binary": true, + "secret_string": true, + "version_stages": [] + } + } + } + ], + "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_db_proxy.bad_db_proxy", + "mode": "managed", + "type": "aws_db_proxy", + "name": "bad_db_proxy", + "provider_config_key": "aws", + "expressions": { + "auth": [ + { + "auth_scheme": { + "constant_value": "SECRETS" + }, + "secret_arn": { + "references": [ + "aws_secretsmanager_secret.rds_secret.arn", + "aws_secretsmanager_secret.rds_secret" + ] + } + } + ], + "engine_family": { + "constant_value": "POSTGRESQL" + }, + "name": { + "constant_value": "bad-db-proxy-02" + }, + "role_arn": { + "constant_value": "arn:aws:iam::xxxx:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS" + }, + "vpc_subnet_ids": { + "constant_value": [ + "subnet-0a3043a2ad9bd85a7", + "subnet-03c8d8c9fc4dc6c23" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_secretsmanager_secret.rds_secret", + "mode": "managed", + "type": "aws_secretsmanager_secret", + "name": "rds_secret", + "provider_config_key": "aws", + "expressions": { + "name": { + "constant_value": "rds-db-secret" + }, + "tags": { + "constant_value": { + "Name": "rds-db-secret" + } + } + }, + "schema_version": 0 + }, + { + "address": "aws_secretsmanager_secret_version.rds_secret_version", + "mode": "managed", + "type": "aws_secretsmanager_secret_version", + "name": "rds_secret_version", + "provider_config_key": "aws", + "expressions": { + "secret_id": { + "references": [ + "aws_secretsmanager_secret.rds_secret.id", + "aws_secretsmanager_secret.rds_secret" + ] + }, + "secret_string": {} + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_secretsmanager_secret.rds_secret", + "attribute": [ + "id" + ] + }, + { + "resource": "aws_secretsmanager_secret.rds_secret", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-10-01T08:03:48Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/binding.yaml b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/chainsaw-test.yaml b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/chainsaw-test.yaml new file mode 100644 index 00000000..a9e6b8c3 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/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-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./good-test/good-payload-01.json --policy ../check-rds-db-proxy-tls.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-db-proxy-tls + rules: + - rule: + name: check-rds-db-proxy-tls + 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 --payload ./bad-test/bad-payload-01.json --policy ../check-rds-db-proxy-tls.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-db-proxy-tls + rules: + - rule: + name: check-rds-db-proxy-tls + error: ~ + violations: + - message: RDS Database Proxy should use TLS (CHECK=spec.rules[0].assert.all[0]) + 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 --payload ./bad-test/bad-payload-02.json --policy ../check-rds-db-proxy-tls.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-db-proxy-tls + rules: + - rule: + name: check-rds-db-proxy-tls + error: ~ + violations: + - message: RDS Database Proxy should use TLS (CHECK=spec.rules[0].assert.all[0]) + errors: + - type: FieldValueInvalid + value: false + detail: "Expected value: true" \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/good-test/good-01.tf b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/good-test/good-01.tf new file mode 100644 index 00000000..35a2c3a4 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/good-test/good-01.tf @@ -0,0 +1,43 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_secretsmanager_secret" "rds_secret" { + name = "rds-db-secret" + + tags = { + Name = "rds-db-secret" + } +} + +resource "aws_secretsmanager_secret_version" "rds_secret_version" { + secret_id = aws_secretsmanager_secret.rds_secret.id + secret_string = jsonencode({ + username = "admin" + password = "admin1234" + }) +} + +resource "aws_db_proxy" "good_db_proxy" { + name = "good-db-proxy-01" + engine_family = "POSTGRESQL" + role_arn = "arn:aws:iam::xxxx:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS" + vpc_subnet_ids = ["subnet-id-1", "subnet-id-2"] + require_tls = true + + auth { + auth_scheme = "SECRETS" + secret_arn = aws_secretsmanager_secret.rds_secret.arn + } +} diff --git a/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/good-test/good-payload-01.json b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/good-test/good-payload-01.json new file mode 100644 index 00000000..535db5bf --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-db-proxy-tls/test/good-test/good-payload-01.json @@ -0,0 +1,342 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_proxy.good_db_proxy", + "mode": "managed", + "type": "aws_db_proxy", + "name": "good_db_proxy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "auth": [ + { + "auth_scheme": "SECRETS", + "description": "", + "iam_auth": "", + "username": "" + } + ], + "debug_logging": null, + "engine_family": "POSTGRESQL", + "name": "good-db-proxy-01", + "require_tls": true, + "role_arn": "arn:aws:iam::xxxx:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS", + "tags": null, + "timeouts": null, + "vpc_subnet_ids": [ + "subnet-id-1", + "subnet-id-2" + ] + }, + "sensitive_values": { + "auth": [ + {} + ], + "tags_all": {}, + "vpc_security_group_ids": [], + "vpc_subnet_ids": [ + false, + false + ] + } + }, + { + "address": "aws_secretsmanager_secret.rds_secret", + "mode": "managed", + "type": "aws_secretsmanager_secret", + "name": "rds_secret", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "description": null, + "force_overwrite_replica_secret": false, + "kms_key_id": null, + "name": "rds-db-secret", + "recovery_window_in_days": 30, + "tags": { + "Name": "rds-db-secret" + }, + "tags_all": { + "Name": "rds-db-secret" + } + }, + "sensitive_values": { + "replica": [], + "tags": {}, + "tags_all": {} + } + }, + { + "address": "aws_secretsmanager_secret_version.rds_secret_version", + "mode": "managed", + "type": "aws_secretsmanager_secret_version", + "name": "rds_secret_version", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 0, + "values": { + "secret_binary": null, + "secret_string": "{\"password\":\"admin1234\",\"username\":\"admin\"}" + }, + "sensitive_values": { + "secret_binary": true, + "secret_string": true, + "version_stages": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_proxy.good_db_proxy", + "mode": "managed", + "type": "aws_db_proxy", + "name": "good_db_proxy", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "auth": [ + { + "auth_scheme": "SECRETS", + "description": "", + "iam_auth": "", + "username": "" + } + ], + "debug_logging": null, + "engine_family": "POSTGRESQL", + "name": "good-db-proxy-01", + "require_tls": true, + "role_arn": "arn:aws:iam::xxxx:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS", + "tags": null, + "timeouts": null, + "vpc_subnet_ids": [ + "subnet-id-1", + "subnet-id-2" + ] + }, + "after_unknown": { + "arn": true, + "auth": [ + { + "client_password_auth_type": true, + "secret_arn": true + } + ], + "endpoint": true, + "id": true, + "idle_client_timeout": true, + "tags_all": true, + "vpc_security_group_ids": true, + "vpc_subnet_ids": [ + false, + false + ] + }, + "before_sensitive": false, + "after_sensitive": { + "auth": [ + {} + ], + "tags_all": {}, + "vpc_security_group_ids": [], + "vpc_subnet_ids": [ + false, + false + ] + } + } + }, + { + "address": "aws_secretsmanager_secret.rds_secret", + "mode": "managed", + "type": "aws_secretsmanager_secret", + "name": "rds_secret", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "description": null, + "force_overwrite_replica_secret": false, + "kms_key_id": null, + "name": "rds-db-secret", + "recovery_window_in_days": 30, + "tags": { + "Name": "rds-db-secret" + }, + "tags_all": { + "Name": "rds-db-secret" + } + }, + "after_unknown": { + "arn": true, + "id": true, + "name_prefix": true, + "policy": true, + "replica": true, + "tags": {}, + "tags_all": {} + }, + "before_sensitive": false, + "after_sensitive": { + "replica": [], + "tags": {}, + "tags_all": {} + } + } + }, + { + "address": "aws_secretsmanager_secret_version.rds_secret_version", + "mode": "managed", + "type": "aws_secretsmanager_secret_version", + "name": "rds_secret_version", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "secret_binary": null, + "secret_string": "{\"password\":\"admin1234\",\"username\":\"admin\"}" + }, + "after_unknown": { + "arn": true, + "id": true, + "secret_id": true, + "version_id": true, + "version_stages": true + }, + "before_sensitive": false, + "after_sensitive": { + "secret_binary": true, + "secret_string": true, + "version_stages": [] + } + } + } + ], + "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_db_proxy.good_db_proxy", + "mode": "managed", + "type": "aws_db_proxy", + "name": "good_db_proxy", + "provider_config_key": "aws", + "expressions": { + "auth": [ + { + "auth_scheme": { + "constant_value": "SECRETS" + }, + "secret_arn": { + "references": [ + "aws_secretsmanager_secret.rds_secret.arn", + "aws_secretsmanager_secret.rds_secret" + ] + } + } + ], + "engine_family": { + "constant_value": "POSTGRESQL" + }, + "name": { + "constant_value": "good-db-proxy-01" + }, + "require_tls": { + "constant_value": true + }, + "role_arn": { + "constant_value": "arn:aws:iam::xxxx:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS" + }, + "vpc_subnet_ids": { + "constant_value": [ + "subnet-id-1", + "subnet-id-2" + ] + } + }, + "schema_version": 0 + }, + { + "address": "aws_secretsmanager_secret.rds_secret", + "mode": "managed", + "type": "aws_secretsmanager_secret", + "name": "rds_secret", + "provider_config_key": "aws", + "expressions": { + "name": { + "constant_value": "rds-db-secret" + }, + "tags": { + "constant_value": { + "Name": "rds-db-secret" + } + } + }, + "schema_version": 0 + }, + { + "address": "aws_secretsmanager_secret_version.rds_secret_version", + "mode": "managed", + "type": "aws_secretsmanager_secret_version", + "name": "rds_secret_version", + "provider_config_key": "aws", + "expressions": { + "secret_id": { + "references": [ + "aws_secretsmanager_secret.rds_secret.id", + "aws_secretsmanager_secret.rds_secret" + ] + }, + "secret_string": {} + }, + "schema_version": 0 + } + ] + } + }, + "relevant_attributes": [ + { + "resource": "aws_secretsmanager_secret.rds_secret", + "attribute": [ + "id" + ] + }, + { + "resource": "aws_secretsmanager_secret.rds_secret", + "attribute": [ + "arn" + ] + } + ], + "timestamp": "2024-10-01T07:44:38Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/README.md b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/README.md new file mode 100644 index 00000000..da163770 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/README.md @@ -0,0 +1,78 @@ +# Check RDS Instance Copy Tags To Snapshots Enabled + +This policy checks whether RDS DB instances are configured to copy all tags to snapshots when the snapshots are created. +Identification and inventory of your IT assets is a crucial aspect of governance and security. +You need to have visibility of all your RDS DB instances so that you can assess their security posture and take action on +potential areas of weakness. Snapshots should be tagged in the same way as their parent RDS database instances. +Enabling this setting ensures that snapshots inherit the tags of their parent database instances. +Read more about it [here](https://docs.aws.amazon.com/securityhub/latest/userguide/rds-controls.html#rds-17) + +## Policy Details: + +- **Policy Name:** check-rds-instance-copy-tags-to-snapshots-enabled +- **Check Description:** This policy checks if RDS DB instances are configured to copy tags to snapshots +- **Policy Category:** AWS RDS 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:** + ```bash + kyverno-json scan --payload payload.json --policy policy.yaml + ``` + + a. **Test Policy Against Valid Payload:** + ```bash + kyverno-json scan --payload test/good-test/good-payload-01.json --policy check-rds-instance-copy-tags-to-snapshots-enabled.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=check-rds-instance-copy-tags-to-snapshots-enabled, RULE=check-rds-instance-copy-tags-to-snapshots-enabled) + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-rds-instance-copy-tags-to-snapshots-enabled.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=check-rds-instance-copy-tags-to-snapshots-enabled, RULE=check-rds-instance-copy-tags-to-snapshots-enabled) + -> RDS DB instances should be configured to copy tags to snapshots (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: false: Expected value: true (PATH=~.(planned_values.root_module.resources[?type=='aws_db_instance'])[0].values.copy_tags_to_snapshot) + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/check-rds-instance-copy-tags-to-snapshots-enabled.yaml b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/check-rds-instance-copy-tags-to-snapshots-enabled.yaml new file mode 100644 index 00000000..af96b5b9 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/check-rds-instance-copy-tags-to-snapshots-enabled.yaml @@ -0,0 +1,28 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-rds-instance-copy-tags-to-snapshots-enabled + annotations: + policies.kyverno.io/title: Check RDS Instance Copy Tags To Snapshots Enabled + policies.kyverno.io/category: AWS RDS Best Practices + policies.kyverno.io/severity: low + policies.kyverno.io/description: >- + This policy checks whether RDS DB instances are configured to copy all tags to snapshots when the snapshots are created. + Identification and inventory of your IT assets is a crucial aspect of governance and security. + You need to have visibility of all your RDS DB instances so that you can assess their security posture and take action on + potential areas of weakness. Snapshots should be tagged in the same way as their parent RDS database instances. + Enabling this setting ensures that snapshots inherit the tags of their parent database instances. +spec: + rules: + - name: check-rds-instance-copy-tags-to-snapshots-enabled + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_db_instance'] || `[]` | length(@) > `0`): true + assert: + all: + - message: RDS DB instances should be configured to copy tags to snapshots + check: + ~.(planned_values.root_module.resources[?type=='aws_db_instance']): + values: + copy_tags_to_snapshot: true \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/bad-test/bad-01.tf b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/bad-test/bad-01.tf new file mode 100644 index 00000000..d86ab723 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/bad-test/bad-01.tf @@ -0,0 +1,25 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "bad_mysql_instance" { + identifier = "bad-mysql-instance-01" + instance_class = "db.t3.micro" + engine = "mysql" + username = "admin" + password = "secret99" + allocated_storage = 5 + skip_final_snapshot = true + copy_tags_to_snapshot = false +} diff --git a/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/bad-test/bad-02.tf b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/bad-test/bad-02.tf new file mode 100644 index 00000000..f7c1209a --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/bad-test/bad-02.tf @@ -0,0 +1,26 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "bad_mysql_instance" { + identifier = "bad-mysql-instance-02" + instance_class = "db.t3.micro" + engine = "mysql" + username = "admin" + password = "secret99" + allocated_storage = 5 + skip_final_snapshot = true + # copy_tags_to_snapshot defaults to false + # copy_tags_to_snapshot = false +} diff --git a/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/bad-test/bad-payload-01.json b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..9cc481f2 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/bad-test/bad-payload-01.json @@ -0,0 +1,240 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "bad-mysql-instance-01", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "bad-mysql-instance-01", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 5 + }, + "copy_tags_to_snapshot": { + "constant_value": false + }, + "engine": { + "constant_value": "mysql" + }, + "identifier": { + "constant_value": "bad-mysql-instance-01" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "password": { + "constant_value": "secret99" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "admin" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T11:10:14Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/bad-test/bad-payload-02.json b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/bad-test/bad-payload-02.json new file mode 100644 index 00000000..5610098c --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/bad-test/bad-payload-02.json @@ -0,0 +1,237 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "bad-mysql-instance-02", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "bad-mysql-instance-02", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 5 + }, + "engine": { + "constant_value": "mysql" + }, + "identifier": { + "constant_value": "bad-mysql-instance-02" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "password": { + "constant_value": "secret99" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "admin" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T11:10:35Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/binding.yaml b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/chainsaw-test.yaml b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/chainsaw-test.yaml new file mode 100644 index 00000000..ec44cd12 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/chainsaw-test.yaml @@ -0,0 +1,92 @@ +# 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-rds-instance-copy-tags-to-snapshots-enabled.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-instance-copy-tags-to-snapshots-enabled + rules: + - rule: + name: check-rds-instance-copy-tags-to-snapshots-enabled + 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 --payload ./bad-test/bad-payload-01.json --policy ../check-rds-instance-copy-tags-to-snapshots-enabled.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-instance-copy-tags-to-snapshots-enabled + rules: + - rule: + name: check-rds-instance-copy-tags-to-snapshots-enabled + error: ~ + violations: + - message: RDS DB instances should be configured to copy tags to snapshots (CHECK=spec.rules[0].assert.all[0]) + 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 --payload ./bad-test/bad-payload-02.json --policy ../check-rds-instance-copy-tags-to-snapshots-enabled.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-instance-copy-tags-to-snapshots-enabled + rules: + - rule: + name: check-rds-instance-copy-tags-to-snapshots-enabled + error: ~ + violations: + - message: RDS DB instances should be configured to copy tags to snapshots (CHECK=spec.rules[0].assert.all[0]) + errors: + - type: FieldValueInvalid + value: false + detail: "Expected value: true" + diff --git a/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/good-test/good-01.tf b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/good-test/good-01.tf new file mode 100644 index 00000000..474f8e0b --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/good-test/good-01.tf @@ -0,0 +1,25 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "good_mysql_instance" { + identifier = "good-mysql-instance-01" + instance_class = "db.t3.micro" + engine = "mysql" + username = "admin" + password = "secret99" + allocated_storage = 5 + skip_final_snapshot = true + copy_tags_to_snapshot = true +} diff --git a/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/good-test/good-payload-01.json b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/good-test/good-payload-01.json new file mode 100644 index 00000000..ffd793b5 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-copy-tags-to-snapshots-enabled/test/good-test/good-payload-01.json @@ -0,0 +1,240 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": true, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "good-mysql-instance-01", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": true, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "good-mysql-instance-01", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 5 + }, + "copy_tags_to_snapshot": { + "constant_value": true + }, + "engine": { + "constant_value": "mysql" + }, + "identifier": { + "constant_value": "good-mysql-instance-01" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "password": { + "constant_value": "secret99" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "admin" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T11:08:35Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-instance-public-access/README.md b/terraform/plan/rds-best-practices/check-rds-instance-public-access/README.md new file mode 100644 index 00000000..02925a92 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-public-access/README.md @@ -0,0 +1,75 @@ +# Check RDS Instance Public Access + +The `PubliclyAccessible` value in the RDS instance configuration indicates whether the DB instance is publicly accessible. When the DB instance is configured with `PubliclyAccessible`, it is an Internet-facing instance with a publicly resolvable DNS name, which resolves to a public IP address. When the DB instance isn't publicly accessible, it is an internal instance with a DNS name that resolves to a private IP address. + +Unless you intend for your RDS instance to be publicly accessible, the RDS instance should not be configured with `PubliclyAccessible` value. Doing so might allow unnecessary traffic to your database instance. You can read about it [here](https://docs.aws.amazon.com/securityhub/latest/userguide/rds-controls.html#rds-2) + +## Policy Details: + +- **Policy Name:** check-rds-instance-public-access +- **Check Description:** This policy ensures that RDS instances are not publicly accessible +- **Policy Category:** AWS RDS 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:** + ```bash + kyverno-json scan --payload payload.json --policy policy.yaml + ``` + + a. **Test Policy Against Valid Payload:** + ```bash + kyverno-json scan --payload test/good-test/good-payload-01.json --policy check-rds-instance-public-access.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=check-rds-instance-public-access, RULE=check-rds-instance-public-access) + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-rds-instance-public-access.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=check-rds-instance-public-access, RULE=check-rds-instance-public-access) + -> RDS Database Instance should not be publicly accessible (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: true: Expected value: false (PATH=~.(planned_values.root_module.resources[?type=='aws_db_instance'])[0].values.publicly_accessible) + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-instance-public-access/check-rds-instance-public-access.yaml b/terraform/plan/rds-best-practices/check-rds-instance-public-access/check-rds-instance-public-access.yaml new file mode 100644 index 00000000..922f758b --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-public-access/check-rds-instance-public-access.yaml @@ -0,0 +1,28 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-rds-instance-public-access + annotations: + policies.kyverno.io/title: Check RDS Instance Public Access + policies.kyverno.io/category: AWS RDS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + The `PubliclyAccessible` value in the RDS instance configuration indicates whether the DB instance is publicly accessible. + When the DB instance is configured with `PubliclyAccessible`, it is an Internet-facing instance with a publicly resolvable DNS name, + which resolves to a public IP address. When the DB instance isn't publicly accessible, it is an internal instance with a DNS name + that resolves to a private IP address. Unless you intend for your RDS instance to be publicly accessible, the RDS instance + should not be configured with `PubliclyAccessible` value. Doing so might allow unnecessary traffic to your database instance. +spec: + rules: + - name: check-rds-instance-public-access + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_db_instance'] || `[]` | length(@) > `0`): true + assert: + all: + - message: RDS Database Instance should not be publicly accessible + check: + ~.(planned_values.root_module.resources[?type=='aws_db_instance']): + values: + publicly_accessible: false diff --git a/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/bad-test/bad-01.tf b/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/bad-test/bad-01.tf new file mode 100644 index 00000000..b450e97d --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/bad-test/bad-01.tf @@ -0,0 +1,26 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "bad-db-instance" { + allocated_storage = 10 + engine = "mysql" + engine_version = "8.0" + instance_class = "db.t3.micro" + db_name = "mydb" + username = "username" + password = "password" + publicly_accessible = true + skip_final_snapshot = true +} diff --git a/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/bad-test/bad-payload-01.json b/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..01382aeb --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/bad-test/bad-payload-01.json @@ -0,0 +1,244 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.bad-db-instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad-db-instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 10, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "db_name": "mydb", + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "engine_version": "8.0", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "password", + "performance_insights_enabled": false, + "publicly_accessible": true, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "username" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.bad-db-instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad-db-instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 10, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "db_name": "mydb", + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "engine_version": "8.0", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "password", + "performance_insights_enabled": false, + "publicly_accessible": true, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "username" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.bad-db-instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad-db-instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 10 + }, + "db_name": { + "constant_value": "mydb" + }, + "engine": { + "constant_value": "mysql" + }, + "engine_version": { + "constant_value": "8.0" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "password": { + "constant_value": "password" + }, + "publicly_accessible": { + "constant_value": true + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "username" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T05:24:15Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/binding.yaml b/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/chainsaw-test.yaml b/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/chainsaw-test.yaml new file mode 100644 index 00000000..3c75ff93 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-public-access/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 --payload ./good-test/good-payload-01.json --policy ../check-rds-instance-public-access.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-instance-public-access + rules: + - rule: + name: check-rds-instance-public-access + 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 --payload ./good-test/good-payload-02.json --policy ../check-rds-instance-public-access.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-instance-public-access + rules: + - rule: + name: check-rds-instance-public-access + 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 --payload ./bad-test/bad-payload-01.json --policy ../check-rds-instance-public-access.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-instance-public-access + rules: + - rule: + name: check-rds-instance-public-access + error: ~ + violations: + - message: RDS Database Instance should not be publicly accessible (CHECK=spec.rules[0].assert.all[0]) + errors: + - type: FieldValueInvalid + value: true + detail: "Expected value: false" \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/good-test/good-01.tf b/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/good-test/good-01.tf new file mode 100644 index 00000000..01276359 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/good-test/good-01.tf @@ -0,0 +1,26 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "good-db-instance" { + allocated_storage = 10 + engine = "mysql" + engine_version = "8.0" + instance_class = "db.t3.micro" + db_name = "mydb" + username = "username" + password = "password" + publicly_accessible = false + skip_final_snapshot = true +} diff --git a/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/good-test/good-02.tf b/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/good-test/good-02.tf new file mode 100644 index 00000000..5b1d7268 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/good-test/good-02.tf @@ -0,0 +1,27 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "good-db-instance" { + allocated_storage = 10 + engine = "mysql" + engine_version = "8.0" + instance_class = "db.t3.micro" + db_name = "mydb" + username = "username" + password = "password" + # publicly_accessible defaults to false + # publicly_accessible = false + skip_final_snapshot = true +} diff --git a/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/good-test/good-payload-01.json b/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/good-test/good-payload-01.json new file mode 100644 index 00000000..f43551fb --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/good-test/good-payload-01.json @@ -0,0 +1,244 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.good-db-instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good-db-instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 10, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "db_name": "mydb", + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "engine_version": "8.0", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "password", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "username" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.good-db-instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good-db-instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 10, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "db_name": "mydb", + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "engine_version": "8.0", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "password", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "username" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.good-db-instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good-db-instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 10 + }, + "db_name": { + "constant_value": "mydb" + }, + "engine": { + "constant_value": "mysql" + }, + "engine_version": { + "constant_value": "8.0" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "password": { + "constant_value": "password" + }, + "publicly_accessible": { + "constant_value": false + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "username" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T05:26:46Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/good-test/good-payload-02.json b/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/good-test/good-payload-02.json new file mode 100644 index 00000000..976d0cfa --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-instance-public-access/test/good-test/good-payload-02.json @@ -0,0 +1,241 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.good-db-instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good-db-instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 10, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "db_name": "mydb", + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "engine_version": "8.0", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "password", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "username" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.good-db-instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good-db-instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 10, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "db_name": "mydb", + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "engine_version": "8.0", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "password", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "username" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.good-db-instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good-db-instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 10 + }, + "db_name": { + "constant_value": "mydb" + }, + "engine": { + "constant_value": "mysql" + }, + "engine_version": { + "constant_value": "8.0" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "password": { + "constant_value": "password" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "username" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T05:27:36Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-multi-az-support/README.md b/terraform/plan/rds-best-practices/check-rds-multi-az-support/README.md new file mode 100644 index 00000000..245bcf0e --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-multi-az-support/README.md @@ -0,0 +1,77 @@ +# Check RDS Multi AZ Support + +This policy checks whether high availability is enabled for your RDS DB instances. +RDS DB instances should be configured for multiple Availability Zones (AZs). +This ensures the availability of the data stored. Multi-AZ deployments allow for automated failover +if there is an issue with AZ availability and during regular RDS maintenance. +You can read more about it [here](https://docs.aws.amazon.com/securityhub/latest/userguide/rds-controls.html#rds-5) + +## Policy Details: + +- **Policy Name:** check-rds-multi-az-support +- **Check Description:** This policy ensures that RDS DB instances have Multi AZ enabled +- **Policy Category:** AWS RDS 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:** + ```bash + kyverno-json scan --payload payload.json --policy policy.yaml + ``` + + a. **Test Policy Against Valid Payload:** + ```bash + kyverno-json scan --payload test/good-test/good-payload-01.json --policy check-rds-multi-az-support.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=check-rds-multi-az-support, RULE=check-rds-multi-az-support) + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-rds-multi-az-support.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=check-rds-multi-az-support, RULE=check-rds-multi-az-support) + -> RDS DB instances should be configured with multiple Availability Zones (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: false: Expected value: true (PATH=~.(planned_values.root_module.resources[?type=='aws_db_instance'])[0].values.(!!multi_az)) + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-multi-az-support/check-rds-multi-az-support.yaml b/terraform/plan/rds-best-practices/check-rds-multi-az-support/check-rds-multi-az-support.yaml new file mode 100644 index 00000000..3602f44a --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-multi-az-support/check-rds-multi-az-support.yaml @@ -0,0 +1,27 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-rds-multi-az-support + annotations: + policies.kyverno.io/title: Check RDS Multi AZ Support + policies.kyverno.io/category: AWS RDS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy checks whether high availability is enabled for your RDS DB instances. + RDS DB instances should be configured for multiple Availability Zones (AZs). + This ensures the availability of the data stored. Multi-AZ deployments allow for automated failover + if there is an issue with AZ availability and during regular RDS maintenance. +spec: + rules: + - name: check-rds-multi-az-support + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_db_instance'] || `[]` | length(@) > `0`): true + assert: + all: + - message: RDS DB instances should be configured with multiple Availability Zones + check: + ~.(planned_values.root_module.resources[?type=='aws_db_instance']): + values: + (!!multi_az): true \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/bad-test/bad-01.tf b/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/bad-test/bad-01.tf new file mode 100644 index 00000000..ef53bfba --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/bad-test/bad-01.tf @@ -0,0 +1,25 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "bad_mysql_instance" { + identifier = "bad-mysql-instance-01" + instance_class = "db.t3.micro" + engine = "mysql" + username = "admin" + password = "secret99" + allocated_storage = 5 + skip_final_snapshot = true + multi_az = false +} diff --git a/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/bad-test/bad-02.tf b/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/bad-test/bad-02.tf new file mode 100644 index 00000000..a7134d0f --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/bad-test/bad-02.tf @@ -0,0 +1,24 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "bad_mysql_instance" { + identifier = "bad-mysql-instance-02" + instance_class = "db.t3.micro" + engine = "mysql" + username = "admin" + password = "secret99" + allocated_storage = 5 + skip_final_snapshot = true +} diff --git a/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/bad-test/bad-payload-01.json b/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..478a47c5 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/bad-test/bad-payload-01.json @@ -0,0 +1,241 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "bad-mysql-instance-01", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "multi_az": false, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "bad-mysql-instance-01", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "multi_az": false, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 5 + }, + "engine": { + "constant_value": "mysql" + }, + "identifier": { + "constant_value": "bad-mysql-instance-01" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "multi_az": { + "constant_value": false + }, + "password": { + "constant_value": "secret99" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "admin" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T10:19:03Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/bad-test/bad-payload-02.json b/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/bad-test/bad-payload-02.json new file mode 100644 index 00000000..185ca419 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/bad-test/bad-payload-02.json @@ -0,0 +1,237 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "bad-mysql-instance-02", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "bad-mysql-instance-02", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 5 + }, + "engine": { + "constant_value": "mysql" + }, + "identifier": { + "constant_value": "bad-mysql-instance-02" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "password": { + "constant_value": "secret99" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "admin" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T10:25:53Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/binding.yaml b/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/chainsaw-test.yaml b/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/chainsaw-test.yaml new file mode 100644 index 00000000..ec6413d9 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/chainsaw-test.yaml @@ -0,0 +1,92 @@ +# 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-rds-multi-az-support.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-multi-az-support + rules: + - rule: + name: check-rds-multi-az-support + 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 --payload ./bad-test/bad-payload-01.json --policy ../check-rds-multi-az-support.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-multi-az-support + rules: + - rule: + name: check-rds-multi-az-support + error: ~ + violations: + - message: RDS DB instances should be configured with multiple Availability Zones (CHECK=spec.rules[0].assert.all[0]) + 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 --payload ./bad-test/bad-payload-02.json --policy ../check-rds-multi-az-support.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-multi-az-support + rules: + - rule: + name: check-rds-multi-az-support + error: ~ + violations: + - message: RDS DB instances should be configured with multiple Availability Zones (CHECK=spec.rules[0].assert.all[0]) + errors: + - type: FieldValueInvalid + value: false + detail: "Expected value: true" + diff --git a/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/good-test/good-01.tf b/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/good-test/good-01.tf new file mode 100644 index 00000000..a53a3107 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/good-test/good-01.tf @@ -0,0 +1,25 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "good_mysql_instance" { + identifier = "good-mysql-instance" + instance_class = "db.t3.micro" + engine = "mysql" + username = "admin" + password = "secret99" + allocated_storage = 5 + skip_final_snapshot = true + multi_az = true +} diff --git a/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/good-test/good-payload-01.json b/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/good-test/good-payload-01.json new file mode 100644 index 00000000..3a7c106d --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-multi-az-support/test/good-test/good-payload-01.json @@ -0,0 +1,241 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "good-mysql-instance", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "multi_az": true, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "good-mysql-instance", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "multi_az": true, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 5 + }, + "engine": { + "constant_value": "mysql" + }, + "identifier": { + "constant_value": "good-mysql-instance" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "multi_az": { + "constant_value": true + }, + "password": { + "constant_value": "secret99" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "admin" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T10:18:16Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-storage-encrypted/check-rds-storage-encrypted.yaml b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/check-rds-storage-encrypted.yaml new file mode 100644 index 00000000..395ae915 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/check-rds-storage-encrypted.yaml @@ -0,0 +1,31 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: check-rds-storage-encrypted + annotations: + policies.kyverno.io/title: Check RDS Storage Encrypted + policies.kyverno.io/category: AWS RDS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy checks whether storage encryption is enabled for your Amazon RDS DB instances. + For an added layer of security for your sensitive data in RDS DB instances, you should configure your + RDS DB instances to be encrypted at rest. To encrypt your RDS DB instances and snapshots at rest, enable the + encryption option for your RDS DB instances. Data that is encrypted at rest includes the underlying storage + for DB instances, its automated backups, read replicas, and snapshots. RDS encrypted DB instances use the open + standard AES-256 encryption algorithm to encrypt your data on the server that hosts your RDS DB instances. + After your data is encrypted, Amazon RDS handles authentication of access and decryption of your data transparently + with a minimal impact on performance. You do not need to modify your database client applications to use encryption. +spec: + rules: + - name: check-rds-storage-encrypted + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_db_instance'] || `[]` | length(@) > `0`): true + assert: + all: + - message: RDS DB instances should have encryption at-rest enabled + check: + ~.(planned_values.root_module.resources[?type=='aws_db_instance']): + values: + (!!storage_encrypted): true \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/README.md b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/README.md new file mode 100644 index 00000000..1f449ecd --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/README.md @@ -0,0 +1,110 @@ +# Check RDS Storage Encrypted + +This policy checks whether storage encryption is enabled for your Amazon RDS DB instances. +For an added layer of security for your sensitive data in RDS DB instances, you should configure your +RDS DB instances to be encrypted at rest. To encrypt your RDS DB instances and snapshots at rest, enable the +encryption option for your RDS DB instances. Data that is encrypted at rest includes the underlying storage +for DB instances, its automated backups, read replicas, and snapshots. RDS encrypted DB instances use the open +standard AES-256 encryption algorithm to encrypt your data on the server that hosts your RDS DB instances. +After your data is encrypted, Amazon RDS handles authentication of access and decryption of your data transparently +with a minimal impact on performance. You do not need to modify your database client applications to use encryption. +You can read more about it [here](https://docs.aws.amazon.com/securityhub/latest/userguide/rds-controls.html#rds-3) + +## Policy Details: + +- **Policy Name:** check-rds-storage-encrypted +- **Check Description:** This policy ensures that RDS DB instances have encryption at-rest enabled +- **Policy Category:** AWS RDS 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. **Create the RDS Database Instance:** + + a. Good RDS Database Instance + ```bash + aws rds create-db-instance \ + --db-instance-identifier good-mysql-instance \ + --db-instance-class db.t3.micro \ + --engine mysql \ + --master-username admin \ + --master-user-password secret99 \ + --allocated-storage 5 \ + --storage-encrypted + ``` + + b. Bad RDS Database Instance + ```bash + aws rds create-db-instance \ + --db-instance-identifier bad-mysql-instance-01 \ + --db-instance-class db.t3.micro \ + --engine mysql \ + --master-username admin \ + --master-user-password secret99 \ + --allocated-storage 5 \ + --no-storage-encrypted + ``` + +2. **Get the Payloads:** + + a. Bad Payload + ```bash + aws rds describe-db-instances --db-instance-identifier bad-mysql-instance-01 > bad-payload-01.json + ``` + + b. Good Payload + ```bash + aws rds describe-db-instances --db-instance-identifier good-mysql-instance > good-payload-01.json + ``` +3. **Clean Up Resources:** + + a. Delete the Bad RDS Instance + ```bash + aws rds delete-db-instance --db-instance-identifier bad-mysql-instance-01 --skip-final-snapshot + ``` + + b. Delete the Good RDS Instance + + ```bash + aws rds delete-db-instance --db-instance-identifier good-mysql-instance --skip-final-snapshot + ``` + +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-rds-storage-encrypted.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - check-rds-storage-encrypted / check-rds-storage-encrypted / PASSED + Done + ``` + + b. **Test Against Invalid Payload:** + ```bash + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy check-rds-storage-encrypted.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - check-rds-storage-encrypted / check-rds-storage-encrypted / FAILED + -> RDS DB instances should have encryption at-rest enabled + -> all[0].check.~.(DBInstances)[0].StorageEncrypted: Invalid value: false: Expected value: true + Done + ``` \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/bad-test/bad-01.tf b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/bad-test/bad-01.tf new file mode 100644 index 00000000..ac1c5a83 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/bad-test/bad-01.tf @@ -0,0 +1,25 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "bad_mysql_instance" { + identifier = "bad-mysql-instance-01" + instance_class = "db.t3.micro" + engine = "mysql" + username = "admin" + password = "secret99" + allocated_storage = 5 + skip_final_snapshot = true + storage_encrypted = false +} diff --git a/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/bad-test/bad-02.tf b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/bad-test/bad-02.tf new file mode 100644 index 00000000..a7134d0f --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/bad-test/bad-02.tf @@ -0,0 +1,24 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "bad_mysql_instance" { + identifier = "bad-mysql-instance-02" + instance_class = "db.t3.micro" + engine = "mysql" + username = "admin" + password = "secret99" + allocated_storage = 5 + skip_final_snapshot = true +} diff --git a/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/bad-test/bad-payload-01.json b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..65d76aa5 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/bad-test/bad-payload-01.json @@ -0,0 +1,240 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "bad-mysql-instance-01", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": false, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "bad-mysql-instance-01", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": false, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 5 + }, + "engine": { + "constant_value": "mysql" + }, + "identifier": { + "constant_value": "bad-mysql-instance-01" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "password": { + "constant_value": "secret99" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "storage_encrypted": { + "constant_value": false + }, + "username": { + "constant_value": "admin" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T10:41:18Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/bad-test/bad-payload-02.json b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/bad-test/bad-payload-02.json new file mode 100644 index 00000000..185ca419 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/bad-test/bad-payload-02.json @@ -0,0 +1,237 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "bad-mysql-instance-02", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "bad-mysql-instance-02", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 5 + }, + "engine": { + "constant_value": "mysql" + }, + "identifier": { + "constant_value": "bad-mysql-instance-02" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "password": { + "constant_value": "secret99" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "admin" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T10:25:53Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/binding.yaml b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/chainsaw-test.yaml b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/chainsaw-test.yaml new file mode 100644 index 00000000..0cfdf8d1 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/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-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./good-test/good-payload-01.json --policy ../check-rds-storage-encrypted.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-storage-encrypted + rules: + - rule: + name: check-rds-storage-encrypted + 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 --payload ./bad-test/bad-payload-01.json --policy ../check-rds-storage-encrypted.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-storage-encrypted + rules: + - rule: + name: check-rds-storage-encrypted + error: ~ + violations: + - message: RDS DB instances should have encryption at-rest enabled (CHECK=spec.rules[0].assert.all[0]) + 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 --payload ./bad-test/bad-payload-02.json --policy ../check-rds-storage-encrypted.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: check-rds-storage-encrypted + rules: + - rule: + name: check-rds-storage-encrypted + error: ~ + violations: + - message: RDS DB instances should have encryption at-rest enabled (CHECK=spec.rules[0].assert.all[0]) + errors: + - type: FieldValueInvalid + value: false + detail: "Expected value: true" \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/good-test/good-01.tf b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/good-test/good-01.tf new file mode 100644 index 00000000..7df5cfea --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/good-test/good-01.tf @@ -0,0 +1,25 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "good_mysql_instance" { + identifier = "good-mysql-instance" + instance_class = "db.t3.micro" + engine = "mysql" + username = "admin" + password = "secret99" + allocated_storage = 5 + skip_final_snapshot = true + storage_encrypted = true +} diff --git a/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/good-test/good-payload-01.json b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/good-test/good-payload-01.json new file mode 100644 index 00000000..5f3a5df9 --- /dev/null +++ b/terraform/plan/rds-best-practices/check-rds-storage-encrypted/test/good-test/good-payload-01.json @@ -0,0 +1,240 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "good-mysql-instance", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": true, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "good-mysql-instance", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": true, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 5 + }, + "engine": { + "constant_value": "mysql" + }, + "identifier": { + "constant_value": "good-mysql-instance" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "password": { + "constant_value": "secret99" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "storage_encrypted": { + "constant_value": true + }, + "username": { + "constant_value": "admin" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T10:45:49Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/README.md b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/README.md new file mode 100644 index 00000000..c6b6d064 --- /dev/null +++ b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/README.md @@ -0,0 +1,89 @@ +# RDS Instance IAM Authentication Enabled + +This policy checks whether an RDS DB instance has IAM database authentication enabled. The policy fails if IAM authentication is not configured for RDS DB instances. This policy only evaluates RDS instances with the following engine types: `mysql`, `postgres`, `aurora`, `aurora-mysql`, `aurora-postgresql` and `mariadb`. IAM database authentication allows authentication to database instances with an authentication token instead of a password. traffic to and from the database is encrypted using SSL. + +## Policy Details: + +- **Policy Name:** rds-instance-iam-authentication-enabled +- **Check Description:** This policy ensures that IAM authentication is configured for RDS instances +- **Policy Category:** AWS RDS 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:** + ```bash + kyverno-json scan --payload payload.json --policy policy.yaml + ``` + + a. **Test Policy Against Valid Payload:** + ```bash + kyverno-json scan --payload test/good-test/good-payload-01.json --policy rds-instance-iam-authentication-enabled.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - PASSED (POLICY=rds-instance-iam-authentication-enabled, RULE=rds-instance-iam-authentication-enabled) + Done + ``` + + b. **Test Against Invalid Payload:** + ``` + kyverno-json scan --payload test/bad-test/bad-payload-01.json --policy rds-instance-iam-authentication-enabled.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + - FAILED (POLICY=rds-instance-iam-authentication-enabled, RULE=rds-instance-iam-authentication-enabled) + -> IAM authentication should be configured for RDS instances (CHECK=spec.rules[0].assert.all[0]) + -> Invalid value: false: Expected value: true (PATH=~.(planned_values.root_module.resources[?type=='aws_db_instance' && contains($engineTypes, values.engine)])[0].values.(!!iam_database_authentication_enabled)) + Done + ``` + + c. **Test against Payload to Be Skipped:** + ``` + kyverno-json scan --payload test/skip-test/skip-payload-01.json --policy rds-instance-iam-authentication-enabled.yaml --bindings test/binding.yaml + ``` + + This produces the output: + ```bash + Loading policies ... + Loading bindings ... + - analyzer -> map[resource:map[type:terraform-plan]] + Loading payload ... + Pre processing ... + Running ( evaluating 1 resource against 1 policy ) ... + Done + ``` + +--- \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/rds-instance-iam-authentication-enabled.yaml b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/rds-instance-iam-authentication-enabled.yaml new file mode 100644 index 00000000..cea2d0bf --- /dev/null +++ b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/rds-instance-iam-authentication-enabled.yaml @@ -0,0 +1,37 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: ValidatingPolicy +metadata: + name: rds-instance-iam-authentication-enabled + annotations: + policies.kyverno.io/title: RDS Instance IAM Authentication Enabled + policies.kyverno.io/category: AWS RDS Best Practices + policies.kyverno.io/severity: medium + policies.kyverno.io/description: >- + This policy checks whether an RDS DB instance has IAM database authentication enabled. + The policy fails if IAM authentication is not configured for RDS DB instances. + This policy only evaluates RDS instances with the following engine types: mysql, postgres, aurora, aurora-mysql, aurora-postgresql, and mariadb. + IAM database authentication allows authentication to database instances with an authentication token instead of a password. Network traffic to and from the database is encrypted using SSL. +spec: + rules: + - name: rds-instance-iam-authentication-enabled + match: + all: + - ($analyzer.resource.type): terraform-plan + - (planned_values.root_module.resources[?type=='aws_db_instance' && contains($engineTypes, values.engine)] || `[]` | length(@) > `0`): true + context: + - name: engineTypes + variable: + - 'mysql' + - 'postgres' + - 'aurora' + - 'aurora-mysql' + - 'aurora-postgresql' + - 'mariadb' + assert: + all: + - message: IAM authentication should be configured for RDS instances + check: + ~.(planned_values.root_module.resources[?type=='aws_db_instance' && contains($engineTypes, values.engine)]): + values: + (!!iam_database_authentication_enabled): true + \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/bad-test/bad-01.tf b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/bad-test/bad-01.tf new file mode 100644 index 00000000..f8218015 --- /dev/null +++ b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/bad-test/bad-01.tf @@ -0,0 +1,25 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "bad_mysql_instance" { + identifier = "bad-mysql-instance-01" + instance_class = "db.t3.micro" + engine = "mysql" + username = "admin" + password = "secret99" + allocated_storage = 5 + skip_final_snapshot = true + iam_database_authentication_enabled = false +} diff --git a/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/bad-test/bad-02.tf b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/bad-test/bad-02.tf new file mode 100644 index 00000000..82b3245f --- /dev/null +++ b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/bad-test/bad-02.tf @@ -0,0 +1,24 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "bad_mysql_instance" { + identifier = "bad-mysql-instance-02" + instance_class = "db.t3.micro" + engine = "mysql" + username = "admin" + password = "secret99" + allocated_storage = 5 + skip_final_snapshot = true +} diff --git a/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/bad-test/bad-payload-01.json b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/bad-test/bad-payload-01.json new file mode 100644 index 00000000..1d16b53d --- /dev/null +++ b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/bad-test/bad-payload-01.json @@ -0,0 +1,240 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": false, + "identifier": "bad-mysql-instance-01", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": false, + "identifier": "bad-mysql-instance-01", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 5 + }, + "engine": { + "constant_value": "mysql" + }, + "iam_database_authentication_enabled": { + "constant_value": false + }, + "identifier": { + "constant_value": "bad-mysql-instance-01" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "password": { + "constant_value": "secret99" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "admin" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T11:37:51Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/bad-test/bad-payload-02.json b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/bad-test/bad-payload-02.json new file mode 100644 index 00000000..69649932 --- /dev/null +++ b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/bad-test/bad-payload-02.json @@ -0,0 +1,237 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "bad-mysql-instance-02", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "bad-mysql-instance-02", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.bad_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "bad_mysql_instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 5 + }, + "engine": { + "constant_value": "mysql" + }, + "identifier": { + "constant_value": "bad-mysql-instance-02" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "password": { + "constant_value": "secret99" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "admin" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T11:37:49Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/binding.yaml b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/binding.yaml new file mode 100644 index 00000000..a3dd760d --- /dev/null +++ b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/binding.yaml @@ -0,0 +1,3 @@ +analyzer: + resource: + type: terraform-plan \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/chainsaw-test.yaml b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/chainsaw-test.yaml new file mode 100644 index 00000000..e138c0e0 --- /dev/null +++ b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/chainsaw-test.yaml @@ -0,0 +1,114 @@ +# 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 ../rds-instance-iam-authentication-enabled.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: rds-instance-iam-authentication-enabled + rules: + - rule: + name: rds-instance-iam-authentication-enabled + 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 --payload ./bad-test/bad-payload-01.json --policy ../rds-instance-iam-authentication-enabled.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: rds-instance-iam-authentication-enabled + rules: + - rule: + name: rds-instance-iam-authentication-enabled + error: ~ + violations: + - message: IAM authentication should be configured for RDS instances (CHECK=spec.rules[0].assert.all[0]) + 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 --payload ./bad-test/bad-payload-02.json --policy ../rds-instance-iam-authentication-enabled.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: rds-instance-iam-authentication-enabled + rules: + - rule: + name: rds-instance-iam-authentication-enabled + error: ~ + violations: + - message: IAM authentication should be configured for RDS instances (CHECK=spec.rules[0].assert.all[0]) + errors: + - type: FieldValueInvalid + value: false + detail: "Expected value: true" +--- +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: skip-test-01 +spec: + steps: + - name: kyverno-json + try: + - script: + content: | + set -e + kyverno-json scan --payload ./skip-test/skip-payload-01.json --policy ../rds-instance-iam-authentication-enabled.yaml --output json --bindings ./binding.yaml + check: + ($error): ~ + (json_parse($stdout)): + - results: + - policy: + apiVersion: json.kyverno.io/v1alpha1 + kind: ValidatingPolicy + metadata: + name: rds-instance-iam-authentication-enabled + rules: ~ \ No newline at end of file diff --git a/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/good-test/good-01.tf b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/good-test/good-01.tf new file mode 100644 index 00000000..0c19ed99 --- /dev/null +++ b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/good-test/good-01.tf @@ -0,0 +1,25 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "good_mysql_instance" { + identifier = "good-mysql-instance" + instance_class = "db.t3.micro" + engine = "mysql" + username = "admin" + password = "secret99" + allocated_storage = 5 + skip_final_snapshot = true + iam_database_authentication_enabled = true +} diff --git a/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/good-test/good-payload-01.json b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/good-test/good-payload-01.json new file mode 100644 index 00000000..9b7bded2 --- /dev/null +++ b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/good-test/good-payload-01.json @@ -0,0 +1,240 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": true, + "identifier": "good-mysql-instance", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 5, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "mysql", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": true, + "identifier": "good-mysql-instance", + "instance_class": "db.t3.micro", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secret99", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "admin" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.good_mysql_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "good_mysql_instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 5 + }, + "engine": { + "constant_value": "mysql" + }, + "iam_database_authentication_enabled": { + "constant_value": true + }, + "identifier": { + "constant_value": "good-mysql-instance" + }, + "instance_class": { + "constant_value": "db.t3.micro" + }, + "password": { + "constant_value": "secret99" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "admin" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T11:37:47Z", + "applyable": true, + "complete": true, + "errored": false +} diff --git a/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/skip-test/skip-01.tf b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/skip-test/skip-01.tf new file mode 100644 index 00000000..331fdd20 --- /dev/null +++ b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/skip-test/skip-01.tf @@ -0,0 +1,24 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 5.32" + } + } +} + +provider "aws" { + region = "us-west-2" +} + +resource "aws_db_instance" "skip_instance" { + identifier = "skip-instance-01" + instance_class = "db.m5.large" + engine = "oracle-ee" # Engine is oracle-ee. Hence, this test is skipped. + username = "master_username" + password = "secure_password" + allocated_storage = 10 + skip_final_snapshot = true +} diff --git a/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/skip-test/skip-payload-01.json b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/skip-test/skip-payload-01.json new file mode 100644 index 00000000..8f98d052 --- /dev/null +++ b/terraform/plan/rds-best-practices/rds-instance-iam-authentication-enabled/test/skip-test/skip-payload-01.json @@ -0,0 +1,237 @@ +{ + "format_version": "1.2", + "terraform_version": "1.9.2", + "planned_values": { + "root_module": { + "resources": [ + { + "address": "aws_db_instance.skip_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "skip_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "schema_version": 2, + "values": { + "allocated_storage": 10, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "oracle-ee", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "skip-instance-01", + "instance_class": "db.m5.large", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secure_password", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "master_username" + }, + "sensitive_values": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + ] + } + }, + "resource_changes": [ + { + "address": "aws_db_instance.skip_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "skip_instance", + "provider_name": "registry.terraform.io/hashicorp/aws", + "change": { + "actions": [ + "create" + ], + "before": null, + "after": { + "allocated_storage": 10, + "allow_major_version_upgrade": null, + "apply_immediately": false, + "auto_minor_version_upgrade": true, + "blue_green_update": [], + "copy_tags_to_snapshot": false, + "custom_iam_instance_profile": null, + "customer_owned_ip_enabled": null, + "dedicated_log_volume": false, + "delete_automated_backups": true, + "deletion_protection": null, + "domain": null, + "domain_auth_secret_arn": null, + "domain_dns_ips": null, + "domain_iam_role_name": null, + "domain_ou": null, + "enabled_cloudwatch_logs_exports": null, + "engine": "oracle-ee", + "final_snapshot_identifier": null, + "iam_database_authentication_enabled": null, + "identifier": "skip-instance-01", + "instance_class": "db.m5.large", + "manage_master_user_password": null, + "max_allocated_storage": null, + "monitoring_interval": 0, + "password": "secure_password", + "performance_insights_enabled": false, + "publicly_accessible": false, + "replicate_source_db": null, + "restore_to_point_in_time": [], + "s3_import": [], + "skip_final_snapshot": true, + "storage_encrypted": null, + "tags": null, + "timeouts": null, + "upgrade_storage_config": null, + "username": "master_username" + }, + "after_unknown": { + "address": true, + "arn": true, + "availability_zone": true, + "backup_retention_period": true, + "backup_target": true, + "backup_window": true, + "blue_green_update": [], + "ca_cert_identifier": true, + "character_set_name": true, + "db_name": true, + "db_subnet_group_name": true, + "domain_fqdn": true, + "endpoint": true, + "engine_lifecycle_support": true, + "engine_version": true, + "engine_version_actual": true, + "hosted_zone_id": true, + "id": true, + "identifier_prefix": true, + "iops": true, + "kms_key_id": true, + "latest_restorable_time": true, + "license_model": true, + "listener_endpoint": true, + "maintenance_window": true, + "master_user_secret": true, + "master_user_secret_kms_key_id": true, + "monitoring_role_arn": true, + "multi_az": true, + "nchar_character_set_name": true, + "network_type": true, + "option_group_name": true, + "parameter_group_name": true, + "performance_insights_kms_key_id": true, + "performance_insights_retention_period": true, + "port": true, + "replica_mode": true, + "replicas": true, + "resource_id": true, + "restore_to_point_in_time": [], + "s3_import": [], + "snapshot_identifier": true, + "status": true, + "storage_throughput": true, + "storage_type": true, + "tags_all": true, + "timezone": true, + "vpc_security_group_ids": true + }, + "before_sensitive": false, + "after_sensitive": { + "blue_green_update": [], + "listener_endpoint": [], + "master_user_secret": [], + "password": true, + "replicas": [], + "restore_to_point_in_time": [], + "s3_import": [], + "tags_all": {}, + "vpc_security_group_ids": [] + } + } + } + ], + "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_db_instance.skip_instance", + "mode": "managed", + "type": "aws_db_instance", + "name": "skip_instance", + "provider_config_key": "aws", + "expressions": { + "allocated_storage": { + "constant_value": 10 + }, + "engine": { + "constant_value": "oracle-ee" + }, + "identifier": { + "constant_value": "skip-instance-01" + }, + "instance_class": { + "constant_value": "db.m5.large" + }, + "password": { + "constant_value": "secure_password" + }, + "skip_final_snapshot": { + "constant_value": true + }, + "username": { + "constant_value": "master_username" + } + }, + "schema_version": 2 + } + ] + } + }, + "timestamp": "2024-10-01T11:37:44Z", + "applyable": true, + "complete": true, + "errored": false +}