def _run_test(self, params, expected):
        logfile = '%s.in' % params
        profile_dummy_file = 'AATest_does_exist'

        # we need to find out the profile name and aamode (complain vs. enforce mode) so that the test can access the correct place in storage
        parser = ReadLog('', '', '', '')
        parsed_event = parser.parse_event(read_file(logfile))

        if not parsed_event:  # AA_RECORD_INVALID
            return

        if params.split('/')[-1] in log_to_profile_skip:
            return

        aamode = parsed_event['aamode']

        if aamode in [
                'AUDIT', 'STATUS', 'HINT'
        ]:  # ignore some event types  # XXX maybe we shouldn't ignore AUDIT events?
            return

        if aamode not in ['PERMITTING', 'REJECTING']:
            raise Exception('Unexpected aamode %s' % parsed_event['aamode'])

        # cleanup apparmor.aa storage
        apparmor.aa.log = dict()
        apparmor.aa.aa = apparmor.aa.hasher()
        apparmor.aa.prelog = apparmor.aa.hasher()

        profile = parsed_event['profile']
        hat = profile
        if '//' in profile:
            profile, hat = profile.split('//')

        apparmor.aa.existing_profiles = {profile: profile_dummy_file}

        log_reader = ReadLog(dict(), logfile, apparmor.aa.existing_profiles,
                             '')
        log = log_reader.read_log('')

        for root in log:
            apparmor.aa.handle_children('', '',
                                        root)  # interactive for exec events!

        log_dict = apparmor.aa.collapse_log()

        apparmor.aa.filelist = apparmor.aa.hasher()
        apparmor.aa.filelist[profile_dummy_file]['profiles'][profile] = True

        new_profile = apparmor.aa.serialize_profile(log_dict[aamode][profile],
                                                    profile, None)

        expected_profile = read_file('%s.profile' % params)

        if params.split('/')[-1] in log_to_profile_known_failures:
            self.assertNotEqual(new_profile, expected_profile)  # known failure
        else:
            self.assertEqual(new_profile, expected_profile)
