Example #1
0
 def testServiceIncorrectSyntax(self):
     badservicedata = []
     badservicedata.append('SVC1 = 80//tcp 80/udp')
     badservicedata.append('SVC2 = 81/tcp')
     testdefs = naming.Naming(None)
     self.assertRaises(naming.NamingSyntaxError, testdefs.ParseServiceList,
                       badservicedata)
Example #2
0
 def testNamespaceCollisionError(self):
     badservicedata = []
     badservicedata.append('SVC1 = 80/tcp')
     badservicedata.append('SVC1 = 81/udp')
     testdefs = naming.Naming(None)
     self.assertRaises(naming.NamespaceCollisionError,
                       testdefs.ParseServiceList, badservicedata)
Example #3
0
    def setUp(self):
        super().setUp()
        self.defs = naming.Naming(None)
        servicedata = []
        servicedata.append('SVC1 = 80/tcp 81/udp 82/tcp')
        servicedata.append('SVC2 = 80/tcp 81/udp 82/tcp SVC2')
        servicedata.append('SVC3 = 80/tcp 81/udp')
        servicedata.append('SVC4 = 80/tcp # some service')
        servicedata.append('TCP_90 = 90/tcp')
        servicedata.append('SVC5 = TCP_90')
        servicedata.append('SVC6 = SVC1 SVC5')
        networkdata = []
        networkdata.append('NET1 = 10.1.0.0/8 # network1')
        networkdata.append('NET2 = 10.2.0.0/16 # network2.0')
        networkdata.append('       NET1')
        networkdata.append('9OCLOCK = 1.2.3.4/32 # 9 is the time')
        networkdata.append('FOOBAR = 9OCLOCK')
        networkdata.append('FOO_V6 = ::FFFF:FFFF:FFFF:FFFF')
        networkdata.append('BAR_V6 = ::1/128')
        networkdata.append('BAZ = FOO_V6')
        networkdata.append('      BAR_V6')
        networkdata.append('BING = NET1 # foo')
        networkdata.append('       FOO_V6')

        self.defs.ParseServiceList(servicedata)
        self.defs.ParseNetworkList(networkdata)
Example #4
0
    def testServiceMap(self):
        definitions = naming.Naming()
        definitions._ParseLine('SSH = 22/tcp', 'services')
        definitions._ParseLine('SMTP = 25/tcp', 'services')
        definitions._ParseLine('FOOBAR = 10.0.0.0/8', 'networks')
        definitions._ParseLine('         2001:4860:8000::/33', 'networks')

        pol1 = paloaltofw.PaloAltoFW(
            policy.ParsePolicy(GOOD_HEADER_1 + SVC_TERM_1, definitions),
            EXP_INFO)
        self.assertEqual(
            pol1.service_map.entries, {
                ((), ('22', ), 'tcp'): {
                    'name': 'service-ssh-term-1-tcp'
                },
                ((), ('25', ), 'tcp'): {
                    'name': 'service-smtp-term-1-tcp'
                }
            }, pol1.service_map.entries)

        pol2 = paloaltofw.PaloAltoFW(
            policy.ParsePolicy(GOOD_HEADER_1 + SVC_TERM_2, definitions),
            EXP_INFO)
        # The expectation is that there will be a single port mapped.
        self.assertEqual(
            pol2.service_map.entries,
            {((), ('25', ), 'tcp'): {
                 'name': 'service-smtp-term-1-tcp'
             }}, pol2.service_map.entries)
Example #5
0
def get_definitions(networks_file, services_file):
    defs = naming.Naming()
    with open(networks_file, "r") as f:
        defs._ParseFile(f, "networks")
    with open(services_file, "r") as f:
        defs._ParseFile(f, "services")
    return defs
Example #6
0
def main():
  # TODO(robankeny): Lets move this to gflags
  usage = 'usage: %prog [options] arg'
  _parser = OptionParser(usage)
  _parser.add_option('--definitions-directory', dest='definitions',
                     help='definitions directory', default='./def')
  _parser.add_option('-p', '--policy-file', dest='pol',
                     help='policy file', default='./policies/sample.pol')
  _parser.add_option('-d', '--destination', dest='dst',
                     help='destination IP', default='200.1.1.1')
  _parser.add_option('-s', '--source', dest='src',
                     help='source IP', default='any')
  _parser.add_option('--proto', '--protocol', dest='proto',
                     help='Protocol (tcp, udp, icmp, etc.)', default='tcp')
  _parser.add_option('--dport', '--destination-port', dest='dport',
                     help='destination port', default='80')
  _parser.add_option('--sport', '--source-port', dest='sport',
                     help='source port', default='1025')
  (FLAGS, unused_args) = _parser.parse_args()

  defs = naming.Naming(FLAGS.definitions)
  policy_obj = policy.ParsePolicy(open(FLAGS.pol).read(), defs)
  check = aclcheck.AclCheck(policy_obj, src=FLAGS.src, dst=FLAGS.dst,
                            sport=FLAGS.sport, dport=FLAGS.dport,
                            proto=FLAGS.proto)
  print(str(check))
