checkov icon indicating copy to clipboard operation
checkov copied to clipboard

Checkov is unable to resolve the 'engine' terraform variable

Open mifonpe opened this issue 1 year ago • 1 comments

Describe the issue Hi, we are using Checkov's custom checks with python to ensure our teams use the right versions of postgres through our self-maintained terraform modules. We use tfvars files to provide values per environment and invoke them using the --var-file flag.

Checkov downloads our private modules from the registry and it works fine for other custom checks.

The problem is that Checkov does not seem to recognize the engine key for the RDS module, even though it is able to parse all other keys with the variables values.

Examples Our module invocation looks like this:

module "rds" { 
  source  = "gitlab.com/blah/blah/blah"
  version = "> 8.0.0, <9.0.0"

  team           = var.team
  project        = var.project
  region         = var.region
  namespace      = var.namespace
  env            = var.env
  component_name = var.project

  database_name  = var.database_name
  engine         = var.engine
  engine_version = var.engine_version
  instance_class = var.instance_class
  storage_size   = var.storage_size
  port           = var.port

  username      = var.username
  password      = aws_ssm_parameter.database_master_password.value

  default_tags = module.labels.tags

  deletion_protection     = var.deletion_protection
  backup_retention_period = var.backup_retention_period
  monitoring_interval     = var.monitoring_interval
  allow_vpn_access        = true

  enable_replication      = true

  switch_off = var.switch_off # only affects non-prod envs

  providers = {
    aws       = aws
    aws.admin = aws.admin
  }
}

The variables are defined as follows:

variable "engine" {
  type        = string
  description = "Database Engine"
}

variable "engine_version" {
  type        = string
  description = "Database Engine Version"
}

variable "instance_class" {
  type        = string
  description = "Database Instance Type"
}

The tfvars file looks like this:

env            = "prod"
engine_version = "14"
instance_class = "db.t4g.micro"
storage_size   = "25"
engine         = "postgres"
database_name  = "galileoprod"
username       = "galileo"
port           = "5432"
switch_off     = false

Our custom check code looks like this. Note that we are outputting the contents of conf into a file (out.txt).

from checkov.common.models.enums import CheckResult, CheckCategories
from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
from checkov.terraform.checks.module.base_module_check import BaseModuleCheck
from packaging import version


class EnsureRDSPGVersion(BaseModuleCheck):
    def __init__(self)-> None:
        name = "Ensure RDS module uses at least PostgreSQL 13"
        id = "CUSTOM_TF_RDS_PG_VERSION"
        supported_resources = ['module',]
        categories = [CheckCategories.CONVENTION]
        guideline = "Your RDS Database should be using at least PostgreSQL 13. Please upgrade the database to the latest version or you will not be able to deploy your infrastructure starting on 2025-28-02."
        super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources, guideline=guideline)

    def scan_module_conf(self, conf):
        """
            Validate RDS PostgreSQL engine version is at least 13
        :return: <CheckResult>
        """
        if 'source' in conf.keys() and 'version' in conf.keys():
            module_source = conf['source'][0]
            # Check if this is the specific module we want to enforce the version on
            if "gitlab.com/blah/blah" == module_source:
                with open('out.txt', 'w') as f:
                    print(conf, file=f)
                if 'engine' in conf.keys() and 'engine_version' in conf.keys():
                    engine = conf['engine'][0]
                    engine_version = conf['engine_version'][0]
                    # Check if the engine is PostgreSQL
                    if "postgres" == engine:
                        # Extract major version number
                        major_version = int(engine_version.split(".")[0])
                        # Check if the major version is at least 13
                        if major_version >= 13:
                            return CheckResult.PASSED
                        else:
                            return CheckResult.FAILED

check = EnsureRDSPGVersion()

Exception Trace

The command we run is the following (within the terraform folder).

checkov -d .  --external-checks-dir <path-to-checks> --check "CUSTOM_TF_RDS_PG_VERSION" --download-external-modules true --framework terraform --var-file <path-to-tfvars>

Once we cat the out.txt file, we get the following output, in which as you can see, all parameters are correctly substituted but engine contains the following value '${var.engine}'

{'__end_line__': 47, '__resolved__': [], '__start_line__': 11, 'allow_vpn_access': [True], 'backup_retention_period': [1], 'component_name': ['galileo'], 'database_name': ['galileoprod'], 'default_tags': ['module.labels.tags'], 'deletion_protection': [True], 'enable_replication': [True], 'engine': ['${var.engine}'], 'engine_version': ['14'], 'env': ['prod'], 'instance_class': ['db.t4g.micro'], 'monitoring_interval': [30], 'namespace': ['sennder'], 'password': ['aws_ssm_parameter.database_master_password.value'], 'port': ['5432'], 'project': ['galileo'], 'providers': [{'aws': 'aws', 'aws.admin': '${aws.admin}'}], 'region': ['eu-central-1'], 'source': ['gitlab.com/blah/blah'], 'storage_size': ['25'], 'switch_off': [False], 'team': ['infraops'], 'username': ['galileo'], 'version': ['> 8.0.0, <9.0.0'], '__address__': 'rds'}

So far, we have no clue why this happens, and we have noticed that if we change the module key from engine to db_engine, the substitution works as expected!

Desktop (please complete the following information):

  • OS: OSx 14.6.1 (sonoma)
  • Checkov Version 3.2.250

mifonpe avatar Oct 03 '24 11:10 mifonpe

Hi @mifonpe , is this still up for grab?

alpha-neutr0n avatar Oct 06 '24 09:10 alpha-neutr0n

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 Apr 05 '25 05:04 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 Apr 20 '25 21:04 stale[bot]