terraform-compliance / cli

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

Unable to access Terraform data resource #461

Open preeny95 opened 3 years ago

preeny95 commented 3 years ago

Description : I have a data resource for aws_iam_policy_document to create a IAM policy document for my flow logs. However when I am trying to write compliance tests to check that it isn't overpermissive it cannot find the resource in question. I can see the resource in the terminal output of my plan, and in the plan json file. I have attached 2 different attempts to find the resource in the example code

I have tried different ways to assert on the resource including selecting any and then trying the type, and also

To Reproduce

  1. <Either a sample terraform code, or your terraform plan file if it doesn't have any confidential information>

    data "aws_iam_policy_document" "flow_log_policy_doc" {
    statement {
    effect = "Allow"
    
    actions = [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents",
        "logs:DescribeLogGroups",
        "logs:DescribeLogStreams"
    ]
    
    resources = [aws_cloudwatch_log_group.vpc_flow_log_group.arn]
    }
    }
    {
                        "address": "module.vpc.module.vpc.data.aws_iam_policy_document.flow_log_policy_doc",
                        "mode": "data",
                        "type": "aws_iam_policy_document",
                        "name": "flow_log_policy_doc",
                        "provider_name": "registry.terraform.io/hashicorp/aws",
                        "schema_version": 0,
                        "values": {
                            "override_json": null,
                            "override_policy_documents": null,
                            "policy_id": null,
                            "source_json": null,
                            "source_policy_documents": null,
                            "statement": [{
                                "actions": ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:DescribeLogGroups", "logs:DescribeLogStreams", "logs:PutLogEvents"],
                                "condition": [],
                                "effect": "Allow",
                                "not_actions": null,
                                "not_principals": [],
                                "not_resources": null,
                                "principals": [],
                                "resources": [],
                                "sid": null
                            }],
                            "version": null
                        }
                    }
  2. <Used terraform-compliance parameters> docker run \ --rm \ -v ${CURRENT_DIR}:/target \ eerkunt/terraform-compliance \ --features compliance/ \ --planfile examples/plan.json

  3. I am using the Docker image https://hub.docker.com/r/eerkunt/terraform-compliance/ to run my tests.
  4. ``` Scenario: Reject overpermissive roles Given I have any resource defined * SKIPPING: Can not find data mode in module.vpc.aws_ecs_cluster.ecs, module.vpc.module.vpc.aws_cloudwatch_log_group.vpc_flow_log_group, module.vpc.module.vpc.aws_eip.nat_protected[0], module.vpc.module.vpc.aws_eip.nat_protected[1], module.vpc.module.vpc.aws_eip.nat_protected[2], module.vpc.module.vpc.aws_flow_log.vpc_flow_log, module.vpc.module.vpc.aws_iam_policy.flow_log_policy, module.vpc.module.vpc.aws_iam_policy_attachment.flow-log-attachment, module.vpc.module.vpc.aws_iam_role.vpc_flow_log_role, module.vpc.module.vpc.aws_internet_gateway.ig, module.vpc.module.vpc.aws_nat_gateway.nat[0], module.vpc.module.vpc.aws_nat_gateway.nat[1], module.vpc.module.vpc.aws_nat_gateway.nat[2], module.vpc.module.vpc.aws_network_acl.private_subnets, module.vpc.module.vpc.aws_network_acl.public, module.vpc.module.vpc.aws_network_acl_rule.private_all_egress, module.vpc.module.vpc.aws_network_acl_rule.private_vpc_ephemeral_ingress, module.vpc.module.vpc.aws_network_acl_rule.private_vpc_ingress, module.vpc.module.vpc.aws_network_acl_rule.public_all_egress, module.vpc.module.vpc.aws_network_acl_rule.public_ephemeral_ingress, module.vpc.module.vpc.aws_network_acl_rule.public_http_ingress, module.vpc.module.vpc.aws_network_acl_rule.public_https_ingress, module.vpc.module.vpc.aws_route.private_nat[0], module.vpc.module.vpc.aws_route.private_nat[1], module.vpc.module.vpc.aws_route.private_nat[2], module.vpc.module.vpc.aws_route.public_internet, module.vpc.module.vpc.aws_route_table.private[0], module.vpc.module.vpc.aws_route_table.private[1], module.vpc.module.vpc.aws_route_table.private[2], module.vpc.module.vpc.aws_route_table.public, module.vpc.module.vpc.aws_route_table_association.private_nat[0], module.vpc.module.vpc.aws_route_table_association.private_nat[1], module.vpc.module.vpc.aws_route_table_association.private_nat[2], module.vpc.module.vpc.aws_route_table_association.public_igw[0], module.vpc.module.vpc.aws_route_table_association.public_igw[1], module.vpc.module.vpc.aws_route_table_association.public_igw[2], module.vpc.module.vpc.aws_subnet.private[0], module.vpc.module.vpc.aws_subnet.private[1], module.vpc.module.vpc.aws_subnet.private[2], module.vpc.module.vpc.aws_subnet.public[0], module.vpc.module.vpc.aws_subnet.public[1], module.vpc.module.vpc.aws_subnet.public[2], module.vpc.module.vpc.aws_vpc.vpc, module.vpc.module.logs.aws_s3_bucket.logs[0], module.vpc.module.logs.aws_s3_bucket_public_access_block.logs[0]. ``` ``` Scenario: Reject overpermissive roles * SKIPPING: Can not find aws_iam_policy_document defined in target terraform plan. Given I have aws_iam_policy_document data configured When it has address And its value is module.vpc.module.vpc.data.aws_iam_policy_document.flow_log_policy_doc ```
  5. <Your feature/scenario/steps>

    Scenario: Reject overpermissive roles
        Given I have any resource defined
        When its mode is data 
        And its value is module.vpc.module.vpc.data.aws_iam_policy_document.flow_log_policy_doc
    Scenario: Reject overpermissive roles
        Given I have aws_iam_policy_document data configured
        When it has address
        And its value is module.vpc.module.vpc.data.aws_iam_policy_document.flow_log_policy_doc

