Skip to content

Commit 5f3248d

Browse files
committed
Support list definition
1 parent 4c0d1e2 commit 5f3248d

3 files changed

Lines changed: 66 additions & 0 deletions

File tree

checkov/common/checks_infra/checks_parser.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ def validate_check_config(self, file_path: str, raw_check: dict[str, dict[str, A
202202
def parse_raw_check(self, raw_check: Dict[str, Dict[str, Any]], **kwargs: Any) -> BaseGraphCheck:
203203
providers = self._get_check_providers(raw_check)
204204
policy_definition = raw_check.get("definition", {})
205+
if isinstance(policy_definition, list):
206+
# a list of conditions is treated as an implicit AND
207+
policy_definition = {"and": policy_definition}
205208
check = self._parse_raw_check(policy_definition, kwargs.get("resources_types"), providers)
206209
check.id = raw_check.get("metadata", {}).get("id", "")
207210
check.name = raw_check.get("metadata", {}).get("name", "")
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
metadata:
2+
name: "Ensure S3 bucket has versioning and encryption"
3+
id: CUSTOM_LIST_DEF
4+
category: "GENERAL_SECURITY"
5+
definition:
6+
- cond_type: attribute
7+
resource_types:
8+
- aws_s3_bucket
9+
attribute: versioning.enabled
10+
operator: equals
11+
value: "true"
12+
- cond_type: attribute
13+
resource_types:
14+
- aws_s3_bucket
15+
attribute: server_side_encryption_configuration
16+
operator: exists

tests/common/checks_infra/test_checks_parser.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from checkov.common.checks_infra.checks_parser import GraphCheckParser
77
from checkov.common.checks_infra.resources_types import resources_types as raw_resources_types
8+
from checkov.common.graph.checks_infra.enums import SolverType
89

910
EXAMPLES_DIR = Path(__file__).parent / "examples"
1011

@@ -91,3 +92,49 @@ def test_parse_taggable_resource_list():
9192
providers = ["azure"]
9293
check = parser._parse_raw_check(raw_check, [], providers)
9394
assert check.resource_types == raw_resources_types.get("azure_taggable")
95+
96+
97+
def test_validate_check_config_list_definition(caplog: LogCaptureFixture):
98+
"""A definition that is a list should pass validation."""
99+
# given
100+
file_path = EXAMPLES_DIR / "valid_check_list_definition.yaml"
101+
check_yaml = yaml.safe_load(file_path.read_text())
102+
103+
# when
104+
valid = GraphCheckParser().validate_check_config(file_path=str(file_path), raw_check=check_yaml)
105+
106+
# then
107+
assert valid
108+
assert len(caplog.messages) == 0
109+
110+
111+
def test_parse_raw_check_list_definition():
112+
"""A list-type definition should be treated as an implicit AND of its elements."""
113+
parser = GraphCheckParser()
114+
raw_check = {
115+
"metadata": {"id": "TEST_LIST", "name": "Test List Def", "category": "GENERAL_SECURITY"},
116+
"definition": [
117+
{
118+
"cond_type": "attribute",
119+
"resource_types": ["aws_s3_bucket"],
120+
"attribute": "versioning.enabled",
121+
"operator": "equals",
122+
"value": "true",
123+
},
124+
{
125+
"cond_type": "attribute",
126+
"resource_types": ["aws_s3_bucket"],
127+
"attribute": "server_side_encryption_configuration",
128+
"operator": "exists",
129+
},
130+
],
131+
}
132+
133+
check = parser.parse_raw_check(raw_check)
134+
135+
assert check.id == "TEST_LIST"
136+
assert check.type == SolverType.COMPLEX
137+
assert check.operator == "and"
138+
assert len(check.sub_checks) == 2
139+
assert check.sub_checks[0].attribute == "versioning.enabled"
140+
assert check.sub_checks[1].attribute == "server_side_encryption_configuration"

0 commit comments

Comments
 (0)