Exemple #1
0
def test_load_attribute_required():
    attr = Model.load(None, ET.fromstring('<test:RequiredAttributeFixture xmlns:test="http://jaymes.biz/test" required_attribute="test" />'))
    assert isinstance(attr, RequiredAttributeFixture)
    assert hasattr(attr, 'required_attribute')
    assert attr.required_attribute == 'test'

    with pytest.raises(RequiredAttributeException):
        attr = Model.load(None, ET.fromstring('<test:RequiredAttributeFixture xmlns:test="http://jaymes.biz/test" />'))
Exemple #2
0
def test_load_root_model():
    root = Model.load(None, ET.fromstring('<test:RootFixture xmlns:test="http://jaymes.biz/test" />'))
    assert isinstance(root, RootFixture)

    with pytest.raises(UnregisteredNamespaceException):
        Model.load(None, ET.fromstring('<test:RootFixture xmlns:test="http://jaymes.biz/derp" />'))

    with pytest.raises(TagMappingException):
        Model.load(None, ET.fromstring('<test:Derp xmlns:test="http://jaymes.biz/test" />'))
    def resolve(self, benchmark):
        ### Loading.Resolve.Items

        # For each Item in the Benchmark that has an extends property, resolve
        # it by using the following steps:
        if self.extends is None:
            logger.debug('Extendable not extending: ' + self.id)
            return

        # (2) resolve the extended Item,
        extended = self.get_extended(benchmark)
        logger.debug('Found extended Extendable: ' + extended.id)
        extended.resolve(benchmark)

        # (3) prepend the property sequence from the extended Item to the
        # extending Item,
        # (5) remove duplicate properties and apply property overrides, and
        for name in self.model_map['attributes']:
            attr_map = self.model_map['attributes'][name]
            if 'ignore' in attr_map and attr_map['ignore']:
                continue

            if 'in' in attr_map:
                attr_name = attr_map['in']
            else:
                xml_namespace, attr_name = Model.parse_tag(name)
                attr_name = attr_name.replace('-', '_')
            self.resolve_property(extended, attr_name)

        for tag in self.model_map['elements']:
            xml_namespace, tag_name = Model.parse_tag(tag)
            if tag.endswith('*'):
                continue

            tag_map = self.model_map['elements'][tag]
            if 'ignore' in tag_map and tag_map['ignore']:
                continue

            if 'append' in tag_map:
                self.resolve_property(extended, tag_map['append'])
            elif 'map' in tag_map:
                self.resolve_property(extended, tag_map['map'])
            else:
                if 'in' in tag_map:
                    name = tag_map['in']
                else:
                    name = tag_name.replace('-', '_')
            self.resolve_property(extended, name)

        # (6) remove the extends property.
        self.extends = None
Exemple #4
0
def test_namespace_registration():
    Model.register_namespace('scap.model.derp', 'http://jaymes.biz/derp')

    Model.xmlns_to_package('http://jaymes.biz/derp') == 'scap.model.derp'

    Model.unregister_namespace('scap.model.derp')

    with pytest.raises(UnregisteredNamespaceException):
        Model.xmlns_to_package('http://jaymes.biz/derp')
Exemple #5
0
def test_load_element_min():
    el = Model.load(None, ET.fromstring('''
        <test:MinMaxElementFixture xmlns:test="http://jaymes.biz/test">
        <test:min>test1</test:min>
        <test:min>test2</test:min>
        <test:min>test3</test:min>
        <test:max>test4</test:max>
        <test:max>test5</test:max>
        </test:MinMaxElementFixture>
        '''))
    assert isinstance(el, MinMaxElementFixture)

    assert hasattr(el, 'min')
    assert isinstance(el.min, ModelList)
    assert len(el.min) == 3
    assert el.min[0].text == 'test1'
    assert el.min[1].text == 'test2'
    assert el.min[2].text == 'test3'

    assert hasattr(el, 'max')
    assert isinstance(el.max, ModelList)
    assert len(el.max) == 2
    assert el.max[0].text == 'test4'
    assert el.max[1].text == 'test5'

    with pytest.raises(MinimumElementException):
        el = Model.load(None, ET.fromstring('''
            <test:MinMaxElementFixture xmlns:test="http://jaymes.biz/test">
            <test:min>test1</test:min>
            <test:max>test4</test:max>
            <test:max>test5</test:max>
            </test:MinMaxElementFixture>
            '''))

    with pytest.raises(MaximumElementException):
        el = Model.load(None, ET.fromstring('''
            <test:MinMaxElementFixture xmlns:test="http://jaymes.biz/test">
            <test:min>test1</test:min>
            <test:min>test2</test:min>
            <test:min>test3</test:min>
            <test:max>test4</test:max>
            <test:max>test5</test:max>
            <test:max>test6</test:max>
            </test:MinMaxElementFixture>
            '''))
Exemple #6
0
def test_simple_remote():
    model = Model.load(None, ET.fromstring('<test:XLinkFixture ' +
        'xmlns:test="http://jaymes.biz/test" ' +
        'xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" ' +
        'xlink:href="http://jaymes.biz/test.xml" />'))
    assert isinstance(model._elements, ModelList)
    assert len(model._elements) > 0
    assert isinstance(model._elements[0], RootFixture)
    assert isinstance(model._elements[0].EnclosedFixture, EnclosedFixture)