Example #7
0
def Run(base_directory, definitions_directory, policy_file, output_directory,
        context):
    definitions = None
    try:
        definitions = naming.Naming(definitions_directory)
    except naming.NoDefinitionsError:
        err_msg = 'bad definitions directory: %s' % definitions_directory
        logging.fatal(err_msg)

    # thead-safe list for storing files to write
    manager = context.Manager()
    write_files = manager.list()

    with_errors = False
    if policy_file:
        # render just one file
        logging.info('rendering one file')
        RenderFile(base_directory, policy_file, output_directory, definitions,
                   FLAGS.exp_info, write_files)
    elif FLAGS.max_renderers == 1:
        # If only one process, run it sequentially
        policies = DiscoverAllPolicies(base_directory, output_directory,
                                       definitions)
        for pol in policies:
            RenderFile(base_directory, pol.get('in_file'), pol.get('out_dir'),
                       definitions, FLAGS.exp_info, write_files)
    else:
        # render all files in parallel
        policies = DiscoverAllPolicies(base_directory, output_directory,
                                       definitions)
        pool = context.Pool(processes=FLAGS.max_renderers)
        results = []
        for pol in policies:
            results.append(
                pool.apply_async(RenderFile,
                                 args=(base_directory, pol.get('in_file'),
                                       pol.get('out_dir'), definitions,
                                       FLAGS.exp_info, write_files)))
        pool.close()
        pool.join()

        for result in results:
            try:
                result.get()
            except (ACLParserError, ACLGeneratorError) as e:
                with_errors = True
                logging.warning(
                    '\n\nerror encountered in rendering '
                    'process:\n%s\n\n', e)

    # actually write files to disk
    WriteFiles(write_files)

    if with_errors:
        logging.warning('done, with errors.')
        sys.exit(1)
    else:
        logging.info('done.')
Example #8
0
def _load_test_definitions(netstr, svcstr=None):
    # type: (Text, Text) -> naming.Naming
    """Parses a Capirca Naming from the given network and services strings."""
    defs = naming.Naming()
    if netstr:
        defs._ParseFile(StringIO(netstr), 'networks')
    if svcstr:
        defs._ParseFile(StringIO(svcstr), 'services')
    return defs
Example #9
0
def Run(base_directory, definitions_directory, policy_file, output_directory,
        exp_info, max_renderers, ignore_directories, optimize, shade_check,
        context):
    definitions = None
    try:
        definitions = naming.Naming(definitions_directory)
    except naming.NoDefinitionsError:
        err_msg = 'bad definitions directory: %s' % definitions_directory
        logging.fatal(err_msg)

    # thead-safe list for storing files to write
    manager = context.Manager()
    write_files = manager.list()

    with_errors = False
    if policy_file:
        # render just one file
        logging.info('rendering one file')
        RenderFile(base_directory, policy_file, output_directory, definitions,
                   exp_info, optimize, shade_check, write_files)
    else:
        # render all files in parallel
        logging.info('finding policies...')
        pols = []
        pols.extend(
            DescendRecursively(base_directory, output_directory, definitions,
                               ignore_directories))

        pool = context.Pool(processes=max_renderers)
        results = []
        for pol in pols:
            results.append(
                pool.apply_async(RenderFile,
                                 args=(base_directory, pol.get('in_file'),
                                       pol.get('out_dir'), definitions,
                                       exp_info, optimize, shade_check,
                                       write_files)))
        pool.close()
        pool.join()

        for result in results:
            try:
                result.get()
            except (ACLParserError, ACLGeneratorError) as e:
                with_errors = True
                logging.warning(
                    '\n\nerror encountered in rendering '
                    'process:\n%s\n\n', e)

    # actually write files to disk
    WriteFiles(write_files)

    if with_errors:
        logging.warning('done, with errors.')
        sys.exit(1)
    else:
        logging.info('done.')
Example #10
0
 def testUndefinedTokenNesting(self):
     bad_servicedata = ['FOO = 7/tcp BAR']
     bad_networkdata = ['NETGROUP = 10.0.0.0/8 FOOBAR']
     baddefs = naming.Naming(None)
     baddefs.ParseServiceList(bad_servicedata)
     baddefs.ParseNetworkList(bad_networkdata)
     self.assertRaises(naming.UndefinedServiceError, baddefs._CheckUnseen,
                       'services')
     self.assertRaises(naming.UndefinedAddressError, baddefs._CheckUnseen,
                       'networks')
Example #11
0
    def setUp(self):
        self.defs = naming.Naming(None)
        servicedata = []
        servicedata.append('SSH = 22/tcp')
        networkdata = []
        networkdata.append('NET172 = 172.16.0.0/12')
        networkdata.append('NET10 = 10.0.0.0/8')

        self.defs.ParseServiceList(servicedata)
        self.defs.ParseNetworkList(networkdata)
        self.pol = policy.ParsePolicy(POLICYTEXT, self.defs)
