示例#1
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 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 _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)
示例#4
0
 def test_get_ports_strings_from_list(self):
     self.assertEqual(PortsRangeHelper.get_ports_strings_from_list([]),
                      [])
     self.assertEqual(PortsRangeHelper.get_ports_strings_from_list([10, 11]),
                      ['10-11'])
     self.assertEqual(PortsRangeHelper.get_ports_strings_from_list([10, 12, 13, 14]),
                      ['10', '12-14'])
     self.assertEqual(PortsRangeHelper.get_ports_strings_from_list([10, 12, 13, 14, 20, 21, 22]),
                      ['10', '12-14', '20-22'])
示例#5
0
 def test_get_ports(self):
     self.assertEqual(
         PortsRangeHelper.get_ports_set_from_string("5, 4-5, 9"), {4, 5, 9})
     rule = {'properties': {'destinationPortRange': '10-12'}}
     self.assertEqual(PortsRangeHelper.get_ports_set_from_rule(rule),
                      {10, 11, 12})
     rule = {'properties': {'destinationPortRanges': ['80', '10-12']}}
     self.assertEqual(PortsRangeHelper.get_ports_set_from_rule(rule),
                      {10, 11, 12, 80})
 def test_get_ports_strings_from_list(self):
     self.assertEqual(PortsRangeHelper.get_ports_strings_from_list([]),
                      [])
     self.assertEqual(PortsRangeHelper.get_ports_strings_from_list([10, 11]),
                      ['10-11'])
     self.assertEqual(PortsRangeHelper.get_ports_strings_from_list([10, 12, 13, 14]),
                      ['10', '12-14'])
     self.assertEqual(PortsRangeHelper.get_ports_strings_from_list([10, 12, 13, 14, 20, 21, 22]),
                      ['10', '12-14', '20-22'])
    def validate(self):
        # Check that variable values are valid

        if PORTS in self.data:
            if not PortsRangeHelper.validate_ports_string(self.data[PORTS]):
                raise FilterValidationError("ports string has wrong format.")

        if EXCEPT_PORTS in self.data:
            if not PortsRangeHelper.validate_ports_string(self.data[EXCEPT_PORTS]):
                raise FilterValidationError("exceptPorts string has wrong format.")
        return True
示例#8
0
 def test_validate_ports_string(self):
     self.assertEqual(PortsRangeHelper.validate_ports_string('80'), True)
     self.assertEqual(PortsRangeHelper.validate_ports_string('22-26'), True)
     self.assertEqual(PortsRangeHelper.validate_ports_string('80,22'), True)
     self.assertEqual(PortsRangeHelper.validate_ports_string('80,22-26'), True)
     self.assertEqual(PortsRangeHelper.validate_ports_string('80,22-26,30-34'), True)
     self.assertEqual(PortsRangeHelper.validate_ports_string('65537'), False)
     self.assertEqual(PortsRangeHelper.validate_ports_string('-1'), False)
     self.assertEqual(PortsRangeHelper.validate_ports_string('10-8'), False)
     self.assertEqual(PortsRangeHelper.validate_ports_string('80,30,25-65538'), False)
     self.assertEqual(PortsRangeHelper.validate_ports_string('65536-65537'), False)
 def test_validate_ports_string(self):
     self.assertEqual(PortsRangeHelper.validate_ports_string('80'), True)
     self.assertEqual(PortsRangeHelper.validate_ports_string('22-26'), True)
     self.assertEqual(PortsRangeHelper.validate_ports_string('80,22'), True)
     self.assertEqual(PortsRangeHelper.validate_ports_string('80,22-26'), True)
     self.assertEqual(PortsRangeHelper.validate_ports_string('80,22-26,30-34'), True)
     self.assertEqual(PortsRangeHelper.validate_ports_string('65537'), False)
     self.assertEqual(PortsRangeHelper.validate_ports_string('-1'), False)
     self.assertEqual(PortsRangeHelper.validate_ports_string('10-8'), False)
     self.assertEqual(PortsRangeHelper.validate_ports_string('80,30,25-65538'), False)
     self.assertEqual(PortsRangeHelper.validate_ports_string('65536-65537'), False)
    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
    def _check_nsg(self, nsg):
        nsg_ports = PortsRangeHelper.build_ports_dict(nsg, self.direction_key, self.ip_protocol)

        num_allow_ports = len([p for p in self.ports if nsg_ports.get(p)])
        num_deny_ports = len(self.ports) - num_allow_ports

        if self.match == 'all':
            if self.IsAllowed:
                return num_deny_ports == 0
            else:
                return num_allow_ports == 0
        if self.match == 'any':
            if self.IsAllowed:
                return num_allow_ports > 0
            else:
                return num_deny_ports > 0
