def _process_resource_set(self, resources, event=None):
        client = self.manager.get_client(
            'azure.mgmt.resource.locks.ManagementLockClient')
        result = []
        for resource in resources:
            if resource.get('resourceGroup') is None:
                locks = [
                    r.serialize(True) for r in client.management_locks.
                    list_at_resource_group_level(resource['name'])
                ]
            else:
                locks = [
                    r.serialize(True)
                    for r in client.management_locks.list_at_resource_level(
                        resource['resourceGroup'],
                        ResourceIdParser.get_namespace(resource['id']),
                        ResourceIdParser.get_resource_name(
                            resource.get('c7n:parent-id')) or '',
                        ResourceIdParser.get_resource_type(resource['id']),
                        resource['name'])
                ]

            if StringUtils.equal('Absent', self.lock_type) and not locks:
                result.append(resource)
            else:
                for lock in locks:
                    if StringUtils.equal('Any', self.lock_type) or \
                            StringUtils.equal(lock['properties']['level'], self.lock_type):
                        result.append(resource)
                        break

        return result
Example #2
0
    def _process_resource_set(self, resources, event=None):
        client = self.manager.get_client()
        result = []
        for resource in resources:
            database_name = resource['name']
            if StringUtils.equal(database_name, "master"):
                continue

            if 'c7n:data-masking-policy' not in resource:
                server_id = resource[ChildTypeInfo.parent_key]
                server_name = ResourceIdParser.get_resource_name(server_id)

                dmr = client.data_masking_policies.get(
                    resource['resourceGroup'], server_name, database_name)

                if dmr:
                    resource['c7n:data-masking-policy'] = dmr.serialize(
                        True).get('properties', {})
                else:
                    resource['c7n:data-masking-policy'] = {}

            required_status = 'Enabled' if self.enabled else 'Disabled'

            if StringUtils.equal(
                    resource['c7n:data-masking-policy'].get(
                        'dataMaskingState'), required_status):
                result.append(resource)

        return result
Example #3
0
    def _get_tag_value_from_event(self, event):
        principal_role = self.principal_role_jmes_path.search(event)
        principal_type = self.principal_type_jmes_path.search(event)
        user = None
        # The Subscription Admins role does not have a principal type
        if StringUtils.equal(principal_role, 'Subscription Admin'):
            user = self.service_admin_jmes_path.search(event)
        # ServicePrincipal type
        elif StringUtils.equal(principal_type, 'ServicePrincipal'):
            user = self.sp_jmes_path.search(event)

        if not user:
            known_claims = {
                'upn': self.upn_jmes_path.search(event),
                'name': self.name_jmes_path.search(event)
            }
            if known_claims[self.default_claim]:
                user = known_claims[self.default_claim]
            elif self.default_claim == 'upn' and known_claims['name']:
                user = known_claims['name']
            elif self.default_claim == 'name' and known_claims['upn']:
                user = known_claims['upn']

        # Last effort search for an email address in the claims
        if not user:
            claims = event['data'].get('claims', [])
            for c in claims:
                value = claims[c]
                if self._is_email(value):
                    user = value
                    break

        if not user:
            self.log.error('Principal could not be determined.')
        return user
Example #4
0
    def _get_user_from_event(self, event):
        principal_role = self.principal_role_jmes_path.search(event)
        principal_type = self.principal_type_jmes_path.search(event)
        user = None
        # The Subscription Admins role does not have a principal type
        if StringUtils.equal(principal_role, 'Subscription Admin'):
            user = self.service_admin_jmes_path.search(event)
        # ServicePrincipal type
        elif StringUtils.equal(principal_type, 'ServicePrincipal'):
            user = self.sp_jmes_path.search(event)

        # Other types and main fallback (e.g. User, Office 365 Groups, and Security Groups)
        if not user and self.upn_jmes_path.search(event):
            user = self.upn_jmes_path.search(event)

        # Last effort search for an email address in the claims
        if not user:
            claims = event['data']['claims']
            for c in claims:
                value = claims[c]
                if self._is_email(value):
                    user = value

        if not user:
            self.log.error('Principal could not be determined.')

        return user