Beispiel #2
0
    def test_signal_from_log(self):
        parser = ReadLog('', '', '', '')
        event = 'type=AVC msg=audit(1409438250.564:201): apparmor="DENIED" operation="signal" profile="/usr/bin/pulseaudio" pid=2531 comm="pulseaudio" requested_mask="send" denied_mask="send" signal=term peer="/usr/bin/pulseaudio///usr/lib/pulseaudio/pulse/gconf-helper"'

        parsed_event = parser.parse_event(event)

        self.assertEqual(
            parsed_event, {
                'request_mask': 'send',
                'denied_mask': 'send',
                'error_code': 0,
                'magic_token': 0,
                'parent': 0,
                'profile': '/usr/bin/pulseaudio',
                'signal': 'term',
                'peer':
                '/usr/bin/pulseaudio///usr/lib/pulseaudio/pulse/gconf-helper',
                'operation': 'signal',
                'resource': None,
                'info': None,
                'aamode': 'REJECTING',
                'time': 1409438250,
                'active_hat': None,
                'pid': 2531,
                'task': 0,
                'attr': None,
                'name2': None,
                'name': None,
                'family': None,
                'protocol': None,
                'sock_type': None,
            })

        obj = SignalRule(parsed_event['denied_mask'],
                         parsed_event['signal'],
                         parsed_event['peer'],
                         log_event=parsed_event)

        #              audit  allow  deny   comment    access        all?   signal       all?   peer                                                           all?
        expected = exp(
            False, False, False, '', {'send'}, False, {'term'}, False,
            '/usr/bin/pulseaudio///usr/lib/pulseaudio/pulse/gconf-helper',
            False)

        self._compare_obj(obj, expected)

        self.assertEqual(
            obj.get_raw(1),
            '  signal send set=term peer=/usr/bin/pulseaudio///usr/lib/pulseaudio/pulse/gconf-helper,'
        )
    def test_ptrace_from_log(self):
        parser = ReadLog('', '', '', '')
        event = 'type=AVC msg=audit(1409700683.304:547661): apparmor="DENIED" operation="ptrace" profile="/home/ubuntu/bzr/apparmor/tests/regression/apparmor/ptrace" pid=22465 comm="ptrace" requested_mask="tracedby" denied_mask="tracedby" peer="/home/ubuntu/bzr/apparmor/tests/regression/apparmor/ptrace"'

        parsed_event = parser.parse_event(event)

        self.assertEqual(
            parsed_event, {
                'request_mask': 'tracedby',
                'denied_mask': 'tracedby',
                'error_code': 0,
                'magic_token': 0,
                'parent': 0,
                'profile':
                '/home/ubuntu/bzr/apparmor/tests/regression/apparmor/ptrace',
                'peer':
                '/home/ubuntu/bzr/apparmor/tests/regression/apparmor/ptrace',
                'operation': 'ptrace',
                'resource': None,
                'info': None,
                'aamode': 'REJECTING',
                'time': 1409700683,
                'active_hat': None,
                'pid': 22465,
                'task': 0,
                'attr': None,
                'name2': None,
                'name': None,
                'family': None,
                'protocol': None,
                'sock_type': None,
            })

        obj = PtraceRule(parsed_event['denied_mask'],
                         parsed_event['peer'],
                         log_event=parsed_event)

        #              audit  allow  deny   comment    access        all?   peer                                                           all?
        expected = exp(
            False, False, False, '', {'tracedby'}, False,
            '/home/ubuntu/bzr/apparmor/tests/regression/apparmor/ptrace',
            False)

        self._compare_obj(obj, expected)

        self.assertEqual(
            obj.get_raw(1),
            '  ptrace tracedby peer=/home/ubuntu/bzr/apparmor/tests/regression/apparmor/ptrace,'
        )
Beispiel #4
0
class TestParseEventForTreeInvalid(AATest):
    tests = [
        ('type=AVC msg=audit(1556742870.707:3614): apparmor="ALLOWED" operation="open" profile="/bin/hello" name="/dev/tty" pid=12856 comm="hello" requested_mask="wr" denied_mask="foo" fsuid=1000 ouid=0',    AppArmorException),  # invalid file permissions "foo"
        ('type=AVC msg=audit(1556742870.707:3614): apparmor="ALLOWED" operation="open" profile="/bin/hello" name="/dev/tty" pid=12856 comm="hello" requested_mask="wr" denied_mask="wr::w" fsuid=1000 ouid=0',  AppArmorException),  # "wr::w" mixes owner and other
    ]

    def _fake_profile_exists(self, program):
        return True

    def _run_test(self, params, expected):
        self.parser = ReadLog('', '', '')
        self.parser.profile_exists = self._fake_profile_exists  # inject fake function that always returns True - much easier than handing over a ProfileList object to __init__
        parsed_event = self.parser.parse_event(params)
        with self.assertRaises(expected):
            self.parser.parse_event_for_tree(parsed_event)
