Example #1
0
    def process(self, resources, event=None):
        client = local_session(self.manager.session_factory).client('ecr')
        for r in resources:
            if self.policy_annotation in r:
                continue
            try:
                r[self.policy_annotation] = json.loads(
                    client.get_lifecycle_policy(
                        repositoryName=r['repositoryName']).get(
                            'lifecyclePolicyText', ''))
            except client.exceptions.LifecyclePolicyNotFoundException:
                r[self.policy_annotation] = {}

        state = self.data.get('state', False)
        matchers = []
        for matcher in self.data.get('match', []):
            vf = ValueFilter(matcher)
            vf.annotate = False
            matchers.append(vf)

        results = []
        for r in resources:
            found = False
            for rule in r[self.policy_annotation].get('rules', []):
                found = True
                for m in matchers:
                    if not m(rule):
                        found = False
            if found and state:
                results.append(r)
            if not found and not state:
                results.append(r)
        return results
Example #2
0
    def process(self, resources, event=None):
        filters = []
        for f in self.data.get('eval_filters', ()):
            vf = ValueFilter(f)
            vf.annotate = False
            filters.append(vf)

        resource_model = self.manager.get_model()
        resource_map = self.get_resource_map(filters, resource_model,
                                             resources)

        # Avoid static/import time dep on boto in filters package
        from c7n.resources.aws import Arn
        results = []
        for arn, r in zip(self.manager.get_arns(resources), resources):
            # many aws provided rules are inconsistent in their
            # treatment of resource ids, some use arns, some use names
            # as identifiers for the same resource type. security
            # hub in particular is bad at consistency.
            rid = None
            if arn in resource_map:
                rid = arn
            elif r[resource_model.id] in resource_map:
                rid = r[resource_model.id]
            if arn == r[resource_model.id] and not rid:
                rid = Arn.parse(arn).resource
                if rid not in resource_map:
                    rid = None
            if rid is None:
                continue
            r[self.annotation_key] = resource_map[rid]
            results.append(r)
        return results
Example #3
0
    def process(self, resources, event=None):
        client = local_session(self.manager.session_factory).client('ecr')
        for r in resources:
            if self.policy_annotation in r:
                continue
            try:
                r[self.policy_annotation] = json.loads(
                    client.get_lifecycle_policy(
                        repositoryName=r['repositoryName']).get(
                            'lifecyclePolicyText', ''))
            except client.exceptions.LifecyclePolicyNotFoundException:
                r[self.policy_annotation] = {}

        state = self.data.get('state', False)
        matchers = []
        for matcher in self.data.get('match', []):
            vf = ValueFilter(matcher)
            vf.annotate = False
            matchers.append(vf)

        results = []
        for r in resources:
            found = False
            for rule in r[self.policy_annotation].get('rules', []):
                found = True
                for m in matchers:
                    if not m(rule):
                        found = False
            if found and state:
                results.append(r)
            if not found and not state:
                results.append(r)
        return results
Example #4
0
 def process_cidrs(self, perm):
     found = False
     if 'IpRanges' in perm and 'Cidr' in self.data:
         match_range = self.data['Cidr']
         match_range['key'] = 'CidrIp'
         vf = ValueFilter(match_range)
         vf.annotate = False
         for ip_range in perm.get('IpRanges', []):
             found = vf(ip_range)
             if found:
                 break
     return found
Example #5
0
    def process_cidrs(self, perm):
        found = False

        if 'IpRanges' in perm and 'Cidr' in self.data:
            match_range = self.data['Cidr']
            match_range['key'] = 'CidrIp'
            vf = ValueFilter(match_range)
            vf.annotate = False
            for ip_range in perm.get('IpRanges', []):
                found = vf(ip_range)
                if found:
                    break
        return found
Example #6
0
    def process(self, resources, event=None):
        self.vfilters = []
        fattrs = list(sorted(self.attrs.intersection(self.data.keys())))

        for f in fattrs:
            fv = self.data.get(f)
            if isinstance(fv, dict):
                fv['key'] = f
            else:
                fv = {f: fv}
            vf = ValueFilter(fv)
            vf.annotate = False
            self.vfilters.append(vf)
        return super(SGPermission, self).process(resources, event)