Example #12
0
 def setUp(self):
     """Call before every test case."""
     super().setUp()
     parser = optparse.OptionParser()
     parser.add_option('-d',
                       '--def',
                       dest='definitions',
                       help='definitions directory',
                       default='../def')
     (FLAGS, args) = parser.parse_args()
     self.defs = naming.Naming(FLAGS.definitions)
Example #13
0
  def __init__(self, filename, defs_data=None):
    """Build policy object and naming definitions from provided filenames.

    Args:
      filename: location of a .pol file
      defs_data: location of naming definitions directory, if any
    """
    self.defs = naming.Naming(defs_data)
    self.filter = []
    try:
      self.data = open(filename, 'r').readlines()
    except IOError, error_info:
      info = str(filename) + ' cannot be opened'
      raise FileOpenError('%s\n%s' % (info, error_info))
Example #14
0
    def __init__(self, config: Mapping, device_policies: List[str],
                 netbox: pynetbox.api):
        """Initialize the instance.

        Arguments:
            config (dict): the Homer config.
            device_policies (list): List of Capirca policies to generate.
            netbox (pynetbox.api): the Netbox API instance.

        """
        self._config = config
        self._device_policies = device_policies
        self._public_policies_dir = Path(self._config['base_paths']['public'],
                                         'policies')
        self._private_base_path = self._config['base_paths'].get(
            'private', None)
        definitions_path = Path(self._config['base_paths']['public'],
                                'definitions')
        self.definitions = naming.Naming(str(definitions_path))
        # If we want to use Netbox as network definition source
        if self._config['capirca'].get('netbox_definitons', False) and netbox:
            try:
                script_result = netbox.extras.scripts.get(
                    'capirca.GetHosts').result
                if str(script_result.status) != 'Completed':
                    raise HomerError(
                        'Netbox capirca.GetHosts script status is: {}.'.format(
                            script_result.status))
                runtime = datetime.fromisoformat(
                    script_result.completed[:-1])  # To remove the final Z
                now = datetime.utcnow()
                # Warn the user if the Netbox data is 3 day old or more
                if runtime < now - timedelta(days=3):
                    logger.warning(
                        'Netbox capirca.GetHosts script is > 3 days old.')
                netbox_definitons = script_result.data.output
            except pynetbox.RequestError:
                raise HomerError(
                    'Make sure homer can reach the capirca.GetHosts script on Netbox.'
                )
            # ParseNetworkList expects an array of lines, while Netbox API returns a string with \n
            self.definitions.ParseNetworkList(netbox_definitons.splitlines())
Example #15
0
    def __init__(self, filename, defs_data=None):
        """Build policy object and naming definitions from provided filenames.

    Args:
      filename: location of a .pol file
      defs_data: location of naming definitions directory, if any
    """
        self.defs = naming.Naming(defs_data)
        self.filter = []
        try:
            self.data = open(filename, 'r').readlines()
        except IOError as error_info:
            info = str(filename) + ' cannot be opened'
            raise FileOpenError('%s\n%s' % (info, error_info))

        indent = 0
        in_header = False
        in_term = False
        filt = Filter()
        term = Term()
        in_string = False

        for line in self.data:
            words = line.strip().split()
            quotes = len(line.split('"')) + 1
            if quotes % 2:  # are we in or out of double quotes
                in_string = not in_string  # flip status of quote status
            if not in_string:
                if '{' in words:
                    indent += 1
                if words:
                    if words[0] == 'header':
                        in_header = True
                    if words[0] == 'term':
                        in_term = True
                        term = Term(words[1])
                    if in_header and words[0] == 'target::':
                        if filt.name != words[
                                2]:  # avoid empty dupe filters due to
                            filt = Filter(
                                words[2])  # multiple target header lines
                    if in_term:
                        if words[0] == 'source-address::':
                            term.source.extend(words[1:])
                        if words[0] == 'destination-address::':
                            term.destination.extend(words[1:])
                        if words[0] == 'source-port::':
                            term.sport.extend(words[1:])
                        if words[0] == 'destination-port::':
                            term.dport.extend(words[1:])
                        if words[0] == 'action::':
                            term.action.extend(words[1:])
                        if words[0] == 'protocol::':
                            term.protocol.extend(words[1:])
                        if words[0] == 'option::':
                            term.option.extend(words[1:])

                if '}' in words:
                    indent -= 1
                    if in_header:
                        self.filter.append(filt)
                        in_header = False
                    if in_term:
                        filt.term.append(term)
                        in_term = False
Example #16
0
 def setUp(self):
     self.db = naming.Naming(None)
     self.db.ParseServiceList(_SERVICE.split('\n'))
     self.db.ParseNetworkList(_NETWORK.split('\n'))
