terraform-compliance / cli

a lightweight, security focused, BDD test framework against terraform.
https://terraform-compliance.com
MIT License
1.35k stars 152 forks source link

Tags Policy Parsing Incorrect Properties #543

Closed mgarber-ops closed 3 years ago

mgarber-ops commented 3 years ago

Description

When deploying an ECS Task Definition with a container_definitions JSON that contains a list of maps for environment variables defined my tagging policy is incorrectly parsing them and treating them as a value for "tags"

To Reproduce

Feature File:

Feature: Test tagging compliance

Scenario: Ensure all resources have tags
    Given I have resource that supports tags defined
    Then it must contain tags
    And its value must not be null

Scenario Outline: Ensure that specific tags are defined
    Given I have resource that supports tags defined
    When it has tags
    Then it must contain <tags>
    And its value must match the "<value>" regex

    Examples:
      | tags             | value              |
      | Creator          | .+                 |
      | Application      | .+                 |
      | Role             | .+                 |
      | Environment      | ^(prod\|uat\|dev\|stg\|sbx\|ams\|dr\|devops\|ephemeral)$ |

Plan File:

{
    "format_version": "0.1",
    "terraform_version": "0.13.5",
    "variables": {
        "cluster_name": {
            "value": "fargate-test"
        },
        "container_cpu_units": {
            "value": 256
        },
        "container_image": {
            "value": "nginx:latest"
        },
        "container_memory": {
            "value": 512
        },
        "container_port": {
            "value": 80
        },
        "desired_count": {
            "value": 1
        },
        "environment_vars": {
            "value": [{
                "name": "BAR",
                "value": "FOO"
            }]
        },
        "iam_exec_role_name": {
            "value": "test-default-role"
        },
        "log_group_name": {
            "value": "/aws/ecs/app"
        },
        "log_group_prefix": {
            "value": "test-service"
        },
        "log_retention": {
            "value": 1
        },
        "service_name": {
            "value": "test-service"
        },
        "subnets": {
            "value": ["subnet-49599277", "subnet-52b9ee18"]
        },
        "tags": {
            "value": {
                "Application": "ECS-POC",
                "Creator": "Contino",
                "Environment": "dev",
                "Role": "POC",
                "Terraform": "True"
            }
        },
        "task_def_name": {
            "value": "service-example-td"
        }
    },
    "planned_values": {
        "root_module": {
            "child_modules": [{
                "resources": [{
                    "address": "module.ecs_service.aws_ecs_service.ecs_service",
                    "mode": "managed",
                    "type": "aws_ecs_service",
                    "name": "ecs_service",
                    "provider_name": "registry.terraform.io/hashicorp/aws",
                    "schema_version": 0,
                    "values": {
                        "capacity_provider_strategy": [],
                        "deployment_circuit_breaker": [],
                        "deployment_controller": [],
                        "deployment_maximum_percent": 200,
                        "deployment_minimum_healthy_percent": 100,
                        "desired_count": 1,
                        "enable_ecs_managed_tags": false,
                        "enable_execute_command": false,
                        "force_new_deployment": null,
                        "health_check_grace_period_seconds": null,
                        "launch_type": "FARGATE",
                        "load_balancer": [],
                        "name": "test-service",
                        "network_configuration": [{
                            "assign_public_ip": false,
                            "security_groups": null,
                            "subnets": ["subnet-49599277", "subnet-52b9ee18"]
                        }],
                        "ordered_placement_strategy": [],
                        "placement_constraints": [],
                        "propagate_tags": null,
                        "scheduling_strategy": "REPLICA",
                        "service_registries": [],
                        "tags": {
                            "Application": "ECS-POC",
                            "Creator": "Contino",
                            "Environment": "dev",
                            "Role": "POC",
                            "Terraform": "True"
                        },
                        "tags_all": {
                            "Application": "ECS-POC",
                            "Creator": "Contino",
                            "Environment": "dev",
                            "Role": "POC",
                            "Terraform": "True"
                        },
                        "timeouts": null,
                        "wait_for_steady_state": false
                    }
                }],
                "address": "module.ecs_service"
            }, {
                "resources": [{
                    "address": "module.ecs_task_def.aws_cloudwatch_log_group.app_log_group",
                    "mode": "managed",
                    "type": "aws_cloudwatch_log_group",
                    "name": "app_log_group",
                    "provider_name": "registry.terraform.io/hashicorp/aws",
                    "schema_version": 0,
                    "values": {
                        "kms_key_id": null,
                        "name": "/aws/ecs/app",
                        "name_prefix": null,
                        "retention_in_days": 1,
                        "tags": {
                            "Application": "ECS-POC",
                            "Creator": "Contino",
                            "Environment": "dev",
                            "Role": "POC",
                            "Terraform": "True"
                        },
                        "tags_all": {
                            "Application": "ECS-POC",
                            "Creator": "Contino",
                            "Environment": "dev",
                            "Role": "POC",
                            "Terraform": "True"
                        }
                    }
                }, {
                    "address": "module.ecs_task_def.aws_ecs_task_definition.task_def",
                    "mode": "managed",
                    "type": "aws_ecs_task_definition",
                    "name": "task_def",
                    "provider_name": "registry.terraform.io/hashicorp/aws",
                    "schema_version": 1,
                    "values": {
                        "container_definitions": "[{\"environment\":[{\"name\":\"BAR\",\"value\":\"FOO\"}],\"image\":\"nginx:latest\",\"logConfiguration\":{\"logDriver\":\"awslogs\",\"options\":{\"awslogs-group\":\"/aws/ecs/app\",\"awslogs-region\":\"us-east-1\",\"awslogs-stream-prefix\":\"test-service\"}},\"name\":\"service-example-td\",\"portMappings\":[{\"containerPort\":80}]}]",
                        "cpu": "256",
                        "ephemeral_storage": [],
                        "family": "service-example-td",
                        "inference_accelerator": [],
                        "ipc_mode": null,
                        "memory": "512",
                        "network_mode": "awsvpc",
                        "pid_mode": null,
                        "placement_constraints": [],
                        "proxy_configuration": [],
                        "requires_compatibilities": ["FARGATE"],
                        "tags": {
                            "Application": "ECS-POC",
                            "Creator": "Contino",
                            "Environment": "dev",
                            "Role": "POC",
                            "Terraform": "True"
                        },
                        "tags_all": {
                            "Application": "ECS-POC",
                            "Creator": "Contino",
                            "Environment": "dev",
                            "Role": "POC",
                            "Terraform": "True"
                        },
                        "task_role_arn": null,
                        "volume": []
                    }
                }, {
                    "address": "module.ecs_task_def.aws_iam_role.default",
                    "mode": "managed",
                    "type": "aws_iam_role",
                    "name": "default",
                    "provider_name": "registry.terraform.io/hashicorp/aws",
                    "schema_version": 0,
                    "values": {
                        "assume_role_policy": "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Sid\": \"\",\n      \"Effect\": \"Allow\",\n      \"Action\": \"sts:AssumeRole\",\n      \"Principal\": {\n        \"Service\": \"ecs-tasks.amazonaws.com\"\n      }\n    }\n  ]\n}",
                        "description": "Default IAM Role Created for ECS Task",
                        "force_detach_policies": false,
                        "max_session_duration": 3600,
                        "name": "test-default-role",
                        "name_prefix": null,
                        "path": "/",
                        "permissions_boundary": null,
                        "tags": {
                            "Application": "ECS-POC",
                            "Creator": "Contino",
                            "Environment": "dev",
                            "Role": "POC",
                            "Terraform": "True"
                        },
                        "tags_all": {
                            "Application": "ECS-POC",
                            "Creator": "Contino",
                            "Environment": "dev",
                            "Role": "POC",
                            "Terraform": "True"
                        }
                    }
                }, {
                    "address": "module.ecs_task_def.aws_iam_role_policy_attachment.default_exec_role",
                    "mode": "managed",
                    "type": "aws_iam_role_policy_attachment",
                    "name": "default_exec_role",
                    "provider_name": "registry.terraform.io/hashicorp/aws",
                    "schema_version": 0,
                    "values": {
                        "policy_arn": "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",
                        "role": "test-default-role"
                    }
                }, {
                    "address": "module.ecs_task_def.data.aws_iam_policy_document.assume_role_policy",
                    "mode": "data",
                    "type": "aws_iam_policy_document",
                    "name": "assume_role_policy",
                    "provider_name": "registry.terraform.io/hashicorp/aws",
                    "schema_version": 0,
                    "values": {
                        "id": "320642683",
                        "json": "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Sid\": \"\",\n      \"Effect\": \"Allow\",\n      \"Action\": \"sts:AssumeRole\",\n      \"Principal\": {\n        \"Service\": \"ecs-tasks.amazonaws.com\"\n      }\n    }\n  ]\n}",
                        "override_json": null,
                        "override_policy_documents": null,
                        "policy_id": null,
                        "source_json": null,
                        "source_policy_documents": null,
                        "statement": [{
                            "actions": ["sts:AssumeRole"],
                            "condition": [],
                            "effect": "Allow",
                            "not_actions": [],
                            "not_principals": [],
                            "not_resources": [],
                            "principals": [{
                                "identifiers": ["ecs-tasks.amazonaws.com"],
                                "type": "Service"
                            }],
                            "resources": [],
                            "sid": ""
                        }],
                        "version": "2012-10-17"
                    }
                }],
                "address": "module.ecs_task_def"
            }, {
                "resources": [{
                    "address": "module.fargate_cluster.aws_ecs_cluster.fargate_cluster",
                    "mode": "managed",
                    "type": "aws_ecs_cluster",
                    "name": "fargate_cluster",
                    "provider_name": "registry.terraform.io/hashicorp/aws",
                    "schema_version": 0,
                    "values": {
                        "capacity_providers": ["FARGATE"],
                        "configuration": [],
                        "default_capacity_provider_strategy": [],
                        "name": "fargate-test",
                        "setting": [{
                            "name": "containerInsights",
                            "value": "enabled"
                        }],
                        "tags": {
                            "Application": "ECS-POC",
                            "Creator": "Contino",
                            "Environment": "dev",
                            "Role": "POC",
                            "Terraform": "True"
                        },
                        "tags_all": {
                            "Application": "ECS-POC",
                            "Creator": "Contino",
                            "Environment": "dev",
                            "Role": "POC",
                            "Terraform": "True"
                        }
                    }
                }],
                "address": "module.fargate_cluster"
            }]
        }
    },
    "resource_changes": [{
        "address": "module.ecs_service.aws_ecs_service.ecs_service",
        "module_address": "module.ecs_service",
        "mode": "managed",
        "type": "aws_ecs_service",
        "name": "ecs_service",
        "provider_name": "registry.terraform.io/hashicorp/aws",
        "change": {
            "actions": ["create"],
            "before": null,
            "after": {
                "capacity_provider_strategy": [],
                "deployment_circuit_breaker": [],
                "deployment_controller": [],
                "deployment_maximum_percent": 200,
                "deployment_minimum_healthy_percent": 100,
                "desired_count": 1,
                "enable_ecs_managed_tags": false,
                "enable_execute_command": false,
                "force_new_deployment": null,
                "health_check_grace_period_seconds": null,
                "launch_type": "FARGATE",
                "load_balancer": [],
                "name": "test-service",
                "network_configuration": [{
                    "assign_public_ip": false,
                    "security_groups": null,
                    "subnets": ["subnet-49599277", "subnet-52b9ee18"]
                }],
                "ordered_placement_strategy": [],
                "placement_constraints": [],
                "propagate_tags": null,
                "scheduling_strategy": "REPLICA",
                "service_registries": [],
                "tags": {
                    "Application": "ECS-POC",
                    "Creator": "Contino",
                    "Environment": "dev",
                    "Role": "POC",
                    "Terraform": "True"
                },
                "tags_all": {
                    "Application": "ECS-POC",
                    "Creator": "Contino",
                    "Environment": "dev",
                    "Role": "POC",
                    "Terraform": "True"
                },
                "timeouts": null,
                "wait_for_steady_state": false
            },
            "after_unknown": {
                "capacity_provider_strategy": [],
                "cluster": true,
                "deployment_circuit_breaker": [],
                "deployment_controller": [],
                "iam_role": true,
                "id": true,
                "load_balancer": [],
                "network_configuration": [{
                    "subnets": [false, false]
                }],
                "ordered_placement_strategy": [],
                "placement_constraints": [],
                "platform_version": true,
                "service_registries": [],
                "tags": {},
                "tags_all": {},
                "task_definition": true
            }
        }
    }, {
        "address": "module.ecs_task_def.aws_cloudwatch_log_group.app_log_group",
        "module_address": "module.ecs_task_def",
        "mode": "managed",
        "type": "aws_cloudwatch_log_group",
        "name": "app_log_group",
        "provider_name": "registry.terraform.io/hashicorp/aws",
        "change": {
            "actions": ["create"],
            "before": null,
            "after": {
                "kms_key_id": null,
                "name": "/aws/ecs/app",
                "name_prefix": null,
                "retention_in_days": 1,
                "tags": {
                    "Application": "ECS-POC",
                    "Creator": "Contino",
                    "Environment": "dev",
                    "Role": "POC",
                    "Terraform": "True"
                },
                "tags_all": {
                    "Application": "ECS-POC",
                    "Creator": "Contino",
                    "Environment": "dev",
                    "Role": "POC",
                    "Terraform": "True"
                }
            },
            "after_unknown": {
                "arn": true,
                "id": true,
                "tags": {},
                "tags_all": {}
            }
        }
    }, {
        "address": "module.ecs_task_def.aws_ecs_task_definition.task_def",
        "module_address": "module.ecs_task_def",
        "mode": "managed",
        "type": "aws_ecs_task_definition",
        "name": "task_def",
        "provider_name": "registry.terraform.io/hashicorp/aws",
        "change": {
            "actions": ["create"],
            "before": null,
            "after": {
                "container_definitions": "[{\"environment\":[{\"name\":\"BAR\",\"value\":\"FOO\"}],\"image\":\"nginx:latest\",\"logConfiguration\":{\"logDriver\":\"awslogs\",\"options\":{\"awslogs-group\":\"/aws/ecs/app\",\"awslogs-region\":\"us-east-1\",\"awslogs-stream-prefix\":\"test-service\"}},\"name\":\"service-example-td\",\"portMappings\":[{\"containerPort\":80}]}]",
                "cpu": "256",
                "ephemeral_storage": [],
                "family": "service-example-td",
                "inference_accelerator": [],
                "ipc_mode": null,
                "memory": "512",
                "network_mode": "awsvpc",
                "pid_mode": null,
                "placement_constraints": [],
                "proxy_configuration": [],
                "requires_compatibilities": ["FARGATE"],
                "tags": {
                    "Application": "ECS-POC",
                    "Creator": "Contino",
                    "Environment": "dev",
                    "Role": "POC",
                    "Terraform": "True"
                },
                "tags_all": {
                    "Application": "ECS-POC",
                    "Creator": "Contino",
                    "Environment": "dev",
                    "Role": "POC",
                    "Terraform": "True"
                },
                "task_role_arn": null,
                "volume": []
            },
            "after_unknown": {
                "arn": true,
                "ephemeral_storage": [],
                "execution_role_arn": true,
                "id": true,
                "inference_accelerator": [],
                "placement_constraints": [],
                "proxy_configuration": [],
                "requires_compatibilities": [false],
                "revision": true,
                "tags": {},
                "tags_all": {},
                "volume": []
            }
        }
    }, {
        "address": "module.ecs_task_def.aws_iam_role.default",
        "module_address": "module.ecs_task_def",
        "mode": "managed",
        "type": "aws_iam_role",
        "name": "default",
        "provider_name": "registry.terraform.io/hashicorp/aws",
        "change": {
            "actions": ["create"],
            "before": null,
            "after": {
                "assume_role_policy": "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Sid\": \"\",\n      \"Effect\": \"Allow\",\n      \"Action\": \"sts:AssumeRole\",\n      \"Principal\": {\n        \"Service\": \"ecs-tasks.amazonaws.com\"\n      }\n    }\n  ]\n}",
                "description": "Default IAM Role Created for ECS Task",
                "force_detach_policies": false,
                "max_session_duration": 3600,
                "name": "test-default-role",
                "name_prefix": null,
                "path": "/",
                "permissions_boundary": null,
                "tags": {
                    "Application": "ECS-POC",
                    "Creator": "Contino",
                    "Environment": "dev",
                    "Role": "POC",
                    "Terraform": "True"
                },
                "tags_all": {
                    "Application": "ECS-POC",
                    "Creator": "Contino",
                    "Environment": "dev",
                    "Role": "POC",
                    "Terraform": "True"
                }
            },
            "after_unknown": {
                "arn": true,
                "create_date": true,
                "id": true,
                "inline_policy": true,
                "managed_policy_arns": true,
                "tags": {},
                "tags_all": {},
                "unique_id": true
            }
        }
    }, {
        "address": "module.ecs_task_def.aws_iam_role_policy_attachment.default_exec_role",
        "module_address": "module.ecs_task_def",
        "mode": "managed",
        "type": "aws_iam_role_policy_attachment",
        "name": "default_exec_role",
        "provider_name": "registry.terraform.io/hashicorp/aws",
        "change": {
            "actions": ["create"],
            "before": null,
            "after": {
                "policy_arn": "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",
                "role": "test-default-role"
            },
            "after_unknown": {
                "id": true
            }
        }
    }, {
        "address": "module.ecs_task_def.data.aws_iam_policy_document.assume_role_policy",
        "module_address": "module.ecs_task_def",
        "mode": "data",
        "type": "aws_iam_policy_document",
        "name": "assume_role_policy",
        "provider_name": "registry.terraform.io/hashicorp/aws",
        "change": {
            "actions": ["no-op"],
            "before": {
                "id": "320642683",
                "json": "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Sid\": \"\",\n      \"Effect\": \"Allow\",\n      \"Action\": \"sts:AssumeRole\",\n      \"Principal\": {\n        \"Service\": \"ecs-tasks.amazonaws.com\"\n      }\n    }\n  ]\n}",
                "override_json": null,
                "override_policy_documents": null,
                "policy_id": null,
                "source_json": null,
                "source_policy_documents": null,
                "statement": [{
                    "actions": ["sts:AssumeRole"],
                    "condition": [],
                    "effect": "Allow",
                    "not_actions": [],
                    "not_principals": [],
                    "not_resources": [],
                    "principals": [{
                        "identifiers": ["ecs-tasks.amazonaws.com"],
                        "type": "Service"
                    }],
                    "resources": [],
                    "sid": ""
                }],
                "version": "2012-10-17"
            },
            "after": {
                "id": "320642683",
                "json": "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Sid\": \"\",\n      \"Effect\": \"Allow\",\n      \"Action\": \"sts:AssumeRole\",\n      \"Principal\": {\n        \"Service\": \"ecs-tasks.amazonaws.com\"\n      }\n    }\n  ]\n}",
                "override_json": null,
                "override_policy_documents": null,
                "policy_id": null,
                "source_json": null,
                "source_policy_documents": null,
                "statement": [{
                    "actions": ["sts:AssumeRole"],
                    "condition": [],
                    "effect": "Allow",
                    "not_actions": [],
                    "not_principals": [],
                    "not_resources": [],
                    "principals": [{
                        "identifiers": ["ecs-tasks.amazonaws.com"],
                        "type": "Service"
                    }],
                    "resources": [],
                    "sid": ""
                }],
                "version": "2012-10-17"
            },
            "after_unknown": {}
        }
    }, {
        "address": "module.fargate_cluster.aws_ecs_cluster.fargate_cluster",
        "module_address": "module.fargate_cluster",
        "mode": "managed",
        "type": "aws_ecs_cluster",
        "name": "fargate_cluster",
        "provider_name": "registry.terraform.io/hashicorp/aws",
        "change": {
            "actions": ["create"],
            "before": null,
            "after": {
                "capacity_providers": ["FARGATE"],
                "configuration": [],
                "default_capacity_provider_strategy": [],
                "name": "fargate-test",
                "setting": [{
                    "name": "containerInsights",
                    "value": "enabled"
                }],
                "tags": {
                    "Application": "ECS-POC",
                    "Creator": "Contino",
                    "Environment": "dev",
                    "Role": "POC",
                    "Terraform": "True"
                },
                "tags_all": {
                    "Application": "ECS-POC",
                    "Creator": "Contino",
                    "Environment": "dev",
                    "Role": "POC",
                    "Terraform": "True"
                }
            },
            "after_unknown": {
                "arn": true,
                "capacity_providers": [false],
                "configuration": [],
                "default_capacity_provider_strategy": [],
                "id": true,
                "setting": [{}],
                "tags": {},
                "tags_all": {}
            }
        }
    }],
    "prior_state": {
        "format_version": "0.1",
        "terraform_version": "0.13.5",
        "values": {
            "root_module": {
                "child_modules": [{
                    "resources": [{
                        "address": "module.ecs_task_def.data.aws_iam_policy.ecs_task_execution_policy",
                        "mode": "data",
                        "type": "aws_iam_policy",
                        "name": "ecs_task_execution_policy",
                        "provider_name": "registry.terraform.io/hashicorp/aws",
                        "schema_version": 0,
                        "values": {
                            "arn": "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",
                            "description": "Provides access to other AWS service resources that are required to run Amazon ECS tasks",
                            "id": "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",
                            "name": "AmazonECSTaskExecutionRolePolicy",
                            "path": "/service-role/",
                            "path_prefix": null,
                            "policy": "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"ecr:GetAuthorizationToken\",\n        \"ecr:BatchCheckLayerAvailability\",\n        \"ecr:GetDownloadUrlForLayer\",\n        \"ecr:BatchGetImage\",\n        \"logs:CreateLogStream\",\n        \"logs:PutLogEvents\"\n      ],\n      \"Resource\": \"*\"\n    }\n  ]\n}",
                            "policy_id": "ANPAJG4T4G4PV56DE72PY",
                            "tags": {}
                        }
                    }, {
                        "address": "module.ecs_task_def.data.aws_iam_policy_document.assume_role_policy",
                        "mode": "data",
                        "type": "aws_iam_policy_document",
                        "name": "assume_role_policy",
                        "provider_name": "registry.terraform.io/hashicorp/aws",
                        "schema_version": 0,
                        "values": {
                            "id": "320642683",
                            "json": "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Sid\": \"\",\n      \"Effect\": \"Allow\",\n      \"Action\": \"sts:AssumeRole\",\n      \"Principal\": {\n        \"Service\": \"ecs-tasks.amazonaws.com\"\n      }\n    }\n  ]\n}",
                            "override_json": null,
                            "override_policy_documents": null,
                            "policy_id": null,
                            "source_json": null,
                            "source_policy_documents": null,
                            "statement": [{
                                "actions": ["sts:AssumeRole"],
                                "condition": [],
                                "effect": "Allow",
                                "not_actions": [],
                                "not_principals": [],
                                "not_resources": [],
                                "principals": [{
                                    "identifiers": ["ecs-tasks.amazonaws.com"],
                                    "type": "Service"
                                }],
                                "resources": [],
                                "sid": ""
                            }],
                            "version": "2012-10-17"
                        }
                    }, {
                        "address": "module.ecs_task_def.data.aws_region.current",
                        "mode": "data",
                        "type": "aws_region",
                        "name": "current",
                        "provider_name": "registry.terraform.io/hashicorp/aws",
                        "schema_version": 0,
                        "values": {
                            "description": "US East (N. Virginia)",
                            "endpoint": "ec2.us-east-1.amazonaws.com",
                            "id": "us-east-1",
                            "name": "us-east-1"
                        }
                    }],
                    "address": "module.ecs_task_def"
                }]
            }
        }
    },
    "configuration": {
        "provider_config": {
            "aws": {
                "name": "aws"
            }
        },
        "root_module": {
            "module_calls": {
                "ecs_service": {
                    "source": "git@github.com:SomosIAC/tf-aws-ecs-service-module?ref=feature/cnas-iac",
                    "expressions": {
                        "cluster_id": {
                            "references": ["module.fargate_cluster.cluster_id"]
                        },
                        "desired_count": {
                            "references": ["var.desired_count"]
                        },
                        "service_name": {
                            "references": ["var.service_name"]
                        },
                        "subnets": {
                            "references": ["var.subnets"]
                        },
                        "tags": {
                            "references": ["var.tags"]
                        },
                        "task_definition": {
                            "references": ["module.ecs_task_def.task_definition_arn"]
                        }
                    },
                    "module": {
                        "resources": [{
                            "address": "aws_ecs_service.ecs_service",
                            "mode": "managed",
                            "type": "aws_ecs_service",
                            "name": "ecs_service",
                            "provider_config_key": "ecs_service:aws",
                            "expressions": {
                                "cluster": {
                                    "references": ["var.cluster_id"]
                                },
                                "desired_count": {
                                    "references": ["var.desired_count"]
                                },
                                "launch_type": {
                                    "references": ["var.launch_type"]
                                },
                                "name": {
                                    "references": ["var.service_name"]
                                },
                                "network_configuration": [{
                                    "assign_public_ip": {
                                        "references": ["var.assign_public_ip"]
                                    },
                                    "security_groups": {
                                        "references": ["var.security_groups"]
                                    },
                                    "subnets": {
                                        "references": ["var.subnets"]
                                    }
                                }],
                                "tags": {
                                    "references": ["var.tags"]
                                },
                                "task_definition": {
                                    "references": ["var.task_definition"]
                                }
                            },
                            "schema_version": 0
                        }],
                        "variables": {
                            "assign_public_ip": {
                                "default": false,
                                "description": "Assign Public IP's to the ENI associated with our ECS Service"
                            },
                            "cluster_id": {
                                "description": "The ID of our ECS Fargate Cluster Where our Service will be deployed"
                            },
                            "desired_count": {
                                "description": "How many replicas of our application do we want running concurrently"
                            },
                            "launch_type": {
                                "default": "FARGATE",
                                "description": "Where we would like to deploy this service"
                            },
                            "security_groups": {
                                "default": [],
                                "description": "List of Security-Groups associated with our service. If left undefined a default security-group will be created allowing all traffic"
                            },
                            "service_name": {
                                "description": "The name of our ECS Service"
                            },
                            "subnets": {
                                "description": "List of subnets where our service should be deployed"
                            },
                            "tags": {
                                "description": "common tags to apply to ecs service resources"
                            },
                            "task_definition": {
                                "description": "The Task Definition ID that contains our Container Definition"
                            }
                        }
                    }
                },
                "ecs_task_def": {
                    "source": "git@github.com:SomosIAC/tf-aws-ecs-task-definition-module?ref=feature/cnas-iac",
                    "expressions": {
                        "container_cpu_units": {
                            "references": ["var.container_cpu_units"]
                        },
                        "container_image": {
                            "references": ["var.container_image"]
                        },
                        "container_memory": {
                            "references": ["var.container_memory"]
                        },
                        "container_port": {
                            "references": ["var.container_port"]
                        },
                        "environment_vars": {
                            "references": ["var.environment_vars"]
                        },
                        "iam_exec_role_name": {
                            "references": ["var.iam_exec_role_name"]
                        },
                        "log_group_name": {
                            "references": ["var.log_group_name"]
                        },
                        "log_group_prefix": {
                            "references": ["var.log_group_prefix"]
                        },
                        "log_retention": {
                            "references": ["var.log_retention"]
                        },
                        "tags": {
                            "references": ["var.tags"]
                        },
                        "task_def_name": {
                            "references": ["var.task_def_name"]
                        }
                    },
                    "module": {
                        "outputs": {
                            "task_definition_arn": {
                                "expression": {
                                    "references": ["aws_ecs_task_definition.task_def"]
                                }
                            }
                        },
                        "resources": [{
                            "address": "aws_cloudwatch_log_group.app_log_group",
                            "mode": "managed",
                            "type": "aws_cloudwatch_log_group",
                            "name": "app_log_group",
                            "provider_config_key": "ecs_task_def:aws",
                            "expressions": {
                                "name": {
                                    "references": ["var.log_group_name"]
                                },
                                "retention_in_days": {
                                    "references": ["var.log_retention"]
                                },
                                "tags": {
                                    "references": ["var.tags"]
                                }
                            },
                            "schema_version": 0
                        }, {
                            "address": "aws_ecs_task_definition.task_def",
                            "mode": "managed",
                            "type": "aws_ecs_task_definition",
                            "name": "task_def",
                            "provider_config_key": "ecs_task_def:aws",
                            "expressions": {
                                "container_definitions": {
                                    "references": ["var.task_def_name", "var.container_image", "var.environment_vars", "aws_cloudwatch_log_group.app_log_group", "var.log_group_prefix", "data.aws_region.current", "var.container_port"]
                                },
                                "cpu": {
                                    "references": ["var.container_cpu_units"]
                                },
                                "execution_role_arn": {
                                    "references": ["aws_iam_role.default"]
                                },
                                "family": {
                                    "references": ["var.task_def_name"]
                                },
                                "memory": {
                                    "references": ["var.container_memory"]
                                },
                                "network_mode": {
                                    "constant_value": "awsvpc"
                                },
                                "requires_compatibilities": {
                                    "references": ["var.req_compatibilities"]
                                },
                                "tags": {
                                    "references": ["var.tags"]
                                },
                                "task_role_arn": {
                                    "references": ["var.iam_task_role_arn", "var.iam_task_role_arn", "aws_iam_role.default"]
                                }
                            },
                            "schema_version": 1
                        }, {
                            "address": "aws_iam_role.default",
                            "mode": "managed",
                            "type": "aws_iam_role",
                            "name": "default",
                            "provider_config_key": "ecs_task_def:aws",
                            "expressions": {
                                "assume_role_policy": {
                                    "references": ["data.aws_iam_policy_document.assume_role_policy"]
                                },
                                "description": {
                                    "constant_value": "Default IAM Role Created for ECS Task"
                                },
                                "name": {
                                    "references": ["var.iam_exec_role_name"]
                                },
                                "tags": {
                                    "references": ["var.tags"]
                                }
                            },
                            "schema_version": 0
                        }, {
                            "address": "aws_iam_role_policy_attachment.default_exec_role",
                            "mode": "managed",
                            "type": "aws_iam_role_policy_attachment",
                            "name": "default_exec_role",
                            "provider_config_key": "ecs_task_def:aws",
                            "expressions": {
                                "policy_arn": {
                                    "references": ["data.aws_iam_policy.ecs_task_execution_policy"]
                                },
                                "role": {
                                    "references": ["aws_iam_role.default"]
                                }
                            },
                            "schema_version": 0
                        }, {
                            "address": "data.aws_iam_policy.ecs_task_execution_policy",
                            "mode": "data",
                            "type": "aws_iam_policy",
                            "name": "ecs_task_execution_policy",
                            "provider_config_key": "ecs_task_def:aws",
                            "expressions": {
                                "arn": {
                                    "constant_value": "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
                                }
                            },
                            "schema_version": 0
                        }, {
                            "address": "data.aws_iam_policy_document.assume_role_policy",
                            "mode": "data",
                            "type": "aws_iam_policy_document",
                            "name": "assume_role_policy",
                            "provider_config_key": "ecs_task_def:aws",
                            "expressions": {
                                "statement": [{
                                    "actions": {
                                        "constant_value": ["sts:AssumeRole"]
                                    },
                                    "principals": [{
                                        "identifiers": {
                                            "constant_value": ["ecs-tasks.amazonaws.com"]
                                        },
                                        "type": {
                                            "constant_value": "Service"
                                        }
                                    }]
                                }]
                            },
                            "schema_version": 0
                        }, {
                            "address": "data.aws_region.current",
                            "mode": "data",
                            "type": "aws_region",
                            "name": "current",
                            "provider_config_key": "ecs_task_def:aws",
                            "schema_version": 0
                        }],
                        "variables": {
                            "container_cpu_units": {
                                "description": "The amount of CPU units required for this application"
                            },
                            "container_image": {
                                "description": "The Container Image for our application"
                            },
                            "container_memory": {
                                "description": "The amount of Memory in MiB necessary for this application"
                            },
                            "container_port": {
                                "description": "The TCP Port thats required to be exposed for this application"
                            },
                            "environment_vars": {
                                "default": [],
                                "description": "Env Vars required for this application"
                            },
                            "iam_exec_role_name": {
                                "description": "The name of the task IAM Role for application"
                            },
                            "iam_task_role_arn": {
                                "default": null,
                                "description": "The ARN of the task-role to be used by the application"
                            },
                            "log_group_name": {
                                "description": "The name of our log-group for our application"
                            },
                            "log_group_prefix": {
                                "description": "The log group prefix for our application CWL Group"
                            },
                            "log_retention": {
                                "description": "How long we should retain log events for our application"
                            },
                            "req_compatibilities": {
                                "default": "FARGATE",
                                "description": "What constraints does this task-def have as far as where it can be deployed"
                            },
                            "tags": {
                                "description": "Tags for all relevant resources"
                            },
                            "task_def_name": {
                                "description": "The name of our ECS Task Definition"
                            }
                        }
                    }
                },
                "fargate_cluster": {
                    "source": "git@github.com:SomosIAC/tf-aws-ecs-fargate-module?ref=feature/cnas-iac",
                    "expressions": {
                        "cluster_name": {
                            "references": ["var.cluster_name"]
                        },
                        "tags": {
                            "references": ["var.tags"]
                        }
                    },
                    "module": {
                        "outputs": {
                            "cluster_id": {
                                "expression": {
                                    "references": ["aws_ecs_cluster.fargate_cluster"]
                                }
                            }
                        },
                        "resources": [{
                            "address": "aws_ecs_cluster.fargate_cluster",
                            "mode": "managed",
                            "type": "aws_ecs_cluster",
                            "name": "fargate_cluster",
                            "provider_config_key": "fargate_cluster:aws",
                            "expressions": {
                                "capacity_providers": {
                                    "constant_value": ["FARGATE"]
                                },
                                "name": {
                                    "references": ["var.cluster_name"]
                                },
                                "setting": [{
                                    "name": {
                                        "constant_value": "containerInsights"
                                    },
                                    "value": {
                                        "constant_value": "enabled"
                                    }
                                }],
                                "tags": {
                                    "references": ["var.tags"]
                                }
                            },
                            "schema_version": 0
                        }],
                        "variables": {
                            "cluster_name": {
                                "description": "The name of our ECS Cluster"
                            },
                            "tags": {
                                "description": "Tags for ECS Cluster resource"
                            }
                        }
                    }
                }
            },
            "variables": {
                "cluster_name": {},
                "container_cpu_units": {},
                "container_image": {},
                "container_memory": {},
                "container_port": {},
                "desired_count": {},
                "environment_vars": {},
                "iam_exec_role_name": {},
                "log_group_name": {},
                "log_group_prefix": {},
                "log_retention": {},
                "service_name": {},
                "subnets": {},
                "tags": {},
                "task_def_name": {}
            }
        }
    }
}

