mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00

... instead of converting log_dict to traditional [profile][hat] layout in do_logprof_pass(). A nice side effect is that we get sorting the main profile before its hats for free and can remove the sorting code. Also update a comment in ask_rule_questions(). Finally, adjust aa-mergeprof so that it hands over a merged log_dict (using split_to_merged())
133 lines
4.7 KiB
Python
Executable file
133 lines
4.7 KiB
Python
Executable file
#! /usr/bin/python3
|
|
# ----------------------------------------------------------------------
|
|
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
|
|
# Copyright (C) 2014-2018 Christian Boltz <apparmor@cboltz.de>
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of version 2 of the GNU General Public
|
|
# License as published by the Free Software Foundation.
|
|
#
|
|
# This program 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.
|
|
#
|
|
# ----------------------------------------------------------------------
|
|
import argparse
|
|
|
|
import apparmor.aa
|
|
|
|
import apparmor.severity
|
|
import apparmor.cleanprofile as cleanprofile
|
|
import apparmor.ui as aaui
|
|
|
|
|
|
|
|
# setup exception handling
|
|
from apparmor.fail import enable_aa_exception_handler
|
|
enable_aa_exception_handler()
|
|
|
|
# setup module translations
|
|
from apparmor.translations import init_translation
|
|
_ = init_translation()
|
|
|
|
parser = argparse.ArgumentParser(description=_('Merge the given profiles into /etc/apparmor.d/ (or the directory specified with -d)'))
|
|
parser.add_argument('files', nargs='+', type=str, help=_('Profile(s) to merge'))
|
|
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'))
|
|
parser.add_argument('--configdir', type=str, help=argparse.SUPPRESS)
|
|
args = parser.parse_args()
|
|
|
|
args.other = None
|
|
|
|
apparmor.aa.init_aa(confdir=args.configdir, profiledir=args.dir)
|
|
|
|
profiles = args.files
|
|
|
|
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.active_profiles.profiles_in_file(file_name):
|
|
profile_to_filename[profile_name] = file_name
|
|
apparmor.aa.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_from_profile_name(profile_name, True)
|
|
|
|
apparmor.aa.reset_aa()
|
|
|
|
return profile_to_filename
|
|
|
|
def main():
|
|
base_profile_to_file = find_profiles_from_files(profiles)
|
|
|
|
profiles_to_merge = set(base_profile_to_file.keys())
|
|
|
|
user_profile_to_file = find_files_from_profiles(profiles_to_merge)
|
|
|
|
for profile_name in profiles_to_merge:
|
|
aaui.UI_Info("\n\n" + _("Merging profile for %s" % profile_name))
|
|
user_file = user_profile_to_file[profile_name]
|
|
base_file = base_profile_to_file.get(profile_name, None)
|
|
|
|
act(user_file, base_file, profile_name)
|
|
|
|
apparmor.aa.reset_aa()
|
|
|
|
def act(user_file, base_file, merging_profile):
|
|
mergeprofiles = Merge(user_file, base_file)
|
|
#Get rid of common/superfluous stuff
|
|
mergeprofiles.clear_common()
|
|
|
|
mergeprofiles.ask_merge_questions()
|
|
|
|
apparmor.aa.changed[merging_profile] = True # force asking to save the profile
|
|
apparmor.aa.save_profiles(True)
|
|
|
|
class Merge(object):
|
|
def __init__(self, user, base):
|
|
#Read and parse base profile and save profile data, include data from it and reset them
|
|
apparmor.aa.read_profile(base, True)
|
|
self.base = cleanprofile.Prof(base)
|
|
|
|
apparmor.aa.reset_aa()
|
|
|
|
#Read and parse user profile
|
|
apparmor.aa.read_profile(user, True)
|
|
self.user = cleanprofile.Prof(user)
|
|
|
|
def clear_common(self):
|
|
deleted = 0
|
|
|
|
#Remove off the parts in base profile which are common/superfluous from user profile
|
|
user_base = cleanprofile.CleanProf(False, self.user, self.base)
|
|
deleted += user_base.compare_profiles()
|
|
|
|
def ask_merge_questions(self):
|
|
other = self.base
|
|
log_dict = {'merge': apparmor.aa.split_to_merged(other.aa)}
|
|
|
|
apparmor.aa.loadincludes()
|
|
|
|
if not apparmor.aa.sev_db:
|
|
apparmor.aa.sev_db = apparmor.severity.Severity(apparmor.aa.CONFDIR + '/severity.db', _('unknown'))
|
|
|
|
# ask about preamble rules
|
|
apparmor.aa.ask_rule_questions(
|
|
other.active_profiles.files[other.filename], # prof_events aka log_dict
|
|
'[preamble]', # displayed profile name
|
|
self.user.active_profiles.files[self.user.filename], # profile to update
|
|
['abi', 'inc_ie'] # rule types - TODO: don't hardcode
|
|
)
|
|
|
|
apparmor.aa.ask_the_questions(log_dict)
|
|
|
|
if __name__ == '__main__':
|
|
main()
|