Exemplo n.º 1
0
 def check_az_ref(self, value, path, parameters, resources):
     """Check ref for AZ"""
     matches = []
     allowed_types = [
         'AWS::EC2::AvailabilityZone::Name', 'String',
         'AWS::SSM::Parameter::Value<AWS::EC2::AvailabilityZone::Name>'
     ]
     if value in resources:
         message = 'AvailabilityZone can\'t use a Ref to a resource for {0}'
         matches.append(
             RuleMatch(path, message.format(('/'.join(map(str, path))))))
     elif value in parameters:
         parameter = parameters.get(value, {})
         param_type = parameter.get('Type', '')
         if param_type not in allowed_types:
             param_path = ['Parameters', value, 'Type']
             message = 'Availability Zone should be of type [{0}] for {1}'
             matches.append(
                 RuleMatch(
                     param_path,
                     message.format(', '.join(map(str, allowed_types)),
                                    '/'.join(map(str, param_path)))))
     return matches
    def check_value(self, value, path):
        """Count ScheduledExpression value"""
        matches = []

        # Value is either "cron()" or "rate()"
        if value.startswith('rate(') and value.endswith(')'):
            matches.extend(self.check_rate(value, path))
        elif value.startswith('cron(') and value.endswith(')'):
            matches.extend(self.check_cron(value, path))
        else:
            message = 'Invalid ScheduledExpression specified ({}). Value has to be either cron() or rate()'
            matches.append(RuleMatch(path, message.format(value)))

        return matches
Exemplo n.º 3
0
 def check_vpc_ref(self, value, path, parameters, resources):
     """Check ref for VPC"""
     matches = []
     allowed_types = [
         'String',
         'AWS::SSM::Parameter::Value<String>',
     ]
     if value in resources:
         message = 'DefaultTenancy can\'t use a Ref to a resource for {0}'
         matches.append(
             RuleMatch(path, message.format(('/'.join(map(str, path))))))
     elif value in parameters:
         parameter = parameters.get(value, {})
         parameter_type = parameter.get('Type', None)
         if parameter_type not in allowed_types:
             path_error = ['Parameters', value, 'Type']
             message = 'DefaultTenancy parameter should be of type [{0}] for {1}'
             matches.append(
                 RuleMatch(
                     path_error,
                     message.format(', '.join(map(str, allowed_types)),
                                    '/'.join(map(str, path_error)))))
     return matches
Exemplo n.º 4
0
    def match(self, cfn):
        """Check ELB Resource Parameters"""

        matches = []

        results = cfn.get_resource_properties(
            ['AWS::ElasticLoadBalancingV2::Listener'])
        for result in results:
            matches.extend(
                cfn.check_value(
                    result['Value'],
                    'Protocol',
                    result['Path'],
                    check_value=self.check_protocol_value,
                    accepted_protocols=['HTTP', 'HTTPS', 'TCP', 'TLS'],
                    certificate_protocols=['HTTPS', 'TLS'],
                    certificates=result['Value'].get('Certificates')))

        results = cfn.get_resource_properties(
            ['AWS::ElasticLoadBalancing::LoadBalancer', 'Listeners'])
        for result in results:
            if isinstance(result['Value'], list):
                for index, listener in enumerate(result['Value']):
                    matches.extend(
                        cfn.check_value(
                            listener,
                            'Protocol',
                            result['Path'] + [index],
                            check_value=self.check_protocol_value,
                            accepted_protocols=['HTTP', 'HTTPS', 'TCP', 'SSL'],
                            certificate_protocols=['HTTPS', 'SSL'],
                            certificates=listener.get('SSLCertificateId')))

        results = cfn.get_resource_properties(
            ['AWS::ElasticLoadBalancingV2::LoadBalancer'])
        for result in results:
            properties = result['Value']
            elb_type = properties.get('Type')
            if elb_type == 'network':
                if 'SecurityGroups' in properties:
                    path = result['Path'] + ['SecurityGroups']
                    matches.append(
                        RuleMatch(
                            path,
                            'Security groups are not supported for load balancers with type "network"'
                        ))

            matches.extend(self.check_alb_subnets(properties, result['Path']))

        return matches
Exemplo n.º 5
0
    def check_txt_record(self, value, path):
        """Check TXT record Configuration"""
        matches = []

        if not isinstance(value, dict) and not re.match(self.REGEX_TXT, value):
            message = 'TXT record is not structured as one or more items up to 255 characters ' \
                      'enclosed in double quotation marks at {0}'
            matches.append(
                RuleMatch(
                    path,
                    (message.format('/'.join(map(str, path)))),
                ))

        return matches
Exemplo n.º 6
0
    def match(self, cfn):
        """Check CloudFormation GetAtt"""

        matches = list()

        fnnots = cfn.search_deep_keys('Fn::Not')
        for fnnot in fnnots:
            if not isinstance(fnnot[-1], list):
                message = 'Function Not {0} should be a list'
                matches.append(
                    RuleMatch(fnnot,
                              message.format('/'.join(map(str, fnnot[:-2])))))

        return matches
    def check_names_unique(self, value, path):
        """Check that stage names are unique."""
        matches = []
        stage_names = set()

        for sidx, stage in enumerate(value):
            if stage.get('Name') in stage_names:
                message = 'All stage names within a pipeline must be unique. ({name})'.format(
                    name=stage.get('Name'),
                )
                matches.append(RuleMatch(path + [sidx, 'Name'], message))
            stage_names.add(stage.get('Name'))

        return matches
Exemplo n.º 8
0
    def match(self, cfn):
        """Check CloudFormation Mapping"""

        matches = list()

        outputs = cfn.template.get('Outputs', {})
        for output_name, _ in outputs.items():
            if not re.match(REGEX_ALPHANUMERIC, output_name):
                message = 'Output {0} has invalid name.  Name has to be alphanumeric.'
                matches.append(
                    RuleMatch(['Outputs', output_name],
                              message.format(output_name)))

        return matches
    def check_owner(self, action, path):
        """Check that action type owner is valid."""
        matches = []

        owner = action.get('ActionTypeId').get('Owner')
        if owner not in self.VALID_OWNER_STRINGS and owner is not None:
            message = (
                'For all currently supported action types, the only valid owner '
                'strings are {owners}').format(
                    owners=', '.join(list(self.VALID_OWNER_STRINGS)))
            matches.append(RuleMatch(path + ['ActionTypeId', 'Owner'],
                                     message))

        return matches
Exemplo n.º 10
0
    def check_version(self, action, path):
        """Check that action type version is valid."""
        matches = []

        REGEX_VERSION_STRING = re.compile(r'^[0-9A-Za-z_-]+$')
        LENGTH_MIN = 1
        LENGTH_MAX = 9

        version = action.get('ActionTypeId', {}).get('Version')
        if isinstance(version, dict):
            self.logger.debug(
                'Unable to validate version when an object is used.  Skipping')
        elif isinstance(version, (six.string_types)):
            if not LENGTH_MIN <= len(version) <= LENGTH_MAX:
                message = 'Version string ({0}) must be between {1} and {2} characters in length.'
                matches.append(
                    RuleMatch(path + ['ActionTypeId', 'Version'],
                              message.format(version, LENGTH_MIN, LENGTH_MAX)))
            elif not re.match(REGEX_VERSION_STRING, version):
                message = 'Version string must match the pattern [0-9A-Za-z_-]+.'
                matches.append(
                    RuleMatch(path + ['ActionTypeId', 'Version'], message))
        return matches
    def check_version(self, action, path):
        """Check that action type version is valid."""
        matches = []

        version = action.get('ActionTypeId', {}).get('Version')
        if isinstance(version, dict):
            self.logger.debug('Unable to validate version when an object is used.  Skipping')
        elif version != '1':
            message = 'For all currently supported action types, the only valid version string is "1".'
            matches.append(RuleMatch(
                path + ['ActionTypeId', 'Version'],
                message
            ))
        return matches
Exemplo n.º 12
0
    def match(self, cfn):
        """Check CloudFormation Parameters"""

        matches = []

        for paramname, paramvalue in cfn.get_parameters().items():
            for propname, _ in paramvalue.items():
                if propname not in self.valid_keys:
                    message = 'Parameter {0} has invalid property {1}'
                    matches.append(
                        RuleMatch(['Parameters', paramname, propname],
                                  message.format(paramname, propname)))

        return matches
Exemplo n.º 13
0
    def match(self, cfn):
        """Check CloudFormation Mapping"""

        matches = []

        resources = cfn.template.get('Resources', {})
        for resource_name, _ in resources.items():
            if not re.match(REGEX_ALPHANUMERIC, resource_name):
                message = 'Resources {0} has invalid name.  Name has to be alphanumeric.'
                matches.append(
                    RuleMatch(['Resources', resource_name],
                              message.format(resource_name)))

        return matches
Exemplo n.º 14
0
    def match(self, cfn):
        """Basic Matching"""
        matches = list()

        top_level = []
        for x in cfn.template:
            top_level.append(x)
            if x not in self.valid_keys:
                message = "Top level item {0} isn't valid"
                matches.append(RuleMatch(
                    [x],
                    message.format(x)
                ))

        for y in self.required_keys:
            if y not in top_level:
                message = "Missing top level item {0} to file module"
                matches.append(RuleMatch(
                    ['AWSTemplateFormatVersion'],
                    message.format(y)
                ))

        return matches
Exemplo n.º 15
0
    def match(self, cfn):
        """Check CloudFormation Mappings"""

        matches = []

        mappings = cfn.template.get('Mappings', {})

        for mapping_name in mappings:
            path = ['Mappings', mapping_name]
            if len(mapping_name) > LIMITS['mappings']['name']:
                message = 'The length of mapping name ({0}) exceeds the limit ({1})'
                matches.append(RuleMatch(path, message.format(len(mapping_name), LIMITS['mappings']['name'])))

        return matches
Exemplo n.º 16
0
    def check_cidr_ref(self, value, path, parameters, resources):
        """Check ref for VPC"""
        matches = list()

        if value in parameters:
            parameter = parameters.get(value, {})
            allowed_pattern = parameter.get('AllowedPattern', None)
            allowed_values = parameter.get('AllowedValues', None)
            if not allowed_pattern and not allowed_values:
                param_path = ['Parameters', value]
                message = 'AllowedPattern and/or AllowedValues for Parameter should be specified at {1}. Example for AllowedPattern "{0}"'
                matches.append(RuleMatch(param_path, message.format(self.cidr_regex, ('/'.join(param_path)))))

        return matches
Exemplo n.º 17
0
    def check_names_unique(self, action, path, action_names):
        """Check that action names are unique."""
        matches = []

        action_name = action.get('Name')
        if isinstance(action_name, six.string_types):
            if action.get('Name') in action_names:
                message = 'All action names within a stage must be unique. ({name})'.format(
                    name=action.get('Name')
                )
                matches.append(RuleMatch(path + ['Name'], message))
            action_names.add(action.get('Name'))

        return matches
Exemplo n.º 18
0
    def match(self, cfn):
        """Check CloudFormation Parameters"""

        matches = list()

        # Check number of parameters against the defined limit
        parameters = cfn.template.get('Parameters', {})
        if len(parameters) > LIMITS['parameters']['number']:
            message = 'Maximum number of parameters ({0}) exceeded'
            matches.append(
                RuleMatch(['Parameters'],
                          message.format(LIMITS['parameters']['number'])))

        return matches
    def check_first_stage(self, stages, path):
        """Validate the first stage of a pipeline has source actions."""
        matches = []

        if len(stages) < 1:  # pylint: disable=C1801
            self.logger.debug(
                'Stages was empty. Should have been caught by generic linting.'
            )
            return matches

        # pylint: disable=R1718
        first_stage = set([
            a.get('ActionTypeId').get('Category') for a in stages[0]['Actions']
        ])
        if first_stage and 'Source' not in first_stage:
            message = 'The first stage of a pipeline must contain at least one source action.'
            matches.append(RuleMatch(path + [0], message))

        if len(first_stage) != 1:
            message = 'The first stage of a pipeline must contain only source actions.'
            matches.append(RuleMatch(path + [0], message))

        return matches
Exemplo n.º 20
0
    def check_allowed_pattern(self, allowed_value, allowed_pattern, path):
        """
            Check allowed value against allowed pattern
        """
        message = 'Default should be allowed by AllowedPattern'
        try:
            if not re.match(allowed_pattern, str(allowed_value)):
                return ([RuleMatch(path, message)])
        except re.error as ex:
            self.logger.debug(
                'Regex pattern "%s" isn\'t supported by Python: %s',
                allowed_pattern, ex)

        return []
Exemplo n.º 21
0
    def check_mx_record(self, path, recordset):
        """Check MX record Configuration"""
        matches = []

        resource_records = recordset.get('ResourceRecords')

        for index, record in enumerate(resource_records):
            tree = path[:] + ['ResourceRecords', index]

            if not isinstance(record, dict):
                # Split the record up to the mandatory settings (priority domainname)
                items = record.split(' ')

                # Check if the 3 settings are given.
                if len(items) != 2:
                    message = 'MX record must contain 2 settings (priority domainname), record contains {} settings.'
                    matches.append(
                        RuleMatch(tree, message.format(len(items), record)))
                else:
                    # Check the priority value
                    if not items[0].isdigit():
                        message = 'MX record priority setting ({}) should be of type Integer.'
                        matches.append(
                            RuleMatch(tree, message.format(items[0], record)))
                    else:
                        if not 0 <= int(items[0]) <= 65535:
                            message = 'Invalid MX record priority setting ({}) given, must be between 0 and 65535.'
                            matches.append(
                                RuleMatch(tree,
                                          message.format(items[0], record)))

                    # Check the domainname value
                    if not re.match(self.REGEX_DOMAINNAME, items[1]):
                        matches.append(
                            RuleMatch(tree, message.format(items[1])))

        return matches
Exemplo n.º 22
0
    def match(self, cfn):
        """Check Ec2 Ebs Resource Parameters"""

        matches = list()

        results = cfn.get_resource_properties(
            ['AWS::EC2::Instance', 'BlockDeviceMappings'])
        results.extend(
            cfn.get_resource_properties([
                'AWS::AutoScaling::LaunchConfiguration', 'BlockDeviceMappings'
            ]))
        for result in results:
            path = result['Path']
            for index, properties in enumerate(result['Value']):
                virtual_name = properties.get('VirtualName')
                ebs = properties.get('Ebs')
                if not virtual_name and not ebs:
                    pathmessage = path[:] + [index]
                    message = "Property ebs and virtual_name cannot be used together for {0}"
                    matches.append(
                        RuleMatch(
                            pathmessage,
                            message.format('/'.join(map(str, pathmessage)))))
                elif virtual_name:
                    # switch to regex
                    if not re.match(r'^ephemeral[0-9]$', virtual_name):
                        pathmessage = path[:] + [index, 'VirtualName']
                        message = "Property VirtualName should be of type ephemeral(n) for {0}"
                        matches.append(
                            RuleMatch(
                                pathmessage,
                                message.format('/'.join(map(str,
                                                            pathmessage)))))
                elif ebs:
                    matches.extend(
                        self._checkEbs(cfn, ebs, path[:] + [index, 'Ebs']))
        return matches
Exemplo n.º 23
0
    def match(self, cfn):
        """Check CloudFormation Join"""

        matches = list()

        split_objs = cfn.search_deep_keys('Fn::Split')

        supported_functions = [
            'Fn::Base64', 'Fn::FindInMap', 'Fn::GetAtt', 'Fn::GetAZs',
            'Fn::ImportValue', 'Fn::If', 'Fn::Join', 'Fn::Select', 'Ref'
        ]

        for split_obj in split_objs:
            split_value_obj = split_obj[-1]
            tree = split_obj[:-1]
            if isinstance(split_value_obj, list):
                if len(split_value_obj) == 2:
                    split_delimiter = split_value_obj[0]
                    split_string = split_value_obj[1]
                    if not isinstance(split_delimiter, six.string_types):
                        message = 'Split delimiter has to be of type string for {0}'
                        matches.append(
                            RuleMatch(tree + [0],
                                      message.format('/'.join(map(str,
                                                                  tree)))))
                    if isinstance(split_string, dict):
                        if len(split_string) == 1:
                            for key, _ in split_string.items():
                                if key not in supported_functions:
                                    message = 'Split unsupported function for {0}'
                                    matches.append(
                                        RuleMatch(
                                            tree + [key],
                                            message.format('/'.join(
                                                map(str, tree)))))
                        else:
                            message = 'Split list of singular function or string for {0}'
                            matches.append(
                                RuleMatch(
                                    tree,
                                    message.format('/'.join(map(str, tree)))))
                    elif not isinstance(split_string, six.string_types):
                        message = 'Split has to be of type string or valid function for {0}'
                        matches.append(
                            RuleMatch(tree,
                                      message.format('/'.join(map(str,
                                                                  tree)))))
                else:
                    message = 'Split should be an array of 2 for {0}'
                    matches.append(
                        RuleMatch(tree, message.format('/'.join(map(str,
                                                                    tree)))))
            else:
                message = 'Split should be an array of 2 for {0}'
                matches.append(
                    RuleMatch(tree, message.format('/'.join(map(str, tree)))))
        return matches
    def check_value(self, key, path, res_type):
        """Check resource names for UpdateReplacePolicy"""
        matches = []

        valid_values = [
            'Delete',
            'Retain',
            'Snapshot'
        ]

        valid_snapshot_types = [
            'AWS::EC2::Volume',
            'AWS::ElastiCache::CacheCluster',
            'AWS::ElastiCache::ReplicationGroup',
            'AWS::Neptune::DBCluster',
            'AWS::RDS::DBCluster',
            'AWS::RDS::DBInstance',
            'AWS::Redshift::Cluster'
        ]
        if not isinstance(key, (six.text_type, six.string_types)):
            message = 'UpdateReplacePolicy values should be of string at {0}'
            matches.append(RuleMatch(path, message.format('/'.join(map(str, path)))))
            return matches
        if key not in valid_values:
            message = 'UpdateReplacePolicy should be only one of {0} at {1}'
            matches.append(RuleMatch(
                path,
                message.format(', '.join(map(str, valid_values)),
                               '/'.join(map(str, path)))))
        if key == 'Snapshot' and res_type not in valid_snapshot_types:
            message = 'UpdateReplacePolicy cannot be Snapshot for resources of type {0} at {1}'
            matches.append(RuleMatch(
                path,
                message.format(res_type,
                               '/'.join(map(str, path)))))

        return matches
Exemplo n.º 25
0
    def match(self, cfn):
        """Check CloudFormation ImportValue"""

        matches = list()

        iv_objs = cfn.search_deep_keys('Fn::ImportValue')

        supported_functions = [
            'Fn::Base64',
            'Fn::FindInMap',
            'Fn::If',
            'Fn::Join',
            'Fn::Select',
            'Fn::Split',
            'Fn::Sub',
            'Ref'
        ]

        for iv_obj in iv_objs:
            iv_value = iv_obj[-1]
            tree = iv_obj[:-1]
            if isinstance(iv_value, dict):
                if len(iv_value) == 1:
                    for key, _ in iv_value.items():
                        if key not in supported_functions:
                            message = "ImportValue should be using supported function for {0}"
                            matches.append(RuleMatch(
                                tree, message.format('/'.join(map(str, tree[:-1])))))
                else:
                    message = "ImportValue should have one mapping for {0}"
                    matches.append(RuleMatch(
                        tree, message.format('/'.join(map(str, tree[:-1])))))
            elif not isinstance(iv_value, six.string_types):
                message = "ImportValue should have supported function or string for {0}"
                matches.append(RuleMatch(
                    tree, message.format('/'.join(map(str, tree)))))
        return matches
Exemplo n.º 26
0
    def match(self, cfn):
        """Check CloudFormation VpcId Parameters"""

        matches = list()

        # Build the list of refs
        trees = cfn.search_deep_keys('VpcId')
        parameters = cfn.get_parameter_names()
        allowed_types = [
            'AWS::EC2::VPC::Id',
            'AWS::SSM::Parameter::Value<AWS::EC2::VPC::Id>'
        ]
        fix_param_types = set()
        trees = [x for x in trees if x[0] == 'Resources']
        for tree in trees:
            obj = tree[-1]
            if isinstance(obj, dict):
                if len(obj) == 1:
                    for key in obj:
                        if key == 'Ref':
                            paramname = obj[key]
                            if paramname in parameters:
                                param = cfn.template['Parameters'][paramname]
                                if 'Type' in param:
                                    paramtype = param['Type']
                                    if paramtype not in allowed_types:
                                        fix_param_types.add(paramname)
                else:
                    message = 'Innappropriate map found for vpcid on %s' % (
                        '/'.join(map(str, tree[:-1])))
                    matches.append(RuleMatch(tree[:-1], message))

        for paramname in fix_param_types:
            message = 'Parameter %s should be of type %s' % (paramname, ', '.join(map(str, allowed_types)))
            tree = ['Parameters', paramname]
            matches.append(RuleMatch(tree, message))
        return matches
    def check_sgid_ref(self, value, path, parameters, resources):
        """Check ref for VPC"""
        matches = []

        allowed_types = [
            'AWS::SSM::Parameter::Value<AWS::EC2::SecurityGroup::Id>',
            'AWS::EC2::SecurityGroup::Id',
            'String'
        ]
        if value in parameters:
            parameter_properties = parameters.get(value)
            parameter_type = parameter_properties.get('Type')
            if parameter_type not in allowed_types:
                path_error = ['Parameters', value, 'Type']
                message = 'Security Group Id Parameter should be of type [{0}] for {1}'
                matches.append(
                    RuleMatch(
                        path_error,
                        message.format(
                            ', '.join(map(str, allowed_types)),
                            '/'.join(map(str, path_error)))))
        if value in resources:
            resource = resources.get(value, {})
            resource_type = resource.get('Type', '')
            if resource_type != 'AWS::EC2::SecurityGroup':
                message = 'Security Group Id resources should be of type AWS::EC2::SecurityGroup for {0}'
                matches.append(
                    RuleMatch(path, message.format('/'.join(map(str, path)))))
            else:
                resource_properties = resource.get('Properties', {})
                vpc_property = resource_properties.get('VpcId', None)
                if not vpc_property:
                    message = 'Security Group Id should reference a VPC based AWS::EC2::SecurityGroup for {0}'
                    matches.append(
                        RuleMatch(path, message.format('/'.join(map(str, path)))))

        return matches
Exemplo n.º 28
0
    def match(self, cfn):
        """Check CloudFormation Conditions"""

        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):
                ref_conditions[iftree[-1][0]] = iftree
            else:
                ref_conditions[iftree[-1]] = iftree

        # Get resource's Conditions
        for resource_name, resource_values in cfn.get_resources().items():
            condition = resource_values.get('Condition')
            if isinstance(condition, six.string_types):  # 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, six.text_type, six.string_types)):
                    path = ['Conditions', condtree[-1]]
                    ref_conditions[condtree[-1]] = path

        # Get Output Conditions
        for _, output_values in cfn.template.get('Outputs', {}).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
Exemplo n.º 29
0
    def match(self, cfn):
        """Check CloudFormation Conditions"""

        matches = list()
        ref_conditions = list()

        conditions = cfn.template.get('Conditions', {})
        if 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):
                    ref_conditions.append(iftree[-1][0])
                else:
                    ref_conditions.append(iftree[-1])
            # Get resource's Conditions
            for _, resource_values in cfn.get_resources().items():
                if 'Condition' in resource_values:
                    ref_conditions.append(resource_values['Condition'])

            # 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, six.text_type, six.string_types)):
                        ref_conditions.append(condtree[-1])

            # Get resource's Conditions
            for _, resource_values in cfn.get_resources().items():
                if 'Condition' in resource_values:
                    ref_conditions.append(resource_values['Condition'])

            # Get Output Conditions
            for _, output_values in cfn.template.get('Outputs', {}).items():
                if 'Condition' in output_values:
                    ref_conditions.append(output_values['Condition'])

            # Check if the confitions are used
            for condname, _ in conditions.items():
                if condname not in ref_conditions:
                    message = 'Condition {0} not used'
                    matches.append(RuleMatch(
                        ['Conditions', condname],
                        message.format(condname)
                    ))

        return matches
Exemplo n.º 30
0
    def check(self, properties, exclusions, path):
        """Check itself"""
        matches = list()

        for prop in properties:
            if prop in exclusions:
                for excl_property in exclusions[prop]:
                    if excl_property in properties:
                        message = 'Parameter {0} should NOT exist with {1} for {2}'
                        matches.append(RuleMatch(
                            path + [prop],
                            message.format(excl_property, prop, '/'.join(map(str, path)))
                        ))

        return matches