Beispiel #5
0
    def test_change_profile_from_log(self):
        parser = ReadLog('', '', '', '')

        event = 'type=AVC msg=audit(1428699242.551:386): apparmor="DENIED" operation="change_profile" profile="/foo/changeprofile" pid=3459 comm="changeprofile" target="/foo/rename"'

        # libapparmor doesn't understand this log format (from JJ)
        # event = '[   97.492562] audit: type=1400 audit(1431116353.523:77): apparmor="DENIED" operation="change_profile" profile="/foo/changeprofile" pid=3459 comm="changeprofile" target="/foo/rename"'

        parsed_event = parser.parse_event(event)

        self.assertEqual(
            parsed_event,
            {
                'request_mask': None,
                'denied_mask': None,
                'error_code': 0,
                'magic_token': 0,
                'parent': 0,
                'profile': '/foo/changeprofile',
                'operation': 'change_profile',
                'resource': None,
                'info': None,
                'aamode': 'REJECTING',
                'time': 1428699242,
                'active_hat': None,
                'pid': 3459,
                'task': 0,
                'attr': None,
                'name2': '/foo/rename',  # target
                'name': None,
                'family': None,
                'protocol': None,
                'sock_type': None,
            })

        obj = ChangeProfileRule(None,
                                ChangeProfileRule.ALL,
                                parsed_event['name2'],
                                log_event=parsed_event)

        #              audit  allow  deny   comment        execmode execcond  all?   targetprof     all?
        expected = exp(False, False, False, '', None, None, True,
                       '/foo/rename', False)

        self._compare_obj(obj, expected)

        self.assertEqual(obj.get_raw(1), '  change_profile -> /foo/rename,')
Beispiel #6
0
    def test_cap_from_log(self):
        parser = ReadLog('', '', '', '')
        event = 'type=AVC msg=audit(1415403814.628:662): apparmor="ALLOWED" operation="capable" profile="/bin/ping" pid=15454 comm="ping" capability=13  capname="net_raw"'

        parsed_event = parser.parse_event(event)

        self.assertEqual(
            parsed_event, {
                'request_mask': None,
                'denied_mask': None,
                'error_code': 0,
                'magic_token': 0,
                'parent': 0,
                'profile': '/bin/ping',
                'operation': 'capable',
                'resource': None,
                'info': None,
                'aamode': 'PERMITTING',
                'time': 1415403814,
                'active_hat': None,
                'pid': 15454,
                'task': 0,
                'attr': None,
                'name2': None,
                'name': 'net_raw',
                'family': None,
                'protocol': None,
                'sock_type': None,
            })

        obj = CapabilityRule(parsed_event['name'], log_event=parsed_event)

        self._compare_obj(
            obj, {
                'allow_keyword': False,
                'deny': False,
                'audit': False,
                'capability': {'net_raw'},
                'all_caps': False,
                'comment': "",
            })

        self.assertEqual(obj.get_raw(1), '  capability net_raw,')
Beispiel #7
0
    def test_net_from_log(self):
        parser = ReadLog('', '', '', '')
        event = 'type=AVC msg=audit(1428699242.551:386): apparmor="DENIED" operation="create" profile="/bin/ping" pid=10589 comm="ping" family="inet" sock_type="raw" protocol=1'

        parsed_event = parser.parse_event(event)

        self.assertEqual(
            parsed_event, {
                'request_mask': None,
                'denied_mask': None,
                'error_code': 0,
                'family': 'inet',
                'magic_token': 0,
                'parent': 0,
                'profile': '/bin/ping',
                'protocol': 'icmp',
                'sock_type': 'raw',
                'operation': 'create',
                'resource': None,
                'info': None,
                'aamode': 'REJECTING',
                'time': 1428699242,
                'active_hat': None,
                'pid': 10589,
                'task': 0,
                'attr': None,
                'name2': None,
                'name': None,
            })

        obj = NetworkRule(parsed_event['family'],
                          parsed_event['sock_type'],
                          log_event=parsed_event)

        #              audit  allow  deny   comment        domain    all?   type/proto  all?
        expected = exp(False, False, False, '', 'inet', False, 'raw', False)

        self._compare_obj(obj, expected)

        self.assertEqual(obj.get_raw(1), '  network inet raw,')
    def test_net_from_log(self):
        parser = ReadLog('', '', '', '', '')

        event = 'type=AVC msg=audit(1428699242.551:386): apparmor="DENIED" operation="change_profile" profile="/foo/changeprofile" pid=3459 comm="changeprofile" target="/foo/rename"'

        # libapparmor doesn't understand this log format (from JJ)
        # event = '[   97.492562] audit: type=1400 audit(1431116353.523:77): apparmor="DENIED" operation="change_profile" profile="/foo/changeprofile" pid=3459 comm="changeprofile" target="/foo/rename"'

        parsed_event = parser.parse_event(event)

        self.assertEqual(parsed_event, {
            'request_mask': None,
            'denied_mask': None,
            'error_code': 0,
            #'family': 'inet',
            'magic_token': 0,
            'parent': 0,
            'profile': '/foo/changeprofile',
            'operation': 'change_profile',
            'resource': None,
            'info': None,
            'aamode': 'REJECTING',
            'time': 1428699242,
            'active_hat': None,
            'pid': 3459,
            'task': 0,
            'attr': None,
            'name2': '/foo/rename', # target
            'name': None,
        })

        obj = ChangeProfileRule(ChangeProfileRule.ALL, parsed_event['name2'], log_event=parsed_event)

        #              audit  allow  deny   comment        execcond  all?   targetprof     all?
        expected = exp(False, False, False, ''           , None,     True,  '/foo/rename', False)

        self._compare_obj(obj, expected)

        self.assertEqual(obj.get_raw(1), '  change_profile -> /foo/rename,')