Exemple #7
0
    def resolve(self, benchmark):
        ### Loading.Resolve.Items

        # For each Item in the Benchmark that has an extends property, resolve
        # it by using the following steps:

        # (1) if the Item is Group, resolve all the enclosed Items,
        for item_id in self.items:
            logger.debug('Resolving item: ' + item_id)
            self.items[item_id].resolve(benchmark)

        # (2) resolve the extended Item,
        if self.extends is None:
            return

        extended = self.get_extended(benchmark)
        extended.resolve(benchmark)

        # (3) prepend the property sequence from the extended Item to the
        # extending Item,
        # (5) remove duplicate properties and apply property overrides, and
        for name in self._model_map['attributes']:
            attr_map = self._model_map['attributes'][name]

            if 'in' in attr_map:
                attr_name = attr_map['in']
            else:
                xmlns, attr_name = Model.parse_tag(name)
                attr_name = attr_name.replace('-', '_')
            self.resolve_property(extended, attr_name)

        for element_def in self._model_map['elements']:
            if element_def['tag_name'].endswith('*'):
                continue

            if 'list' in element_def:
                self.resolve_property(extended, element_def['list'])
            elif 'dict' in element_def:
                self.resolve_property(extended, element_def['dict'])
            else:
                if 'in' in element_def:
                    name = element_def['in']
                else:
                    name = element_def['tag_name'].replace('-', '_')
            self.resolve_property(extended, name)

        # (4) if the Item is a Group, assign values for the id properties of
        # Items copied from the extended Group,
        if hasattr(extended, 'items') and len(extended.items) > 0:
            for ext_item in extended.items:
                # make a copy of the item and append to our items
                self.items.append(ext_item.copy())

        # (6) remove the extends property.
        self.extends = None
    def check(self, benchmark, host, exports, import_names):
        content = Model.find_content(self.href)
        if content is None:
            raise ReferenceException(self.href + ' was not loaded')

        # find the named content
        if self.name is not None:
            content = content.find_reference(self.name)

        # apply content
        return content.check(host, exports, import_names)
Exemple #9
0
def test_simple_remote():
    model = Model.load(
        None,
        ET.fromstring(
            '<test:XLinkFixture ' + 'xmlns:test="http://jaymes.biz/test" ' +
            'xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" ' +
            'xlink:href="http://jaymes.biz/test.xml" />'))
    assert isinstance(model._elements, ModelList)
    assert len(model._elements) > 0
    assert isinstance(model._elements[0], RootFixture)
    assert isinstance(model._elements[0].EnclosedFixture, EnclosedFixture)
Exemple #10
0
def test_load_enclosed_model():
    root = RootFixture()
    el = Model.load(root, ET.fromstring('<test:EnclosedFixture xmlns:test="http://jaymes.biz/test" />'))
    assert isinstance(el, EnclosedFixture)

    el = Model.load(root, ET.fromstring('<EnclosedFixture />'))
    assert isinstance(el, EnclosedFixture)

    with pytest.raises(UnregisteredNamespaceException):
        Model.load(root, ET.fromstring('<test:EnclosedFixture xmlns:test="http://jaymes.biz/derp" />'))
    with pytest.raises(UnregisteredNamespaceException):
        Model.load(None, ET.fromstring('<EnclosedFixture />'))
    with pytest.raises(TagMappingException):
        Model.load(root, ET.fromstring('<Derp />'))
Exemple #11
0
def test_oval_5_3_detected():
    test_xml = '<oval_definitions ' + \
        'xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5" ' + \
        'xmlns:oval="http://oval.mitre.org/XMLSchema/oval-common-5" ' + \
        'xmlns:oval-def="http://oval.mitre.org/XMLSchema/oval-definitions-5">' + \
        '<generator>' + \
        '<oval:product_name>The OVAL Repository</oval:product_name>' + \
        '<oval:schema_version>5.3</oval:schema_version>' + \
        '<oval:timestamp>2008-04-10T09:00:10.653-04:00</oval:timestamp>' + \
      '</generator>' + \
      '</oval_definitions>'
    model = Model.load(None, ET.fromstring(test_xml))
    from scap.model.oval_5.defs.OvalDefinitionsElement import OvalDefinitionsElement
    assert isinstance(model, OvalDefinitionsElement)
Exemple #12
0
def test_simple_local():
    path = (
        pathlib.Path(str(pytest.config.rootdir)) / 'tests' / 'model' / 'test_xlink.xml'
    ).as_posix()
    if not path.startswith('/'):
        path = '/' + path
    model = Model.load(None, ET.fromstring('<test:XLinkFixture ' +
        'xmlns:test="http://jaymes.biz/test" ' +
        'xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" ' +
        'xlink:href="file://' + path + '" />'))
    assert isinstance(model._elements, ModelList)
    assert len(model._elements) > 0
    assert isinstance(model._elements[0], RootFixture)
    assert isinstance(model._elements[0].EnclosedFixture, EnclosedFixture)
Exemple #13
0
def test_load_element_wildcard_not_in():
    el = Model.load(None, ET.fromstring('''
        <test:WildcardElementNotInFixture xmlns:test2="http://jaymes.biz/test2" xmlns:test="http://jaymes.biz/test">
        <test:wildcard_element>test1</test:wildcard_element>
        <test2:wildcard_element>test2</test2:wildcard_element>
        </test:WildcardElementNotInFixture>
        '''))
    assert isinstance(el, WildcardElementNotInFixture)
    assert hasattr(el, '_elements')
    assert isinstance(el._elements, ModelList)
    assert len(el._elements) == 2
    assert isinstance(el._elements[0], EnclosedFixture)
    assert isinstance(el._elements[1], EnclosedFixture2)
    assert el._elements[0].text == 'test1'
    assert el._elements[1].text == 'test2'
Exemple #14
0
def test_simple_local():
    path = (pathlib.Path(str(pytest.config.rootdir)) / 'tests' / 'model' /
            'test_xlink.xml').as_posix()
    if not path.startswith('/'):
        path = '/' + path
    model = Model.load(
        None,
        ET.fromstring(
            '<test:XLinkFixture ' + 'xmlns:test="http://jaymes.biz/test" ' +
            'xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" ' +
            'xlink:href="file://' + path + '" />'))
    assert isinstance(model._elements, ModelList)
    assert len(model._elements) > 0
    assert isinstance(model._elements[0], RootFixture)
    assert isinstance(model._elements[0].EnclosedFixture, EnclosedFixture)
Exemple #15
0
def test_load_element_map_value_type():
    el = Model.load(None, ET.fromstring('''
        <test:MapElementFixture xmlns:test="http://jaymes.biz/test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <test:map_value_type id="test1">test1</test:map_value_type>
        <test:map_value_type id="test2">test2</test:map_value_type>
        </test:MapElementFixture>
        '''))

    assert isinstance(el, MapElementFixture)

    assert hasattr(el, 'map_value_type')
    assert len(el.map_value_type) == 2

    assert 'test1' in el.map_value_type
    assert el.map_value_type['test1'] == 'test1'

    assert 'test2' in el.map_value_type
    assert el.map_value_type['test2'] == 'test2'
