Пример #1
0
class EffectiveRouteTableFilter(ValueFilter):
    """Filters network interfaces by the Effective Route Table

    :example:

    This policy will get Network Interfaces that have VirtualNetworkGateway and VNet hops.

    .. code-block:: yaml

        policies:
          - name: virtual-network-gateway-hop
            resource: azure.networkinterface
            filters:
              - type: effective-route-table
                key: routes.value[?source == 'User'].nextHopType
                op: difference
                value:
                  - Internet
                  - None
                  - VirtualAppliance
    """
    schema = type_schema('effective-route-table', rinherit=ValueFilter.schema)
    schema_alias = False

    def process(self, resources, event=None):

        resources, _ = ThreadHelper.execute_in_parallel(
            resources=resources,
            event=event,
            execution_method=self._process_resource_set,
            executor_factory=self.executor_factory,
            log=log,
            max_workers=max_workers,
            chunk_size=chunk_size)
        return resources

    def _process_resource_set(self, resources, event):
        client = self.manager.get_client()
        matched = []

        for resource in resources:
            try:
                if 'routes' not in resource:
                    route_table = (
                        client.network_interfaces.get_effective_route_table(
                            resource['resourceGroup'],
                            resource['name']).result())

                    resource['routes'] = route_table.serialize()
                    filtered_effective_route_table = super(EffectiveRouteTableFilter, self)\
                        .process([resource], event)

                    if filtered_effective_route_table:
                        matched.append(resource)

            except Exception as error:
                log.warning(error)

        return matched
Пример #2
0
class VmRestartAction(BaseAction):

    schema = type_schema('restart')

    def process(self, vms):
        client = self.manager.get_client()
        for vm in vms:
            client.virtual_machines.restart(vm['resourceGroup'], vm['name'])
Пример #3
0
class VmStopAction(BaseAction):

    schema = type_schema('stop')

    def process(self, vms):
        client = self.manager.get_client()
        for vm in vms:
            client.virtual_machines.deallocate(vm['resourceGroup'], vm['name'])
Пример #4
0
class VmPowerOffAction(BaseAction):

    schema = type_schema('poweroff')

    def process(self, vms):
        client = self.manager.get_client()
        for vm in vms:
            client.virtual_machines.power_off(vm['resourceGroup'], vm['name'])
Пример #5
0
class Delete(AzureBaseAction):
    schema = type_schema('delete')

    def process_resource_set(self, resources):
        client = self.manager.get_client()
        for resource in resources:
            client.event_subscriptions.delete(resource['properties']['topic'],
                                              resource['name'])
Пример #6
0
class VmPowerOffAction(AzureBaseAction):

    schema = type_schema('poweroff')

    def _prepare_processing(self,):
        self.client = self.manager.get_client()

    def _process_resource(self, resource):
        self.client.virtual_machines.power_off(resource['resourceGroup'], resource['name'])
Пример #7
0
class VmStopAction(AzureBaseAction):

    schema = type_schema('stop')

    def _prepare_processing(self,):
        self.client = self.manager.get_client()

    def _process_resource(self, resource):
        self.client.virtual_machines.deallocate(resource['resourceGroup'], resource['name'])
Пример #8
0
class VmRestartAction(AzureBaseAction):

    schema = type_schema('restart')

    def _prepare_processing(self,):
        self.client = self.manager.get_client()

    def _process_resource(self, resource):
        self.client.virtual_machines.restart(resource['resourceGroup'], resource['name'])
Пример #9
0
class Delete(AzureBaseAction):
    schema = type_schema('delete')

    def _prepare_processing(self, ):
        self.client = self.manager.get_client()

    def _process_resource(self, resource):
        self.client.event_subscriptions.delete(resource['properties']['topic'],
                                               resource['name'])
Пример #10
0
class InstanceViewFilter(ValueFilter):
    schema = type_schema('instance-view', rinherit=ValueFilter.schema)

    def __call__(self, i):
        if 'instanceView' not in i:
            client = self.manager.get_client()
            instance = client.virtual_machines.get(i['resourceGroup'], i['name'], expand='instanceview').instance_view
            i['instanceView'] = instance.serialize()

        return super(InstanceViewFilter, self).__call__(i['instanceView'])
Пример #11
0
class ConfigurationFilter(ValueFilter):
    schema = type_schema('configuration', rinherit=ValueFilter.schema)

    def __call__(self, i):
        if 'c7n:configuration' not in i:
            client = self.manager.get_client().web_apps
            instance = (client.get_configuration(i['resourceGroup'],
                                                 i['name']))
            i['c7n:configuration'] = instance.serialize(
                keep_readonly=True)['properties']

        return super(ConfigurationFilter,
                     self).__call__(i['c7n:configuration'])
Пример #12
0
class VmStartAction(BaseAction):

    schema = type_schema('start')

    def __init__(self, data=None, manager=None, log_dir=None):
        super(VmStartAction, self).__init__(data, manager, log_dir)
        self.client = self.manager.get_client()

    def start(self, resource_group, vm_name):
        self.client.virtual_machines.start(resource_group, vm_name)

    def process(self, vms):
        for vm in vms:
            self.start(vm['resourceGroup'], vm['name'])
