checkov icon indicating copy to clipboard operation
checkov copied to clipboard

Terraform - variable rendering of a string variable passed to a function changes it to a non string

Open nicholas-marchini opened this issue 2 years ago • 14 comments

Describe the issue I have written a custom check which looks for the tag keys and values. when running checkov with the --evaluate-variable as true the check fails due to not being able to determine the value of a local value. The check works if the value of the tag is not a variable or defined in locals

I expect checkov to evaluate the lookup(local.BackupPlan, var.env) to the value depending on the result of the local lookup.

Examples Custom Check

---
metadata:
  name: "Check that all resources are tagged with the key - BackupPlan and have a valid value"
  id: "CKV2_AWS_IT_BR_C2_001"
  category: "CMP_IT_CONTROLS"
scope:
  provider: aws
definition:
  and:
    - cond_type: "attribute"
      resource_types:
      - "aws_s3_bucket"
      - "aws_docdb_cluster"
      - "aws_dynamodb_table"
      - "aws_efs_file_system"
      - "aws_rds_cluster"
      - "aws_rds_cluster_instance"
      attribute: "tags.BackupPlan"
      operator: "equals"
      value: "Daily5"
    - or:
        - cond_type: "attribute"
          resource_types:
          - "aws_s3_bucket"
          attribute: "tags.BackupPlan"
          operator: "equals"
          value: "Daily15"
        - cond_type: "attribute"
          resource_types:
          - "aws_s3_bucket"
          attribute: "tags.BackupPlan"
          operator: "equals"
          value: "Daily35"

S3 Bucket resource

resource "aws_s3_bucket" "artifacts" {
  bucket = "${var.prefix}-artifacts-${var.env}"
  count  = var.env == "shared" ? 1 : 0
  tags = {
    Name                  = "${var.prefix}-artifacts-${var.env}"
    team                  = var.prefix
    "PII Relevant"        = "NULL"
    "BackupPlan"      = lookup(local.BackupPlan, var.env)
    }
}

Locals

  BackupPlan = {
    dev     = "Daily5"
    preprod = "Daily15"
    prod    = "Daily35"
    shared  = "Daily35"
  }
}

Failure