Example #17
0
    def testPanPorts(self):
        POL = """
header {
  target:: paloalto from-zone trust to-zone untrust
}
term rule-1 {
%s
  action:: accept
}"""

        T = """
  protocol:: udp
  destination-port:: NTP
"""

        definitions = naming.Naming()
        definitions._ParseLine('NTP = 123/tcp 123/udp', 'services')
        definitions._ParseLine('DNS = 53/tcp 53/udp', 'services')

        pol = policy.ParsePolicy(POL % T, definitions)
        paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
        output = str(paloalto)
        name = "service-rule-1-udp"
        path = "/entry[@name='%s']/protocol/udp/port" % name
        x = paloalto.config.findtext(PATH_SERVICE + path)
        self.assertEqual(x, "123", output)
        path = "/entry[@name='%s']/protocol/udp/source-port" % name
        x = paloalto.config.findtext(PATH_SERVICE + path)
        self.assertIsNone(x, output)

        T = """
  protocol:: udp
  source-port:: NTP
"""

        pol = policy.ParsePolicy(POL % T, definitions)
        paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
        output = str(paloalto)
        name = "service-rule-1-udp"
        path = "/entry[@name='%s']/protocol/udp/port" % name
        x = paloalto.config.findtext(PATH_SERVICE + path)
        self.assertEqual(x, "0-65535", output)
        path = "/entry[@name='%s']/protocol/udp/source-port" % name
        x = paloalto.config.findtext(PATH_SERVICE + path)
        self.assertEqual(x, "123", output)

        T = """
  protocol:: tcp
  source-port:: NTP
  destination-port:: NTP DNS
"""

        pol = policy.ParsePolicy(POL % T, definitions)
        paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
        output = str(paloalto)
        name = "service-rule-1-tcp"
        path = "/entry[@name='%s']/protocol/tcp/port" % name
        x = paloalto.config.findtext(PATH_SERVICE + path)
        self.assertEqual(x, "53,123", output)
        path = "/entry[@name='%s']/protocol/tcp/source-port" % name
        x = paloalto.config.findtext(PATH_SERVICE + path)
        self.assertEqual(x, "123", output)

        T = """
  protocol:: tcp
"""

        pol = policy.ParsePolicy(POL % T, definitions)
        paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
        output = str(paloalto)
        name = "any-tcp"
        path = "/entry[@name='%s']/protocol/tcp/port" % name
        x = paloalto.config.findtext(PATH_SERVICE + path)
        self.assertEqual(x, "0-65535", output)
        path = "/entry[@name='%s']/protocol/tcp/source-port" % name
        x = paloalto.config.find(PATH_SERVICE + path)
        self.assertIsNone(x, output)

        T = """
  protocol:: tcp udp
"""

        pol = policy.ParsePolicy(POL % T, definitions)
        paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
        output = str(paloalto)
        name = "any-tcp"
        path = "/entry[@name='%s']/protocol/tcp/port" % name
        x = paloalto.config.findtext(PATH_SERVICE + path)
        self.assertEqual(x, "0-65535", output)
        name = "any-udp"
        path = "/entry[@name='%s']/protocol/udp/port" % name
        x = paloalto.config.findtext(PATH_SERVICE + path)
        self.assertEqual(x, "0-65535", output)
        x = paloalto.config.findall(PATH_RULES +
                                    "/entry[@name='rule-1']/service/member")
        services = {elem.text for elem in x}
        self.assertEqual({"any-tcp", "any-udp"}, services, output)