Пример #13
0
class Delete(BaseAction):
    schema = type_schema('delete')

    def process(self, resources, event=None):
        return ThreadHelper.execute_in_parallel(
            resources=resources,
            execution_method=self.process_resource_set,
            executor_factory=self.executor_factory,
            log=self.log)

    def process_resource_set(self, resources):
        client = self.manager.get_client()
        for resource in resources:
            client.event_subscriptions.delete(resource['properties']['topic'],
                                              resource['name'])
Пример #14
0
class StorageSetNetworkRulesAction(AzureBaseAction):

    schema = type_schema(
        'set-network-rules',
        required=['default-action'],
        **{
            'default-action': {'enum': ['Allow', 'Deny']},
            'bypass': {'type': 'array', 'items': {'enum': ['AzureServices', 'Logging', 'Metrics']}},
            'ip-rules': {
                'type': 'array',
                'items': {'ip-address-or-range': {'type': 'string'}}
            },
            'virtual-network-rules': {
                'type': 'array',
                'items': {'virtual-network-resource-id': {'type': 'string'}}
            }
        }
    )

    def _prepare_processing(self,):
        self.client = self.manager.get_client()

    def _process_resource(self, resource):
        rule_set = NetworkRuleSet(default_action=self.data['default-action'])

        if 'ip-rules' in self.data:
            rule_set.ip_rules = [
                IPRule(
                    ip_address_or_range=r['ip-address-or-range'],
                    action='Allow')  # 'Allow' is the only allowed action
                for r in self.data['ip-rules']]

        if 'virtual-network-rules' in self.data:
            rule_set.virtual_network_rules = [
                VirtualNetworkRule(
                    virtual_network_resource_id=r['virtual-network-resource-id'],
                    action='Allow')  # 'Allow' is the only allowed action
                for r in self.data['virtual-network-rules']]

        if len(self.data.get('bypass', [])) > 0:
            rule_set.bypass = '******'.join(self.data['bypass'])
        else:
            rule_set.bypass = '******'

        self.client.storage_accounts.update(
            resource['resourceGroup'],
            resource['name'],
            StorageAccountUpdateParameters(network_rule_set=rule_set))
class ResourceTypeFilter(Filter):
    schema = type_schema('resource-type',
                         required=['values'],
                         values={'type': 'array', 'items': {'type': 'string'}})

    def __init__(self, data, manager=None):
        super(ResourceTypeFilter, self).__init__(data, manager)
        self.allowed_types = [t.lower() for t in self.data['values']]

    def process(self, resources, event=None):
        result = []
        for r in resources:
            if r['type'].lower() in self.allowed_types:
                result.append(r)

        return result
Пример #16
0
class VmResizeAction(AzureBaseAction):
    """Change a VM's size

    :example:

    Resize specific VM by name

    .. code-block:: yaml

        policies:
          - name: resize-vm
            resource: azure.vm
            filters:
              - type: value
                key: name
                op: eq
                value_type: normalize
                value: fake_vm_name
            actions:
              - type: resize
                vmSize: Standard_A2_v2
    """

    schema = type_schema('resize',
                         required=['vmSize'],
                         **{'vmSize': {
                             'type': 'string'
                         }})

    def __init__(self, data, manager=None):
        super(VmResizeAction, self).__init__(data, manager)
        self.vm_size = self.data['vmSize']

    def _prepare_processing(self):
        self.client = self.manager.get_client()

    def _process_resource(self, resource):
        hardware_profile = HardwareProfile(vm_size=self.vm_size)

        self.client.virtual_machines.begin_update(
            resource['resourceGroup'], resource['name'],
            VirtualMachineUpdate(hardware_profile=hardware_profile))
Пример #17
0
class StorageContainerSetPublicAccessAction(AzureBaseAction):
    """Action that updates the access level setting on Storage Containers.
    Programmatically, this will be seen by updating the Public Access setting

    :example:

       Finds all Blob Storage Containers that are not private and sets them to private

    .. code-block:: yaml

        policies:
            - name: set-non-production-accounts-private
              resource: azure.storage-container
              filters:
                - type: value
                  key: properties.publicAccess
                  op: not-equal
                  value: None
              actions:
                - type: set-public-access
                  value: None
    """
    schema = type_schema('set-public-access',
                         required=['value'],
                         **{'value': {
                             'enum': ['Container', 'Blob', 'None']
                         }})

    schema_alias = True

    def _prepare_processing(self):
        self.client = self.manager.get_client()

    def _process_resource(self, resource):
        resource_group = ResourceIdParser.get_resource_group(resource['id'])
        account_name = ResourceIdParser.get_resource_name(
            resource['c7n:parent-id'])

        self.client.blob_containers.update(resource_group,
                                           account_name,
                                           resource['name'],
                                           public_access=self.data['value'])