Exemple #16
0
def test_load_element_append_nil():
    el = Model.load(None, ET.fromstring('''
        <test:AppendElementFixture xmlns:test="http://jaymes.biz/test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <test:append_nil xsi:nil="true" />
        <test:append_nil>test2</test:append_nil>
        </test:AppendElementFixture>
        '''))

    assert isinstance(el, AppendElementFixture)

    assert hasattr(el, 'append_nil')
    assert isinstance(el.append_nil, ModelList)
    assert len(el.append_nil) == 2

    assert el.append_nil[0] is None

    assert isinstance(el.append_nil[1], EnclosedFixture)
    assert el.append_nil[1].text == 'test2'
def test_def():
    test_xml = '''<?xml version="1.0" encoding="UTF-8"?>
<oval_definitions
    xmlns:unix-def="http://oval.mitre.org/XMLSchema/oval-definitions-5#unix"
    xmlns:ind-def="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent"
    xmlns:lin-def="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux"
    xmlns:oval="http://oval.mitre.org/XMLSchema/oval-common-5"
    xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
	<generator>
		<oval:product_name>Text Editors</oval:product_name>
		<oval:schema_version>5.8</oval:schema_version>
		<oval:timestamp>2013-12-17T12:00:00-04:00</oval:timestamp>
	</generator>
	<definitions>
    		<definition class="compliance" id="oval:gov.nist.usgcb.rhel:def:20000" version="2">
    			<metadata>
    				<title>Ensure that /tmp has its own partition or logical volume</title>
    				<description>The /tmp directory is a world-writable directory used for temporary file storage. Verify that it has its own partition or logical volume.</description>
    			</metadata>
    			<criteria>
    				<!-- <criterion test_ref="oval:gov.nist.usgcb.rhel:tst:20000" comment="Check in /etc/fstab for a /tmp mount point"/> -->
    				<criterion test_ref="oval:gov.nist.usgcb.rhel:tst:2000000" comment="Check if /tmp partition exists"/>
    			</criteria>
    		</definition>
	</definitions>
	<tests>
		<lin-def:partition_test id="oval:gov.nist.usgcb.rhel:tst:2000000" comment="Check if /tmp partition exists" check_existence="at_least_one_exists" check="at least one" version="1">
			<lin-def:object object_ref="oval:gov.nist.usgcb.rhel:obj:144120"/>
		</lin-def:partition_test>
    </tests>
    <objects>
		<lin-def:partition_object version="1" id="oval:gov.nist.usgcb.rhel:obj:144120">
			<lin-def:mount_point>/tmp</lin-def:mount_point>
		</lin-def:partition_object>
    </objects>
	<states>
	</states>
	<variables>
	</variables>
</oval_definitions>'''
    model = Model.load(None, ET.fromstring(test_xml))
    from scap.model.oval_5.defs.OvalDefinitionsElement import OvalDefinitionsElement
    assert isinstance(model, OvalDefinitionsElement)
Exemple #18
0
    def resolve(self, benchmark):
        ### Loading.Resolve.Items

        # For each Item in the Benchmark that has an extends property, resolve
        # it by using the following steps:
        if self.extends is None:
            logger.debug('Extendable not extending: ' + self.id)
            return

        # (2) resolve the extended Item,
        extended = self.get_extended(benchmark)
        logger.debug('Found extended Extendable: ' + extended.id)
        extended.resolve(benchmark)

        # (3) prepend the property sequence from the extended Item to the
        # extending Item,
        # (5) remove duplicate properties and apply property overrides, and
        for name in self._model_map['attributes']:
            attr_map = self._model_map['attributes'][name]

            if 'in' in attr_map:
                attr_name = attr_map['in']
            else:
                xmlns, attr_name = Model.parse_tag(name)
                attr_name = attr_name.replace('-', '_')
            self.resolve_property(extended, attr_name)

        for element_def in self._model_map['elements']:
            if element_def['tag_name'].endswith('*'):
                continue

            if 'list' in element_def:
                self.resolve_property(extended, element_def['list'])
            elif 'dict' in tag_map:
                self.resolve_property(extended, element_def['dict'])
            else:
                if 'in' in element_def:
                    name = element_def['in']
                else:
                    name = element_def['tag_name'].replace('-', '_')
            self.resolve_property(extended, name)

        # (6) remove the extends property.
        self.extends = None
Exemple #19
0
def test_load_element_append_class():
    el = Model.load(None, ET.fromstring('''
        <test:AppendElementFixture xmlns:test="http://jaymes.biz/test">
        <test:append_class>test1</test:append_class>
        <test:append_class>test2</test:append_class>
        </test:AppendElementFixture>
        '''))

    assert isinstance(el, AppendElementFixture)

    assert hasattr(el, 'append_class')
    assert isinstance(el.append_class, ModelList)
    assert len(el.append_class) == 2

    assert isinstance(el.append_class[0], EnclosedFixture)
    assert el.append_class[0].text == 'test1'

    assert isinstance(el.append_class[1], EnclosedFixture)
    assert el.append_class[1].text == 'test2'
Exemple #20
0
def test_load_element_append_type():
    el = Model.load(None, ET.fromstring('''
        <test:AppendElementFixture xmlns:test="http://jaymes.biz/test">
        <test:append_type>1.1</test:append_type>
        <test:append_type>1.2</test:append_type>
        </test:AppendElementFixture>
        '''))

    assert isinstance(el, AppendElementFixture)

    assert hasattr(el, 'append_type')
    assert isinstance(el.append_type, ModelList)
    assert len(el.append_type) == 2

    assert isinstance(el.append_type[0], float)
    assert el.append_type[0] == 1.1

    assert isinstance(el.append_type[1], float)
    assert el.append_type[1] == 1.2