Example #18
0
    def testNoAddrObj(self):
        definitions = naming.Naming()
        definitions._ParseLine('NET1 = 10.1.0.0/24', 'networks')
        definitions._ParseLine('NET2 = 10.2.0.0/24', 'networks')
        definitions._ParseLine('NET3 = 10.3.1.0/24', 'networks')
        definitions._ParseLine('       10.3.2.0/24', 'networks')
        definitions._ParseLine('NET4 = 2001:db8:0:aa::/64', 'networks')
        definitions._ParseLine('       2001:db8:0:bb::/64', 'networks')
        definitions._ParseLine('NET5 = NET3 NET4', 'networks')

        POL = """
header {
  target:: paloalto from-zone trust to-zone untrust %s no-addr-obj
}
term rule-1 {
%s
  action:: accept
  protocol:: tcp
}"""

        T = """
  source-address:: NET1
  destination-address:: NET2 NET3
"""

        pol = policy.ParsePolicy(POL % ("inet", T), definitions)
        paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
        output = str(paloalto)
        x = paloalto.config.findall(PATH_RULES +
                                    "/entry[@name='rule-1']/source/member")
        self.assertTrue(len(x) > 0, output)
        addrs = {elem.text for elem in x}
        self.assertEqual({"10.1.0.0/24"}, addrs, output)
        x = paloalto.config.findall(
            PATH_RULES + "/entry[@name='rule-1']/destination/member")
        self.assertTrue(len(x) > 0, output)
        addrs = {elem.text for elem in x}
        self.assertEqual({"10.2.0.0/24", "10.3.1.0/24", "10.3.2.0/24"}, addrs,
                         output)

        T = """
  source-address:: NET4
"""

        pol = policy.ParsePolicy(POL % ("inet6", T), definitions)
        paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
        output = str(paloalto)
        x = paloalto.config.findall(PATH_RULES +
                                    "/entry[@name='rule-1']/source/member")
        self.assertTrue(len(x) > 0, output)
        addrs = {elem.text for elem in x}
        self.assertEqual({"2001:db8:0:aa::/64", "2001:db8:0:bb::/64"}, addrs,
                         output)
        x = paloalto.config.findall(
            PATH_RULES + "/entry[@name='rule-1']/destination/member")
        self.assertTrue(len(x) > 0, output)
        addrs = {elem.text for elem in x}
        self.assertEqual({"any"}, addrs, output)

        T = """
  destination-address:: NET5
"""

        pol = policy.ParsePolicy(POL % ("mixed", T), definitions)
        paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
        output = str(paloalto)
        x = paloalto.config.findall(PATH_RULES +
                                    "/entry[@name='rule-1']/source/member")
        self.assertTrue(len(x) > 0, output)
        addrs = {elem.text for elem in x}
        self.assertEqual({"any"}, addrs, output)
        x = paloalto.config.findall(
            PATH_RULES + "/entry[@name='rule-1']/destination/member")
        self.assertTrue(len(x) > 0, output)
        addrs = {elem.text for elem in x}
        self.assertEqual(
            {
                "10.3.1.0/24", "10.3.2.0/24", "2001:db8:0:aa::/64",
                "2001:db8:0:bb::/64"
            }, addrs, output)

        POL = """
header {
  target:: paloalto from-zone trust to-zone untrust inet no-addr-obj
}
term rule-1 {
  source-address:: NET1 NET2
  action:: accept
  protocol:: tcp
}
header {
  target:: paloalto from-zone trust to-zone untrust inet addr-obj
}
term rule-1 {
  destination-address:: NET3
  action:: accept
  protocol:: tcp
}"""

        pol = policy.ParsePolicy(POL, definitions)
        self.assertRaisesRegex(
            paloaltofw.UnsupportedHeaderError,
            '^Cannot mix addr-obj and no-addr-obj header '
            'option in a single policy file$', paloaltofw.PaloAltoFW, pol,
            EXP_INFO)
Example #19
0
def _init_definitions(definitions_or_path):
    # type: (Union[str, naming.Naming]) -> naming.Naming
    if isinstance(definitions_or_path, naming.Naming):
        return definitions_or_path

    return naming.Naming(naming_dir=definitions_or_path)
Example #20
0
 def testParseServiceFile(self):
     filedefs = naming.Naming(None)
     data = io.BytesIO('HTTP = 80/tcp\n'.encode('utf8'))
     filedefs._ParseFile(data, 'services')
     self.assertEqual(filedefs.GetService('HTTP'), ['80/tcp'])