Пример #18
0
class EffectiveRouteTableFilter(ValueFilter):
    schema = type_schema('effective-route-table', rinherit=ValueFilter.schema)
    schema_alias = False
    def process(self, resources, event=None):

        resources, _ = ThreadHelper.execute_in_parallel(
            resources=resources,
            event=event,
            execution_method=self._process_resource_set,
            executor_factory=self.executor_factory,
            log=log,
            max_workers=max_workers,
            chunk_size=chunk_size
        )
        return resources

    def _process_resource_set(self, resources, event):
        client = self.manager.get_client()
        matched = []

        for resource in resources:
            try:
                if 'routes' not in resource:
                    route_table = (
                        client.network_interfaces
                        .get_effective_route_table(resource['resourceGroup'], resource['name'])
                        .result()
                    )

                    resource['routes'] = route_table.serialize()
                    filtered_effective_route_table = super(EffectiveRouteTableFilter, self)\
                        .process([resource], event)

                    if filtered_effective_route_table:
                        matched.append(resource)

            except Exception as error:
                log.warning(error)

        return matched
Пример #19
0
class FrontEndIp(RelatedResourceFilter):
    """Filters load balancers by frontend public ip.

    :Example:

        .. code-block:: yaml

            policies:
               - name: loadbalancer-with-ipv6-frontend
                 resource: azure.loadbalancer
                 filters:
                    - type: frontend-public-ip
                      key: properties.publicIPAddressVersion
                      op: in
                      value_type: normalize
                      value: "ipv6"
    """

    schema = type_schema('frontend-public-ip', rinherit=ValueFilter.schema)

    RelatedResource = "c7n_azure.resources.public_ip.PublicIPAddress"
    RelatedIdsExpression = "properties.frontendIPConfigurations[].properties.publicIPAddress.id"
Пример #20
0
class RequireSecureTransferAction(AzureBaseAction):
    """Action that updates the Secure Transfer setting on Storage Accounts.
    Programmatically, this will be seen by updating the EnableHttpsTrafficOnly setting

    :example:

       Turns on Secure transfer required for all storage accounts. This will reject requests that
       use HTTP to your storage accounts.

    .. code-block:: yaml

        policies:
            - name: require-secure-transfer
              resource: azure.storage
              actions:
              - type: require-secure-transfer
                value: True
    """

    # Default to true assuming user wants secure connection
    schema = type_schema('require-secure-transfer', **{
        'value': {
            'type': 'boolean',
            "default": True
        },
    })

    def __init__(self, data, manager=None):
        super(RequireSecureTransferAction, self).__init__(data, manager)

    def _prepare_processing(self):
        self.client = self.manager.get_client()

    def _process_resource(self, resource):
        self.client.storage_accounts.update(
            resource['resourceGroup'], resource['name'],
            StorageAccountUpdateParameters(
                enable_https_traffic_only=self.data.get('value')))
