Ejemplo n.º 1
0
    def _TranslatePolicy(self, pol, exp_info):
        """Transform a policy object into a JuniperSRX object.

    Args:
      pol: policy.Policy object
      exp_info: print a info message when a term is set to expire
                in that many weeks

    Raises:
      UnsupportedFilterError: An unsupported filter was specified
      UnsupportedHeader: A header option exists that is not understood/usable
      SRXDuplicateTermError: Two terms were found with same name in same filter
      ConflictingTargetOptions: Two target options are conflicting in the header
      MixedAddrBookTypes: Global and Zone address books in the same policy
      ConflictingApplicationSets: When two duplicate named terms have
                                  conflicting applicaiton entries
    """
        self.srx_policies = []
        self.addressbook = collections.OrderedDict()
        self.applications = []
        self.ports = []
        self.from_zone = ''
        self.to_zone = ''
        self.addr_book_type_global = True

        current_date = datetime.datetime.utcnow().date()
        exp_info_date = current_date + datetime.timedelta(weeks=exp_info)

        # list is used for check if policy only utilizes one type of address book.
        # (global or zone)
        addr_book_types = []
        self._FixLargePolices()
        for header, terms in pol.filters:
            if self._PLATFORM not in header.platforms:
                continue

            filter_options = header.FilterOptions(self._PLATFORM)

            if (len(filter_options) < 4 or filter_options[0] != 'from-zone'
                    or filter_options[2] != 'to-zone'):
                raise UnsupportedFilterError(
                    'SRX filter arguments must specify '
                    'from-zone and to-zone.')

            # check if to-zone is not a supported target option
            if filter_options[1] in self._SUPPORTED_TARGET_OPTIONS:
                raise UnsupportedFilterError(
                    'to-zone %s cannot be the same as any '
                    'valid SRX target-options' % (filter_options[1]))
            else:
                self.from_zone = filter_options[1]

            # check if from-zone is not a supported target option
            if filter_options[3] in self._SUPPORTED_TARGET_OPTIONS:
                raise UnsupportedFilterError(
                    'from-zone %s cannot be the same as any '
                    'valid SRX target-options' % (filter_options[3]))
            else:
                self.to_zone = filter_options[3]

            # variables used to collect target-options and set defaults
            target_options = []
            filter_type = ''
            address_book_type = ''

            # parse srx target options
            for filter_opt in filter_options[4:]:

                # validate address families
                if filter_opt in self._SUPPORTED_AF:
                    if not filter_type:
                        filter_type = filter_opt
                    else:
                        raise ConflictingTargetOptions(
                            'only one address family can be '
                            'specified per header "%s"' %
                            ' '.join(filter_options))

                elif filter_opt in self._SUPPORTED_TARGET_OPTIONS:
                    target_options.append(filter_opt)

                    # check to see if option is an address-book-type and only one
                    # address-book-type is specified per header
                    if filter_opt == 'address-book-zone':
                        if not address_book_type:
                            address_book_type = 'zone'
                        else:
                            raise ConflictingTargetOptions(
                                'only one address-book-type can '
                                'be specified per header "%s"' %
                                ' '.join(filter_options))
                    elif filter_opt == 'address-book-global':
                        if not address_book_type:
                            address_book_type = 'global'
                        else:
                            raise ConflictingTargetOptions(
                                'only one address-book-type can '
                                'be specified per header "%s"' %
                                ' '.join(filter_options))
                    else:
                        raise UnsupportedHeader(
                            'SRX Generator currently does not '
                            'support %s as a header option "%s"' %
                            (filter_opt, ' '.join(filter_options)))
                else:
                    raise UnsupportedHeader(
                        'SRX Generator currently does not support '
                        '%s as a header option "%s"' %
                        (filter_opt, ' '.join(filter_options)))

            # if address-family and address-book-type have not been set then default
            if not filter_type:
                filter_type = 'mixed'
            if not address_book_type:
                address_book_type = 'global'

            addr_book_types.append(address_book_type)

            # check if policy is global
            if self.from_zone == 'all' and self.to_zone == 'all':
                if address_book_type == 'zone':
                    raise UnsupportedFilterError(
                        'Zone address books cannot be used with '
                        'a global policy.')
            elif self.from_zone == 'all' or self.to_zone == 'all':
                raise UnsupportedFilterError(
                    'The zone name all is reserved for global '
                    'policies.')

            term_dup_check = set()
            new_terms = []
            for term in terms:
                term.name = self.FixTermLength(term.name)
                if term.name in term_dup_check:
                    raise SRXDuplicateTermError(
                        'You have a duplicate term: %s' % term.name)
                term_dup_check.add(term.name)

                if term.expiration:
                    if term.expiration <= exp_info_date:
                        logging.info(
                            'INFO: Term %s in policy %s>%s expires '
                            'in less than two weeks.', term.name,
                            self.from_zone, self.to_zone)
                    if term.expiration <= current_date:
                        logging.warn(
                            'WARNING: Term %s in policy %s>%s is expired.',
                            term.name, self.from_zone, self.to_zone)
                        continue

                for i in term.source_address_exclude:
                    term.source_address = nacaddr.RemoveAddressFromList(
                        term.source_address, i)
                for i in term.destination_address_exclude:
                    term.destination_address = nacaddr.RemoveAddressFromList(
                        term.destination_address, i)

                # SRX policies are controlled by addresses that are used within, so
                # policy can be at the same time inet and inet6.

                for addr in term.source_address:
                    if addr.version in self._AF_MAP[filter_type]:
                        self._BuildAddressBook(self.from_zone, addr)
                for addr in term.destination_address:
                    if addr.version in self._AF_MAP[filter_type]:
                        self._BuildAddressBook(self.to_zone, addr)

                new_term = Term(term, filter_options)
                new_terms.append(new_term)

                # Because SRX terms can contain inet and inet6 addresses. We have to
                # have ability to recover proper AF for ICMP type we need.
                # If protocol is empty or we cannot map to inet or inet6 we insert bogus
                # af_type name which will cause new_term.NormalizeIcmpTypes to fail.
                if not term.protocol:
                    icmp_af_type = 'unknown_af_icmp'
                else:
                    icmp_af_type = self._AF_ICMP_MAP.get(
                        term.protocol[0], 'unknown_af_icmp')
                tmp_icmptype = new_term.NormalizeIcmpTypes(
                    term.icmp_type, term.protocol, icmp_af_type)
                # NormalizeIcmpTypes returns [''] for empty, convert to [] for eval
                normalized_icmptype = tmp_icmptype if tmp_icmptype != [
                    ''
                ] else []
                # rewrites the protocol icmpv6 to icmp6
                if 'icmpv6' in term.protocol:
                    protocol = list(term.protocol)
                    protocol[protocol.index('icmpv6')] = 'icmp6'
                else:
                    protocol = term.protocol
                new_application_set = {
                    'sport': self._BuildPort(term.source_port),
                    'dport': self._BuildPort(term.destination_port),
                    'name': term.name,
                    'protocol': protocol,
                    'icmp-type': normalized_icmptype,
                    'timeout': term.timeout
                }

                for application_set in self.applications:
                    if (term.name == application_set['name']
                            and new_application_set != application_set):
                        raise ConflictingApplicationSets(
                            'Application set %s has a conflicting entry' %
                            term.name)

                self.applications.append(new_application_set)

            self.srx_policies.append((header, new_terms, filter_options))

        # Check if policy only utilizes one type of address book. (global or zone)
        if all(p == 'global' for p in addr_book_types):
            self.addr_book_type_global = True
        elif all(p == 'zone' for p in addr_book_types):
            self.addr_book_type_global = False
        else:
            raise MixedAddrBookTypes(
                'Global and Zone address-book-types cannot '
                'be used in the same policy')