Beispiel #9
0
    def test_cap_from_log(self):
        parser = ReadLog('', '', '', '', '')
        event = 'type=AVC msg=audit(1415403814.628:662): apparmor="ALLOWED" operation="capable" profile="/bin/ping" pid=15454 comm="ping" capability=13  capname="net_raw"'

        parsed_event = parser.parse_event(event)

        self.assertEqual(parsed_event, {
            'request_mask': None,
            'denied_mask': None,
            'error_code': 0,
            'magic_token': 0,
            'parent': 0,
            'profile': '/bin/ping',
            'operation': 'capable',
            'resource': None,
            'info': None,
            'aamode': 'PERMITTING',
            'time': 1415403814,
            'active_hat': None,
            'pid': 15454,
            'task': 0,
            'attr': None,
            'name2': None,
            'name': 'net_raw'
        })

        obj = CapabilityRule(parsed_event['name'], log_event=parsed_event)

        self._compare_obj(obj, {
            'allow_keyword':    False,
            'deny':             False,
            'audit':            False,
            'capability':       {'net_raw'},
            'all_caps':         False,
            'comment':          "",
        })

        self.assertEqual(obj.get_raw(1), '  capability net_raw,')
Beispiel #10
0
    def test_net_from_log(self):
        parser = ReadLog('', '', '', '', '')
        event = 'type=AVC msg=audit(1428699242.551:386): apparmor="DENIED" operation="create" profile="/bin/ping" pid=10589 comm="ping" family="inet" sock_type="raw" protocol=1'

        parsed_event = parser.parse_event(event)

        self.assertEqual(parsed_event, {
            'request_mask': None,
            'denied_mask': None,
            'error_code': 0,
            'family': 'inet',
            'magic_token': 0,
            'parent': 0,
            'profile': '/bin/ping',
            'protocol': 'icmp',
            'sock_type': 'raw',
            'operation': 'create',
            'resource': None,
            'info': None,
            'aamode': 'REJECTING',
            'time': 1428699242,
            'active_hat': None,
            'pid': 10589,
            'task': 0,
            'attr': None,
            'name2': None,
            'name': None,
        })

        obj = NetworkRule(parsed_event['family'], parsed_event['sock_type'], log_event=parsed_event)

        #              audit  allow  deny   comment        domain    all?   type/proto  all?
        expected = exp(False, False, False, ''           , 'inet',   False, 'raw'    , False)

        self._compare_obj(obj, expected)

        self.assertEqual(obj.get_raw(1), '  network inet raw,')