Exemple #21
0
def test_in_and_out():
    test_xml = b'<test:InitFixture xmlns:test="http://jaymes.biz/test" xmlns:test2="http://jaymes.biz/test2">' + \
        b'<test:list id="test1" />' + \
        b'<test:list id="test2" />' + \
        b'<test:list id="test3" />' + \
        b'<test:dict id="test4" />' + \
        b'<test:dict id="test5" />' + \
        b'<test:dict id="test6" />' + \
        b'<test:dict id="test7" />' + \
        b'<test:dict id="test8" />' + \
        b'<test:in_test id="test9" />' + \
        b'<test:dash-test id="test10" />' + \
        b'<test2:wildcard_element id="test11" />' + \
        b'<test:wildcard_element id="test12" />' + \
        b'<test:dict id="test13" />' + \
        b'<test:list id="test14" />' + \
        b'</test:InitFixture>'
    model = Model.load(None, ET.fromstring(test_xml))

    out_xml = ET.tostring(model.to_xml())
    print(test_xml)
    print(out_xml)
    assert out_xml == test_xml
Exemple #22
0
def test_load_element_map_value_class():
    el = Model.load(None, ET.fromstring('''
        <test:MapElementFixture xmlns:test="http://jaymes.biz/test" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <test:map_value_class id="test1" tag="blue">text1</test:map_value_class>
        <test:map_value_class id="test2" tag="red">text2</test:map_value_class>
        </test:MapElementFixture>
        '''))

    assert isinstance(el, MapElementFixture)

    assert hasattr(el, 'map_value_class')
    assert len(el.map_value_class) == 2

    assert 'test1' in el.map_value_class
    assert isinstance(el.map_value_class['test1'], MappableElementFixture)
    assert el.map_value_class['test1'].id == 'test1'
    assert el.map_value_class['test1'].tag == 'blue'
    assert el.map_value_class['test1'].text == 'text1'

    assert 'test2' in el.map_value_class
    assert isinstance(el.map_value_class['test2'], MappableElementFixture)
    assert el.map_value_class['test2'].id == 'test2'
    assert el.map_value_class['test2'].tag == 'red'
    assert el.map_value_class['test2'].text == 'text2'