Ejemplo n.º 2
0
  def _TranslatePolicy(self, pol, exp_info):
    """Transform a policy object into a PaloAltoFW object.

    Args:
      pol: policy.Policy object
      exp_info: print a info message when a term is set to expire
                in that many weeks

    Raises:
      UnsupportedFilterError: An unsupported filter was specified
      UnsupportedHeader: A header option exists that is not
      understood/usable
      PaloAltoFWDuplicateTermError: Two terms were found with same name in
      same filter
    """
    self.pafw_policies = []
    self.addressbook = collections.OrderedDict()
    self.applications = []
    self.pan_applications = []
    self.ports = []
    self.from_zone = ""
    self.to_zone = ""
    self.policy_name = ""

    current_date = datetime.date.today()
    exp_info_date = current_date + datetime.timedelta(weeks=exp_info)
    for header, terms in pol.filters:
      if self._PLATFORM not in header.platforms:
        continue

      filter_options = header.FilterOptions(self._PLATFORM)

      if (len(filter_options) < 4 or filter_options[0] != "from-zone" or
          filter_options[2] != "to-zone"):
        raise UnsupportedFilterError(
            "Palo Alto Firewall filter arguments must specify from-zone and "
            "to-zone."
        )

      self.from_zone = filter_options[1]
      self.to_zone = filter_options[3]

      if len(filter_options) > 4:
        filter_type = filter_options[4]
      else:
        filter_type = "inet"

      if filter_type not in self._SUPPORTED_AF:
        raise UnsupportedHeader(
            "Palo Alto Firewall Generator currently does not support"
            " %s as a header option" % (filter_type))

      term_dup_check = set()
      new_terms = []
      for term in terms:
        term.name = self.FixTermLength(term.name)
        if term.name in term_dup_check:
          raise PaloAltoFWDuplicateTermError("You have a duplicate term: %s" %
                                             term.name)
        term_dup_check.add(term.name)

        if term.expiration:
          if term.expiration <= exp_info_date:
            logging.info("INFO: Term %s in policy %s>%s expires "
                         "in less than two weeks.", term.name, self.from_zone,
                         self.to_zone)
          if term.expiration <= current_date:
            logging.warn("WARNING: Term %s in policy %s>%s is expired and "
                         "will not be rendered.",
                         term.name, self.from_zone, self.to_zone)
            continue

        for i in term.source_address_exclude:
          term.source_address = nacaddr.RemoveAddressFromList(
              term.source_address, i)
        for i in term.destination_address_exclude:
          term.destination_address = nacaddr.RemoveAddressFromList(
              term.destination_address, i)

        for addr in term.source_address:
          self._BuildAddressBook(self.from_zone, addr)
        for addr in term.destination_address:
          self._BuildAddressBook(self.to_zone, addr)

        new_term = Term(term, filter_type, filter_options)
        new_terms.append(new_term)
        tmp_icmptype = new_term.NormalizeIcmpTypes(term.icmp_type,
                                                   term.protocol, filter_type)
        # NormalizeIcmpTypes returns [''] for empty, convert to [] for
        # eval
        normalized_icmptype = tmp_icmptype if tmp_icmptype != [""] else []
        # rewrites the protocol icmpv6 to icmp6
        if "icmpv6" in term.protocol:
          protocol = list(term.protocol)
          protocol[protocol.index("icmpv6")] = "icmp6"
        else:
          protocol = term.protocol
        self.applications.append({
            "sport": self._BuildPort(term.source_port),
            "dport": self._BuildPort(term.destination_port),
            "name": term.name,
            "protocol": protocol,
            "icmp-type": normalized_icmptype,
            "timeout": term.timeout
        })
      self.pafw_policies.append((header, new_terms, filter_options))
      # create Palo Alto Firewall Rule object
      for term in new_terms:
        unused_rule = Rule(self.from_zone, self.to_zone, term)
