To add checks that validate the provider configuration itself (e.g., preventing hardcoded secrets in a provider block):
- Create a Test: Create
tests/terraform/checks/provider/<provider_name>/test_<check_name>.py. Use check.scan_provider_conf(conf=provider_conf) to verify the CheckResult. - Implement the Provider Check: Create
checkov/terraform/checks/provider/<provider_name>/<check_name>.py. Implement a class inheriting from BaseProviderCheck.- Define
name, id, supported_provider, and categories in __init__. - Implement
scan_provider_conf(self, conf: Dict[str, List[Any]]) -> CheckResult to perform the validation logic.
- Define Security Patterns: If the check relies on a new regex pattern (like a secret token), add the pattern to
checkov/common/models/consts.py. - Register the Provider Check: Add an
__init__.py in your provider's check directory to export modules. Then, update checkov/terraform/checks/provider/__init__.py by adding from checkov.terraform.checks.provider.<provider_name> import *.
# Example implementation of a provider check
import re
from typing import Dict, List, Any, Pattern
from checkov.common.models.enums import CheckResult, CheckCategories
from checkov.terraform.checks.provider.base_check import BaseProviderCheck
class LinodeCredentials(BaseProviderCheck):
def __init__(self):
name = "Ensure no hard coded Linode tokens exist in provider"
id = "CKV_LIN_1"
supported_provider = ("linode",)
categories = (CheckCategories.SECRETS,)
super().__init__(name=name, id=id, categories=categories, supported_provider=supported_provider)
def scan_provider_conf(self, conf: Dict[str, List[Any]]) -> CheckResult:
# Logic to check for secrets using a pattern
if self.secret_found(conf, "token", linode_token_pattern):
return CheckResult.FAILED
return CheckResult.PASSED
@staticmethod
def secret_found(conf: Dict[str, List[Any]], field: str, pattern: Pattern[str]) -> bool:
if field in conf.keys():
value = conf[field][0]
if re.match(pattern, value) is not None:
return True
return False
check = LinodeCredentials()