Checkov is unable to resolve the 'engine' terraform variable
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
Hi @mifonpe , is this still up for grab?
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!
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!