Example #5
0
    def _get_tag_value_from_event(self, event):
        principal_role = self.principal_role_jmes_path.search(event)
        principal_type = self.principal_type_jmes_path.search(event)
        user = None
        # The Subscription Admins role does not have a principal type
        if StringUtils.equal(principal_role, 'Subscription Admin'):
            user = self.service_admin_jmes_path.search(event)
        # ServicePrincipal type
        elif StringUtils.equal(principal_type, 'ServicePrincipal'):
            user = self.sp_jmes_path.search(event)

        # Other types and main fallback (e.g. User, Office 365 Groups, and Security Groups)
        if not user and self.upn_jmes_path.search(event):
            user = self.upn_jmes_path.search(event)

        # Last effort search for an email address in the claims
        if not user:
            claims = event['data']['claims']
            for c in claims:
                value = claims[c]
                if self._is_email(value):
                    user = value

        if not user:
            self.log.error('Principal could not be determined.')

        return user
Example #6
0
    def _get_user_from_event(self, event):
        principal_role = self.principal_role_jmes_path.search(event)
        principal_type = self.principal_type_jmes_path.search(event)

        # The Subscription Admins role does not have a principal type
        if StringUtils.equal(principal_role, 'Subscription Admin'):
            return self.service_admin_jmes_path.search(event)
        # ServicePrincipal type
        elif StringUtils.equal(principal_type, 'ServicePrincipal'):
            return self.sp_jmes_path.search(event)
        # Other types (e.g. User, Office 365 Groups, and Security Groups)
        elif self.upn_jmes_path.search(event):
            return self.upn_jmes_path.search(event)
        else:
            self.log.error('Principal could not be determined.')
    def is_match(self, security_rule):
        if not StringUtils.equal(self.direction_key,
                                 security_rule['properties']['direction']):
            return False
        ranges_match = self.is_ranges_match(security_rule)
        protocol_match = (self.ip_protocol is None) or \
                         (StringUtils.equal(self.ip_protocol,
                                            security_rule['properties']['protocol']))

        if self.access is not None:
            access_match = StringUtils.equal(
                self.access, security_rule['properties']['access'])
            return self.match_op([ranges_match, protocol_match, access_match])
        else:
            return self.match_op([ranges_match, protocol_match])
Example #8
0
    def _process_resource_set(self, resources, event=None):
        client = self.manager.get_client()
        result = []
        for resource in resources:
            if 'transparentDataEncryption' not in resource['properties']:
                server_id = resource[ChildTypeInfo.parent_key]
                server_name = ResourceIdParser.get_resource_name(server_id)

                tde = client.transparent_data_encryptions.get(
                    resource['resourceGroup'],
                    server_name,
                    resource['name'],
                    "current")

                resource['properties']['transparentDataEncryption'] = \
                    tde.serialize(True).get('properties', {})

            required_status = 'Enabled' if self.enabled else 'Disabled'

            if StringUtils.equal(
                    resource['properties']['transparentDataEncryption'].get('status'),
                    required_status):
                result.append(resource)

        return result
Example #9
0
    def resource_api_version(self, resource_id):
        """ latest non-preview api version for resource """

        namespace = ResourceIdParser.get_namespace(resource_id)
        resource_type = ResourceIdParser.get_resource_type(resource_id)

        cache_id = namespace + resource_type

        if cache_id in self._provider_cache:
            return self._provider_cache[cache_id]

        resource_client = self.client(
            'azure.mgmt.resource.ResourceManagementClient')
        provider = resource_client.providers.get(namespace)

        # The api version may be directly provided
        if not provider.resource_types and resource_client.providers.api_version:
            return resource_client.providers.api_version

        rt = next((t for t in provider.resource_types
                   if StringUtils.equal(t.resource_type, resource_type)), None)

        if rt and rt.api_versions:
            versions = [
                v for v in rt.api_versions if 'preview' not in v.lower()
            ]
            api_version = versions[0] if versions else rt.api_versions[0]
            self._provider_cache[cache_id] = api_version
            return api_version
Example #10
0
    def _provision(self, params):
        rg_unit = ResourceGroupUnit()
        rg_unit.provision_if_not_exists({'name': params['resource_group_name'],
                                         'location': params['location']})

        plan_params = AppServicePlan(
            app_service_plan_name=params['name'],
            location=params['location'],
            sku=SkuDescription(
                name=params['sku_name'],
                capacity=1,
                tier=params['sku_tier']),
            kind='linux',
            target_worker_size_id=0,
            reserved=True)

        plan = self.client.app_service_plans.begin_create_or_update(params['resource_group_name'],
                                                                    params['name'],
                                                                    plan_params).result()

        # Deploy default autoscale rule for dedicated plans if required by the policy
        autoscale_params = copy.deepcopy(params.get('auto_scale', {}))
        if bool(autoscale_params.get('enabled')) and \
           not StringUtils.equal(plan.sku, 'dynamic'):
            autoscale_params['name'] = 'autoscale'
            autoscale_params['resource_group_name'] = params['resource_group_name']
            autoscale_params['service_plan_id'] = plan.id
            autoscale_params['location'] = plan.location

            ac_unit = AutoScaleUnit()
            ac_unit.provision(autoscale_params)

        return plan