Exemple #23
0
def main():
    import argparse
    import atexit
    from io import StringIO
    import locale
    import logging
    import os
    import pathlib
    import pprint
    import sys
    import time
    import xml.dom.minidom
    import xml.etree.ElementTree as ET

    from scap import register_namespaces
    from scap.ColorFormatter import ColorFormatter
    from scap.Model import Model
    from scap.Host import Host
    from scap.Inventory import Inventory
    from scap.Reporter import Reporter

    # set up logging
    rootLogger = logging.getLogger()
    ch = logging.StreamHandler()
    fh = logging.FileHandler(filename="pyscap.log", mode='w')
    fh_formatter = logging.Formatter(
        "%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    fh.setFormatter(fh_formatter)
    ch_formatter = ColorFormatter(
        "%(asctime)s - %(name)s - %(levelname)s - %(message)s")
    ch.setFormatter(ch_formatter)
    rootLogger.addHandler(ch)
    rootLogger.addHandler(fh)

    rootLogger.setLevel(logging.DEBUG)
    ch.setLevel(logging.WARNING)

    # report start time & end time
    logger = logging.getLogger(__name__)
    logger.debug('Start: ' + time.asctime(time.localtime()))

    register_namespaces()

    output = None

    def end_func():
        if output is not None:
            output.close()
        logger.debug('End: ' + time.asctime(time.localtime()))

    atexit.register(end_func)

    # set up argument parsing
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument('--version',
                            '-V',
                            action='version',
                            version='%(prog)s 1.0')
    arg_parser.add_argument('--verbose', '-v', action='count')
    arg_parser.add_argument('--output', '-o', nargs='?', default='-')
    arg_parser.add_argument('--inventory', nargs='+')
    arg_parser.add_argument('--host', nargs='+')

    group = arg_parser.add_mutually_exclusive_group()
    group.add_argument('--list-hosts',
                       help='outputs a list of the hosts',
                       action='store_true')
    group.add_argument('--parse',
                       help='parse the supplied files',
                       nargs='+',
                       type=argparse.FileType('r'))
    group.add_argument('--detect',
                       help='detect facts about the host',
                       action='store_true')
    group.add_argument('--collect',
                       help='collect system characteristics about the host',
                       action='store_true')
    group.add_argument('--benchmark',
                       help='benchmark hosts and produce a report',
                       action='store_true')
    # group.add_argument('--test', help='perform a test on the selected hosts', nargs='+')

    # pre-parse arguments
    args = arg_parser.parse_known_args()
    if len(args) <= 0:
        arg_parser.error('No valid operation was given')

    # change verbosity
    if args[0].verbose:
        if (args[0].verbose == 1):
            ch.setLevel(logging.INFO)
            logger.debug('Set console logging level to INFO')
        elif (args[0].verbose == 2):
            ch.setLevel(logging.DEBUG)
            logger.debug('Set console logging level to DEBUG')
        elif (args[0].verbose >= 3):
            ch.setLevel(logging.NOTSET)
            logger.debug('Set console logging level to NOTSET')

    # set up the modes
    if args[0].list_hosts:
        logger.info("List hosts operation")
    elif args[0].parse:
        logger.info('File parsing operation')
    elif args[0].detect:
        logger.info("Detect operation")
    elif args[0].collect:
        logger.info("Collect operation")
        arg_parser.add_argument('--content', required=True, nargs='+')
    elif args[0].benchmark:
        logger.info("Benchmark operation")
        arg_parser.add_argument('--content', required=True, nargs='+')
        arg_parser.add_argument('--data_stream', nargs=1)
        arg_parser.add_argument('--checklist', nargs=1)
        arg_parser.add_argument('--profile', nargs=1)
        arg_parser.add_argument('--pretty', action='store_true')
    else:
        arg_parser.error('No valid operation was given')

    # final argument parsing
    args = vars(arg_parser.parse_args())
    for arg in args:
        logger.debug('Argument: ' + arg + ' = ' + str(args[arg]))

    # expand the hosts
    inventory = Inventory()
    if args['inventory'] is not None:
        for filename in args['inventory']:
            try:
                with open(filename, 'r') as fp:
                    logger.debug('Loading inventory from ' + filename)
                    Inventory().readfp(fp)
            except IOError:
                logger.error('Could not read from inventory file ' + filename)
    else:
        filename = str(
            pathlib.Path(os.path.expanduser('~')) / '.pyscap' /
            'inventory.ini')
        try:
            with open(filename, 'r') as fp:
                logger.debug('Loading inventory from ' + filename)
                Inventory().readfp(fp)
        except IOError:
            logger.error('Could not read from inventory file ' + filename)

    if args['host'] is None or len(args['host']) == 0:
        arg_parser.error('No host specified (--host)')

    hosts = []
    for hostname in args['host']:
        host = Host.load(hostname)
        hosts.append(host)

    # open output if it's not stdout
    if args['output'] != '-':
        output = open(args['output'], mode='wb')
    else:
        output = sys.stdout.buffer

    detection_collectors = [
        'UniqueIdCollector',
        'CpeCollector',
        'FqdnCollector',
        'HostnameCollector',
        'NetworkConnectionCollector',
        'NetworkServiceCollector',
        'IdentityCollector',
    ]

    if args['list_hosts']:
        print('Hosts: ')
        for host in hosts:
            print(host.hostname)

    elif args['parse']:
        for uri in args['parse']:
            logger.debug('Loading content file: ' + uri)
            with open(uri, mode='r', encoding='utf_8') as f:
                content = ET.parse(f).getroot()
                model = Model.load(None, content)
                logger.debug('Loaded ' + uri + ' successfully')

    elif args['detect']:
        for host in hosts:
            host.connect()

            # run detection collectors
            for col_name in detection_collectors:
                col = host.load_collector(col_name, {})
                col.collect()

            host.disconnect()

            logger.info('Host detection dump:')
            pp = pprint.PrettyPrinter(width=132)
            pp.pprint(host.facts)

    elif args['collect']:
        if args['content'] is None or len(args['content']) == 0:
            arg_parser.error('No content specified (--content)')

        # this mode will collect oval system characteristics
        for host in hosts:
            host.connect()

            # run detection collectors
            for col_name in detection_collectors:
                col = host.load_collector(col_name, {})
                col.collect()

            raise NotImplementedError(
                'System characteristic collection is not implemented')

            host.disconnect()

    elif args['benchmark']:
        ### Loading.Import
        # Import the XCCDF document into the program and build an initial internal
        # representation of the Benchmark object, Groups, Rules, and other objects.
        # If the file cannot be read or parsed, then Loading fails. (At the
        # beginning of this step, any inclusion processing specified with XInclude
        # elements should be performed. The resulting XML information set should be
        # validated against the XCCDF schema given in Appendix A.) Go to the next
        # step: Loading.Noticing.

        if args['content'] is None or len(args['content']) == 0:
            arg_parser.error('No content specified (--content)')

        from scap.model.xccdf_1_1.BenchmarkType import BenchmarkType as xccdf_1_1_BenchmarkType
        from scap.model.xccdf_1_2.BenchmarkType import BenchmarkType as xccdf_1_2_BenchmarkType
        benchmark_model = None
        for uri in args['content']:
            logger.debug('Loading content file: ' + uri)
            with open(uri, mode='r', encoding='utf_8') as f:
                content = ET.parse(f).getroot()
                model = Model.load(None, content)

                if isinstance(model, xccdf_1_1_BenchmarkType) \
                or isinstance(model, xccdf_1_2_BenchmarkType):
                    benchmark_model = model

        for host in hosts:
            host.connect()

            # run detection collectors
            for col_name in detection_collectors:
                col = host.load_collector(col_name, {})
                col.collect()

            benchmark_model.noticing()

            benchmark_model.selected_profiles = []
            if args['profile'] is None or len(args['profile']) == 0:
                # check them all
                benchmark_model.selected_profiles.extend(
                    benchmark_model.profiles.keys())
            else:
                for profile in args['profile']:
                    if profile not in list(benchmark_model.profiles.keys()):
                        raise ValueError(
                            'Unable to select non-existent profile: ' +
                            profile + ' Available profiles: ' +
                            str(benchmark_model.profiles.keys()))
                    benchmark_model.selected_profiles.append(profile)

            benchmark_model.resolve()

            benchmark_model.process(host)

            host.disconnect()

        rep = Reporter.load(args, model)
        report = ET.ElementTree(element=rep.report(hosts))

        logger.debug('Preferred encoding: ' + locale.getpreferredencoding())
        sio = StringIO()
        report.write(sio, encoding='unicode', xml_declaration=True)
        sio.write("\n")
        if args['pretty']:
            pretty_xml = xml.dom.minidom.parseString(
                sio.getvalue()).toprettyxml(indent='  ')
            output.write(pretty_xml.encode(locale.getpreferredencoding()))
        else:
            output.write(sio.getvalue().encode(locale.getpreferredencoding()))

    else:
        arg_parser.error('No valid operation was given')
Exemple #24
0
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument('--content', required=True, nargs=1)
arg_parser.add_argument('--output', required=True, nargs=1)
args = vars(arg_parser.parse_args())
for arg in args:
    logger.debug('Argument: ' + arg + ' = ' + str(args[arg]))

if args['content'] is None or len(args['content']) == 0:
    arg_parser.error('No content specified (--content)')
if args['output'] is None or len(args['output']) == 0:
    arg_parser.error('No output specified (--output)')

content = args['content'][0]
logger.debug('Loading content file: ' + content)
with open(content, mode='r', encoding='utf_8') as f:
    content = ET.parse(f).getroot()
    model = Model.load(None, content)
    if not isinstance(model, SchemaElement):
        arg_parser.error('Invalid content. Expecting xsd (XMLSchema) file')

rootLogger.setLevel(logging.DEBUG)

output = args['output'][0]
logger.debug('Creating class stubs in path: ' + output)

if not os.path.isdir(output):
    os.makedirs(output, mode=0o755, exist_ok=True)

model.stub(output)
Exemple #25
0
import pkgutil
import xml.etree.ElementTree as ET

from scap.Model import Model
from scap.model.oval_5.defs.SetElement import SetElement

# import all the classes in the package
import scap.model.oval_5 as pkg
for m_finder, m_name, m_ispkg in pkgutil.iter_modules(path=pkg.__path__):
    try:
        mod = importlib.import_module(pkg.__name__ + '.' + m_name, pkg.__name__)
        globals()[m_name] = getattr(mod, m_name)
    except AttributeError:
        pass

Model.register_namespace('scap.model.oval_5', 'http://oval.mitre.org/XMLSchema/oval-common-5')
Model.register_namespace('scap.model.oval_5.defs', 'http://oval.mitre.org/XMLSchema/oval-definitions-5')
Model.register_namespace('scap.model.oval_5.defs.independent', 'http://oval.mitre.org/XMLSchema/oval-definitions-5#independent')
Model.register_namespace('scap.model.oval_5.defs.linux', 'http://oval.mitre.org/XMLSchema/oval-definitions-5#linux')
Model.register_namespace('scap.model.oval_5.defs.windows', 'http://oval.mitre.org/XMLSchema/oval-definitions-5#windows')

logging.basicConfig(level=logging.DEBUG)

def test_oval_5_3_detected():
    test_xml = '<oval_definitions ' + \
        'xmlns="http://oval.mitre.org/XMLSchema/oval-definitions-5" ' + \
        'xmlns:oval="http://oval.mitre.org/XMLSchema/oval-common-5" ' + \
        'xmlns:oval-def="http://oval.mitre.org/XMLSchema/oval-definitions-5">' + \
        '<generator>' + \
        '<oval:product_name>The OVAL Repository</oval:product_name>' + \
        '<oval:schema_version>5.3</oval:schema_version>' + \
Exemple #26
0
def test_is_not_nil():
    root = Model.load(None, ET.fromstring('<test:RootFixture xmlns:test="http://jaymes.biz/test" />'))
    assert not root.is_nil()
# PySCAP is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PySCAP.  If not, see <http://www.gnu.org/licenses/>.

import logging
import pathlib
import pytest
import xml.etree.ElementTree as ET

from scap.Model import Model
import scap.model.xccdf_1_1

logging.basicConfig(level=logging.DEBUG)
Model.register_namespace('scap.model.xccdf_1_1',
                         'http://checklists.nist.gov/xccdf/1.1')
Model.register_namespace('scap.model.xhtml', 'http://www.w3.org/1999/xhtml')
Model.register_namespace('scap.model.dc_elements_1_1',
                         'http://purl.org/dc/elements/1.1/')
Model.register_namespace('scap.model.cpe_lang_2_3',
                         'http://cpe.mitre.org/language/2.0')


def test_benchmark():
    path = pathlib.Path(str(pytest.config.rootdir)
                        ) / 'test' / 'scap' / 'model' / 'test_xccdf_1_1.xml'
    model = Model.load(None, ET.parse(str(path)).getroot())
def test_benchmark():
    path = pathlib.Path(str(pytest.config.rootdir)
                        ) / 'test' / 'scap' / 'model' / 'test_xccdf_1_1.xml'
    model = Model.load(None, ET.parse(str(path)).getroot())
Exemple #29
0
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PySCAP.  If not, see <http://www.gnu.org/licenses/>.

import logging
import pytest
import xml.etree.ElementTree as ET

from scap.Model import Model
import scap.model.xml_cat_1_1
from scap.model.xml_cat_1_1.Catalog import Catalog

logging.basicConfig(level=logging.DEBUG)
Model.register_namespace('scap.model.xml_cat_1_1', 'urn:oasis:names:tc:entity:xmlns:xml:catalog')

cat1 = Model.load(None, ET.fromstring('''<xml_cat_1_1:catalog xmlns:xml_cat_1_1="urn:oasis:names:tc:entity:xmlns:xml:catalog">
    <xml_cat_1_1:uri name="name1" uri="uri1"/>
    <xml_cat_1_1:uri name="name2" uri="uri2"/>
    <xml_cat_1_1:uri name="name3" uri="uri3"/>
</xml_cat_1_1:catalog>'''))

def test_parsed():
    assert 'name1' in cat1.entries
    assert 'name2' in cat1.entries
    assert 'name2' in cat1.entries
    assert cat1.entries['name1'] == 'uri1'
    assert cat1.entries['name2'] == 'uri2'
    assert cat1.entries['name3'] == 'uri3'
    assert 'name4' not in cat1.entries
    try:
        mod = importlib.import_module(pkg.__name__ + '.' + m_name,
                                      pkg.__name__)
        globals()[m_name] = getattr(mod, m_name)
    except AttributeError:
        pass
import scap.model.oval_5.sc.independent as pkg
for m_finder, m_name, m_ispkg in pkgutil.iter_modules(path=pkg.__path__):
    try:
        mod = importlib.import_module(pkg.__name__ + '.' + m_name,
                                      pkg.__name__)
        globals()[m_name] = getattr(mod, m_name)
    except AttributeError:
        pass

Model.register_namespace('scap.model.oval_5',
                         'http://oval.mitre.org/XMLSchema/oval-common-5')
Model.register_namespace('scap.model.oval_5.defs',
                         'http://oval.mitre.org/XMLSchema/oval-definitions-5')
Model.register_namespace(
    'scap.model.oval_5.defs.independent',
    'http://oval.mitre.org/XMLSchema/oval-definitions-5#independent')
Model.register_namespace(
    'scap.model.oval_5.sc',
    'http://oval.mitre.org/XMLSchema/oval-system-characteristics-5')
Model.register_namespace(
    'scap.model.oval_5.sc.independent',
    'http://oval.mitre.org/XMLSchema/oval-system-characteristics-5#independent'
)

logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.DEBUG)
Exemple #31
0
def test_parse_xsd():
    path = pathlib.Path(str(pytest.config.rootdir)) / 'tests' / 'model' / 'test_xs_stub.xsd'
    model = Model.load(None, ET.parse(str(path)).getroot())