Example #21
0
    def testPanApplication(self):
        POL1 = """
header {
  target:: paloalto from-zone trust to-zone untrust
}
term rule-1 {
  action:: accept
}"""

        POL2 = """
header {
  target:: paloalto from-zone trust to-zone untrust
}
term rule-1 {
  pan-application:: %s
  action:: accept
  %s
}"""

        APPS = [
            {'app1'},
            {'app1', 'app2'},
            {'app1', 'app2', 'app3'},
        ]

        POL3 = """
header {
  target:: paloalto from-zone trust to-zone untrust
}
term rule-1 {
  pan-application:: web-browsing
  action:: accept%s
}"""

        T0 = ''
        T1 = """
  protocol:: tcp
"""
        T2 = """
  protocol:: tcp
  destination-port:: PORT1 PORT2
"""

        POL4 = """
header {
  target:: paloalto from-zone trust to-zone untrust %s
}
term rule-1 {
  pan-application:: web-browsing
  action:: accept
  protocol:: %s
}"""

        POL5 = """
header {
  target:: paloalto from-zone trust to-zone untrust
}
term rule-1 {
  pan-application:: web-browsing
  action:: accept
  protocol:: icmp
  icmp-type:: echo-request
}"""

        POL6 = """
header {
  target:: paloalto from-zone trust to-zone untrust
}
term rule-1 {
  pan-application:: web-browsing
  protocol:: tcp icmp
  destination-port:: PORT1
  action:: accept
}"""

        pol = policy.ParsePolicy(POL1, self.naming)
        paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
        output = str(paloalto)
        x = paloalto.config.findtext(
            PATH_RULES + "/entry[@name='rule-1']/application/member")
        self.assertEqual(x, 'any', output)

        for i, app in enumerate(APPS):
            pol = policy.ParsePolicy(POL2 % (' '.join(app), ''), self.naming)
            paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
            output = str(paloalto)
            x = paloalto.config.findall(
                PATH_RULES + "/entry[@name='rule-1']/application/member")
            apps = {elem.text for elem in x}
            self.assertEqual(APPS[i], apps, output)

        for i, app in enumerate(APPS):
            pol = policy.ParsePolicy(POL2 % (' '.join(app), 'protocol:: tcp'),
                                     self.naming)
            paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
            output = str(paloalto)
            x = paloalto.config.findall(
                PATH_RULES + "/entry[@name='rule-1']/application/member")
            apps = {elem.text for elem in x}
            self.assertEqual(APPS[i], apps, output)

        pol = policy.ParsePolicy(POL3 % T0, self.naming)
        paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
        output = str(paloalto)
        x = paloalto.config.findtext(PATH_RULES +
                                     "/entry[@name='rule-1']/service/member")
        self.assertEqual(x, 'application-default', output)

        pol = policy.ParsePolicy(POL3 % T1, self.naming)
        paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
        output = str(paloalto)
        x = paloalto.config.findtext(PATH_RULES +
                                     "/entry[@name='rule-1']/service/member")
        self.assertEqual(x, 'any-tcp', output)

        definitions = naming.Naming()
        definitions._ParseLine('PORT1 = 8080/tcp', 'services')
        definitions._ParseLine('PORT2 = 8081/tcp', 'services')
        pol = policy.ParsePolicy(POL3 % T2, definitions)
        paloalto = paloaltofw.PaloAltoFW(pol, EXP_INFO)
        output = str(paloalto)
        x = paloalto.config.findtext(PATH_RULES +
                                     "/entry[@name='rule-1']/service/member")
        self.assertEqual(x, 'service-rule-1-tcp', output)

        regex = ('^Term rule-1 contains non tcp, udp protocols '
                 'with pan-application:')
        pol = policy.ParsePolicy(POL4 % ('inet', 'tcp icmp'), self.naming)
        self.assertRaisesRegex(paloaltofw.UnsupportedFilterError, regex,
                               paloaltofw.PaloAltoFW, pol, EXP_INFO)

        pol = policy.ParsePolicy(POL4 % ('inet6', 'icmpv6'), self.naming)
        self.assertRaisesRegex(paloaltofw.UnsupportedFilterError, regex,
                               paloaltofw.PaloAltoFW, pol, EXP_INFO)

        pol = policy.ParsePolicy(POL5, self.naming)
        self.assertRaisesRegex(paloaltofw.UnsupportedFilterError, regex,
                               paloaltofw.PaloAltoFW, pol, EXP_INFO)

        self.assertRaisesRegex(
            policy.MixedPortandNonPortProtos,
            '^Term rule-1 contains mixed uses of protocols '
            'with and without port numbers', policy.ParsePolicy, POL6,
            definitions)
Example #22
0
 def testParseNetFile(self):
     filedefs = naming.Naming(None)
     data = ['FOO = 127.0.0.1 # some network\n']
     filedefs._ParseFile(data, 'networks')
     self.assertEqual(filedefs.GetNetAddr('FOO'),
                      [nacaddr.IPv4('127.0.0.1')])
Example #23
0
def Run(base_directory: str, definitions_directory: str, policy_file: str,
        output_directory: str, exp_info: int, max_renderers: int,
        ignore_directories: List[str], optimize: bool, shade_check: bool,
        context: multiprocessing.context.BaseContext):
    """Generate ACLs.

  Args:
    base_directory: directory containing policy files.
    definitions_directory: directory containing NETWORK and SERVICES definition
      files.
    policy_file: path to a single policy file to render.
    output_directory: directory in which rendered files are placed.
    exp_info: print a info message when a term is set to expire in that many
      weeks.
    max_renderers: the number of renderers to run in parallel.
    ignore_directories: directories to ignore when searching for policy files.
    optimize: a boolean indicating if we should turn on optimization or not.
    shade_check: should we raise an error if a term is completely shaded.
    context: multiprocessing context
  """
    definitions = None
    try:
        definitions = naming.Naming(definitions_directory)
    except naming.NoDefinitionsError:
        err_msg = 'bad definitions directory: %s' % definitions_directory
        logging.fatal(err_msg)
        return  # static type analyzer can't detect that logging.fatal exits program

    # thead-safe list for storing files to write
    manager: multiprocessing.managers.SyncManager = context.Manager()
    write_files: WriteList = manager.list()

    with_errors = False
    logging.info('finding policies...')
    if policy_file:
        # render just one file
        logging.info('rendering one file')
        RenderFile(base_directory, pathlib.Path(policy_file),
                   pathlib.Path(output_directory), definitions, exp_info,
                   optimize, shade_check, write_files)
    elif max_renderers == 1:
        # If only one process, run it sequentially
        policies = DescendDirectory(base_directory, ignore_directories)
        for pol in policies:
            RenderFile(base_directory, pol, pathlib.Path(output_directory),
                       definitions, exp_info, optimize, shade_check,
                       write_files)
    else:
        # render all files in parallel
        policies = DescendDirectory(base_directory, ignore_directories)
        pool = context.Pool(processes=max_renderers)
        results: List[multiprocessing.pool.AsyncResult] = []
        for pol in policies:
            results.append(
                pool.apply_async(RenderFile,
                                 args=(base_directory, pol, output_directory,
                                       definitions, exp_info, optimize,
                                       shade_check, write_files)))
        pool.close()
        pool.join()

        for result in results:
            try:
                result.get()
            except (ACLParserError, ACLGeneratorError) as e:
                with_errors = True
                logging.warning(
                    '\n\nerror encountered in rendering process:\n%s\n\n', e)

    # actually write files to disk
    WriteFiles(write_files)

    if with_errors:
        logging.warning('done, with errors.')
        sys.exit(1)
    else:
        logging.info('done.')
