mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 01:57:43 +00:00
aa-notify: Allow writing to local profiles
The new option --local allows user to write new rules to local profiles instead of system profiles, enabling cleaner profile deployment. This option support the values (yes, no and auto) Signed-off-by: Maxime Bélair <maxime.belair@canonical.com>
This commit is contained in:
parent
4c30a0ac65
commit
df1a4c8782
@ -612,7 +612,8 @@ def add_to_profile(rule, profile_name):
|
||||
return
|
||||
|
||||
update_profile_path = update_profile.__file__
|
||||
command = ['pkexec', '--keep-cwd', update_profile_path, 'add_rule', rule, profile_name]
|
||||
|
||||
command = ['pkexec', '--keep-cwd', update_profile_path, 'add_rule', args.local, rule, profile_name]
|
||||
try:
|
||||
subprocess.run(command, check=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
@ -647,7 +648,7 @@ def allow_rules(clean_rules, allow_all=False):
|
||||
with open(tmp.name, mode='w') as f:
|
||||
|
||||
for profile_name, profile_rules in clean_rules.items():
|
||||
written += f.write(profile_rules.get_writable_rules(template_path))
|
||||
written += f.write(profile_rules.get_writable_rules(template_path, args.local))
|
||||
|
||||
if written > 0:
|
||||
create_from_file(tmp.name)
|
||||
@ -849,6 +850,7 @@ def main():
|
||||
parser.add_argument('-w', '--wait', type=int, metavar=('NUM'), help=_('wait NUM seconds before displaying notifications (with -p)'))
|
||||
parser.add_argument('-m', '--merge-notifications', action='store_true', help=_('Merge notification for improved readability (with -p)'))
|
||||
parser.add_argument('-F', '--foreground', action='store_true', help=_('Do not fork to the background'))
|
||||
parser.add_argument('-L', '--local', nargs='?', const='yes', default='auto', choices=['yes', 'no', 'auto'], help=_('Add to local profile'))
|
||||
parser.add_argument('--prompt-filter', type=str, metavar=('PF'), help=_('kind of operations which display a popup prompt'))
|
||||
parser.add_argument('--debug', action='store_true', help=_('debug mode'))
|
||||
parser.add_argument('--configdir', type=str, help=argparse.SUPPRESS)
|
||||
@ -938,6 +940,7 @@ def main():
|
||||
- prompt_filter
|
||||
- maximum_number_notification_profiles
|
||||
- keys_to_aggregate
|
||||
- use_local_profiles
|
||||
- filter.profile,
|
||||
- filter.operation,
|
||||
- filter.name,
|
||||
@ -960,6 +963,7 @@ def main():
|
||||
'message_footer',
|
||||
'maximum_number_notification_profiles',
|
||||
'keys_to_aggregate',
|
||||
'use_local_profiles',
|
||||
'filter.profile',
|
||||
'filter.operation',
|
||||
'filter.name',
|
||||
@ -1068,6 +1072,15 @@ def main():
|
||||
keys_to_aggregate = config['']['keys_to_aggregate'].strip().split(',')
|
||||
else:
|
||||
keys_to_aggregate = {'operation', 'class', 'name', 'denied', 'target'}
|
||||
if 'use_local_profiles' in config['']:
|
||||
if config['']['use_local_profiles'] in {'auto', 'yes', 'no'}:
|
||||
args.local = config['']['use_local_profiles']
|
||||
elif config['']['use_local_profiles'] is None:
|
||||
args.local = 'yes'
|
||||
else:
|
||||
sys.exit(_('ERROR: using an invalid value for use_local_profiles in config {}\nSupported values: {}').format(
|
||||
config['']['use_local_profiles'], ', '.join({'yes', 'auto', 'no'})
|
||||
))
|
||||
|
||||
if args.file:
|
||||
logfile = args.file
|
||||
|
@ -100,12 +100,12 @@ class ProfileRules:
|
||||
for raw_rule in raw_rules:
|
||||
self.rules.append(SelectableRule(raw_rule, self.selectable))
|
||||
|
||||
def get_writable_rules(self, template_path, allow_all=False):
|
||||
def get_writable_rules(self, template_path, local='yes', allow_all=False):
|
||||
out = ''
|
||||
for rule in self.rules:
|
||||
if allow_all or rule.selected.get():
|
||||
if not self.is_userns_profile:
|
||||
out += 'add_rule\t{}\t{}\n'.format(rule.rule, self.profile_name)
|
||||
out += 'add_rule\t{}\t{}\t{}\n'.format(local, rule.rule, self.profile_name)
|
||||
else:
|
||||
out += 'create_userns\t{}\t{}\t{}\t{}\t{}\n'.format(template_path, self.profile_name, self.bin_path, self.profile_path, 'allow')
|
||||
return out
|
||||
|
@ -8,8 +8,19 @@ from apparmor import aa
|
||||
from apparmor.logparser import ReadLog
|
||||
|
||||
from apparmor.translations import init_translation
|
||||
|
||||
_ = init_translation()
|
||||
|
||||
is_aa_inited = False
|
||||
|
||||
|
||||
def init_if_needed():
|
||||
global is_aa_inited
|
||||
if not is_aa_inited:
|
||||
aa.init_aa()
|
||||
aa.read_profiles()
|
||||
is_aa_inited = True
|
||||
|
||||
|
||||
def create_userns(template_path, name, bin_path, profile_path, decision):
|
||||
with open(template_path, 'r') as f:
|
||||
@ -27,27 +38,48 @@ def create_userns(template_path, name, bin_path, profile_path, decision):
|
||||
exit(_('Cannot reload updated profile'))
|
||||
|
||||
|
||||
def add_to_profile(rule, profile_name):
|
||||
aa.init_aa()
|
||||
aa.update_profiles()
|
||||
|
||||
rule_type, rule_class = ReadLog('', '', '').get_rule_type(rule)
|
||||
|
||||
rule_obj = rule_class.create_instance(rule)
|
||||
|
||||
if not aa.active_profiles.profile_exists(profile_name):
|
||||
exit(_('Cannot find {} in profiles').format(profile_name))
|
||||
aa.active_profiles[profile_name][rule_type].add(rule_obj, cleanup=True)
|
||||
def add_to_profile(rule_obj, profile_name):
|
||||
aa.active_profiles[profile_name][rule_obj.rule_name].add(rule_obj, cleanup=True)
|
||||
|
||||
# Save changes
|
||||
aa.write_profile_ui_feedback(profile_name)
|
||||
|
||||
|
||||
def add_to_local_profile(rule_obj, profile_name):
|
||||
inc_file = aa.create_local_profile_if_needed(profile_name, cleanup=True)
|
||||
|
||||
aa.include[inc_file][inc_file].data[rule_obj.rule_name].add(rule_obj)
|
||||
aa.write_include_ui_feedback(aa.include[inc_file][inc_file], inc_file)
|
||||
|
||||
|
||||
def add_rule(mode, rule, profile_name):
|
||||
init_if_needed()
|
||||
|
||||
if not aa.active_profiles.profile_exists(profile_name):
|
||||
exit(_('Cannot find {} in profiles').format(profile_name))
|
||||
|
||||
rule_type, rule_class = ReadLog('', '', '').get_rule_type(rule)
|
||||
rule_obj = rule_class.create_instance(rule)
|
||||
|
||||
if mode == 'yes':
|
||||
add_to_local_profile(rule_obj, profile_name)
|
||||
elif mode == 'no':
|
||||
add_to_profile(rule_obj, profile_name)
|
||||
elif mode == 'auto':
|
||||
if aa.get_local_include(profile_name):
|
||||
add_to_local_profile(rule_obj, profile_name)
|
||||
else:
|
||||
add_to_profile(rule_obj, profile_name)
|
||||
else:
|
||||
usage(False)
|
||||
|
||||
aa.reload_base(profile_name)
|
||||
|
||||
|
||||
def usage(is_help):
|
||||
print('This tool is a low level tool - do not use it directly')
|
||||
print('{} create_userns <template_path> <name> <bin_path> <profile_path> <decision>'.format(sys.argv[0]))
|
||||
print('{} add_rule <rule> <profile_name>'.format(sys.argv[0]))
|
||||
print('{} add_rule <mode=yes|no|auto> <rule> <profile_name>'.format(sys.argv[0]))
|
||||
print('{} from_file <file>'.format(sys.argv[0]))
|
||||
if is_help:
|
||||
exit(0)
|
||||
@ -76,9 +108,9 @@ def do_command(command, args):
|
||||
usage(False)
|
||||
create_userns(args[1], args[2], args[3], args[4], args[5])
|
||||
elif command == 'add_rule':
|
||||
if not len(args) == 3:
|
||||
if not len(args) == 4:
|
||||
usage(False)
|
||||
add_to_profile(args[1], args[2])
|
||||
add_rule(args[1], args[2], args[3])
|
||||
elif command == 'help':
|
||||
usage(True)
|
||||
else:
|
||||
|
Loading…
x
Reference in New Issue
Block a user