Ejemplo n.º 3
0
  def _TranslatePolicy(self, pol, exp_info):
    # pylint: disable=attribute-defined-outside-init
    """Transform a policy object into a JuniperSRX object.

    Args:
      pol: policy.Policy object
      exp_info: print a info message when a term is set to expire
                in that many weeks

    Raises:
      UnsupportedFilterError: An unsupported filter was specified
      UnsupportedHeader: A header option exists that is not understood/usable
      SRXDuplicateTermError: Two terms were found with same name in same filter
      ConflictingTargetOptions: Two target options are conflicting in the header
      MixedAddrBookTypes: Global and Zone address books in the same policy
      ConflictingApplicationSets: When two duplicate named terms have
                                  conflicting application entries
    """
    self.srx_policies = []
    self.addressbook = collections.OrderedDict()
    self.applications = []
    self.ports = []
    self.from_zone = ''
    self.to_zone = ''
    self.addr_book_type = set()

    current_date = datetime.datetime.utcnow().date()
    exp_info_date = current_date + datetime.timedelta(weeks=exp_info)

    for header, terms in pol.filters:
      if self._PLATFORM not in header.platforms:
        continue

      filter_options = header.FilterOptions(self._PLATFORM)

      if (len(filter_options) < 4 or filter_options[0] != 'from-zone' or
          filter_options[2] != 'to-zone'):
        raise UnsupportedFilterError('SRX filter arguments must specify '
                                     'from-zone and to-zone.')

      # check if to-zone is not a supported target option
      if filter_options[1] in self._SUPPORTED_TARGET_OPTIONS:
        raise UnsupportedFilterError('to-zone %s cannot be the same as any '
                                     'valid SRX target-options' %
                                     (filter_options[1]))
      else:
        self.from_zone = filter_options[1]

      # check if from-zone is not a supported target option
      if filter_options[3] in self._SUPPORTED_TARGET_OPTIONS:
        raise UnsupportedFilterError('from-zone %s cannot be the same as any '
                                     'valid SRX target-options' %
                                     (filter_options[3]))
      else:
        self.to_zone = filter_options[3]

      # variables used to collect target-options and set defaults
      target_options = []
      filter_type = ''

      # parse srx target options
      extra_options = filter_options[4:]
      if self._SUPPORTED_TARGET_OPTIONS.issubset(extra_options):
        raise ConflictingTargetOptions('only one address-book-type can '
                                       'be specified per header "%s"' %
                                       ' '.join(filter_options))
      else:
        address_book_type = self._SUPPORTED_TARGET_OPTIONS.intersection(
            extra_options)
        if len(address_book_type) is 0:
          address_book_type = {self._GLOBAL_ADDR_BOOK}
        self.addr_book_type.update(address_book_type)
        if len(self.addr_book_type) > 1:
          raise MixedAddrBookTypes('Global and Zone address-book-types cannot '
                                   'be used in the same policy')
        if self.from_zone == 'all' and self.to_zone == 'all':
          if self._ZONE_ADDR_BOOK in self.addr_book_type:
            raise UnsupportedFilterError('Zone address books cannot be used '
                                         'with a global policy.')
        elif self.from_zone == 'all' or self.to_zone == 'all':
          raise UnsupportedFilterError('The zone name all is reserved for '
                                       'global policies.')

      for filter_opt in filter_options[4:]:

          # validate address families
        if filter_opt in self._SUPPORTED_AF:
          if not filter_type:
            filter_type = filter_opt
          else:
            raise ConflictingTargetOptions('only one address family can be '
                                           'specified per header "%s"' %
                                           ' '.join(filter_options))

        elif filter_opt in self._SUPPORTED_TARGET_OPTIONS:
          target_options.append(filter_opt)

        else:
          raise UnsupportedHeader('SRX Generator currently does not support '
                                  '%s as a header option "%s"' %
                                  (filter_opt, ' '.join(filter_options)))

      # if address-family and address-book-type have not been set then default
      if not filter_type:
        filter_type = 'mixed'

      term_dup_check = set()
      new_terms = []
      self._FixLargePolices(terms, filter_type)
      for term in terms:
        term.name = self.FixTermLength(term.name)
        if term.name in term_dup_check:
          raise SRXDuplicateTermError('You have a duplicate term: %s'
                                      % term.name)
        term_dup_check.add(term.name)

        if term.expiration:
          if term.expiration <= exp_info_date:
            logging.info('INFO: Term %s in policy %s>%s expires '
                         'in less than two weeks.', term.name, self.from_zone,
                         self.to_zone)
          if term.expiration <= current_date:
            logging.warn('WARNING: Term %s in policy %s>%s is expired.',
                         term.name, self.from_zone, self.to_zone)
            continue

        # SRX address books leverage network token names for IPs.
        # When excluding addresses, we lose those distinct names so we need
        # to create a new unique name based off the term name before excluding.
        if term.source_address_exclude:
          # If we have a naked source_exclude, we need something to exclude from
          if not term.source_address:
            term.source_address = [nacaddr.IP('0.0.0.0/0',
                                              term.name.upper(),
                                              term.name.upper())]
          # Use the term name as the token & parent_token
          new_src_parent_token = term.name.upper() + '_SRC_EXCLUDE'
          new_src_token = new_src_parent_token
          for i in term.source_address_exclude:
            term.source_address = nacaddr.RemoveAddressFromList(
                term.source_address, i)
            for i in term.source_address:
              i.token = new_src_token
              i.parent_token = new_src_parent_token

        if term.destination_address_exclude:
          if not term.destination_address:
            term.destination_address = [nacaddr.IP('0.0.0.0/0',
                                                   term.name.upper(),
                                                   term.name.upper())]
          new_dst_parent_token = term.name.upper() + '_DST_EXCLUDE'
          new_dst_token = new_dst_parent_token
          for i in term.destination_address_exclude:
            term.destination_address = nacaddr.RemoveAddressFromList(
                term.destination_address, i)
            for i in term.destination_address:
              i.token = new_dst_token
              i.parent_token = new_dst_parent_token

        # SRX policies are controlled by addresses that are used within, so
        # policy can be at the same time inet and inet6.
        if self._GLOBAL_ADDR_BOOK in self.addr_book_type:
          for zone in self.addressbook:
            for unused_name, ips in sorted(self.addressbook[zone].iteritems()):
              ips = [i for i in ips]
              if term.source_address == ips:
                term.source_address = ips
              if term.destination_address == ips:
                term.destination_address = ips
        for addr in term.source_address:
          if addr.version in self._AF_MAP[filter_type]:
            self._BuildAddressBook(self.from_zone, addr)
        for addr in term.destination_address:
          if addr.version in self._AF_MAP[filter_type]:
            self._BuildAddressBook(self.to_zone, addr)

        new_term = Term(term, filter_options)
        new_terms.append(new_term)

        # Because SRX terms can contain inet and inet6 addresses. We have to
        # have ability to recover proper AF for ICMP type we need.
        # If protocol is empty or we cannot map to inet or inet6 we insert bogus
        # af_type name which will cause new_term.NormalizeIcmpTypes to fail.
        if not term.protocol:
          icmp_af_type = 'unknown_af_icmp'
        else:
          icmp_af_type = self._AF_ICMP_MAP.get(
              term.protocol[0], 'unknown_af_icmp')
        tmp_icmptype = new_term.NormalizeIcmpTypes(
            term.icmp_type, term.protocol, icmp_af_type)
        # NormalizeIcmpTypes returns [''] for empty, convert to [] for eval
        normalized_icmptype = tmp_icmptype if tmp_icmptype != [''] else []
        # rewrites the protocol icmpv6 to icmp6
        if 'icmpv6' in term.protocol:
          protocol = list(term.protocol)
          protocol[protocol.index('icmpv6')] = 'icmp6'
        else:
          protocol = term.protocol
        new_application_set = {'sport': self._BuildPort(term.source_port),
                               'dport': self._BuildPort(term.destination_port),
                               'protocol': protocol,
                               'icmp-type': normalized_icmptype,
                               'timeout': term.timeout}

        for application_set in self.applications:
          if all(item in application_set.items() for item in
                 new_application_set.items()):
            new_application_set = ''
            term.replacement_application_name = application_set['name']
            break
          if (term.name == application_set['name'] and
              new_application_set != application_set):
            raise ConflictingApplicationSets(
                'Application set %s has a conflicting entry' % term.name)

        if new_application_set:
          new_application_set['name'] = term.name
          self.applications.append(new_application_set)

      self.srx_policies.append((header, new_terms, filter_options))