Example #24
0
def main(argv):
    """Determines the code path based on the arguments passed."""
    del argv  # Unused.
    parser = cli_options()
    options = parser.parse_args()
    db = naming.Naming(options.defs)
    p = pprint.PrettyPrinter(indent=1, depth=4, width=1).pprint

    # if -i and any other option:
    if options.ip and any(
        [options.gmp, options.cmp, options.obj, options.svc, options.port]):
        logging.info('You can only use -i with -t or by itself')

    # if -i and -t
    elif options.token and options.ip:
        try:
            get_nets([options.token], db)
        except naming.UndefinedAddressError:
            logging.info("Network group '%s' is not defined!", options.token)
        else:
            results = compare_ip_token(options, db)
            logging.info(results)

    # if -t, but not -i; invalid!
    elif options.token and not options.ip:
        logging.info('You must specify an IP Address with -i [addr]')

    # if -i
    elif options.ip:
        for ip in options.ip:
            groups = get_ip_parents(ip, db)
            logging.info('Results for IP: %s', ip)
            # iterate and print the tokens we found.
            for name, networks in groups:
                # print the group name [0], and the networks it was in [1]
                logging.info('%s  %s', name, networks)

    elif options.gmp:
        common, diff1, diff2 = group_diff(options, db)
        print_diff(options.gmp[0], common, diff1, diff2)
        logging.info('')
        print_diff(options.gmp[1], common, diff2, diff1)

    # if -c
    elif options.cmp:
        meta, results = compare_tokens(options, db)
        first_name = meta[0]
        second_name = meta[1]
        union = meta[2]
        logging.info('Union of %s and %s:\n %s\n', first_name, second_name,
                     union)
        logging.info('Diff of %s and %s:', first_name, second_name)
        for i in results:
            logging.info(' %s', i)
        logging.info('')
        first_obj, sec_obj = options.cmp
        if check_encapsulated('network', first_obj, sec_obj, db):
            logging.info('%s fully encapsulates %s', sec_obj, first_obj)
        else:
            logging.info('%s does _not_ fully encapsulate %s', sec_obj,
                         first_obj)
        # check the other way around.
        if check_encapsulated('network', sec_obj, first_obj, db):
            logging.info('%s fully encapsulates %s', first_obj, sec_obj)
        else:
            logging.info('%s does _not_ fully encapsulate %s', first_obj,
                         sec_obj)

    # if -o
    elif options.obj:
        for obj in options.obj:
            try:
                token, ips = get_nets([obj], db)[0]
            except naming.UndefinedAddressError:
                logging.info('%s is an invalid object', obj)
            else:
                logging.info('%s:', token)
                # convert list of ip objects to strings and sort them
                ips.sort(key=lambda x: int(x.ip))
                p([str(x) for x in ips])

    # if -s
    elif options.svc:
        try:
            results = get_ports(options.svc, db)
        except naming.UndefinedServiceError:
            logging.info('%s contains an invalid service object',
                         str(options.svc))
        else:
            for result in get_ports(options.svc, db):
                svc, port = result
                logging.info('%s:', svc)
                p(port)

    # if -p
    elif options.port:
        port, protocol, result = get_services(options, db)
        logging.info('%s/%s:', port, protocol)
        p(result)

    # if nothing is passed
    elif not any((options.cmp, options.ip, options.token, options.obj,
                  options.svc, options.port)):
        parser.print_help()
    logging.info('')