Пример #21
0
class StorageSetNetworkRulesAction(AzureBaseAction):
    """ Set Network Rules Action

    Updates Azure Storage Firewalls and Virtual Networks settings.

    By default the firewall rules are replaced with the new values.  The ``append``
    flag can be used to force merging the new rules with the existing ones on
    the resource.

    You may also reference azure public cloud Service Tags by name in place of
    an IP address.  Use ``ServiceTags.`` followed by the ``name`` of any group
    from https://www.microsoft.com/en-us/download/details.aspx?id=56519.

    Note that there are firewall rule number limits and that you will likely need to
    use a regional block to fit within the limit.  The limit for storage accounts is
    200 rules.

    .. code-block:: yaml

        - type: set-firewall-rules
              bypass-rules:
                  - Logging
                  - Metrics
              ip-rules:
                  - 11.12.13.0/16
                  - ServiceTags.AppService.CentralUS


    :example:

    Find storage accounts without any firewall rules.

    Configure default-action to ``Deny`` and then allow:
    - Azure Logging and Metrics services
    - Two specific IPs
    - Two subnets

    .. code-block:: yaml

        policies:
            - name: add-storage-firewall
              resource: azure.storage

            filters:
                - type: value
                  key: properties.networkAcls.ipRules
                  value_type: size
                  op: eq
                  value: 0

            actions:
                - type: set-firewall-rules
                  bypass-rules:
                      - Logging
                      - Metrics
                  ip-rules:
                      - 11.12.13.0/16
                      - 21.22.23.24
                  virtual-network-rules:
                      - <subnet_resource_id>
                      - <subnet_resource_id>

    """

    schema = type_schema(
        'set-firewall-rules',
        required=[],
        **{
            'default-action': {'enum': ['Allow', 'Deny'], "default": 'Deny'},
            'append': {'type': 'boolean', "default": False},
            'bypass-rules': {'type': 'array', 'items': {
                'enum': ['AzureServices', 'Logging', 'Metrics']}},
            'ip-rules': {'type': 'array', 'items': {'type': 'string'}},
            'virtual-network-rules': {'type': 'array', 'items': {'type': 'string'}}
        }
    )

    def __init__(self, data, manager=None):
        super(StorageSetNetworkRulesAction, self).__init__(data, manager)
        self._log = logging.getLogger('custodian.azure.storage')
        self.rule_limit = 200

    def _prepare_processing(self):
        self.client = self.manager.get_client()
        self.append = self.data.get('append', False)

    def _process_resource(self, resource):
        rules = self._build_ip_rules(resource, self.data.get('ip-rules', []))

        # Build out the ruleset model to update the resource
        rule_set = NetworkRuleSet(default_action=self.data.get('default-action', 'Deny'))

        # If the user has too many rules log and skip
        if len(rules) > self.rule_limit:
            self._log.error("Skipped updating firewall for %s. "
                            "%s exceeds maximum rule count of %s." %
                            (resource['name'], len(rules), self.rule_limit))
            return

        # Add IP rules
        rule_set.ip_rules = [IPRule(ip_address_or_range=r) for r in rules]

        # Add VNET rules
        vnet_rules = self._build_vnet_rules(resource, self.data.get('virtual-network-rules', []))
        rule_set.virtual_network_rules = [
            VirtualNetworkRule(virtual_network_resource_id=r) for r in vnet_rules]

        # Configure BYPASS
        rule_set.bypass = self._build_bypass_rules(resource, self.data.get('bypass', []))

        # Update resource
        self.client.storage_accounts.update(
            resource['resourceGroup'],
            resource['name'],
            StorageAccountUpdateParameters(network_rule_set=rule_set))

    def _build_bypass_rules(self, resource, new_rules):
        if self.append:
            existing_bypass = resource['properties']['networkAcls'].get('bypass', '').split(',')
            without_duplicates = [r for r in existing_bypass if r not in new_rules]
            new_rules.extend(without_duplicates)
        return ','.join(new_rules or ['None'])

    def _build_vnet_rules(self, resource, new_rules):
        if self.append:
            existing_rules = [r['id'] for r in
                              resource['properties']['networkAcls'].get('virtualNetworkRules', [])]
            without_duplicates = [r for r in existing_rules if r not in new_rules]
            new_rules.extend(without_duplicates)
        return new_rules

    def _build_ip_rules(self, resource, new_rules):
        rules = []
        for rule in new_rules:
            resolved_set = resolve_service_tag_alias(rule)
            if resolved_set:
                ranges = list(resolved_set.iter_cidrs())
                for r in range(len(ranges)):
                    if len(ranges[r]) == 1:
                        ranges[r] = IPAddress(ranges[r].first)
                rules.extend(map(str, ranges))
            else:
                rules.append(rule)

        if self.append:
            existing_rules = resource['properties']['networkAcls'].get('ipRules', [])
            without_duplicates = [r['value'] for r in existing_rules if r['value'] not in rules]
            rules.extend(without_duplicates)
        return rules
Пример #22
0
class StorageSetFirewallAction(SetFirewallAction):
    """ Set Firewall Rules Action

     Updates Azure Storage Firewalls and Virtual Networks settings.

     By default the firewall rules are appended with the new values.  The ``append: False``
     flag can be used to replace the old rules with the new ones on
     the resource.

     You may also reference azure public cloud Service Tags by name in place of
     an IP address.  Use ``ServiceTags.`` followed by the ``name`` of any group
     from https://www.microsoft.com/en-us/download/details.aspx?id=56519.

     Note that there are firewall rule number limits and that you will likely need to
     use a regional block to fit within the limit.  The limit for storage accounts is
     200 rules.

     .. code-block:: yaml

         - type: set-firewall-rules
               bypass-rules:
                   - Logging
                   - Metrics
               ip-rules:
                   - 11.12.13.0/16
                   - ServiceTags.AppService.CentralUS


     :example:

     Find storage accounts without any firewall rules.

     Configure default-action to ``Deny`` and then allow:
     - Azure Logging and Metrics services
     - Two specific IPs
     - Two subnets

     .. code-block:: yaml

         policies:
             - name: add-storage-firewall
               resource: azure.storage

             filters:
                 - type: value
                   key: properties.networkAcls.ipRules
                   value_type: size
                   op: eq
                   value: 0

             actions:
                 - type: set-firewall-rules
                   append: False
                   bypass-rules:
                       - Logging
                       - Metrics
                   ip-rules:
                       - 11.12.13.0/16
                       - 21.22.23.24
                   virtual-network-rules:
                       - <subnet_resource_id>
                       - <subnet_resource_id>

     """

    schema = type_schema('set-firewall-rules',
                         rinherit=SetFirewallAction.schema,
                         **{
                             'default-action': {
                                 'enum': ['Allow', 'Deny'],
                                 "default": 'Deny'
                             },
                             'bypass-rules': {
                                 'type': 'array',
                                 'items': {
                                     'enum':
                                     ['AzureServices', 'Logging', 'Metrics']
                                 }
                             },
                         })

    log = logging.getLogger('custodian.azure.storage.StorageSetFirewallAction')

    def __init__(self, data, manager=None):
        super(StorageSetFirewallAction, self).__init__(data, manager)
        self.rule_limit = 200

    def _process_resource(self, resource):
        # Build out the ruleset model to update the resource
        rule_set = NetworkRuleSet(
            default_action=self.data.get('default-action', 'Deny'))

        # Add IP rules
        if self.data.get('ip-rules') is not None:
            existing_ip = [
                r['value'] for r in resource['properties']['networkAcls'].get(
                    'ipRules', [])
            ]
            ip_rules = self._build_ip_rules(existing_ip,
                                            self.data.get('ip-rules', []))

            # If the user has too many rules raise exception
            if len(ip_rules) > self.rule_limit:
                raise ValueError(
                    "Skipped updating firewall for %s. "
                    "%s exceeds maximum rule count of %s." %
                    (resource['name'], len(ip_rules), self.rule_limit))

            rule_set.ip_rules = [
                IPRule(ip_address_or_range=r) for r in ip_rules
            ]

        # Add VNET rules
        if self.data.get('virtual-network-rules') is not None:
            existing_vnet = \
                [r['id'] for r in
                 resource['properties']['networkAcls'].get('virtualNetworkRules', [])]
            vnet_rules = \
                self._build_vnet_rules(existing_vnet, self.data.get('virtual-network-rules', []))
            rule_set.virtual_network_rules = \
                [VirtualNetworkRule(virtual_network_resource_id=r) for r in vnet_rules]

        # Configure BYPASS
        if self.data.get('bypass-rules') is not None:
            existing_bypass = resource['properties']['networkAcls'].get(
                'bypass', '').split(',')
            rule_set.bypass = self._build_bypass_rules(
                existing_bypass, self.data.get('bypass-rules', []))

        # Update resource
        self.client.storage_accounts.update(
            resource['resourceGroup'], resource['name'],
            StorageAccountUpdateParameters(network_rule_set=rule_set))