Exemple #32
0
def test_load_attribute_value_in_enum():
    el = Model.load(None, ET.fromstring('<test:RootFixture xmlns:test="http://jaymes.biz/test"><test:EnumValue>bravo</test:EnumValue></test:RootFixture>'))
    assert isinstance(el, RootFixture)
    assert hasattr(el, 'EnumValue')
    assert el.EnumValue.get_value() == 'bravo'
Exemple #33
0
import pytest
import pkgutil
import xml.etree.ElementTree as ET

from scap.Model import Model

# import all the classes in the package
import scap.model.oval_5.defs.windows as pkg
for m_finder, m_name, m_ispkg in pkgutil.iter_modules(path=pkg.__path__):
    try:
        mod = importlib.import_module(pkg.__name__ + '.' + m_name, pkg.__name__)
        globals()[m_name] = getattr(mod, m_name)
    except AttributeError:
        pass

Model.register_namespace('scap.model.oval_5', 'http://oval.mitre.org/XMLSchema/oval-common-5')
Model.register_namespace('scap.model.oval_5.defs', 'http://oval.mitre.org/XMLSchema/oval-definitions-5')
Model.register_namespace('scap.model.oval_5.defs.independent', 'http://oval.mitre.org/XMLSchema/oval-definitions-5#independent')
Model.register_namespace('scap.model.oval_5.defs.linux', 'http://oval.mitre.org/XMLSchema/oval-definitions-5#linux')
Model.register_namespace('scap.model.oval_5.defs.windows', 'http://oval.mitre.org/XMLSchema/oval-definitions-5#windows')
Model.register_namespace('scap.model.oval_5.defs.unix', 'http://oval.mitre.org/XMLSchema/oval-definitions-5#unix')