Check: CKV2_AWS_IT_BR_C2_001: "Check that all resources are tagged with the key - BackupPlan and have a valid value"
	FAILED for resource: aws_s3_bucket.artifacts
	File: /s3_buckets.tf:336-348

		336 | resource "aws_s3_bucket" "artifacts" {
		337 |   bucket = "${var.prefix}-artifacts-${var.env}"
		338 |   count  = var.env == "shared" ? 1 : 0
		339 |   tags = {
		340 |     Name                  = "${var.prefix}-artifacts-${var.env}"
		341 |     team                  = var.prefix
		342 |     "PII Relevant"        = "NULL"
		343 |     "BackupPlan"      = lookup(local.BackupPlan, var.env)
		344 |     }

Version (please complete the following information):

  • Checkov Version 2.1.236

Additional context Add any other context about the problem here.

nicholas-marchini avatar Sep 28 '22 22:09 nicholas-marchini

hey @nicholas-marchini thanks for reaching out. As far as I can tell from your example, if var.env is not set, then we can't do a lookup.

gruebel avatar Sep 29 '22 06:09 gruebel

@gruebel I pass this into the checkov command on execution --var-file config/dev.tfvars The file contains

env = "dev"

nicholas-marchini avatar Sep 29 '22 07:09 nicholas-marchini

Still an issue in the latest version of Checkov

nicholas-marchini avatar Oct 04 '22 14:10 nicholas-marchini

I took a look and there are 2 issues, one on your side and one in our code. lets start with yours

your usage of lookup(...) is deprecated since Terraform 0.7, so we will not add support for it https://www.terraform.io/language/functions/lookup

For historical reasons, the default parameter is actually optional. However, omitting default is deprecated since v0.7 because that would then be equivalent to the native index syntax, map[key].

the other issue is harder to fix. I tried it, but it breaks other cases, so nothing which will be done in the next days or probably even weeks, depending on my free time.

gruebel avatar Oct 06 '22 12:10 gruebel

Thanks for the reply, so from what I can see I should add a default to the lookup

lookup(local.BackupPlan, var.env, "Daily5")

nicholas-marchini avatar Oct 06 '22 13:10 nicholas-marchini

@gruebel Do you think you will have some time soon to take a look at this please?

nicholas-marchini avatar Dec 06 '22 16:12 nicholas-marchini

I am having the exact same issue, has someone been able to find a solution?

Vykistwo avatar Dec 07 '22 14:12 Vykistwo

I think this is an issue with this block:

https://github.com/bridgecrewio/checkov/blob/307a33648a148a797d83ec22105bb6892d92cfe7/checkov/terraform/graph_builder/local_graph.py#L264-L272

Checkov assumes that the tfvars files are in the same directory as the variable blocks and doesn't appear to respect the --var-file argument. I tested this locally by deleting this condition and my checks began passing:

https://github.com/bridgecrewio/checkov/blob/307a33648a148a797d83ec22105bb6892d92cfe7/checkov/terraform/graph_builder/local_graph.py#L269

Is there any way we can have Checkov use the directories of any of the arguments passed to --var-files in addition to the current directory?

I was able to get my failing policy to pass by putting my tfvars file in the same directory as my variables blocks.

aniu-droid avatar Dec 12 '22 17:12 aniu-droid

@gruebel This is still an issue, any updates on this please?

nicholas-marchini avatar Mar 31 '23 07:03 nicholas-marchini

@aniu-droid I have observed the following today

Running checkov outside the directory the .tf files are in or directly in the directory with the .tf files will work if the -var-file is either in the same directory of a symlink.

For our code we use a terraform.tfvars.json file which holds common tags that are the same across all environments. If I symlink this file then the custom checks work as expected. If the -var-file is a path to another folder then it fails. Hope that makes sense.

nicholas-marchini avatar Mar 31 '23 20:03 nicholas-marchini

@nicholas-marchini Can you post your example, we have the same problem, a simple "tags = var.tags" is not recognize main.tf: resource "azurerm_resource_group" "rg" { name = "rg-hello-tf-${random_uuid.uuid.result}" location = var.location

tags = var.tags }

variables.tf: variable "tags" { type = map(string) description = "Tags obligatorias" default = { Application = "tag_Application", Creation_Date = "tag_Creacion_Date", Modification_Date = "tag_Modification_Date", Creator = "tag_Creator", Domain = "tag_Domain", Environment = "tag_Environment", Project_Name = "tag_Project_Name", Responsible_Area = "tag_Responsible_Area", Responsible_Implementation = "tag_Responsible_Implementation" } }

And Checkov It is not evaluating the tags, it is as if it does not recognize them because they are rendered by means of a terraform variable?

cmoran77 avatar May 25 '23 15:05 cmoran77

Bump - still experiencing this issue

harry1C-cw avatar Jul 17 '23 09:07 harry1C-cw

Seeing this issue as well.

nickcaballero avatar Aug 08 '23 16:08 nickcaballero

Thanks for contributing to Checkov! We've automatically marked this issue as stale to keep our issues list tidy, because it has not had any activity for 6 months. It will be closed in 14 days if no further activity occurs. Commenting on this issue will remove the stale tag. If you want to talk through the issue or help us understand the priority and context, feel free to add a comment or join us in the Checkov slack channel at codifiedsecurity.slack.com Thanks!

stale[bot] avatar Feb 06 '24 06:02 stale[bot]

Closing issue due to inactivity. If you feel this is in error, please re-open, or reach out to the community via slack: codifiedsecurity.slack.com Thanks!

stale[bot] avatar Feb 22 '24 06:02 stale[bot]