Example #25
0
def get_acl(inputs):
    """Generates an ACL using Capirca.
    Args:
      inputs: Module parameters.
    Returns:
      ACL string.
    """
    header_base = '''
    header {
      comment:: "$comment"
      target:: $platform $options
    }
    '''
    result = ""

    # Create copy of input options removing any spaces
    inputs['options_copy'] = [
        str(elem).replace(" ", "") for elem in inputs['filter_options']
    ]

    # Add from/to-zone to 'paloalto' and 'srx'.
    if inputs['platform'] in ('paloalto' 'srx'):
        if len(inputs['options_copy']) < 2:
            raise AnsibleError(
                "The number of options for {0} is less than 2".format(
                    inputs['platform']))

        inputs['options_copy'][0] = "from-zone " + inputs['options_copy'][0]
        inputs['options_copy'][1] = "to-zone " + inputs['options_copy'][1]

    # Create option string for header
    inputs['options'] = ' '.join(
        [str(elem) for elem in inputs['options_copy']])

    header_template = Template(header_base)
    header = header_template.safe_substitute(inputs)

    defs = naming.Naming(inputs['def_folder'])
    terms = open(inputs['pol_file']).read()
    pol = policy.ParsePolicy(header + '\n' + terms, defs, optimize=True)

    # Exp info in weeks
    EXP_INFO = 2

    # List from https://github.com/google/capirca/blob/master/capirca/aclgen.py#L202
    # Does Python have a Switch statement?
    if inputs['platform'] == 'juniper':
        result = juniper.Juniper(pol, EXP_INFO)
    elif inputs['platform'] == 'cisco':
        result = cisco.Cisco(pol, EXP_INFO)
    elif inputs['platform'] == 'ciscoasa':
        result = ciscoasa.CiscoASA(pol, EXP_INFO)
    elif inputs['platform'] == 'brocade':
        result = brocade.Brocade(pol, EXP_INFO)
    elif inputs['platform'] == 'arista':
        result = arista.Arista(pol, EXP_INFO)
    elif inputs['platform'] == 'aruba':
        result = aruba.Aruba(pol, EXP_INFO)
    elif inputs['platform'] == 'ipset':
        result = ipset.Ipset(pol, EXP_INFO)
    elif inputs['platform'] == 'iptables':
        result = iptables.Iptables(pol, EXP_INFO)
    elif inputs['platform'] == 'nsxv':
        result = nsxv.Nsxv(pol, EXP_INFO)
    elif inputs['platform'] == 'packetfilter':
        result = packetfilter.PacketFilter(pol, EXP_INFO)
    elif inputs['platform'] == 'pcap':
        result = pcap.PcapFilter(pol, EXP_INFO)
    elif inputs['platform'] == 'speedway':
        result = speedway.Speedway(pol, EXP_INFO)
    elif inputs['platform'] == 'srx':
        result = junipersrx.JuniperSRX(pol, EXP_INFO)
    elif inputs['platform'] == 'srxlo':
        result = srxlo.SRXlo(pol, EXP_INFO)
    elif inputs['platform'] == 'windows_advfirewall':
        result = windows_advfirewall.WindowsAdvFirewall(pol, EXP_INFO)
    elif inputs['platform'] == 'ciscoxr':
        result = ciscoxr.CiscoXR(pol, EXP_INFO)
    elif inputs['platform'] == 'nftables':
        result = nftables.Nftables(pol, EXP_INFO)
    elif inputs['platform'] == 'gce':
        result = gce.GCE(pol, EXP_INFO)
    elif inputs['platform'] == 'paloalto':
        result = paloaltofw.PaloAltoFW(pol, EXP_INFO)
    elif inputs['platform'] == 'cloudarmor':
        result = cloudarmor.CloudArmor(pol, EXP_INFO)

    return str(result)
Example #26
0
 def testParseServiceFile(self):
     filedefs = naming.Naming(None)
     data = ['HTTP = 80/tcp\n']
     filedefs._ParseFile(data, 'services')
     self.assertEqual(filedefs.GetService('HTTP'), ['80/tcp'])
Example #27
0
def main(unused_argv):
    if FLAGS.verbose:
        logging.basicConfig(level=logging.INFO)
    if FLAGS.debug:
        logging.basicConfig(level=logging.DEBUG)
    logging.debug(
        'binary: %s\noptimize: %d\nbase_directory: %s\n'
        'policy_file: %s\nrendered_acl_directory: %s', str(sys.argv[0]),
        int(FLAGS.optimize), str(FLAGS.base_directory), str(FLAGS.policy_file),
        str(FLAGS.output_directory))

    definitions = None
    try:
        definitions = naming.Naming(FLAGS.definitions_directory)
    except naming.NoDefinitionsError:
        err_msg = 'bad definitions directory: %s' % FLAGS.definitions_directory
        logging.fatal(err_msg)

    # thead-safe list for storing files to write
    manager = multiprocessing.Manager()
    write_files = manager.list()

    with_errors = False
    if FLAGS.policy_file:
        # render just one file
        logging.info('rendering one file')
        RenderFile(FLAGS.policy_file, FLAGS.output_directory, definitions,
                   FLAGS.exp_info, write_files)
    else:
        # render all files in parallel
        logging.info('finding policies...')
        pols = []
        pols.extend(
            DescendRecursively(FLAGS.base_directory, FLAGS.output_directory,
                               definitions))

        pool = multiprocessing.Pool(processes=FLAGS.max_renderers)
        results = []
        for x in pols:
            results.append(
                pool.apply_async(RenderFile,
                                 args=(x.get('in_file'), x.get('out_dir'),
                                       definitions, FLAGS.exp_info,
                                       write_files)))
        pool.close()
        pool.join()

        for result in results:
            try:
                result.get()
            except (ACLParserError, ACLGeneratorError) as e:
                with_errors = True
                logging.warn(
                    '\n\nerror encountered in rendering process:\n%s\n\n', e)

    # actually write files to disk
    WriteFiles(write_files)

    if with_errors:
        logging.warn('done, with errors.')
        sys.exit(1)
    else:
        logging.info('done.')