Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Checkov is unable to resolve the 'engine' terraform variable #6749

Open
mifonpe opened this issue Oct 3, 2024 · 1 comment
Open

Checkov is unable to resolve the 'engine' terraform variable #6749

mifonpe opened this issue Oct 3, 2024 · 1 comment
Labels

Comments

@mifonpe
Copy link

mifonpe commented Oct 3, 2024

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 mifonpe added the crash label Oct 3, 2024
@alpha-neutr0n
Copy link

Hi @mifonpe , is this still up for grab?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants