[apparmor] [utils] proposed redesign for mergeprof
Kshitij Gupta
kgupta8592 at gmail.com
Thu Sep 4 18:49:12 UTC 2014
Hello,
Version -1:
Changes to facilitate 2-way merge (maybe also 3-way) of multiple
profiles as discussed on IRC ( which someone had to summarize for ml
;-))
The proposal:
- moves reset method to reset_aa function
- modifies message displayed to user
- allows processing of multiple files in 2-way merge
- disables 3-way merge till new syntax has been decided
The changes reflect the approach of providing arbitrary number of
files using wildcards or explicitly. This makes it necessary to define
a way to distinguish the files for base and other case to be used in
3-way merge.
@cboltz Any ideas are welcome!
The changes map the profiles in the given files to their respective
files in the local directory specified using -d. Then the merges take
place profile-wise. There are some cases with this approach with
multiple profiles in a file where unnecessary questions are asked not
relevant to the other profile.
=== modified file 'utils/aa-mergeprof'
--- utils/aa-mergeprof 2014-09-03 23:49:47 +0000
+++ utils/aa-mergeprof 2014-09-04 18:33:34 +0000
@@ -26,19 +26,19 @@
from apparmor.translations import init_translation
_ = init_translation()
-parser = argparse.ArgumentParser(description=_('Perform a 2-way or
3-way merge on the given profiles'),
+parser = argparse.ArgumentParser(description=_('Perform a 2-way or
3-way merge on the given profiles'),
epilog='WARNING: the arguments will change in a future version!')
-parser.add_argument('mine', type=str, help=_('your profile'))
-parser.add_argument('base', type=str, help=_('base profile'))
-parser.add_argument('other', nargs='?', type=str, help=_('other profile'))
+parser.add_argument('files', nargs='+', type=str, help=_('base profile'))
+#parser.add_argument('other', nargs='?', type=str, help=_('other profile'))
parser.add_argument('-d', '--dir', type=str, help=_('path to profiles'))
#parser.add_argument('-a', '--auto', action='store_true',
help=_('Automatically merge profiles, exits incase of *x conflicts'))
args = parser.parse_args()
+args.other = None
# 2-way merge or 3-way merge based on number of params
-merge_mode = 2 if args.other == None else 3
+merge_mode = 2 #if args.other == None else 3
-profiles = [args.mine, args.base, args.other]
+profiles = [args.files, [args.other]]
profiledir = args.dir
if profiledir:
@@ -46,9 +46,78 @@
if not os.path.isdir(apparmor.aa.profile_dir):
raise apparmor.AppArmorException(_("%s is not a directory.")
%profiledir)
+def reset_aa():
+ apparmor.aa.aa = apparmor.aa.hasher()
+ apparmor.aa.filelist = apparmor.aa.hasher()
+ apparmor.aa.include = dict()
+ apparmor.aa.existing_profiles = apparmor.aa.hasher()
+ apparmor.aa.original_aa = apparmor.aa.hasher()
+
+def find_profiles_from_files(files):
+ profile_to_filename = dict()
+ for file_name in files:
+ apparmor.aa.read_profile(file_name, True)
+ for profile_name in apparmor.aa.filelist[file_name]['profiles'].keys():
+ profile_to_filename[profile_name] = file_name
+ reset_aa()
+
+ return profile_to_filename
+
+def find_files_from_profiles(profiles):
+ profile_to_filename = dict()
+ apparmor.aa.read_profiles()
+
+ for profile_name in profiles:
+ profile_to_filename[profile_name] =
apparmor.aa.get_profile_filename(profile_name)
+
+ reset_aa()
+
+ return profile_to_filename
def main():
- mergeprofiles = Merge(profiles)
+ profiles_to_merge = set()
+
+ base_files, other_files = profiles
+
+ base_profile_to_file = find_profiles_from_files(base_files)
+
+ profiles_to_merge =
profiles_to_merge.union(set(base_profile_to_file.keys()))
+
+ other_profile_to_file = dict()
+
+ if merge_mode == 3:
+ other_profile_to_file = find_profiles_from_files(other_files)
+ profiles_to_merge.add(other_profile_to_file.keys())
+
+ user_profile_to_file = find_files_from_profiles(profiles_to_merge)
+
+ print(base_files,"\n",other_files)
+ print(base_profile_to_file,"\n",other_profile_to_file,"\n",user_profile_to_file)
+ print(profiles_to_merge)
+
+ for profile_name in profiles_to_merge:
+ user_file = user_profile_to_file[profile_name]
+ base_file = base_profile_to_file.get(profile_name, None)
+ other_file = None
+
+ if merge_mode == 3:
+ other_file = other_profile_to_file.get(profile_name, None)
+
+ if base_file == None:
+ if other_file == None:
+ continue
+
+ act([user_file, other_file, None], 2, profile_name)
+ else:
+ if other_file == None:
+ act([user_file, base_file, None], 2, profile_name)
+ else:
+ act([user_file, base_file, other_file], 3, profile_name)
+
+ reset_aa()
+
+def act(files, merge_mode, merging_profile):
+ mergeprofiles = Merge(files)
#Get rid of common/superfluous stuff
mergeprofiles.clear_common()
@@ -62,10 +131,10 @@
mergeprofiles.ask_the_questions('base')
q = apparmor.aa.hasher()
- q['title'] = 'Changed Local Profiles'
+ q['title'] = _('Changes for Local Profile: %s')%(merging_profile)
q['headers'] = []
- q['explanation'] = _('The following local profiles were
changed. Would you like to save them?')
- q['functions'] = ['CMD_SAVE_CHANGES', 'CMD_VIEW_CHANGES', 'CMD_ABORT']
+ q['explanation'] = _('Would you like to save them?')
+ q['functions'] = ['CMD_SAVE_CHANGES', 'CMD_VIEW_CHANGES',
'CMD_ABORT', 'CMD_IGNORE_ENTRY']
q['default'] = 'CMD_VIEW_CHANGES'
q['options'] = []
q['selected'] = 0
@@ -84,6 +153,8 @@
#oldprofile =
apparmor.serialize_profile(apparmor.original_aa[program], program, '')
newprofile =
apparmor.aa.serialize_profile(mergeprofiles.user.aa[program], program,
'')
apparmor.aa.display_changes_with_comments(mergeprofiles.user.filename,
newprofile)
+ elif ans == 'CMD_IGNORE_ENTRY':
+ break
class Merge(object):
@@ -94,25 +165,18 @@
apparmor.aa.read_profile(base, True)
self.base = cleanprofile.Prof(base)
- self.reset()
+ reset_aa()
#Read and parse other profile and save profile data, include
data from it and reset them
if merge_mode == 3:
apparmor.aa.read_profile(other, True)
self.other = cleanprofile.Prof(other)
- self.reset()
+ reset_aa()
#Read and parse user profile
apparmor.aa.read_profile(user, True)
self.user = cleanprofile.Prof(user)
- def reset(self):
- apparmor.aa.aa = apparmor.aa.hasher()
- apparmor.aa.filelist = apparmor.aa.hasher()
- apparmor.aa.include = dict()
- apparmor.aa.existing_profiles = apparmor.aa.hasher()
- apparmor.aa.original_aa = apparmor.aa.hasher()
-
def clear_common(self):
deleted = 0
Regards,
Kshitij Gupta
More information about the AppArmor
mailing list