示例#12
0
    def test_build_ports_dict(self):
        securityRules = [
            {'properties': {'destinationPortRange': '80-84',
                            'priority': 100,
                            'direction': 'Outbound',
                            'access': 'Allow',
                            'protocol': 'TCP'}},
            {'properties': {'destinationPortRange': '85-89',
                            'priority': 110,
                            'direction': 'Outbound',
                            'access': 'Allow',
                            'protocol': 'UDP'}},
            {'properties': {'destinationPortRange': '80-84',
                            'priority': 120,
                            'direction': 'Inbound',
                            'access': 'Deny',
                            'protocol': 'TCP'}},
            {'properties': {'destinationPortRange': '85-89',
                            'priority': 130,
                            'direction': 'Inbound',
                            'access': 'Deny',
                            'protocol': 'UDP'}},
            {'properties': {'destinationPortRange': '80-89',
                            'priority': 140,
                            'direction': 'Inbound',
                            'access': 'Allow',
                            'protocol': '*'}}]
        nsg = {'properties': {'securityRules': securityRules}}

        self.assertEqual(PortsRangeHelper.build_ports_dict(nsg, 'Inbound', 'TCP'),
                         {k: k > 84 for k in range(80, 90)})
        self.assertEqual(PortsRangeHelper.build_ports_dict(nsg, 'Inbound', 'UDP'),
                         {k: k < 85 for k in range(80, 90)})
        self.assertEqual(PortsRangeHelper.build_ports_dict(nsg, 'Inbound', '*'),
                         {k: False for k in range(80, 90)})
        self.assertEqual(PortsRangeHelper.build_ports_dict(nsg, 'Outbound', 'TCP'),
                         {k: True for k in range(80, 85)})
        self.assertEqual(PortsRangeHelper.build_ports_dict(nsg, 'Outbound', 'UDP'),
                         {k: True for k in range(85, 90)})
        self.assertEqual(PortsRangeHelper.build_ports_dict(nsg, 'Outbound', '*'),
                         {k: True for k in range(80, 90)})
示例#13
0
    def test_build_ports_dict(self):
        securityRules = [
            {'properties': {'destinationPortRange': '80-84',
                            'priority': 100,
                            'direction': 'Outbound',
                            'access': 'Allow',
                            'protocol': 'TCP'}},
            {'properties': {'destinationPortRange': '85-89',
                            'priority': 110,
                            'direction': 'Outbound',
                            'access': 'Allow',
                            'protocol': 'UDP'}},
            {'properties': {'destinationPortRange': '80-84',
                            'priority': 120,
                            'direction': 'Inbound',
                            'access': 'Deny',
                            'protocol': 'TCP'}},
            {'properties': {'destinationPortRange': '85-89',
                            'priority': 130,
                            'direction': 'Inbound',
                            'access': 'Deny',
                            'protocol': 'UDP'}},
            {'properties': {'destinationPortRange': '80-89',
                            'priority': 140,
                            'direction': 'Inbound',
                            'access': 'Allow',
                            'protocol': '*'}}]
        nsg = {'properties': {'securityRules': securityRules}}

        self.assertEqual(PortsRangeHelper.build_ports_dict(nsg, 'Inbound', 'TCP'),
                         {k: k > 84 for k in range(80, 90)})
        self.assertEqual(PortsRangeHelper.build_ports_dict(nsg, 'Inbound', 'UDP'),
                         {k: k < 85 for k in range(80, 90)})
        self.assertEqual(PortsRangeHelper.build_ports_dict(nsg, 'Inbound', '*'),
                         {k: False for k in range(80, 90)})
        self.assertEqual(PortsRangeHelper.build_ports_dict(nsg, 'Outbound', 'TCP'),
                         {k: True for k in range(80, 85)})
        self.assertEqual(PortsRangeHelper.build_ports_dict(nsg, 'Outbound', 'UDP'),
                         {k: True for k in range(85, 90)})
        self.assertEqual(PortsRangeHelper.build_ports_dict(nsg, 'Outbound', '*'),
                         {k: True for k in range(80, 90)})
示例#14
0
 def test_get_ports(self):
     self.assertEqual(PortsRangeHelper.get_ports_set_from_string("5, 4-5, 9"), set([4, 5, 9]))
     rule = {'properties': {'destinationPortRange': '10-12'}}
     self.assertEqual(PortsRangeHelper.get_ports_set_from_rule(rule), set([10, 11, 12]))
     rule = {'properties': {'destinationPortRanges': ['80', '10-12']}}
     self.assertEqual(PortsRangeHelper.get_ports_set_from_rule(rule), set([10, 11, 12, 80]))