Beispiel #11
0
    def _run_test(self, params, expected):
        # tests[][expected] is a dummy, replace it with the real values
        if params.split('/')[-1] in log_to_skip:
            return

        expected = self._parse_libapparmor_test_multi(params)

        with open_file_read('%s.in' % params) as f_in:
            loglines = f_in.readlines()

        loglines2 = []
        for line in loglines:
            if line.strip():
                loglines2 += [line]

        self.assertEqual(len(loglines2), 1,
                         '%s.in should only contain one line!' % params)

        parser = ReadLog('', '', '')
        parsed_event = parser.parse_event(loglines2[0])

        if parsed_event and expected:
            parsed_items = dict(parsed_event.items())

            # check if the line passes the regex in logparser.py
            if not parser.RE_LOG_ALL.search(loglines2[0]):
                raise Exception("Log event doesn't match RE_LOG_ALL")

            for label in expected:
                if label in [
                        'file',  # filename of the *.in file
                        'event_type',  # mapped to aamode
                        'audit_id',
                        'audit_sub_id',  # not set nor relevant
                        'comm',  # not set, and not too useful
                        # XXX most of the keywords listed below mean "TODO"
                        'fsuid',
                        'ouid',  # file events
                        'flags',
                        'fs_type',  # mount
                        'namespace',  # file_lock only?? (at least the tests don't contain this in other event types with namespace)
                        'net_local_addr',
                        'net_foreign_addr',
                        'net_local_port',
                        'net_foreign_port',  # detailed network events
                        'peer',
                        'signal',  # signal
                        'src_name',  # pivotroot
                        'dbus_bus',
                        'dbus_interface',
                        'dbus_member',
                        'dbus_path',  # dbus
                        'peer_pid',
                        'peer_profile',  # dbus
                ]:
                    pass
                elif parsed_items['operation'] == 'exec' and label in [
                        'sock_type', 'family', 'protocol'
                ]:
                    pass  # XXX 'exec' + network? really?
                elif parsed_items[
                        'operation'] == 'ptrace' and label == 'name2' and params.endswith(
                            '/ptrace_garbage_lp1689667_1'):
                    pass  # libapparmor would better qualify this case as invalid event
                elif not parsed_items.get(label, None):
                    raise Exception('parsed_items[%s] not set' % label)
                elif not expected.get(label, None):
                    raise Exception('expected[%s] not set' % label)
                else:
                    self.assertEqual(str(parsed_items[label]), expected[label],
                                     '%s differs' % label)
        elif expected:
            self.assertIsNone(parsed_event)  # that's why we end up here
            self.assertEqual(dict(), expected, 'parsed_event is none'
                             )  # effectively print the content of expected
        elif parsed_event:
            self.assertIsNone(expected)  # that's why we end up here
            self.assertEqual(parsed_event, dict(), 'expected is none'
                             )  # effectively print the content of parsed_event
        else:
            self.assertIsNone(expected)  # that's why we end up here
            self.assertIsNone(parsed_event)  # that's why we end up here
            self.assertEqual(parsed_event, expected)  # both are None