logging.basicConfig(level=logging.DEBUG)

def test_EntityObjectCmdletVerbType_parse():
    assert EntityObjectCmdletVerbType(value='Request').get_value() == 'Request'

def test_EntityObjectGUIDType_parse():
    assert EntityObjectGUIDType(value='{12345678-1234-1234-1234-1234567890ab}').get_value() == '{12345678-1234-1234-1234-1234567890ab}'

def test_EntityObjectNamingContextType_parse():
Exemple #34
0
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument('--content', required=True, nargs=1)
arg_parser.add_argument('--output', required=True, nargs=1)
args = vars(arg_parser.parse_args())
for arg in args:
    logger.debug('Argument: ' + arg + ' = ' + str(args[arg]))

if args['content'] is None or len(args['content']) == 0:
    arg_parser.error('No content specified (--content)')
if args['output'] is None or len(args['output']) == 0:
    arg_parser.error('No output specified (--output)')

content = args['content'][0]
logger.debug('Loading content file: ' + content)
with open(content, mode='r', encoding='utf_8') as f:
    content = ET.parse(f).getroot()
    model = Model.load(None, content)
    if not isinstance(model, SchemaElement):
        arg_parser.error('Invalid content. Expecting xsd (XMLSchema) file')

rootLogger.setLevel(logging.DEBUG)

output = args['output'][0]
logger.debug('Creating class stubs in path: ' + output)

if not os.path.isdir(output):
    os.makedirs(output, mode=0o755, exist_ok=True)

model.stub(output)
Exemple #35
0
    ### Loading.Import
    # Import the XCCDF document into the program and build an initial internal
    # representation of the Benchmark object, Groups, Rules, and other objects.
    # If the file cannot be read or parsed, then Loading fails. (At the
    # beginning of this step, any inclusion processing specified with XInclude
    # elements should be performed. The resulting XML information set should be
    # validated against the XCCDF schema given in Appendix A.) Go to the next
    # step: Loading.Noticing.

    if len(args['content']) == 0:
        arg_parser.error('No content specified (--content)')

    for uri in args['content']:
        logger.debug('Loading content file: ' + uri)
        with open(uri, mode='r', encoding='utf_8') as f:
            content = Model.load(None, ET.parse(f).getroot(), uri)

    for host in hosts:
        host.connect()
        for collector in host.detect_collectors(args):
            collector.collect()
        chk = Checker.load(host, args, content)
        chk.collect()
        host.disconnect()

    rep = Reporter.load(hosts, content, args)
    report = rep.report()

    if args['pretty']:
        sio = StringIO()
        report.write(sio, encoding='unicode', xml_declaration=True)
Exemple #36
0
def test_xmlns_to_package():
    assert Model.xmlns_to_package('http://jaymes.biz/test') == 'fixtures.test'
    assert Model.xmlns_to_package('http://jaymes.biz/test2') == 'fixtures.test2'

    with pytest.raises(UnregisteredNamespaceException):
        Model.xmlns_to_package('http://jaymes.biz/derp')
Exemple #37
0
# You should have received a copy of the GNU General Public License
# along with PySCAP.  If not, see <http://www.gnu.org/licenses/>.

import logging
import pathlib
import pytest
import xml.etree.ElementTree as ET

from fixtures.test.RootFixture import RootFixture
from fixtures.test.EnclosedFixture import EnclosedFixture
from scap.Model import Model, ModelList
from scap.Inventory import Inventory
import scap.model.xlink

logging.basicConfig(level=logging.DEBUG)
Model.register_namespace('scap.model.xlink', 'http://www.w3.org/1999/xlink')


def test_simple_local():
    path = (pathlib.Path(str(pytest.config.rootdir)) / 'tests' / 'model' /
            'test_xlink.xml').as_posix()
    if not path.startswith('/'):
        path = '/' + path
    model = Model.load(
        None,
        ET.fromstring(
            '<test:XLinkFixture ' + 'xmlns:test="http://jaymes.biz/test" ' +
            'xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple" ' +
            'xlink:href="file://' + path + '" />'))
    assert isinstance(model._elements, ModelList)
    assert len(model._elements) > 0
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PySCAP.  If not, see <http://www.gnu.org/licenses/>.

import logging
import pytest
import xml.etree.ElementTree as ET

from scap.Model import Model
import scap.model.xml_cat_1_1
from scap.model.xml_cat_1_1.Catalog import Catalog

logging.basicConfig(level=logging.DEBUG)
Model.register_namespace('scap.model.xml_cat_1_1',
                         'urn:oasis:names:tc:entity:xmlns:xml:catalog')

