Skip to content

Commit

Permalink
V1 - cleaning up more rules (#2670)
Browse files Browse the repository at this point in the history
* Add back in logic for rule W2031
* Validate conditions when checking resource types for a region
  • Loading branch information
kddejong committed Mar 12, 2024
1 parent 069f8ff commit 4213268
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 437 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"additionalProperties": false,
"awsType": true,
"else": {
"not": {
"required": [
Expand Down Expand Up @@ -55,7 +56,6 @@
"type": "object"
},
"Type": {
"awsType": true,
"type": "string"
},
"UpdatePolicy": {
Expand Down
39 changes: 39 additions & 0 deletions src/cfnlint/rules/parameters/AllowedPattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""
from typing import Generator, List, Union

import regex as re

from cfnlint.jsonschema import ValidationError
from cfnlint.rules import CloudFormationLintRule
from cfnlint.template import Template


class AllowedPattern(CloudFormationLintRule):
Expand All @@ -14,3 +19,37 @@ class AllowedPattern(CloudFormationLintRule):
description = "Check if parameters have a valid value in a pattern. The Parameter's allowed pattern is based on the usages in property (Ref)"
source_url = "https://github.com/aws-cloudformation/cfn-python-lint/blob/main/docs/cfn-resource-specification.md#allowedpattern"
tags = ["parameters", "resources", "property", "allowed pattern"]

def __init__(self):
super().__init__()
self.parameters = {}

def initialize(self, cfn: Template):
"""Initialize the rule"""
self.parameters = cfn.get_parameters()

def _pattern(
self, instance: str, patrn: str, path: List[Union[str, int]]
) -> Generator[ValidationError, None, None]:
if not re.search(patrn, instance):
yield ValidationError(
f"{instance!r} does not match {patrn!r}",
rule=self,
path_override=path,
)

def validate(self, ref: str, patrn: str):
p = self.parameters.get(ref, {})
if isinstance(p, dict):
p_default = p.get("Default", None)
if isinstance(p_default, (str)):
yield from self._pattern(
p_default, patrn, ["Parameters", ref, "Default"]
)

p_avs = p.get("AllowedValues", [])
if isinstance(p_avs, list):
for p_av_index, p_av in enumerate(p_avs):
yield from self._pattern(
p_av, patrn, ["Parameters", ref, "AllowedValues", p_av_index]
)
31 changes: 21 additions & 10 deletions src/cfnlint/rules/resources/Configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,40 @@ def __init__(self):
cfn=None,
rules=None,
)(schema=schema)
self.cfn = None

def initialize(self, cfn):
super().initialize(cfn)
self.regions = cfn.regions
self.cfn = cfn

# pylint: disable=unused-argument
def _awsType(self, validator, iT, instance, schema):
if not validator.is_type(instance, "string"):
resource_type = instance.get("Type")
if not validator.is_type(resource_type, "string"):
return

resource_condition = instance.get("Condition")

for region in self.regions:
if instance in PROVIDER_SCHEMA_MANAGER.get_resource_types(region=region):
return
if not instance.startswith(
if validator.is_type(resource_condition, "string"):
if False in self.cfn.conditions.build_scenerios_on_region(
resource_condition, region
):
continue
if resource_type in PROVIDER_SCHEMA_MANAGER.get_resource_types(
region=region
):
continue
if not resource_type.startswith(
("Custom::", "AWS::Serverless::")
) and not instance.endswith("::MODULE"):
) and not resource_type.endswith("::MODULE"):
yield ValidationError(
f"Resource type `{instance}` does not exist in '{region}'"
f"Resource type `{resource_type}` does not exist in '{region}'"
)

# pylint: disable=unused-argument
def _check_resource(self, cfn, resource_name, resource_values):
def _check_resource(self, resource_name, resource_values):
"""Check Resource"""
matches = []

Expand Down Expand Up @@ -98,8 +111,6 @@ def match(self, cfn):
self.logger.debug(
"Validating resource %s base configuration", resource_name
)
matches.extend(
self._check_resource(cfn, resource_name, resource_values)
)
matches.extend(self._check_resource(resource_name, resource_values))

return matches
10 changes: 10 additions & 0 deletions src/cfnlint/rules/resources/properties/AllowedPattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,19 @@ class AllowedPattern(CloudFormationLintRule):
description = "Check if properties have a valid value in case of a pattern (Regular Expression)"
source_url = "https://github.com/awslabs/cfn-python-lint/blob/main/docs/cfn-resource-specification.md#allowedpattern"
tags = ["resources", "property", "allowed pattern", "regex"]
child_rules = {
"W2031": None,
}

# pylint: disable=unused-argument
def pattern(self, validator, patrn, instance, schema):
if isinstance(instance, dict):
if len(instance) == 1:
for k, v in instance.items():
if k == "Ref":
if self.child_rules.get("W2031"):
yield from self.child_rules["W2031"].validate(v, patrn)
return
if validator.is_type(instance, "string"):
# skip any dynamic reference strings
if REGEX_DYN_REF.findall(instance):
Expand Down
33 changes: 0 additions & 33 deletions src/cfnlint/schema/_constants.py

This file was deleted.

35 changes: 34 additions & 1 deletion src/cfnlint/schema/getatts.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,42 @@
import enum
from typing import Any, Dict, Optional

from cfnlint.schema._constants import _all_property_types
from cfnlint.schema._pointer import resolve_pointer

_all_property_types = [
"AWS::Amplify::Branch",
"AWS::Amplify::Domain",
"AWS::AppSync::DomainName",
"AWS::Backup::BackupSelection",
"AWS::Backup::BackupVault",
"AWS::CodeArtifact::Domain",
"AWS::CodeArtifact::Repository",
"AWS::EC2::CapacityReservation",
"AWS::EC2::Subnet",
"AWS::EC2::VPC",
"AWS::EFS::MountTarget",
"AWS::EKS::Nodegroup",
"AWS::ImageBuilder::Component",
"AWS::ImageBuilder::ContainerRecipe",
"AWS::ImageBuilder::DistributionConfiguration",
"AWS::ImageBuilder::ImagePipeline",
"AWS::ImageBuilder::ImageRecipe",
"AWS::ImageBuilder::InfrastructureConfiguration",
"AWS::RDS::DBParameterGroup",
"AWS::RoboMaker::RobotApplication",
"AWS::RoboMaker::SimulationApplication",
"AWS::Route53Resolver::ResolverRule",
"AWS::Route53Resolver::ResolverRuleAssociation",
"AWS::SNS::Topic",
"AWS::SQS::Queue",
"AWS::SageMaker::DataQualityJobDefinition",
"AWS::SageMaker::ModelBiasJobDefinition",
"AWS::SageMaker::ModelExplainabilityJobDefinition",
"AWS::SageMaker::ModelQualityJobDefinition",
"AWS::SageMaker::MonitoringSchedule",
"AWS::StepFunctions::Activity",
]


class GetAttType(enum.Enum):
ReadOnly = 1
Expand Down
Loading

0 comments on commit 4213268

Please sign in to comment.