Example #11
0
    def process(self, network_security_groups):

        ip_protocol = self.data.get(IP_PROTOCOL, '*')
        direction = self.data[DIRECTION]
        prefix = self.data.get(PREFIX, 'c7n-policy-')
        # Build a list of ports described in the action.
        ports = PortsRangeHelper.get_ports_set_from_string(self.data.get(PORTS, '0-65535'))
        except_ports = PortsRangeHelper.get_ports_set_from_string(self.data.get(EXCEPT_PORTS, ''))
        self.action_ports = ports.difference(except_ports)

        for nsg in network_security_groups:
            nsg_name = nsg['name']
            resource_group = nsg['resourceGroup']

            # Get list of ports to Deny or Allow access to.
            ports = self._build_ports_strings(nsg, direction, ip_protocol)
            if not ports:
                # If its empty, it means NSG already blocks/allows access to all ports,
                # no need to change.
                self.manager.log.info("Network security group %s satisfies provided "
                                      "ports configuration, no actions scheduled.", nsg_name)
                continue

            rules = nsg['properties']['securityRules']
            rules = sorted(rules, key=lambda k: k['properties']['priority'])
            rules = [r for r in rules
                     if StringUtils.equal(r['properties']['direction'], direction)]
            lowest_priority = rules[0]['properties']['priority'] if len(rules) > 0 else 4096

            # Create new top-priority rule to allow/block ports from the action.
            rule_name = prefix + str(uuid.uuid1())
            new_rule = {
                'name': rule_name,
                'properties': {
                    'access': self.access_action,
                    'destinationAddressPrefix': '*',
                    'destinationPortRanges': ports,
                    'direction': self.data[DIRECTION],
                    'priority': lowest_priority - PRIORITY_STEP,
                    'protocol': ip_protocol,
                    'sourceAddressPrefix': '*',
                    'sourcePortRange': '*',
                }
            }
            self.manager.log.info("NSG %s. Creating new rule to %s access for ports %s",
                                  nsg_name, self.access_action, ports)

            try:
                self.manager.get_client().security_rules.create_or_update(
                    resource_group,
                    nsg_name,
                    rule_name,
                    new_rule
                )
            except CloudError as e:
                self.manager.log.error('Failed to create or update security rule for %s NSG.',
                                       nsg_name)
                self.manager.log.error(e)
    def _build_ports_strings(self, nsg, direction_key, ip_protocol):
        nsg_ports = PortsRangeHelper.build_ports_dict(nsg, direction_key, ip_protocol)

        IsAllowed = StringUtils.equal(self.access_action, ALLOW_OPERATION)

        # Find ports with different access level from NSG and this action
        diff_ports = sorted([p for p in self.action_ports if nsg_ports.get(p, False) != IsAllowed])

        return PortsRangeHelper.get_ports_strings_from_list(diff_ports)
    def process(self, network_security_groups):

        ip_protocol = self.data.get(IP_PROTOCOL, '*')
        direction = self.data[DIRECTION]
        # Build a list of ports described in the action.
        ports = PortsRangeHelper.get_ports_set_from_string(self.data.get(PORTS, '0-65535'))
        except_ports = PortsRangeHelper.get_ports_set_from_string(self.data.get(EXCEPT_PORTS, ''))
        self.action_ports = ports.difference(except_ports)

        for nsg in network_security_groups:
            nsg_name = nsg['name']
            resource_group = nsg['resourceGroup']

            # Get list of ports to Deny or Allow access to.
            ports = self._build_ports_strings(nsg, direction, ip_protocol)
            if not ports:
                # If its empty, it means NSG already blocks/allows access to all ports,
                # no need to change.
                self.manager.log.info("Network security group %s satisfies provided "
                                      "ports configuration, no actions scheduled.", nsg_name)
                continue

            rules = nsg['properties']['securityRules']
            rules = sorted(rules, key=lambda k: k['properties']['priority'])
            rules = [r for r in rules
                     if StringUtils.equal(r['properties']['direction'], direction)]
            lowest_priority = rules[0]['properties']['priority'] if len(rules) > 0 else 4096

            # Create new top-priority rule to allow/block ports from the action.
            rule_name = 'c7n-policy-' + str(uuid.uuid1())
            new_rule = {
                'name': rule_name,
                'properties': {
                    'access': self.access_action,
                    'destinationAddressPrefix': '*',
                    'destinationPortRanges': ports,
                    'direction': self.data[DIRECTION],
                    'priority': lowest_priority - PRIORITY_STEP,
                    'protocol': ip_protocol,
                    'sourceAddressPrefix': '*',
                    'sourcePortRange': '*',
                }
            }
            self.manager.log.info("NSG %s. Creating new rule to %s access for ports %s",
                                  nsg_name, self.access_action, ports)

            try:
                self.manager.get_client().security_rules.create_or_update(
                    resource_group,
                    nsg_name,
                    rule_name,
                    new_rule
                )
            except CloudError as e:
                self.manager.log.error('Failed to create or update security rule for %s NSG.',
                                       nsg_name)
                self.manager.log.error(e)
    def process(self, network_security_groups, event=None):
        # Get variables
        self.ip_protocol = self.data.get(IP_PROTOCOL, '*')
        self.IsAllowed = StringUtils.equal(self.data.get(ACCESS), ALLOW_OPERATION)
        self.match = self.data.get(MATCH, 'all')

        # Calculate ports from the settings:
        #   If ports not specified -- assuming the entire range
        #   If except_ports not specifed -- nothing
        ports_set = PortsRangeHelper.get_ports_set_from_string(self.data.get(PORTS, '0-65535'))
        except_set = PortsRangeHelper.get_ports_set_from_string(self.data.get(EXCEPT_PORTS, ''))
        self.ports = ports_set.difference(except_set)

        nsgs = [nsg for nsg in network_security_groups if self._check_nsg(nsg)]
        return nsgs