Sample Terraform Code:

resource "aws_ecs_task_definition" "task_def" {
  family                   = var.task_def_name
  requires_compatibilities = [var.req_compatibilities]
  tags                     = var.tags
  task_role_arn            = var.iam_task_role_arn != "" ? var.iam_task_role_arn : aws_iam_role.default.arn
  execution_role_arn       = aws_iam_role.default.arn
  network_mode             = "awsvpc"
  cpu                      = var.container_cpu_units
  memory                   = var.container_memory
  container_definitions = jsonencode([
    {
      name        = var.task_def_name
      image       = var.container_image
      environment = var.environment_vars
      logConfiguration = {
        logDriver = "awslogs"
        options = {
          awslogs-group         = aws_cloudwatch_log_group.app_log_group.name
          awslogs-stream-prefix = var.log_group_prefix
          awslogs-region        = data.aws_region.current.name
        }

      }
      portMappings = [
        {
          containerPort = var.container_port
        }
      ]
    }
  ])
}

Used terraform-compliance Parameters:

Running via Docker:

Yes

Error Output:


    Scenario: Ensure all resources have tags                                                                                                                     
        Given I have resource that supports tags defined                                                                                                         
        Then it must contain tags                                                                                                                                
        And its value must not be null                                                                                                                           

    Scenario Outline: Ensure that specific tags are defined                                                                                                      
        Given I have resource that supports tags defined                                                                                                         
        When it has tags                                                                                                                                         
        Then it must contain <tags>                                                                                                                              
        And its value must match the "<value>" regex                                                                                                             

    Examples:                                                                                                                                                    
        | tags        | value                                            |                                                                                       
        | Creator     | .+                                               |                                                                                       
        | Application | .+                                               |                                                                                       
        | Role        | .+                                               |                                                                                       
                Failure: Environment property in module.ecs_task_def.aws_ecs_task_definition.task_def resource does not match with ^(prod|uat|dev|stg|sbx|ams|dr|
devops|ephemeral)$ case insensitive regex. It is set to BAR.                                                                                                     
                Failure: Environment property in module.ecs_task_def.aws_ecs_task_definition.task_def resource does not match with ^(prod|uat|dev|stg|sbx|ams|dr|
devops|ephemeral)$ case insensitive regex. It is set to FOO.                                                                                                     
        | Environment | ^(prod|uat|dev|stg|sbx|ams|dr|devops|ephemeral)$ |                                                                                       
          Failure:                                                                                      

Expected Behavior: tags for resources should be in compliance with our .feature rule and pass with a zero exit code

Tested Versions:

Additional Context:

mgarber-ops commented 3 years ago

Looks like this is related to https://github.com/terraform-compliance/cli/issues/454

eerkunt commented 3 years ago

Hi @mgarber-ops,

Yours is a bit different as I understand. In your scenario, you filter out resources with tags with both on GIVEN and WHEN directives, but you don't drill down. Hence, the data Then it must contain <tags> directive looks for everything, not only tags

A small change within your scenario would hit on the correct parameters ;

    Scenario Outline: Ensure that specific tags are defined                                                                                                      
        Given I have resource that supports tags defined                                                                                                         
        Then it must have tags                                                                                                                                      
        And it must contain <tags>                                                                                                                              
        And its value must match the "<value>" regex     

        ....
mgarber-ops commented 3 years ago

Appreciate the speedy reply. I'll give this a shot later and let you know what happens

mgarber-ops commented 3 years ago

All is working now with your recommended changes. Thanks 👍🏻