""" Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: MIT-0 """ from cfnlint.rules import CloudFormationLintRule, RuleMatch class Exists(CloudFormationLintRule): """Check if used Conditions are defined""" id = "E8002" shortdesc = "Check if the referenced Conditions are defined" description = ( "Making sure the used conditions are actually defined in the Conditions section" ) source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/conditions-section-structure.html" tags = ["conditions"] def match(self, cfn): matches = [] ref_conditions = {} # Get all defined conditions conditions = cfn.template.get("Conditions", {}) # Get all "If's" that reference a Condition iftrees = cfn.search_deep_keys("Fn::If") for iftree in iftrees: if isinstance(iftree[-1], list): if isinstance(iftree[-1][0], str): ref_conditions[iftree[-1][0]] = iftree # Get resource's Conditions for resource_name, resource_values in cfn.get_resources().items(): condition = resource_values.get("Condition") if isinstance(condition, str): # make sure its a string path = ["Resources", resource_name, "Condition"] ref_conditions[condition] = path # Get conditions used by another condition condtrees = cfn.search_deep_keys("Condition") for condtree in condtrees: if condtree[0] == "Conditions": if isinstance(condtree[-1], (str)): path = ["Conditions", condtree[-1]] ref_conditions[condtree[-1]] = path # Get Output Conditions for _, output_values in cfn.get_outputs_valid().items(): if "Condition" in output_values: path = ["Outputs", output_values["Condition"]] ref_conditions[output_values["Condition"]] = path # Check if all the conditions are defined for ref_condition, ref_path in ref_conditions.items(): if ref_condition not in conditions: message = "Condition {0} is not defined." matches.append(RuleMatch(ref_path, message.format(ref_condition))) return matches