Expected behavior : I would expect the data resource to be found.

Tested versions :

Additional context Add any other context about the problem here.

eerkunt commented 3 years ago

Hi,

I think the problem here is to write a test against a data object which might not mean much for the compliance, since it may or may not be used within a resource and data objects are read-only objects.

Hence, instead of structuring a test against data.aws_iam_policy_document, I think it should be written against aws_iam_policy resource.

Here is an example about your case ; https://github.com/terraform-compliance/user-friendly-features/blob/master/aws/IAM.feature

Please let us know if you are stuck, happy to help.

lucassrg commented 3 years ago

You might have scenarios where you want to ensure the data source was used with the proper arguments so that It can fetch the data as expected. The fetched data would be used further within a resource but at that point we can't check whether the information is valid or not.

I'm facing similar issue where the data source is not found but I'm using the Oracle OCI provider.

❯ terraform-compliance -p plan.out -f ./terraform-compliance/features
terraform-compliance v1.3.14 initiated

. Converting terraform plan file.
🚩 Features     : /Users/lgomes/Documents/Oracle/projects/git_repos/terraform/oci-arch-jenkins/terraform-compliance/features/
🚩 Plan File    : /Users/lgomes/Documents/Oracle/projects/git_repos/terraform/oci-arch-jenkins/plan.out.json

🚩 Running tests. 🎉

Feature: Validate that only images compatible with shapes are used by the template  # /Users/lgomes/Documents/Oracle/projects/git_repos/terraform/oci-arch-jenkins/terraform-compliance/features/image_shape_compatibility.feature
    In order to successfully launch a compute instance, a compute image selected must be
    compatible with a compute shape due to hardware compatibility

    @noskip
    Scenario: Ensure oci_core_images data source is used with a shape
                Failure: Can not find oci_core_images defined in target terraform plan.
        Given I have oci_core_images defined
          Failure: 
        Then it must contain shape

1 features (0 passed, 1 failed)
1 scenarios (0 passed, 1 failed)
2 steps (0 passed, 1 failed, 1 skipped)

Feature file:

In order to successfully launch a compute instance, a compute image selected must be
compatible with a compute shape due to hardware compatibility

@noskip
Scenario: Ensure oci_core_images data source is used with a shape
  Given I have oci_core_images data defined
  Then it must contain shape

Terraform data source:

data "oci_core_images" "InstanceImageOCID" {
  compartment_id           = var.compartment_ocid
  operating_system         = var.instance_os
  operating_system_version = var.linux_os_version
  shape = "something"
  filter {
    name   = "display_name"
    values = ["^.*Oracle[^G]*$"]
    regex  = true
  }
}

plan.out snippet:

     "root_module": {
        "resources": [
          {
            "address": "data.oci_core_images.InstanceImageOCID",
            "mode": "data",
            "type": "oci_core_images",
            "name": "InstanceImageOCID",
            "provider_name": "registry.terraform.io/hashicorp/oci",
            "schema_version": 0,
            "values": {
              "compartment_id": null,
              "display_name": null,
              "filter": null,
              "id": null,
              "images": null,
              "operating_system": null,
              "operating_system_version": null,
              "shape": null,
              "sort_by": null,
              "sort_order": null,
              "state": null
            }
          },
eerkunt commented 3 years ago

Hmm you are right, haven't thought about this. This could be useful 🤔

Will look into this.