Пример #23
0
class SetLogSettingsAction(AzureBaseAction):
    """Action that updates the logging settings on storage accounts. The action requires
    specifying an array of storage types that will be impacted by the action (blob, queue, table),
    retention (number in days; 0-365), and an array of log settings to enable (read, write, delete).
    The action will disable any settings not listed (e.g. by providing log: [write, delete], the
    action will disable read).

     :example:

        Enable write and delete logging and disable read logging on blob storage,
        and retain logs for 5 days.

     .. code-block:: yaml

        policies:
            - name: enable-blob-storage-logging
              resource: azure.storage
              actions:
                - type: set-log-settings
                  storage-types: [blob]
                  retention: 5
                  log: [write, delete]
    """

    READ = 'read'
    WRITE = 'write'
    DELETE = 'delete'

    schema = type_schema('set-log-settings',
                         required=['storage-types', 'log', 'retention'],
                         **{
                             'storage-types': {
                                 'type': 'array',
                                 'items': {
                                     'type': 'string',
                                     'enum':
                                     [BLOB_TYPE, QUEUE_TYPE, TABLE_TYPE]
                                 }
                             },
                             'log': {
                                 'type': 'array',
                                 'items': {
                                     'type': 'string',
                                     'enum': [READ, WRITE, DELETE]
                                 }
                             },
                             'retention': {
                                 'type': 'number'
                             }
                         })
    log = logging.getLogger('custodian.azure.storage.SetLogSettingsAction')

    def __init__(self, data, manager=None):
        super(SetLogSettingsAction, self).__init__(data, manager)
        self.storage_types = data['storage-types']
        self.logs_to_enable = data['log']
        self.retention = data['retention']
        self.token = None

    def validate(self):
        if self.retention < 0 or self.retention > 365:
            raise PolicyValidationError(
                'attribute: retention can not be less than 0 or greater than 365'
            )

    def process_in_parallel(self, resources, event):
        self.token = StorageUtilities.get_storage_token(self.session)
        return super(SetLogSettingsAction,
                     self).process_in_parallel(resources, event)

    def _process_resource(self, resource, event=None):
        retention = RetentionPolicy(enabled=self.retention != 0,
                                    days=self.retention)
        log_settings = Logging(self.DELETE in self.logs_to_enable,
                               self.READ in self.logs_to_enable,
                               self.WRITE in self.logs_to_enable,
                               retention_policy=retention)

        for storage_type in self.storage_types:
            StorageSettingsUtilities.update_logging(storage_type, resource,
                                                    log_settings, self.session,
                                                    self.token)
