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)
def _test_change_profile_flags(self, profile, old_flags, flags_to_change, set_flag, expected_flags, whitespace='', comment='', more_rules='', expected_more_rules='@-@-@', check_new_flags=True, profile_name='/foo'): if old_flags: old_flags = ' %s' % old_flags if expected_flags: expected_flags = ' flags=(%s)' % (expected_flags) else: expected_flags = '' if expected_more_rules == '@-@-@': expected_more_rules = more_rules if comment: comment = ' %s' % comment dummy_profile_content = ' #include <abstractions/base>\n capability chown,\n /bar r,' prof_template = '%s%s%s {%s\n%s\n%s\n}\n' old_prof = prof_template % (whitespace, profile, old_flags, comment, more_rules, dummy_profile_content) new_prof = prof_template % (whitespace, profile, expected_flags, comment, expected_more_rules, dummy_profile_content) self.file = write_file(self.tmpdir, 'profile', old_prof) change_profile_flags(self.file, profile_name, flags_to_change, set_flag) if check_new_flags: real_new_prof = read_file(self.file) self.assertEqual(new_prof, real_new_prof)
def _test_set_flags(self, profile, old_flags, new_flags, whitespace='', comment='', more_rules='', expected_more_rules='@-@-@', expected_flags='@-@-@', check_new_flags=True, profile_name='/foo'): if old_flags: old_flags = ' %s' % old_flags if expected_flags == '@-@-@': expected_flags = new_flags if expected_flags: expected_flags = ' flags=(%s)' % (expected_flags) else: expected_flags = '' if expected_more_rules == '@-@-@': expected_more_rules = more_rules if comment: comment = ' %s' % comment dummy_profile_content = ' #include <abstractions/base>\n capability chown,\n /bar r,' prof_template = '%s%s%s {%s\n%s\n%s\n}\n' old_prof = prof_template % (whitespace, profile, old_flags, comment, more_rules, dummy_profile_content) new_prof = prof_template % (whitespace, profile, expected_flags, comment, expected_more_rules, dummy_profile_content) self.file = write_file(self.tmpdir, 'profile', old_prof) set_profile_flags(self.file, profile_name, new_flags) if check_new_flags: real_new_prof = read_file(self.file) self.assertEqual(new_prof, real_new_prof)
def test_cleanprof(self): input_file = 'cleanprof_test.in' output_file = 'cleanprof_test.out' #We position the local testfile shutil.copy('./%s'%input_file, self.profile_dir) #Our silly test program whose profile we wish to clean cleanprof_test = '/usr/bin/a/simple/cleanprof/test/profile' subprocess.check_output('%s ./../aa-cleanprof --no-reload -d %s -s %s' % (python_interpreter, self.profile_dir, cleanprof_test), shell=True) #Strip off the first line (#modified line) subprocess.check_output('sed -i 1d %s/%s' % (self.profile_dir, input_file), shell=True) exp_content = read_file('./%s' % output_file) real_content = read_file('%s/%s' % (self.profile_dir, input_file)) self.maxDiff = None self.assertEqual(exp_content, real_content, 'Failed to cleanup profile properly')
def test_cleanprof(self): input_file = 'cleanprof_test.in' output_file = 'cleanprof_test.out' #We position the local testfile shutil.copy('./%s'%input_file, self.profile_dir) #Our silly test program whose profile we wish to clean cleanprof_test = '/usr/bin/a/simple/cleanprof/test/profile' subprocess.check_output('%s ./../aa-cleanprof --no-reload -d %s -s %s' % (python_interpreter, self.profile_dir, cleanprof_test), shell=True) #Strip off the first line (#modified line) subprocess.check_output('sed -i 1d %s/%s' % (self.profile_dir, input_file), shell=True) exp_content = read_file('./%s' % output_file) real_content = read_file('%s/%s' % (self.profile_dir, input_file)) self.maxDiff = None self.assertEqual(exp_content, real_content, 'Failed to cleanup profile properly')
def test_change_profile_flags_no_profile_found(self): # test behaviour if the file doesn't contain any profile orig_prof = '# /comment flags=(complain) {\n# }' self.file = write_file(self.tmpdir, 'profile', orig_prof) with self.assertRaises(AppArmorException): change_profile_flags(self.file, None, 'audit', True) # the file should not be changed real_new_prof = read_file(self.file) self.assertEqual(orig_prof, real_new_prof)
def test_change_profile_flags_other_profile(self): # test behaviour if the file doesn't contain the specified /foo profile orig_prof = '/no-such-profile flags=(complain) {\n}' self.file = write_file(self.tmpdir, 'profile', orig_prof) with self.assertRaises(AppArmorException): change_profile_flags(self.file, '/foo', 'audit', True) # the file should not be changed real_new_prof = read_file(self.file) self.assertEqual(orig_prof, real_new_prof)
def test_set_flags_no_profile_found(self): # test behaviour if the file doesn't contain any profile orig_prof = '# /comment flags=(complain) {\n# }' self.file = write_file(self.tmpdir, 'profile', orig_prof) with self.assertRaises(AppArmorBug): set_profile_flags(self.file, None, 'audit') # the file should not be changed real_new_prof = read_file(self.file) self.assertEqual(orig_prof, real_new_prof)
def test_set_flags_other_profile(self): # test behaviour if the file doesn't contain the specified /foo profile orig_prof = '/no-such-profile flags=(complain) {\n}' self.file = write_file(self.tmpdir, 'profile', orig_prof) with self.assertRaises(AppArmorBug): set_profile_flags(self.file, '/foo', 'audit') # the file should not be changed real_new_prof = read_file(self.file) self.assertEqual(orig_prof, real_new_prof)
def _run_test(self, params, expected): logfile = '%s.in' % params if params.split('/')[-1] in log_to_profile_skip: return profile, new_profile = logfile_to_profile(logfile) if profile is None: return 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)
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