Beispiel #12
0
def logfile_to_profile(logfile):
    profile_dummy_file = 'AATest_does_exist'

    # we need to find out the profile name and aamode (complain vs. enforce mode) so that the test can access the correct place in storage
    parser = ReadLog('', '', '')
    parsed_event = parser.parse_event(read_file(logfile))

    if not parsed_event:  # AA_RECORD_INVALID
        return None, 'INVALID'

    aamode = parsed_event['aamode']

    if aamode in [
            'AUDIT', 'STATUS', 'HINT'
    ]:  # ignore some event types  # XXX maybe we shouldn't ignore AUDIT events?
        return None, aamode

    if aamode not in ['PERMITTING', 'REJECTING']:
        raise Exception('Unexpected aamode %s' % parsed_event['aamode'])

    # cleanup apparmor.aa storage
    apparmor.aa.log = dict()
    apparmor.aa.aa = apparmor.aa.hasher()

    profile, hat = split_name(parsed_event['profile'])

    apparmor.aa.active_profiles = ProfileList()

    # optional for now, might be needed one day
    # if profile.startswith('/'):
    #     apparmor.aa.active_profiles.add_profile(profile_dummy_file, profile, profile)
    # else:
    apparmor.aa.active_profiles.add_profile(profile_dummy_file, profile, '')

    log_reader = ReadLog(logfile, apparmor.aa.active_profiles, '')
    hashlog = log_reader.read_log('')

    apparmor.aa.ask_exec(hashlog)
    apparmor.aa.ask_addhat(hashlog)

    log_dict = apparmor.aa.collapse_log(hashlog, ignore_null_profiles=False)

    if profile != hat:
        # log event for a child profile means log_dict only contains the child profile
        # initialize parent profile in log_dict as ProfileStorage to ensure writing the profile doesn't fail
        # (in "normal" usage outside of this test, log_dict will not be handed over to serialize_profile())

        if log_dict[aamode][profile][profile] != {}:
            raise Exception(
                'event for child profile, but parent profile was initialized nevertheless. Logfile: %s'
                % logfile)

        log_dict[aamode][profile][profile] = apparmor.aa.ProfileStorage(
            'TEST DUMMY for empty parent profile', profile_dummy_file,
            'logfile_to_profile()')

    log_is_empty = True

    for tmpaamode in hashlog:
        for tmpprofile in hashlog[tmpaamode]:
            for tmpruletype in hashlog[tmpaamode][tmpprofile]:
                if tmpruletype == 'final_name' and hashlog[tmpaamode][
                        tmpprofile]['final_name'] == tmpprofile:
                    continue  # final_name is a copy of the profile name (may be changed by ask_exec(), but that won't happen in this test)
                if hashlog[tmpaamode][tmpprofile][tmpruletype]:
                    log_is_empty = False

    if logfile.split('/')[-1][:-3] in log_to_profile_known_empty_log:
        # unfortunately this function might be called outside Unittest.TestCase, therefore we can't use assertEqual / assertNotEqual
        if log_is_empty == False:
            raise Exception(
                'got non-empty log for logfile in log_to_profile_known_empty_log: %s %s'
                % (logfile, hashlog))
    else:
        if log_is_empty == True:
            raise Exception(
                'got empty log for logfile not in log_to_profile_known_empty_log: %s %s'
                % (logfile, hashlog))

    new_profile = apparmor.aa.serialize_profile(log_dict[aamode][profile],
                                                profile, {})

    return profile, new_profile
