Hello community, here is the log from the commit of package apparmor for openSUSE:Factory checked in at 2017-07-23 12:13:24 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/apparmor (Old) and /work/SRC/openSUSE:Factory/.apparmor.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "apparmor" Sun Jul 23 12:13:24 2017 rev:102 rq:511329 version:2.11.0 Changes: -------- --- /work/SRC/openSUSE:Factory/apparmor/apparmor.changes 2017-04-11 12:39:09.145551563 +0200 +++ /work/SRC/openSUSE:Factory/.apparmor.new/apparmor.changes 2017-07-23 12:13:40.981820246 +0200 @@ -1,0 +2,11 @@ +Fri Jul 14 18:51:26 UTC 2017 - suse-b...@cboltz.de + +- don't rely on implementation details for reload in %post + +------------------------------------------------------------------- +Wed Jul 12 13:33:20 UTC 2017 - rgold...@suse.com + +- add JSON support. Required for FATE#323380. + (apparmor-yast-cleanup.patch, apparmor-json-support.patch) + +------------------------------------------------------------------- New: ---- apparmor-json-support.patch apparmor-yast-cleanup.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ apparmor.spec ++++++ --- /var/tmp/diff_new_pack.S0vDu7/_old 2017-07-23 12:13:43.577453592 +0200 +++ /var/tmp/diff_new_pack.S0vDu7/_new 2017-07-23 12:13:43.581453027 +0200 @@ -81,6 +81,10 @@ # add some exceptions to utils/test/test-parser-simple-tests.py (submitted upstream 2017-03-25) Patch11: parser-tests-dbus-duplicated-conditionals.diff +# add JSON support to aa-logprof and aa-genprof (will be in upstream 2.12) +Patch12: apparmor-yast-cleanup.patch +Patch13: apparmor-json-support.patch + PreReq: sed BuildRoot: %{_tmppath}/%{name}-%{version}-build %define apparmor_bin_prefix /lib/apparmor @@ -384,6 +388,8 @@ # patch10 (upstream-changes-r3629..3648.diff) fails to create empty files, do it manually touch libraries/libapparmor/testsuite/test_multi/unconfined-change_hat.err %patch11 +%patch12 -p1 +%patch13 -p1 # search for left-over multiline rules test -z "$(grep -r '^\s*\(unix\|dbus\)[^,]\(([^)]*)\)*[^,]*$' profiles/apparmor.d/)" @@ -737,14 +743,14 @@ %service_del_postun apparmor.service %post abstractions -#restart_on_update boot.apparmor - but non-broken (bnc#853019) -systemctl is-active -q apparmor && /lib/apparmor/apparmor.systemd reload ||: +#restart_on_update apparmor - but non-broken (bnc#853019) +systemctl is-active -q apparmor && systemctl reload apparmor ||: %post profiles # workaround for bnc#904620#c8 / lp#1392042 rm -f /var/lib/apparmor/cache/* 2>/dev/null -#restart_on_update boot.apparmor - but non-broken (bnc#853019) -systemctl is-active -q apparmor && /lib/apparmor/apparmor.systemd reload ||: +#restart_on_update apparmor - but non-broken (bnc#853019) +systemctl is-active -q apparmor && systemctl reload apparmor ||: %if %{with tomcat} ++++++ apparmor-json-support.patch ++++++ commit aa95d7c9d4b0a7386ac52ad8dbcb28922198c8b7 Author: Goldwyn Rodrigues <rgold...@suse.de> Date: Thu Jun 15 18:22:43 2017 +0200 json support for logprof and genprof From: Goldwyn Rodrigues <rgold...@suse.com> Provides json support to tools in order to interact with other utilities such as Yast. The JSON output is one per line, in order to differentiate between multiple records. Each JSON record has a "dialog" entry which defines the type of message passed. A response must contain the "dialog" entry. "info" message does not require a response. "apparmor-json-version" added in order to identify the communication protocol version for future updates. This is based on work done by Christian Boltz. Signed-off-by: Goldwyn Rodrigues <rgold...@suse.com> Acked-by: Christian Boltz <appar...@cboltz.de> Acked-by: Seth Arnold <seth.arn...@canonical.com> diff --git a/utils/aa-genprof b/utils/aa-genprof index e2e65442..c9415e10 100755 --- a/utils/aa-genprof +++ b/utils/aa-genprof @@ -61,8 +61,12 @@ parser = argparse.ArgumentParser(description=_('Generate profile for the given p parser.add_argument('-d', '--dir', type=str, help=_('path to profiles')) parser.add_argument('-f', '--file', type=str, help=_('path to logfile')) parser.add_argument('program', type=str, help=_('name of program to profile')) +parser.add_argument('-j', '--json', action="store_true", help=_('Input and Output in JSON')) args = parser.parse_args() +if args.json: + aaui.set_json_mode() + profiling = args.program profiledir = args.dir diff --git a/utils/aa-logprof b/utils/aa-logprof index c05cbef3..0ff37652 100755 --- a/utils/aa-logprof +++ b/utils/aa-logprof @@ -16,6 +16,7 @@ import argparse import os import apparmor.aa as apparmor +import apparmor.ui as aaui # setup exception handling from apparmor.fail import enable_aa_exception_handler @@ -29,8 +30,12 @@ parser = argparse.ArgumentParser(description=_('Process log entries to generate parser.add_argument('-d', '--dir', type=str, help=_('path to profiles')) parser.add_argument('-f', '--file', type=str, help=_('path to logfile')) parser.add_argument('-m', '--mark', type=str, help=_('mark in the log to start processing after')) +parser.add_argument('-j', '--json', action='store_true', help=_('Input and Output in JSON')) args = parser.parse_args() +if args.json: + aaui.set_json_mode() + profiledir = args.dir logmark = args.mark or '' diff --git a/utils/apparmor/ui.py b/utils/apparmor/ui.py index f25fff31..0010f468 100644 --- a/utils/apparmor/ui.py +++ b/utils/apparmor/ui.py @@ -1,5 +1,7 @@ # ---------------------------------------------------------------------- # Copyright (C) 2013 Kshitij Gupta <kgupta8...@gmail.com> +# Copyright (C) 2017 Christian Boltz <appar...@cboltz.de> +# Copyright (C) 2017 SUSE Linux # # This program is free software; you can redistribute it and/or # modify it under the terms of version 2 of the GNU General Public @@ -11,6 +13,8 @@ # GNU General Public License for more details. # # ---------------------------------------------------------------------- + +import json import sys import re import readline @@ -24,14 +28,32 @@ _ = init_translation() # Set up UI logger for separate messages from UI module debug_logger = DebugLogger('UI') -# The operating mode: yast or text, text by default -UI_mode = 'text' - # If Python3, wrap input in raw_input so make check passes if not 'raw_input' in dir(__builtins__): raw_input = input ARROWS = {'A': 'UP', 'B': 'DOWN', 'C': 'RIGHT', 'D': 'LEFT'} +UI_mode = 'text' + +def write_json(jsonout): + print(json.dumps(jsonout, sort_keys=False, separators=(',', ': '))) + sys.stdout.flush() + +def set_json_mode(): + global UI_mode + UI_mode = 'json' + jsonout = {'dialog': 'apparmor-json-version', 'data': '2.12'} + write_json(jsonout) + +# reads the response on command line for json and verifies the response +# for the dialog type +def json_response(dialog_type): + string = raw_input('\n') + rh = json.loads(string.strip()) + if rh["dialog"] != dialog_type: + raise AppArmorException('Expected response %s got %s.' % (dialog_type, string)) + return rh + def getkey(): key = readkey() if key == '\x1B': @@ -44,12 +66,18 @@ def getkey(): def UI_Info(text): debug_logger.info(text) - if UI_mode == 'text': + if UI_mode == 'json': + jsonout = {'dialog': 'info', 'data': text} + write_json(jsonout) + else: # text mode sys.stdout.write(text + '\n') def UI_Important(text): debug_logger.debug(text) - if UI_mode == 'text': + if UI_mode == 'json': + jsonout = {'dialog': 'important', 'data': text} + write_json(jsonout) + else: # text mode sys.stdout.write('\n' + text + '\n') def get_translated_hotkey(translated, cmsg=''): @@ -67,14 +95,18 @@ def get_translated_hotkey(translated, cmsg=''): def UI_YesNo(text, default): debug_logger.debug('UI_YesNo: %s: %s %s' % (UI_mode, text, default)) default = default.lower() - ans = None - if UI_mode == 'text': - yes = CMDS['CMD_YES'] - no = CMDS['CMD_NO'] - yeskey = get_translated_hotkey(yes).lower() - nokey = get_translated_hotkey(no).lower() - ans = 'XXXINVALIDXXX' - while ans not in ['y', 'n']: + yes = CMDS['CMD_YES'] + no = CMDS['CMD_NO'] + yeskey = get_translated_hotkey(yes).lower() + nokey = get_translated_hotkey(no).lower() + ans = 'XXXINVALIDXXX' + while ans not in ['y', 'n']: + if UI_mode == 'json': + jsonout = {'dialog': 'yesno', 'text': text, 'default': default} + write_json(jsonout) + hm = json_response('yesno') + ans = hm['response_key'] + else: # text mode sys.stdout.write('\n' + text + '\n') if default == 'y': sys.stdout.write('\n[%s] / %s\n' % (yes, no)) @@ -102,18 +134,22 @@ def UI_YesNo(text, default): def UI_YesNoCancel(text, default): debug_logger.debug('UI_YesNoCancel: %s: %s %s' % (UI_mode, text, default)) default = default.lower() - ans = None - if UI_mode == 'text': - yes = CMDS['CMD_YES'] - no = CMDS['CMD_NO'] - cancel = CMDS['CMD_CANCEL'] - - yeskey = get_translated_hotkey(yes).lower() - nokey = get_translated_hotkey(no).lower() - cancelkey = get_translated_hotkey(cancel).lower() - - ans = 'XXXINVALIDXXX' - while ans not in ['c', 'n', 'y']: + yes = CMDS['CMD_YES'] + no = CMDS['CMD_NO'] + cancel = CMDS['CMD_CANCEL'] + + yeskey = get_translated_hotkey(yes).lower() + nokey = get_translated_hotkey(no).lower() + cancelkey = get_translated_hotkey(cancel).lower() + + ans = 'XXXINVALIDXXX' + while ans not in ['c', 'n', 'y']: + if UI_mode == 'json': + jsonout = {'dialog': 'yesnocancel', 'text': text, 'default': default} + write_json(jsonout) + hm = json_response('yesnocancel') + ans = hm['response_key'] + else: # text mode sys.stdout.write('\n' + text + '\n') if default == 'y': sys.stdout.write('\n[%s] / %s / %s\n' % (yes, no, cancel)) @@ -148,7 +184,11 @@ def UI_YesNoCancel(text, default): def UI_GetString(text, default): debug_logger.debug('UI_GetString: %s: %s %s' % (UI_mode, text, default)) string = default - if UI_mode == 'text': + if UI_mode == 'json': + jsonout = {'dialog': 'getstring', 'text': text, 'default': default} + write_json(jsonout) + string = json_response('getstring')["response"] + else: # text mode readline.set_startup_hook(lambda: readline.insert_text(default)) try: string = raw_input('\n' + text) @@ -161,15 +201,18 @@ def UI_GetString(text, default): def UI_GetFile(file): debug_logger.debug('UI_GetFile: %s' % UI_mode) filename = None - if UI_mode == 'text': + if UI_mode == 'json': + jsonout = {'dialog': 'getfile', 'text': file['description']} + write_json(jsonout) + filename = json_response('getfile')["response"] + else: # text mode sys.stdout.write(file['description'] + '\n') filename = sys.stdin.read() return filename def UI_BusyStart(message): debug_logger.debug('UI_BusyStart: %s' % UI_mode) - if UI_mode == 'text': - UI_Info(message) + UI_Info(message) def UI_BusyStop(): debug_logger.debug('UI_BusyStop: %s' % UI_mode) @@ -254,8 +297,7 @@ class PromptQuestion(object): def promptUser(self, params=''): cmd = None arg = None - if UI_mode == 'text': - cmd, arg = self.Text_PromptUser() + cmd, arg = self.Text_PromptUser() if cmd == 'CMD_ABORT': confirm_and_abort() cmd = 'XXXINVALIDXXX' @@ -324,6 +366,17 @@ class PromptQuestion(object): function_regexp += ')$' ans = 'XXXINVALIDXXX' + hdict = dict() + jsonprompt = { + 'dialog': 'promptuser', + 'title': title, + 'headers': hdict, + 'explanation': explanation, + 'options': options, + 'menu_items': menu_items, + 'default_key': default_key, + } + while not re.search(function_regexp, ans, flags=re.IGNORECASE): prompt = '\n' @@ -335,6 +388,7 @@ class PromptQuestion(object): while header_copy: header = header_copy.pop(0) value = header_copy.pop(0) + hdict[header] = value prompt += formatstr % (header + ':', value) prompt += '\n' @@ -352,9 +406,14 @@ class PromptQuestion(object): prompt += ' / '.join(menu_items) - sys.stdout.write(prompt + '\n') - - ans = getkey().lower() + if UI_mode == 'json': + write_json(jsonprompt) + hm = json_response('promptuser') + ans = hm["response_key"] + selected = hm["selected"] + else: # text mode + sys.stdout.write(prompt + '\n') + ans = getkey().lower() if ans: if ans == 'up': @@ -381,7 +440,7 @@ class PromptQuestion(object): selected = ans - 1 ans = 'XXXINVALIDXXX' - if keys.get(ans, False) == 'CMD_HELP': + if keys.get(ans, False) == 'CMD_HELP' and UI_mode != 'json': sys.stdout.write('\n%s\n' % helptext) ans = 'again' ++++++ apparmor-yast-cleanup.patch ++++++ ++++ 602 lines (skipped)