Example #7
0
    def process(self, resources, event=None):
        self.vfilters = []
        fattrs = list(sorted(self.attrs.intersection(self.data.keys())))

        for f in fattrs:
            fv = self.data.get(f)
            if isinstance(fv, dict):
                fv['key'] = f
            else:
                fv = {f: fv}
            vf = ValueFilter(fv)
            vf.annotate = False
            self.vfilters.append(vf)
        return super(SGPermission, self).process(resources, event)
Example #8
0
    def match(self, info):
        if info is None:
            return False
        k = self.data.get('key')
        if '.' not in k:
            vf = ValueFilter(self.data)
            vf.annotate = False
            return vf(info)

        prefix, sk = k.split('.', 1)
        vf = ValueFilter(self.matcher_config)
        vf.annotate = False
        for v in info.get(prefix, ()):
            if vf.match(v):
                return True
Example #9
0
    def process(self, resources, event=None):
        filters = []
        for f in self.data.get('eval_filters', ()):
            vf = ValueFilter(f)
            vf.annotate = False
            filters.append(vf)

        resource_model = self.manager.get_model()
        resource_map = self.get_resource_map(filters, resource_model, resources)

        results = []
        for r in resources:
            if r[resource_model.id] not in resource_map:
                continue
            r[self.annotation_key] = resource_map[r[resource_model.id]]
            results.append(r)
        return results
Example #10
0
    def process(self, resources, event=None):
        filters = []
        for f in self.data.get('eval_filters', ()):
            vf = ValueFilter(f)
            vf.annotate = False
            filters.append(vf)

        resource_model = self.manager.get_model()
        resource_map = self.get_resource_map(filters, resource_model, resources)

        results = []
        for r in resources:
            if r[resource_model.id] not in resource_map:
                continue
            r[self.annotation_key] = resource_map[r[resource_model.id]]
            results.append(r)
        return results
Example #11
0
class AutorecoverAlarm(BaseAction, StateTransitionFilter):
    """Adds a cloudwatch metric alarm to recover an EC2 instance.

    This action takes effect on instances that are NOT part
    of an ASG.

    :Example:

    .. code-block: yaml

        policies:
          - name: ec2-autorecover-alarm
            resource: ec2
            filters:
              - singleton
          actions:
            - autorecover-alarm

    https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-recover.html
    """

    schema = type_schema('autorecover-alarm')
    permissions = ('ec2:DescribeInstanceStatus', 'ec2:RecoverInstances',
                   'ec2:DescribeInstanceRecoveryAttribute')

    valid_origin_states = ('running', 'stopped', 'pending', 'stopping')
    filter_asg_membership = ValueFilter({
        'key': 'tag:aws:autoscaling:groupName',
        'value': 'empty'
    }).validate()

    def process(self, instances):
        instances = self.filter_asg_membership.process(
            self.filter_instance_state(instances))
        if not len(instances):
            return
        client = utils.local_session(
            self.manager.session_factory).client('cloudwatch')
        for i in instances:
            client.put_metric_alarm(
                AlarmName='recover-{}'.format(i['InstanceId']),
                AlarmDescription='Auto Recover {}'.format(i['InstanceId']),
                ActionsEnabled=True,
                AlarmActions=[
                    'arn:aws:automate:{}:ec2:recover'.format(
                        i['Placement']['AvailabilityZone'][:-1])
                ],
                MetricName='StatusCheckFailed_System',
                Namespace='AWS/EC2',
                Statistic='Minimum',
                Dimensions=[{
                    'Name': 'InstanceId',
                    'Value': i['InstanceId']
                }],
                Period=60,
                EvaluationPeriods=2,
                Threshold=0,
                ComparisonOperator='GreaterThanThreshold')
Example #12
0
    def match(self, resource, info):
        if info is None:
            return False
        k = self.data.get('key')
        if '.' not in k:
            vf = ValueFilter(self.data)
            vf.annotate = False
            return vf(info)

        # access key matching
        prefix, sk = k.split('.', 1)
        vf = ValueFilter(self.matcher_config)
        vf.annotate = False

        # annotation merging with previous respecting block operators
        k_matched = []
        for v in info.get(prefix, ()):
            if vf.match(v):
                k_matched.append(v)

        for k in k_matched:
            k['c7n:match-type'] = 'credential'

        self.merge_annotation(resource, self.matched_annotation_key, k_matched)
        return bool(k_matched)