Example #15
0
    def resource_api_version(self, resource_id):
        """ latest non-preview api version for resource """

        namespace = ResourceIdParser.get_namespace(resource_id)
        resource_type = ResourceIdParser.get_resource_type(resource_id)

        if resource_type in self._provider_cache:
            return self._provider_cache[resource_type]

        resource_client = self.client('azure.mgmt.resource.ResourceManagementClient')
        provider = resource_client.providers.get(namespace)

        rt = next((t for t in provider.resource_types
            if StringUtils.equal(t.resource_type, resource_type.split('/')[-1])), None)

        if rt and rt.api_versions:
            versions = [v for v in rt.api_versions if 'preview' not in v.lower()]
            api_version = versions[0] if versions else rt.api_versions[0]
            self._provider_cache[resource_type] = api_version
            return api_version
Example #16
0
    def resource_api_version(self, resource_id):
        """ latest non-preview api version for resource """

        namespace = ResourceIdParser.get_namespace(resource_id)
        resource_type = ResourceIdParser.get_resource_type(resource_id)

        cache_id = namespace + resource_type

        if cache_id in self._provider_cache:
            return self._provider_cache[cache_id]

        resource_client = self.client('azure.mgmt.resource.ResourceManagementClient')
        provider = resource_client.providers.get(namespace)

        rt = next((t for t in provider.resource_types
            if StringUtils.equal(t.resource_type, resource_type)), None)

        if rt and rt.api_versions:
            versions = [v for v in rt.api_versions if 'preview' not in v.lower()]
            api_version = versions[0] if versions else rt.api_versions[0]
            self._provider_cache[cache_id] = api_version
            return api_version
    def test_string_utils_equal(self):
        # Case insensitive matches
        self.assertTrue(StringUtils.equal("FOO", "foo"))
        self.assertTrue(StringUtils.equal("fOo", "FoO"))
        self.assertTrue(StringUtils.equal("ABCDEFGH", "abcdefgh"))
        self.assertFalse(StringUtils.equal("Foo", "Bar"))

        # Case sensitive matches
        self.assertFalse(StringUtils.equal("Foo", "foo", False))
        self.assertTrue(StringUtils.equal("foo", "foo", False))
        self.assertTrue(StringUtils.equal("fOo", "fOo", False))
        self.assertFalse(StringUtils.equal("Foo", "Bar"))

        # Strip whitespace matches
        self.assertTrue(StringUtils.equal(" Foo ", "foo"))
        self.assertTrue(StringUtils.equal("Foo", " foo "))
        self.assertTrue(StringUtils.equal(" Foo ", "Foo", False))
        self.assertTrue(StringUtils.equal("Foo", " Foo ", False))

        # Returns false for non string types
        self.assertFalse(StringUtils.equal(1, "foo"))
        self.assertFalse(StringUtils.equal("foo", 1))
        self.assertFalse(StringUtils.equal(True, False))
 def is_consumption_plan(function_params):
     return StringUtils.equal(function_params.service_plan['sku_tier'], 'dynamic')