Beispiel #13
0
class TestParseEvent(unittest.TestCase):
    def setUp(self):
        self.parser = ReadLog('', '', '', '')

    def test_parse_event_audit_1(self):
        event = 'type=AVC msg=audit(1345027352.096:499): apparmor="ALLOWED" operation="rename_dest" parent=6974 profile="/usr/sbin/httpd2-prefork//vhost_foo" name=2F686F6D652F7777772F666F6F2E6261722E696E2F68747470646F63732F61707061726D6F722F696D616765732F746573742F696D61676520312E6A7067 pid=20143 comm="httpd2-prefork" requested_mask="wc" denied_mask="wc" fsuid=30 ouid=30'
        parsed_event = self.parser.parse_event(event)
        self.assertEqual(
            parsed_event['name'],
            '/home/www/foo.bar.in/httpdocs/apparmor/images/test/image 1.jpg')
        self.assertEqual(parsed_event['profile'],
                         '/usr/sbin/httpd2-prefork//vhost_foo')
        self.assertEqual(parsed_event['aamode'], 'PERMITTING')
        self.assertEqual(parsed_event['request_mask'], 'wc')

        self.assertIsNotNone(ReadLog.RE_LOG_ALL.search(event))

    def test_parse_event_audit_2(self):
        event = 'type=AVC msg=audit(1322614918.292:4376): apparmor="ALLOWED" operation="file_perm" parent=16001 profile=666F6F20626172 name="/home/foo/.bash_history" pid=17011 comm="bash" requested_mask="rw" denied_mask="rw" fsuid=0 ouid=1000'
        parsed_event = self.parser.parse_event(event)
        self.assertEqual(parsed_event['name'], '/home/foo/.bash_history')
        self.assertEqual(parsed_event['profile'], 'foo bar')
        self.assertEqual(parsed_event['aamode'], 'PERMITTING')
        self.assertEqual(parsed_event['request_mask'], 'rw')

        self.assertIsNotNone(ReadLog.RE_LOG_ALL.search(event))

    def test_parse_event_syslog_1(self):
        # from https://bugs.launchpad.net/apparmor/+bug/1399027
        event = '2014-06-09T20:37:28.975070+02:00 geeko kernel: [21028.143765] type=1400 audit(1402339048.973:1421): apparmor="ALLOWED" operation="open" profile="/home/cb/linuxtag/apparmor/scripts/hello" name="/dev/tty" pid=14335 comm="hello" requested_mask="rw" denied_mask="rw" fsuid=1000 ouid=0'
        parsed_event = self.parser.parse_event(event)
        self.assertEqual(parsed_event['name'], '/dev/tty')
        self.assertEqual(parsed_event['profile'],
                         '/home/cb/linuxtag/apparmor/scripts/hello')
        self.assertEqual(parsed_event['aamode'], 'PERMITTING')
        self.assertEqual(parsed_event['request_mask'], 'rw')

        self.assertIsNotNone(ReadLog.RE_LOG_ALL.search(event))

    def test_parse_event_syslog_2(self):
        # from https://bugs.launchpad.net/apparmor/+bug/1399027
        event = 'Dec  7 13:18:59 rosa kernel: audit: type=1400 audit(1417954745.397:82): apparmor="ALLOWED" operation="open" profile="/home/simi/bin/aa-test" name="/usr/bin/" pid=3231 comm="ls" requested_mask="r" denied_mask="r" fsuid=1000 ouid=0'
        parsed_event = self.parser.parse_event(event)
        self.assertEqual(parsed_event['name'], '/usr/bin/')
        self.assertEqual(parsed_event['profile'], '/home/simi/bin/aa-test')
        self.assertEqual(parsed_event['aamode'], 'PERMITTING')
        self.assertEqual(parsed_event['request_mask'], 'r')

        self.assertIsNotNone(ReadLog.RE_LOG_ALL.search(event))

    def test_parse_disconnected_path(self):
        # from https://bugzilla.opensuse.org/show_bug.cgi?id=918787
        event = 'type=AVC msg=audit(1424425690.883:716630): apparmor="ALLOWED" operation="file_mmap" info="Failed name lookup - disconnected path" error=-13 profile="/sbin/klogd" name="var/run/nscd/passwd" pid=25333 comm="id" requested_mask="r" denied_mask="r" fsuid=1002 ouid=0'
        parsed_event = self.parser.parse_event(event)

        self.assertEqual(
            parsed_event,
            {
                'aamode':
                'ERROR',  # aamode for disconnected paths overridden aamode in parse_event()
                'active_hat': None,
                'attr': None,
                'denied_mask': 'r',
                'error_code': 13,
                'fsuid': 1002,
                'info': 'Failed name lookup - disconnected path',
                'magic_token': 0,
                'name': 'var/run/nscd/passwd',
                'name2': None,
                'operation': 'file_mmap',
                'ouid': 0,
                'parent': 0,
                'pid': 25333,
                'profile': '/sbin/klogd',
                'request_mask': 'r',
                'resource': 'Failed name lookup - disconnected path',
                'task': 0,
                'time': 1424425690,
                'family': None,
                'protocol': None,
                'sock_type': None,
            })

        self.assertIsNotNone(ReadLog.RE_LOG_ALL.search(event))