cat1 = Model.load(
    None,
    ET.fromstring(
        '''<xml_cat_1_1:catalog xmlns:xml_cat_1_1="urn:oasis:names:tc:entity:xmlns:xml:catalog">
    <xml_cat_1_1:uri name="name1" uri="uri1"/>
    <xml_cat_1_1:uri name="name2" uri="uri2"/>
    <xml_cat_1_1:uri name="name3" uri="uri3"/>
</xml_cat_1_1:catalog>'''))


def test_parsed():
    assert 'name1' in cat1.entries
    assert 'name2' in cat1.entries
    assert 'name2' in cat1.entries
Exemple #39
0
def test_parse_tag():
    assert Model.parse_tag('{http://jaymes.biz/test}test') == ('http://jaymes.biz/test', 'test')
    assert Model.parse_tag('test') == (None, 'test')
Exemple #40
0
def test_load_attribute_value_matches_pattern():
    el = Model.load(None, ET.fromstring('<test:RootFixture xmlns:test="http://jaymes.biz/test"><test:PatternValue>Bravo12</test:PatternValue></test:RootFixture>'))
    assert isinstance(el, RootFixture)
    assert hasattr(el, 'PatternValue')
    assert el.PatternValue.get_value() == 'Bravo12'
Exemple #41
0
import importlib
import logging
import pytest
import pkgutil

from scap.Model import Model

# import all the classes in the package
import scap.model.oval_5.defs.unix as pkg
for m_finder, m_name, m_ispkg in pkgutil.iter_modules(path=pkg.__path__):
    try:
        mod = importlib.import_module(pkg.__name__ + '.' + m_name,
                                      pkg.__name__)
        globals()[m_name] = getattr(mod, m_name)
    except AttributeError:
        pass

Model.register_namespace('scap.model.oval_5',
                         'http://oval.mitre.org/XMLSchema/oval-common-5')
Model.register_namespace('scap.model.oval_5.defs',
                         'http://oval.mitre.org/XMLSchema/oval-definitions-5')
Model.register_namespace(
    'scap.model.oval_5.defs.unix',
    'http://oval.mitre.org/XMLSchema/oval-definitions-5#unix')

logging.basicConfig(level=logging.DEBUG)


def test_parse():
    pass
# PySCAP is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PySCAP is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PySCAP.  If not, see <http://www.gnu.org/licenses/>.

from scap.Model import Model

Model.register_namespace('scap.model.ai_1_1', 'http://scap.nist.gov/schema/asset-identification/1.1')
Model.register_namespace('scap.model.arf_1_1', 'http://scap.nist.gov/schema/asset-reporting-format/1.1')
Model.register_namespace('scap.model.arf_rel_1_0', 'http://scap.nist.gov/specifications/arf/vocabulary/relationships/1.0')
Model.register_namespace('scap.model.cpe_1_0', 'http://cpe.mitre.org/XMLSchema/cpe/1.0')
Model.register_namespace('scap.model.cpe_dict_2_3', 'http://cpe.mitre.org/dictionary/2.0')
Model.register_namespace('scap.model.cpe_lang_2_3', 'http://cpe.mitre.org/language/2.0')
Model.register_namespace('scap.model.cpe_naming_2_3', 'http://cpe.mitre.org/naming/2.0')
Model.register_namespace('scap.model.dc_elements_1_1', 'http://purl.org/dc/elements/1.1/')
Model.register_namespace('scap.model.tmsad_1_0', 'http://scap.nist.gov/schema/xml-dsig/1.0')
Model.register_namespace('scap.model.ocil_2_0', 'http://scap.nist.gov/schema/ocil/2.0')
Model.register_namespace('scap.model.ocil_2_0', 'http://scap.nist.gov/schema/ocil/2')
Model.register_namespace('scap.model.oval_5', 'http://oval.mitre.org/XMLSchema/oval-common-5')
Model.register_namespace('scap.model.oval_5.defs', 'http://oval.mitre.org/XMLSchema/oval-definitions-5')
Model.register_namespace('scap.model.oval_5.defs.independent', 'http://oval.mitre.org/XMLSchema/oval-definitions-5#independent')
Model.register_namespace('scap.model.oval_5.defs.linux', 'http://oval.mitre.org/XMLSchema/oval-definitions-5#linux')
Model.register_namespace('scap.model.oval_5.defs.windows', 'http://oval.mitre.org/XMLSchema/oval-definitions-5#windows')
Exemple #43
0
def test_load_attribute_value_not_matches_pattern():
    with pytest.raises(ValueError):
        Model.load(None, ET.fromstring('<test:RootFixture xmlns:test="http://jaymes.biz/test"><test:PatternValue>delta</test:PatternValue></test:RootFixture>'))
Exemple #44
0
#
# You should have received a copy of the GNU General Public License
# along with PySCAP.  If not, see <http://www.gnu.org/licenses/>.

import pytest, logging
from scap.Model import Model
from scap.model.xml_cat_1_1.Catalog import Catalog
import xml.etree.ElementTree as ET

logging.basicConfig(level=logging.DEBUG)
ET.register_namespace('cat', 'urn:oasis:names:tc:entity:xmlns:xml:catalog')

cat1 = Model.load(
    None,
    ET.fromstring(
        '''<cat:catalog xmlns:cat="urn:oasis:names:tc:entity:xmlns:xml:catalog">
    <cat:uri name="name1" uri="uri1"/>
    <cat:uri name="name2" uri="uri2"/>
    <cat:uri name="name3" uri="uri3"/>
</cat:catalog>'''))


def test_parsed():
    assert 'name1' in cat1.entries
    assert 'name2' in cat1.entries
    assert 'name2' in cat1.entries
    assert cat1.entries['name1'] == 'uri1'
    assert cat1.entries['name2'] == 'uri2'
    assert cat1.entries['name3'] == 'uri3'
    assert 'name4' not in cat1.entries

Exemple #45
0
def test_package_to_xmlns():
    assert Model.package_to_xmlns('fixtures.test') == 'http://jaymes.biz/test'
    assert Model.package_to_xmlns('fixtures.test2') == 'http://jaymes.biz/test2'

    with pytest.raises(UnregisteredNamespaceException):
        Model.package_to_xmlns('scap.model.derp')