-
Notifications
You must be signed in to change notification settings - Fork 598
/
GetAttFormat.py
70 lines (57 loc) · 2.35 KB
/
GetAttFormat.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""
from typing import Any
from cfnlint.jsonschema import ValidationError, ValidationResult, Validator
from cfnlint.rules.jsonschema import CfnLintKeyword
from cfnlint.schema import PROVIDER_SCHEMA_MANAGER
class GetAttFormat(CfnLintKeyword):
id = "E1040"
shortdesc = "Check if GetAtt matches destination format"
description = (
"Validate that if source and destination format exists that they match"
)
source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/best-practices.html#parmtypes"
tags = ["parameters", "ec2", "imageid"]
def __init__(self):
super().__init__(["*"])
self.parent_rules = ["E1010"]
self._exceptions = [
# Need to measure for completeness of automation
"AWS::EC2::SecurityGroup.GroupId",
"AWS::EC2::SecurityGroup.GroupIds",
]
self._resource_type_exceptions = [
"AWS::CloudFormation::CustomResource",
"AWS::CloudFormation::Stack",
"AWS::ServiceCatalog::CloudFormationProvisionedProduct",
]
self._resource_type_attribute_exceptions = [("AWS::SSM::Parameter", "Value")]
def validate(
self, validator: Validator, _, instance: Any, schema: Any
) -> ValidationResult:
fmt = schema.get("format")
if not fmt or fmt in self._exceptions:
return
resource, attr = instance[0:2]
t = validator.context.resources[resource].type
for (
regions,
resource_schema,
) in PROVIDER_SCHEMA_MANAGER.get_resource_schemas_by_regions(
t, validator.context.regions
):
region = regions[0]
if t in self._resource_type_exceptions:
return
if (t, attr) in self._resource_type_attribute_exceptions:
return
getatt_ptr = validator.context.resources[resource].get_atts(region)[attr]
getatt_schema = resource_schema.resolver.resolve_cfn_pointer(getatt_ptr)
getatt_fmt = getatt_schema.get("format")
if getatt_fmt != fmt:
yield ValidationError(
f"{{'Fn::GetAtt': {instance!r}}} that does not match {fmt!r}",
rule=self,
)