""" Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: MIT-0 """ import cfnlint.helpers from cfnlint.helpers import REGISTRY_SCHEMAS from cfnlint.rules import CloudFormationLintRule, RuleMatch from cfnlint.template import Template class Configuration(CloudFormationLintRule): """Check Base Resource Configuration""" id = "E3001" shortdesc = "Basic CloudFormation Resource Check" description = ( "Making sure the basic CloudFormation resources are properly configured" ) source_url = "https://github.com/aws-cloudformation/cfn-python-lint" tags = ["resources"] def _check_resource(self, cfn: Template, resource_name, resource_values): """Check Resource""" valid_attributes = [ "Condition", "CreationPolicy", "DeletionPolicy", "DependsOn", "Metadata", "Properties", "Type", "UpdatePolicy", "UpdateReplacePolicy", ] valid_custom_attributes = [ "Condition", "DeletionPolicy", "DependsOn", "Metadata", "Properties", "Type", "UpdateReplacePolicy", "Version", ] matches = [] if not isinstance(resource_values, dict): message = "Resource not properly configured at {0}" matches.append( RuleMatch(["Resources", resource_name], message.format(resource_name)) ) return matches # validate condition is a string condition = resource_values.get("Condition", "") if not isinstance(condition, str): message = "Condition for resource {0} should be a string" matches.append( RuleMatch( ["Resources", resource_name, "Condition"], message.format(resource_name), ) ) resource_type = resource_values.get("Type", "") if not isinstance(resource_type, str): message = "Type has to be a string at {0}" matches.append( RuleMatch( ["Resources", resource_name], message.format("/".join(["Resources", resource_name])), ) ) return matches # Type is valid continue analysis if ( resource_type.startswith("Custom::") or resource_type == "AWS::CloudFormation::CustomResource" ): check_attributes = valid_custom_attributes else: check_attributes = valid_attributes for property_key, _ in resource_values.items(): if property_key not in check_attributes: message = "Invalid resource attribute {0} for resource {1}" matches.append( RuleMatch( ["Resources", resource_name, property_key], message.format(property_key, resource_name), ) ) if not resource_type: message = "Type not defined for resource {0}" matches.append( RuleMatch(["Resources", resource_name], message.format(resource_name)) ) elif not isinstance(resource_type, str): message = "Type has to be a string at {0}" matches.append( RuleMatch( ["Resources", resource_name], message.format("/".join(["Resources", resource_name])), ) ) else: self.logger.debug("Check resource types by region...") for region, specs in cfnlint.helpers.RESOURCE_SPECS.items(): if region in cfn.regions: if condition: if False in cfn.conditions.build_scenerios_on_region( condition, region ): continue if resource_type not in specs[ "ResourceTypes" ] and resource_type not in [ s["typeName"] for s in REGISTRY_SCHEMAS ]: if not resource_type.startswith( ("Custom::", "AWS::Serverless::") ) and not resource_type.endswith("::MODULE"): message = "Invalid or unsupported Type {0} for resource {1} in {2}" matches.append( RuleMatch( ["Resources", resource_name, "Type"], message.format( resource_type, resource_name, region ), ) ) if "Properties" not in resource_values: resource_spec = cfnlint.helpers.RESOURCE_SPECS[cfn.regions[0]] if resource_type in resource_spec["ResourceTypes"]: properties_spec = resource_spec["ResourceTypes"][resource_type][ "Properties" ] # pylint: disable=len-as-condition if len(properties_spec) > 0: required = 0 for _, property_spec in properties_spec.items(): if property_spec.get("Required", False): required += 1 if required > 0: if ( resource_type == "AWS::CloudFormation::WaitCondition" and "CreationPolicy" in resource_values.keys() ): self.logger.debug( "Exception to required properties section as CreationPolicy is defined." ) else: message = "Properties not defined for resource {0}" matches.append( RuleMatch( ["Resources", resource_name], message.format(resource_name), ) ) return matches def match(self, cfn): matches = [] resources = cfn.template.get("Resources", {}) if not isinstance(resources, dict): message = "Resource not properly configured" matches.append(RuleMatch(["Resources"], message)) else: for resource_name, resource_values in cfn.template.get( "Resources", {} ).items(): self.logger.debug( "Validating resource %s base configuration", resource_name ) matches.extend( self._check_resource(cfn, resource_name, resource_values) ) return matches
Name | Type | Size | Permission | Actions |
---|---|---|---|---|
__pycache__ | Folder | 0755 |
|
|
backup | Folder | 0755 |
|
|
certificatemanager | Folder | 0755 |
|
|
cloudformation | Folder | 0755 |
|
|
cloudfront | Folder | 0755 |
|
|
codepipeline | Folder | 0755 |
|
|
dynamodb | Folder | 0755 |
|
|
ecs | Folder | 0755 |
|
|
ectwo | Folder | 0755 |
|
|
elasticache | Folder | 0755 |
|
|
elb | Folder | 0755 |
|
|
events | Folder | 0755 |
|
|
iam | Folder | 0755 |
|
|
lmbd | Folder | 0755 |
|
|
properties | Folder | 0755 |
|
|
rds | Folder | 0755 |
|
|
route53 | Folder | 0755 |
|
|
stepfunctions | Folder | 0755 |
|
|
updatepolicy | Folder | 0755 |
|
|
ApproachingLimitName.py | File | 686 B | 0644 |
|
ApproachingLimitNumber.py | File | 690 B | 0644 |
|
BothUpdateReplacePolicyDeletionPolicyNeeded.py | File | 1.74 KB | 0644 |
|
CircularDependency.py | File | 1.18 KB | 0644 |
|
Configuration.py | File | 6.97 KB | 0644 |
|
DeletionPolicy.py | File | 3.91 KB | 0644 |
|
DependsOn.py | File | 2.7 KB | 0644 |
|
DependsOnObsolete.py | File | 3.01 KB | 0644 |
|
HardCodedArnProperties.py | File | 4.71 KB | 0644 |
|
LimitName.py | File | 704 B | 0644 |
|
LimitNumber.py | File | 692 B | 0644 |
|
Modules.py | File | 2.8 KB | 0644 |
|
Name.py | File | 688 B | 0644 |
|
NoEcho.py | File | 3.2 KB | 0644 |
|
PreviousGenerationInstanceType.py | File | 4.2 KB | 0644 |
|
ResourceSchema.py | File | 1.74 KB | 0644 |
|
RetentionPeriodOnResourceTypesWithAutoExpiringContent.py | File | 6.42 KB | 0644 |
|
ServerlessTransform.py | File | 1.59 KB | 0644 |
|
UniqueNames.py | File | 924 B | 0644 |
|
UpdateReplacePolicy.py | File | 4.07 KB | 0644 |
|
UpdateReplacePolicyDeletionPolicyOnStatefulResourceTypes.py | File | 2.09 KB | 0644 |
|
__init__.py | File | 106 B | 0644 |
|