Example #19
0
    def test_string_utils_equal(self):
        # Case insensitive matches
        self.assertTrue(StringUtils.equal("FOO", "foo"))
        self.assertTrue(StringUtils.equal("fOo", "FoO"))
        self.assertTrue(StringUtils.equal("ABCDEFGH", "abcdefgh"))
        self.assertFalse(StringUtils.equal("Foo", "Bar"))

        # Case sensitive matches
        self.assertFalse(StringUtils.equal("Foo", "foo", False))
        self.assertTrue(StringUtils.equal("foo", "foo", False))
        self.assertTrue(StringUtils.equal("fOo", "fOo", False))
        self.assertFalse(StringUtils.equal("Foo", "Bar"))

        # Strip whitespace matches
        self.assertTrue(StringUtils.equal(" Foo ", "foo"))
        self.assertTrue(StringUtils.equal("Foo", " foo "))
        self.assertTrue(StringUtils.equal(" Foo ", "Foo", False))
        self.assertTrue(StringUtils.equal("Foo", " Foo ", False))

        # Returns false for non string types
        self.assertFalse(StringUtils.equal(1, "foo"))
        self.assertFalse(StringUtils.equal("foo", 1))
        self.assertFalse(StringUtils.equal(True, False))
Example #20
0
 def is_consumption_plan(function_params):
     return StringUtils.equal(function_params.service_plan['sku_tier'],
                              'dynamic')
Example #21
0
    def process_resource(self, resource, event_item=None):
        # if the auto-tag-user policy set update to False (or it's unset) then we
        # will skip writing their UserName tag and not overwrite pre-existing values
        if not self.should_update and resource.get('tags', {}).get(
                self.tag_key, None):
            return

        user = self.default_user
        if event_item:
            principal_role = self.principal_role_jmes_path.search(event_item)
            principal_type = self.principal_type_jmes_path.search(event_item)

            # The Subscription Admins role does not have a principal type
            if StringUtils.equal(principal_role, 'Subscription Admin'):
                user = self.service_admin_jmes_path.search(event_item) or user
            # ServicePrincipal type
            elif StringUtils.equal(principal_type, 'ServicePrincipal'):
                user = self.sp_jmes_path.search(event_item) or user
            # Other types (e.g. User, Office 365 Groups, and Security Groups)
            elif self.upn_jmes_path.search(event_item):
                user = self.upn_jmes_path.search(event_item)
            else:
                self.log.error('Principal could not be determined.')
        else:
            # Calculate start time
            delta_days = self.data.get('days', self.max_query_days)
            start_time = utcnow() - datetime.timedelta(days=delta_days)

            # resource group type
            if self.manager.type == 'resourcegroup':
                resource_type = "Microsoft.Resources/subscriptions/resourcegroups"
                query_filter = " and ".join([
                    "eventTimestamp ge '%s'" % start_time,
                    "resourceGroupName eq '%s'" % resource['name'],
                    "eventChannels eq 'Operation'"
                ])
            # other Azure resources
            else:
                resource_type = resource['type']
                query_filter = " and ".join([
                    "eventTimestamp ge '%s'" % start_time,
                    "resourceUri eq '%s'" % resource['id'],
                    "eventChannels eq 'Operation'"
                ])

            # fetch activity logs
            logs = self.client.activity_logs.list(filter=query_filter,
                                                  select=self.query_select)

            # get the user who issued the first operation
            operation_name = "%s/write" % resource_type
            first_op = self.get_first_operation(logs, operation_name)
            if first_op is not None:
                user = first_op.caller

        # issue tag action to label user
        try:
            TagHelper.add_tags(self, resource, {self.tag_key: user})
        except CloudError as e:
            # resources can be locked
            if e.inner_exception.error == 'ScopeLocked':
                pass