Пример #24
0
class StorageDiagnosticSettingsFilter(ValueFilter):
    """Filters storage accounts based on its diagnostic settings. The filter requires
    specifying the storage type (blob, queue, table, file) and will filter based on
    the settings for that specific type.

     :example:

        Find all storage accounts that have a 'delete' logging setting disabled.

     .. code-block:: yaml

        policies:
            - name: find-accounts-with-delete-logging-disabled
              resource: azure.storage
              filters:
                - or:
                    - type: storage-diagnostic-settings
                      storage-type: blob
                      key: logging.delete
                      op: eq
                      value: False
                    - type: storage-diagnostic-settings
                      storage-type: queue
                      key: logging.delete
                      op: eq
                      value: False
                    - type: storage-diagnostic-settings
                      storage-type: table
                      key: logging.delete
                      op: eq
                      value: False

    :example:

    Find Load Balancers that have logs for both LoadBalancerProbeHealthStatus
    category and LoadBalancerAlertEvent category enabled.
    The use of value_type: swap is important for these examples because it swaps
    the value and the evaluated key so that it evaluates the value provided is in the logs.

    .. code-block:: yaml

        policies:
          - name: find-load-balancers-with-logs-enabled
            resource: azure.loadbalancer
            filters:
              - type: diagnostic-settings
                key: logs[?category == 'LoadBalancerProbeHealthStatus'][].enabled
                value: True
                op: in
                value_type: swap
              - type: diagnostic-settings
                key: logs[?category == 'LoadBalancerAlertEvent'][].enabled
                value: True
                op: in
                value_type: swap

    :example:

    Find KeyVaults that have logs enabled for the AuditEvent category.

    .. code-block:: yaml

        policies:
          - name: find-keyvaults-with-logs-enabled
            resource: azure.keyvault
            filters:
              - type: diagnostic-settings
                key: logs[?category == 'AuditEvent'][].enabled
                value: True
                op: in
                value_type: swap

    """

    schema = type_schema(
        'storage-diagnostic-settings',
        rinherit=ValueFilter.schema,
        required=['storage-type'],
        **{
            'storage-type': {
                'type': 'string',
                'enum': [BLOB_TYPE, QUEUE_TYPE, TABLE_TYPE, FILE_TYPE]
            }
        })

    log = logging.getLogger(
        'custodian.azure.storage.StorageDiagnosticSettingsFilter')

    def __init__(self, data, manager=None):
        super(StorageDiagnosticSettingsFilter, self).__init__(data, manager)
        self.storage_type = data.get('storage-type')

    def process(self, resources, event=None):
        session = local_session(self.manager.session_factory)
        token = StorageUtilities.get_storage_token(session)
        result, errors = ThreadHelper.execute_in_parallel(
            resources=resources,
            event=event,
            execution_method=self.process_resource_set,
            executor_factory=self.executor_factory,
            log=self.log,
            session=session,
            token=token)
        return result

    def process_resource_set(self,
                             resources,
                             event=None,
                             session=None,
                             token=None):
        matched = []
        for resource in resources:
            settings = self._get_settings(resource, session, token)
            filtered_settings = super(StorageDiagnosticSettingsFilter,
                                      self).process([settings], event)

            if filtered_settings:
                matched.append(resource)

        return matched

    def _get_settings(self, storage_account, session=None, token=None):
        storage_prefix_property = get_annotation_prefix(self.storage_type)

        if not (storage_prefix_property in storage_account):
            settings = StorageSettingsUtilities.get_settings(
                self.storage_type, storage_account, session, token)
            storage_account[storage_prefix_property] = json.loads(
                jsonpickle.encode(settings))

        return storage_account[storage_prefix_property]
Пример #25
0
class SetFirewallAction(AzureBaseAction):

    schema = type_schema('set-firewall-rules',
                         required=[],
                         **{
                             'append': {
                                 'type': 'boolean',
                                 'default': True
                             },
                             'bypass-rules': {
                                 'type': 'array'
                             },
                             'ip-rules': {
                                 'type': 'array',
                                 'items': {
                                     'type': 'string'
                                 }
                             },
                             'virtual-network-rules': {
                                 'type': 'array',
                                 'items': {
                                     'type': 'string'
                                 }
                             }
                         })

    @abstractmethod
    def __init__(self, data, manager=None):
        super(SetFirewallAction, self).__init__(data, manager)

    def _prepare_processing(self):
        self.client = self.manager.get_client()
        self.append = self.data.get('append', True)

    @abstractmethod
    def _process_resource(self, resource):
        pass

    def _build_bypass_rules(self, existing_bypass, new_rules):
        if self.append:
            without_duplicates = [
                r for r in existing_bypass if r not in new_rules
            ]
            new_rules.extend(without_duplicates)
        return ','.join(new_rules or ['None'])

    def _build_vnet_rules(self, existing_vnet, new_rules):
        if self.append:
            without_duplicates = [
                r for r in existing_vnet if r not in new_rules
            ]
            new_rules.extend(without_duplicates)
        return new_rules

    def _build_ip_rules(self, existing_ip, new_rules):
        rules = []
        for rule in new_rules:
            # attempt to resolve this rule as a service tag alias
            # if it isn't a valid alias then we'll get `None` back.
            resolved_set = resolve_service_tag_alias(rule)
            if resolved_set:
                # this is a service tag alias, so we need to insert the whole
                # aliased array into the ruleset
                ranges = list(resolved_set.iter_cidrs())
                for r in range(len(ranges)):
                    if len(ranges[r]) == 1:
                        ranges[r] = IPAddress(ranges[r].first)
                rules.extend(map(str, ranges))
            else:
                # just a normal rule, append
                rules.append(rule)

        if self.append:
            for ip in existing_ip:
                if str(ip) not in rules:
                    rules.append(str(ip))
        return rules