Example #13
0
    def process_cidrs(self, perm):
        found = None
        if 'Cidr' in self.data:
            ip_perms = perm.get('IpRanges', [])
            if not ip_perms:
                return False

            match_range = self.data['Cidr']
            match_range['key'] = 'CidrIp'
            vf = ValueFilter(match_range)
            vf.annotate = False
            for ip_range in ip_perms:
                found = vf(ip_range)
                if found:
                    break
                else:
                    found = False
        return found
Example #14
0
    def process_cidrs(self, perm):
        found = None
        if 'Cidr' in self.data:
            ip_perms = perm.get('IpRanges', [])
            if not ip_perms:
                return False

            match_range = self.data['Cidr']
            match_range['key'] = 'CidrIp'
            vf = ValueFilter(match_range)
            vf.annotate = False
            for ip_range in ip_perms:
                found = vf(ip_range)
                if found:
                    break
                else:
                    found = False
        return found
Example #15
0
 def process(self, resources, event=None):
     client = local_session(self.manager.session_factory).client('es')
     results = []
     for r in resources:
         if self.annotation_key not in r:
             r[self.annotation_key] = {}
             try:
                 if "inbound" in self.data:
                     inbound = self.manager.retry(
                         client.describe_inbound_cross_cluster_search_connections,
                         Filters=[{'Name': 'destination-domain-info.domain-name',
                                 'Values': [r['DomainName']]}])
                     inbound.pop('ResponseMetadata')
                     r[self.annotation_key]["inbound"] = inbound
                 if "outbound" in self.data:
                     outbound = self.manager.retry(
                         client.describe_outbound_cross_cluster_search_connections,
                         Filters=[{'Name': 'source-domain-info.domain-name',
                                 'Values': [r['DomainName']]}])
                     outbound.pop('ResponseMetadata')
                     r[self.annotation_key]["outbound"] = outbound
             except client.exceptions.ResourceNotFoundExecption:
                 continue
         matchFound = False
         r[self.matched_key] = {}
         for direction in r[self.annotation_key]:
             matcher = self.data.get(direction)
             valueFilter = ValueFilter(matcher)
             valueFilter.annotate = False
             matched = []
             for conn in r[self.annotation_key][direction]['CrossClusterSearchConnections']:
                 if valueFilter(conn):
                     matched.append(conn)
                     matchFound = True
             r[self.matched_key][direction] = matched
         if matchFound:
             results.append(r)
     return results
Example #16
0
    def match(self, info):
        if info is None:
            return False
        k = self.data.get('key')
        if '.' not in k:
            vf = ValueFilter(self.data)
            vf.annotate = False
            return vf(info)

        prefix, sk = k.split('.', 1)
        vf = ValueFilter(self.matcher_config)
        vf.annotate = False
        for v in info.get(prefix, ()):
            if vf.match(v):
                return True
Example #17
0
class SingletonFilter(Filter, StateTransitionFilter):
    """EC2 instances without autoscaling or a recover alarm

    Filters EC2 instances that are not members of an autoscaling group
    and do not have Cloudwatch recover alarms.

    :Example:

    .. code-block: yaml

        policies:
          - name: ec2-recover-instances
            resource: ec2
            filters:
              - singleton
            actions:
              - type: tag
                key: problem
                value: instance is not resilient

    https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-recover.html
    """

    schema = type_schema('singleton')

    permissions = ('cloudwatch:DescribeAlarmsForMetric', )

    valid_origin_states = ('running', 'stopped', 'pending', 'stopping')

    in_asg = ValueFilter({
        'key': 'tag:aws:autoscaling:groupName',
        'value': 'not-null'
    }).validate()

    def process(self, instances, event=None):
        return super(SingletonFilter,
                     self).process(self.filter_instance_state(instances))

    def __call__(self, i):
        if self.in_asg(i):
            return False
        else:
            return not self.has_recover_alarm(i)

    def has_recover_alarm(self, i):
        client = utils.local_session(
            self.manager.session_factory).client('cloudwatch')
        alarms = client.describe_alarms_for_metric(
            MetricName='StatusCheckFailed_System',
            Namespace='AWS/EC2',
            Dimensions=[{
                'Name': 'InstanceId',
                'Value': i['InstanceId']
            }])

        for i in alarms['MetricAlarms']:
            for a in i['AlarmActions']:
                if (a.startswith('arn:aws:automate:')
                        and a.endswith(':ec2:recover')):
                    return True

        return False