Skip to content

Commit cc7e5e8

Browse files
fix(terraform_plan): use provider name not resource address to fix supported_provider matching (#7119)
fix supported_provider matching: use provider name instead of resource address internally Co-authored-by: Taylor <[email protected]>
1 parent cfa62cd commit cc7e5e8

File tree

5 files changed

+93
-11
lines changed

5 files changed

+93
-11
lines changed

checkov/terraform/plan_parser.py

+5-8
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ def _get_providers(template: dict[str, dict[str, Any]]) -> list[dict[str, dict[s
345345
# }
346346
# },
347347
# {
348-
# "aws.west": {
348+
# "aws": {
349349
# "region": ["us-west-1"],
350350
# "alias": ["west"],
351351
# . . .
@@ -360,10 +360,11 @@ def _get_providers(template: dict[str, dict[str, Any]]) -> list[dict[str, dict[s
360360
if _is_provider_key(key=provider_key):
361361
# Not a provider, skip
362362
continue
363+
provider_name = provider_data.get("name")
363364
provider_alias = provider_data.get("alias", "default")
364365
provider_map: dict[str, dict[str, Any]] = {}
365-
provider_map[provider_key] = {}
366-
provider_map_entry = provider_map[provider_key]
366+
provider_map[provider_name] = {}
367+
provider_map_entry = provider_map[provider_name]
367368
for field, value in provider_data.get('expressions', {}).items():
368369
if field in LINE_FIELD_NAMES or not isinstance(value, dict):
369370
continue # don't care about line #s or non dicts
@@ -377,11 +378,7 @@ def _get_providers(template: dict[str, dict[str, Any]]) -> list[dict[str, dict[s
377378
provider_map_entry[start_line] = [provider_data.get(START_LINE, 1) - 1]
378379
provider_map_entry[end_line] = [provider_data.get(END_LINE, 1)]
379380
provider_map_entry['alias'] = [provider_alias]
380-
# provider_key already contains the alias (ie "aws.east") for non-default providers
381-
if provider_alias == "default":
382-
provider_map_entry[TF_PLAN_RESOURCE_ADDRESS] = f"{provider_key}.{provider_alias}"
383-
else:
384-
provider_map_entry[TF_PLAN_RESOURCE_ADDRESS] = provider_key
381+
provider_map_entry[TF_PLAN_RESOURCE_ADDRESS] = f"{provider_name}.{provider_alias}"
385382
providers.append(provider_map)
386383

387384
return providers

tests/terraform/parser/test_plan_parser.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,16 @@ def test_plan_multiple_providers(self):
3737
tf_definition, _ = parse_tf_plan(valid_plan_path, {})
3838
providers = tf_definition['provider']
3939
self.assertEqual( len(providers), 3)
40-
provider_keys = []
40+
provider_names = []
4141
provider_aliases = []
4242
provider_addresses = []
4343
for provider in providers:
4444
key = next(iter(provider))
45-
provider_keys.append(key)
45+
provider_names.append(key)
4646
provider_aliases.append( provider[key]['alias'][0] )
4747
provider_addresses.append( provider[key]['__address__'] )
4848

49-
self.assertEqual(provider_keys, ["aws", "aws.ohio", "aws.oregon"])
49+
self.assertEqual(provider_names, ["aws", "aws", "aws"])
5050
self.assertEqual(provider_aliases, ["default", "ohio", "oregon"])
5151
self.assertEqual(provider_addresses, ["aws.default", "aws.ohio", "aws.oregon"])
5252

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
provider "aws" {
2+
region = "us-east-1"
3+
}
4+
5+
provider "aws" {
6+
region = "us-east-2"
7+
alias = "ohio"
8+
access_key = "AKIAIOSFODNN7EXAMPLE"
9+
}
10+
provider "aws" {
11+
region = "us-west-2"
12+
alias = "oregon"
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"format_version": "1.2",
3+
"terraform_version": "1.11.4",
4+
"planned_values": {
5+
"root_module": {}
6+
},
7+
"configuration": {
8+
"provider_config": {
9+
"aws": {
10+
"name": "aws",
11+
"full_name": "registry.terraform.io/hashicorp/aws",
12+
"expressions": {
13+
"region": {
14+
"constant_value": "us-east-1"
15+
}
16+
}
17+
},
18+
"aws.ohio": {
19+
"name": "aws",
20+
"full_name": "registry.terraform.io/hashicorp/aws",
21+
"alias": "ohio",
22+
"expressions": {
23+
"access_key": {
24+
"constant_value": "AKIAIOSFODNN7EXAMPLE"
25+
},
26+
"region": {
27+
"constant_value": "us-east-2"
28+
}
29+
}
30+
},
31+
"aws.oregon": {
32+
"name": "aws",
33+
"full_name": "registry.terraform.io/hashicorp/aws",
34+
"alias": "oregon",
35+
"expressions": {
36+
"region": {
37+
"constant_value": "us-west-2"
38+
}
39+
}
40+
}
41+
},
42+
"root_module": {}
43+
},
44+
"timestamp": "2025-05-05T16:11:28Z",
45+
"applyable": false,
46+
"complete": true,
47+
"errored": false
48+
}

tests/terraform/runner/test_plan_runner.py

+24
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,30 @@ def test_plan_change_keys(self):
933933
self.assertEqual(passing_resources, passed_check_resources)
934934
self.assertEqual(failing_resources, failed_check_resources)
935935

936+
def test_plan_with_providers(self):
937+
"""
938+
Ensure AWS providers are parsed correctly and the credentials check runs against
939+
providers with aliases, too.
940+
"""
941+
current_dir = os.path.dirname(os.path.realpath(__file__))
942+
valid_plan_path = current_dir + "/resources/plan_with_providers/tfplan.json"
943+
runner = Runner(db_connector=self.db_connector())
944+
checks_allowlist = ["CKV_AWS_41"]
945+
report = runner.run(
946+
root_folder=None,
947+
files=[valid_plan_path],
948+
external_checks_dir=None,
949+
runner_filter=RunnerFilter(framework=["terraform_plan"], checks=checks_allowlist),
950+
)
951+
report_json = report.get_json()
952+
self.assertIsInstance(report_json, str)
953+
self.assertIsNotNone(report_json)
954+
955+
for record in report.failed_checks:
956+
self.assertIn(record.check_id, checks_allowlist)
957+
self.assertEqual(report.get_summary()["failed"], 1)
958+
self.assertEqual(report.get_summary()["passed"], 2)
959+
936960
def tearDown(self) -> None:
937961
resource_registry.checks = deepcopy(self.orig_checks)
938962
BaseCheckRegistry._BaseCheckRegistry__all_registered_checks = deepcopy(self.orig_all_registered_checks)

0 commit comments

Comments
 (0)