Пример #26
0
class VMExtensionsFilter(ValueFilter):
    """
        Provides a value filter targetting the virtual machine
        extensions array.  Requires an additional API call per
        virtual machine to retrieve the extensions.

        Here is an example of the data returned:

        .. code-block:: json

          [{
            "id": "/subscriptions/...",
            "name": "CustomScript",
            "type": "Microsoft.Compute/virtualMachines/extensions",
            "location": "centralus",
            "properties": {
              "publisher": "Microsoft.Azure.Extensions",
              "type": "CustomScript",
              "typeHandlerVersion": "2.0",
              "autoUpgradeMinorVersion": true,
              "settings": {
                "fileUris": []
              },
              "provisioningState": "Succeeded"
            }
          }]

        :examples:

        Find VM's with Custom Script extensions

        .. code-block:: yaml

            policies:
              - name: vm-with-customscript
                description: |
                  Find all virtual machines with a custom
                  script extension installed.
                resource: azure.vm
                filters:
                  - type: vm-extensions
                    op: in
                    key: "[].properties.type"
                    value: CustomScript
                    value_type: swap


        Find VM's without the OMS agent installed

        .. code-block:: yaml

            policies:
              - name: vm-without-oms
                description: |
                  Find all virtual machines without the
                  OMS agent installed.
                resource: azure.vm
                filters:
                  - type: vm-extensions
                    op: not-in
                    key: "[].properties.type"
                    value: OmsAgentForLinux
                    value_type: swap

        """
    schema = type_schema('vm-extensions', rinherit=ValueFilter.schema)
    annotate = False  # cannot annotate arrays

    def __call__(self, i):
        if 'c7n:vm-extensions' not in i:
            client = self.manager.get_client()
            extensions = (client.virtual_machine_extensions.list(
                i['resourceGroup'], i['name']))
            i['c7n:vm-extensions'] = [
                e.serialize(True) for e in extensions.value
            ]

        return super(VMExtensionsFilter, self).__call__(i['c7n:vm-extensions'])
Пример #27
0
class StorageDiagnosticSettingsFilter(ValueFilter):
    """Filters storage accounts based on its diagnostic settings. The filter requires
    specifying the storage type (blob, queue, table, file) and will filter based on
    the settings for that specific type.

     :example:

        Find all storage accounts that have a 'delete' logging setting disabled.

     .. code-block:: yaml

        policies:
            - name: find-accounts-with-delete-logging-disabled
              resource: azure.storage
              filters:
                - or:
                    - type: storage-diagnostic-settings
                      storage-type: blob
                      key: logging.delete
                      op: eq
                      value: False
                    - type: storage-diagnostic-settings
                      storage-type: queue
                      key: logging.delete
                      op: eq
                      value: False
                    - type: storage-diagnostic-settings
                      storage-type: table
                      key: logging.delete
                      op: eq
                      value: False
    """

    schema = type_schema(
        'storage-diagnostic-settings',
        rinherit=ValueFilter.schema,
        required=['storage-type'],
        **{
            'storage-type': {
                'type': 'string',
                'enum': [BLOB_TYPE, QUEUE_TYPE, TABLE_TYPE, FILE_TYPE]
            }
        })

    def __init__(self, data, manager=None):
        super(StorageDiagnosticSettingsFilter, self).__init__(data, manager)
        self.storage_type = data.get('storage-type')
        self.log = logging.getLogger('custodian.azure.storage')

    def process(self, resources, event=None):
        session = local_session(self.manager.session_factory)
        token = StorageUtilities.get_storage_token(session)
        result, errors = ThreadHelper.execute_in_parallel(
            resources=resources,
            event=event,
            execution_method=self.process_resource_set,
            executor_factory=self.executor_factory,
            log=self.log,
            session=session,
            token=token)
        return result

    def process_resource_set(self,
                             resources,
                             event=None,
                             session=None,
                             token=None):
        matched = []
        for resource in resources:
            settings = self._get_settings(resource, session, token)
            filtered_settings = super(StorageDiagnosticSettingsFilter,
                                      self).process([settings], event)

            if filtered_settings:
                matched.append(resource)

        return matched

    def _get_settings(self, storage_account, session=None, token=None):
        storage_prefix_property = get_annotation_prefix(self.storage_type)

        if not (storage_prefix_property in storage_account):
            settings = StorageSettingsUtilities.get_settings(
                self.storage_type, storage_account, session, token)
            storage_account[storage_prefix_property] = json.loads(
                jsonpickle.encode(settings))

        return storage_account[storage_prefix_property]
Пример #28
0
class StorageSetNetworkRulesAction(AzureBaseAction):
    """ Set Network Rules Action

    Updates Azure Storage Firewalls and Virtual Networks settings.

    :example:

    Find storage accounts without any firewall rules.

    Configure default-action to ``Deny`` and then allow:
    - Azure Logging and Metrics services
    - Two specific IPs
    - Two subnets

    .. code-block:: yaml

        policies:
            - name: add-storage-firewall
              resource: azure.storage

            filters:
                - type: value
                  key: properties.networkAcls.ipRules
                  value_type: size
                  op: eq
                  value: 0

            actions:
                - type: set-network-rules
                  default-action: Deny
                  bypass: [Logging, Metrics]
                  ip-rules:
                      - ip-address-or-range: 11.12.13.14
                      - ip-address-or-range: 21.22.23.24
                  virtual-network-rules:
                      - virtual-network-resource-id: <subnet_resource_id>
                      - virtual-network-resource-id: <subnet_resource_id>

    """

    schema = type_schema('set-network-rules',
                         required=['default-action'],
                         **{
                             'default-action': {
                                 'enum': ['Allow', 'Deny']
                             },
                             'bypass': {
                                 'type': 'array',
                                 'items': {
                                     'enum':
                                     ['AzureServices', 'Logging', 'Metrics']
                                 }
                             },
                             'ip-rules': {
                                 'type': 'array',
                                 'items': {
                                     'ip-address-or-range': {
                                         'type': 'string'
                                     }
                                 }
                             },
                             'virtual-network-rules': {
                                 'type': 'array',
                                 'items': {
                                     'virtual-network-resource-id': {
                                         'type': 'string'
                                     }
                                 }
                             }
                         })

    def _prepare_processing(self, ):
        self.client = self.manager.get_client()

    def _process_resource(self, resource):
        rule_set = NetworkRuleSet(default_action=self.data['default-action'])

        if 'ip-rules' in self.data:
            rule_set.ip_rules = [
                IPRule(ip_address_or_range=r['ip-address-or-range'],
                       action='Allow')  # 'Allow' is the only allowed action
                for r in self.data['ip-rules']
            ]

        if 'virtual-network-rules' in self.data:
            rule_set.virtual_network_rules = [
                VirtualNetworkRule(
                    virtual_network_resource_id=r[
                        'virtual-network-resource-id'],
                    action='Allow')  # 'Allow' is the only allowed action
                for r in self.data['virtual-network-rules']
            ]

        if len(self.data.get('bypass', [])) > 0:
            rule_set.bypass = '******'.join(self.data['bypass'])
        else:
            rule_set.bypass = '******'

        self.client.storage_accounts.update(
            resource['resourceGroup'], resource['name'],
            StorageAccountUpdateParameters(network_rule_set=rule_set))
Пример #29
0
class NetworkInterfaceFilter(RelatedResourceFilter):

    schema = type_schema('network-interface', rinherit=ValueFilter.schema)

    RelatedResource = "c7n_azure.resources.network_interface.NetworkInterface"
    RelatedIdsExpression = "properties.networkProfile.networkInterfaces[0].id"
Пример #30
0
class SqlServerFirewallRulesFilter(Filter):
    """Filters SQL servers by the firewall rules

    :example:

    .. code-block:: yaml

            policies:
                - name: servers-with-firewall
                  resource: azure.sqlserver
                  filters:
                      - type: firewall-rules
                        include:
                            - '131.107.160.2-131.107.160.3'
                            - 10.20.20.0/24
    """

    schema = type_schema(
        'firewall-rules',
        **{
            'include': {'type': 'array', 'items': {'type': 'string'}},
            'equal': {'type': 'array', 'items': {'type': 'string'}}
        })

    def __init__(self, data, manager=None):
        super(SqlServerFirewallRulesFilter, self).__init__(data, manager)
        self.policy_include = None
        self.policy_equal = None
        self.client = None

    def validate(self):
        self.policy_include = IpRangeHelper.parse_ip_ranges(self.data, 'include')
        self.policy_equal = IpRangeHelper.parse_ip_ranges(self.data, 'equal')

        has_include = self.policy_include is not None
        has_equal = self.policy_equal is not None

        if has_include and has_equal:
            raise FilterValidationError('Cannot have both include and equal.')

        if not has_include and not has_equal:
            raise FilterValidationError('Must have either include or equal.')

        return True

    def process(self, resources, event=None):
        self.client = self.manager.get_client()

        result, _ = ThreadHelper.execute_in_parallel(
            resources=resources,
            event=event,
            execution_method=self._check_resources,
            executor_factory=self.executor_factory,
            log=log
        )

        return result

    def _check_resources(self, resources, event):
        return [r for r in resources if self._check_resource(r)]

    def _check_resource(self, resource):
        try:
            query = self.client.firewall_rules.list_by_server(
                resource['resourceGroup'],
                resource['name'])

            resource_rules = set([IPRange(r.start_ip_address, r.end_ip_address) for r in query])
        except Exception as error:
            log.warning(error)
            return False

        ok = self._check_rules(resource_rules)

        return ok

    def _check_rules(self, resource_rules):
        if self.policy_equal is not None:
            return self.policy_equal == resource_rules
        elif self.policy_include is not None:
            return self.policy_include.issubset(resource_rules)
        else:  # validated earlier, can never happen
            raise FilterValidationError("Internal error.")