Accepting request 511329 from security:apparmor

- don't rely on implementation details for reload in %post

- add JSON support. Required for FATE#323380.
  (apparmor-yast-cleanup.patch, apparmor-json-support.patch)

OBS-URL: https://build.opensuse.org/request/show/511329
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/apparmor?expand=0&rev=102
This commit is contained in:
Dominique Leuenberger 2017-07-23 10:13:24 +00:00 committed by Git OBS Bridge
commit dcc7263ed5
4 changed files with 930 additions and 4 deletions

307
apparmor-json-support.patch Normal file
View File

@ -0,0 +1,307 @@
commit aa95d7c9d4b0a7386ac52ad8dbcb28922198c8b7
Author: Goldwyn Rodrigues <rgoldwyn@suse.de>
Date: Thu Jun 15 18:22:43 2017 +0200
json support for logprof and genprof
From: Goldwyn Rodrigues <rgoldwyn@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 <rgoldwyn@suse.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
Acked-by: Seth Arnold <seth.arnold@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 <kgupta8592@gmail.com>
+# Copyright (C) 2017 Christian Boltz <apparmor@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'

602
apparmor-yast-cleanup.patch Normal file
View File

@ -0,0 +1,602 @@
commit 99e2b9e1dfccf765dd84f44f1368892b6a082406
Author: Goldwyn Rodrigues <rgoldwyn@suse.com>
Date: Sun Jun 11 13:03:44 2017 +0200
Remove yast from utils
From: Goldwyn Rodrigues <rgoldwyn@suse.com>
This is the yast cleanup from the utils code. All yast communication
should be done with JSON interface now.
Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
diff --git a/utils/apparmor/aa.py b/utils/apparmor/aa.py
index 141c20dd..6db4b277 100644
--- a/utils/apparmor/aa.py
+++ b/utils/apparmor/aa.py
@@ -14,7 +14,6 @@
# ----------------------------------------------------------------------
# No old version logs, only 2.6 + supported
from __future__ import division, with_statement
-import inspect
import os
import re
import shutil
@@ -64,8 +63,6 @@ from apparmor.rule import quote_if_needed
ruletypes = ['capability', 'change_profile', 'dbus', 'file', 'network', 'ptrace', 'rlimit', 'signal']
-from apparmor.yasti import SendDataToYast, GetDataFromYast, shutdown_yast
-
# setup module translations
from apparmor.translations import init_translation
_ = init_translation()
@@ -146,15 +143,9 @@ def fatal_error(message):
# Add the traceback to message
message = tb_stack + '\n\n' + message
debug_logger.error(message)
- caller = inspect.stack()[1][3]
-
- # If caller is SendDataToYast or GetDatFromYast simply exit
- if caller == 'SendDataToYast' or caller == 'GetDatFromYast':
- sys.exit(1)
# Else tell user what happened
aaui.UI_Important(message)
- shutdown_yast()
sys.exit(1)
def check_for_apparmor(filesystem='/proc/filesystems', mounts='/proc/mounts'):
@@ -539,7 +530,6 @@ def confirm_and_abort():
ans = aaui.UI_YesNo(_('Are you sure you want to abandon this set of profile changes and exit?'), 'n')
if ans == 'y':
aaui.UI_Info(_('Abandoning all changes.'))
- shutdown_yast()
for prof in created:
delete_profile(prof)
sys.exit(0)
@@ -601,20 +591,12 @@ def get_profile(prof_name):
p = profile_hash[options[arg]]
q.selected = options.index(options[arg])
if ans == 'CMD_VIEW_PROFILE':
- if aaui.UI_mode == 'yast':
- SendDataToYast({'type': 'dialogue-view-profile',
- 'user': options[arg],
- 'profile': p['profile'],
- 'profile_type': p['profile_type']
- })
- ypath, yarg = GetDataFromYast()
- else:
- pager = get_pager()
- proc = subprocess.Popen(pager, stdin=subprocess.PIPE)
+ pager = get_pager()
+ proc = subprocess.Popen(pager, stdin=subprocess.PIPE)
# proc.communicate('Profile submitted by %s:\n\n%s\n\n' %
# (options[arg], p['profile']))
- proc.communicate(p['profile'].encode())
- proc.kill()
+ proc.communicate(p['profile'].encode())
+ proc.kill()
elif ans == 'CMD_USE_PROFILE':
if p['profile_type'] == 'INACTIVE_LOCAL':
profile_data = p['profile_data']
@@ -864,76 +846,16 @@ def fetch_profiles_by_user(url, distro, user):
def submit_created_profiles(new_profiles):
#url = cfg['repository']['url']
if new_profiles:
- if aaui.UI_mode == 'yast':
- title = 'New Profiles'
- message = 'Please select the newly created profiles that you would like to store in the repository'
- yast_select_and_upload_profiles(title, message, new_profiles)
- else:
- title = 'Submit newly created profiles to the repository'
- message = 'Would you like to upload newly created profiles?'
- console_select_and_upload_profiles(title, message, new_profiles)
+ title = 'Submit newly created profiles to the repository'
+ message = 'Would you like to upload newly created profiles?'
+ console_select_and_upload_profiles(title, message, new_profiles)
def submit_changed_profiles(changed_profiles):
#url = cfg['repository']['url']
if changed_profiles:
- if aaui.UI_mode == 'yast':
- title = 'Changed Profiles'
- message = 'Please select which of the changed profiles would you like to upload to the repository'
- yast_select_and_upload_profiles(title, message, changed_profiles)
- else:
- title = 'Submit changed profiles to the repository'
- message = 'The following profiles from the repository were changed.\nWould you like to upload your changes?'
- console_select_and_upload_profiles(title, message, changed_profiles)
-
-def yast_select_and_upload_profiles(title, message, profiles_up):
- url = cfg['repository']['url']
- profile_changes = hasher()
- profs = profiles_up[:]
- for p in profs:
- profile_changes[p[0]] = get_profile_diff(p[2], p[1])
- SendDataToYast({'type': 'dialog-select-profiles',
- 'title': title,
- 'explanation': message,
- 'default_select': 'false',
- 'disable_ask_upload': 'true',
- 'profiles': profile_changes
- })
- ypath, yarg = GetDataFromYast()
- selected_profiles = []
- changelog = None
- changelogs = None
- single_changelog = False
- if yarg['STATUS'] == 'cancel':
- return
- else:
- selected_profiles = yarg['PROFILES']
- changelogs = yarg['CHANGELOG']
- if changelogs.get('SINGLE_CHANGELOG', False):
- changelog = changelogs['SINGLE_CHANGELOG']
- single_changelog = True
- user, passw = get_repo_user_pass()
- for p in selected_profiles:
- profile_string = serialize_profile(aa[p], p)
- if not single_changelog:
- changelog = changelogs[p]
- status_ok, ret = upload_profile(url, user, passw, cfg['repository']['distro'],
- p, profile_string, changelog)
- if status_ok:
- newprofile = ret
- newid = newprofile['id']
- set_repo_info(aa[p][p], url, user, newid)
- write_profile_ui_feedback(p)
- else:
- if not ret:
- ret = 'UNKNOWN ERROR'
- aaui.UI_Important(_('WARNING: An error occurred while uploading the profile %(profile)s\n%(ret)s') % { 'profile': p, 'ret': ret })
- aaui.UI_Info(_('Uploaded changes to repository.'))
- if yarg.get('NEVER_ASK_AGAIN'):
- unselected_profiles = []
- for p in profs:
- if p[0] not in selected_profiles:
- unselected_profiles.append(p[0])
- set_profiles_local_only(unselected_profiles)
+ title = 'Submit changed profiles to the repository'
+ message = 'The following profiles from the repository were changed.\nWould you like to upload your changes?'
+ console_select_and_upload_profiles(title, message, changed_profiles)
def upload_profile(url, user, passw, distro, p, profile_string, changelog):
# To-Do
@@ -1925,10 +1847,6 @@ def do_logprof_pass(logmark='', passno=0, log_pid=log_pid):
ask_the_questions(log_dict)
- if aaui.UI_mode == 'yast':
- # To-Do
- pass
-
finishing = False
# Check for finished
save_profiles()
@@ -1958,78 +1876,50 @@ def save_profiles():
changed_list = sorted(changed.keys())
if changed_list:
+ q = aaui.PromptQuestion()
+ q.title = 'Changed Local Profiles'
+ q.explanation = _('The following local profiles were changed. Would you like to save them?')
+ q.functions = ['CMD_SAVE_CHANGES', 'CMD_SAVE_SELECTED', 'CMD_VIEW_CHANGES', 'CMD_VIEW_CHANGES_CLEAN', 'CMD_ABORT']
+ q.default = 'CMD_VIEW_CHANGES'
+ q.options = changed
+ q.selected = 0
+ ans = ''
+ arg = None
+ while ans != 'CMD_SAVE_CHANGES':
+ if not changed:
+ return
+ ans, arg = q.promptUser()
+ if ans == 'CMD_SAVE_SELECTED':
+ profile_name = list(changed.keys())[arg]
+ write_profile_ui_feedback(profile_name)
+ reload_base(profile_name)
- if aaui.UI_mode == 'yast':
- # To-Do
- # selected_profiles = [] # XXX selected_profiles_ref?
- profile_changes = dict()
- for prof in changed_list:
- oldprofile = serialize_profile(original_aa[prof], prof)
- newprofile = serialize_profile(aa[prof], prof)
- profile_changes[prof] = get_profile_diff(oldprofile, newprofile)
- explanation = _('Select which profile changes you would like to save to the\nlocal profile set.')
- title = _('Local profile changes')
- SendDataToYast({'type': 'dialog-select-profiles',
- 'title': title,
- 'explanation': explanation,
- 'dialog_select': 'true',
- 'get_changelog': 'false',
- 'profiles': profile_changes
- })
- ypath, yarg = GetDataFromYast()
- if yarg['STATUS'] == 'cancel':
- return None
- else:
- selected_profiles_ref = yarg['PROFILES']
- for profile_name in selected_profiles_ref:
- write_profile_ui_feedback(profile_name)
- reload_base(profile_name)
-
- else:
- q = aaui.PromptQuestion()
- q.title = 'Changed Local Profiles'
- q.explanation = _('The following local profiles were changed. Would you like to save them?')
- q.functions = ['CMD_SAVE_CHANGES', 'CMD_SAVE_SELECTED', 'CMD_VIEW_CHANGES', 'CMD_VIEW_CHANGES_CLEAN', 'CMD_ABORT']
- q.default = 'CMD_VIEW_CHANGES'
- q.options = changed
- q.selected = 0
- ans = ''
- arg = None
- while ans != 'CMD_SAVE_CHANGES':
- if not changed:
- return
- ans, arg = q.promptUser()
- if ans == 'CMD_SAVE_SELECTED':
- profile_name = list(changed.keys())[arg]
- write_profile_ui_feedback(profile_name)
- reload_base(profile_name)
-
- elif ans == 'CMD_VIEW_CHANGES':
- which = list(changed.keys())[arg]
- oldprofile = None
- if aa[which][which].get('filename', False):
- oldprofile = aa[which][which]['filename']
- else:
- oldprofile = get_profile_filename(which)
+ elif ans == 'CMD_VIEW_CHANGES':
+ which = list(changed.keys())[arg]
+ oldprofile = None
+ if aa[which][which].get('filename', False):
+ oldprofile = aa[which][which]['filename']
+ else:
+ oldprofile = get_profile_filename(which)
- try:
- newprofile = serialize_profile_from_old_profile(aa[which], which, '')
- except AttributeError:
- # see https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1528139
- newprofile = "###\n###\n### Internal error while generating diff, please use '%s' instead\n###\n###\n" % _('View Changes b/w (C)lean profiles')
+ try:
+ newprofile = serialize_profile_from_old_profile(aa[which], which, '')
+ except AttributeError:
+ # see https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1528139
+ newprofile = "###\n###\n### Internal error while generating diff, please use '%s' instead\n###\n###\n" % _('View Changes b/w (C)lean profiles')
- display_changes_with_comments(oldprofile, newprofile)
+ display_changes_with_comments(oldprofile, newprofile)
- elif ans == 'CMD_VIEW_CHANGES_CLEAN':
- which = list(changed.keys())[arg]
- oldprofile = serialize_profile(original_aa[which], which, '')
- newprofile = serialize_profile(aa[which], which, '')
+ elif ans == 'CMD_VIEW_CHANGES_CLEAN':
+ which = list(changed.keys())[arg]
+ oldprofile = serialize_profile(original_aa[which], which, '')
+ newprofile = serialize_profile(aa[which], which, '')
- display_changes(oldprofile, newprofile)
+ display_changes(oldprofile, newprofile)
- for profile_name in sorted(changed.keys()):
- write_profile_ui_feedback(profile_name)
- reload_base(profile_name)
+ for profile_name in sorted(changed.keys()):
+ write_profile_ui_feedback(profile_name)
+ reload_base(profile_name)
def get_pager():
return 'less'
@@ -2065,33 +1955,26 @@ def get_profile_diff(oldprofile, newprofile):
return ''.join(diff)
def display_changes(oldprofile, newprofile):
- if aaui.UI_mode == 'yast':
- aaui.UI_LongMessage(_('Profile Changes'), get_profile_diff(oldprofile, newprofile))
- else:
- difftemp = generate_diff(oldprofile, newprofile)
- subprocess.call('less %s' % difftemp.name, shell=True)
- difftemp.delete = True
- difftemp.close()
+ difftemp = generate_diff(oldprofile, newprofile)
+ subprocess.call('less %s' % difftemp.name, shell=True)
+ difftemp.delete = True
+ difftemp.close()
def display_changes_with_comments(oldprofile, newprofile):
"""Compare the new profile with the existing profile inclusive of all the comments"""
if not os.path.exists(oldprofile):
raise AppArmorException(_("Can't find existing profile %s to compare changes.") % oldprofile)
- if aaui.UI_mode == 'yast':
- #To-Do
- pass
- else:
- newtemp = tempfile.NamedTemporaryFile('w')
- newtemp.write(newprofile)
- newtemp.flush()
+ newtemp = tempfile.NamedTemporaryFile('w')
+ newtemp.write(newprofile)
+ newtemp.flush()
- difftemp = tempfile.NamedTemporaryFile('w')
+ difftemp = tempfile.NamedTemporaryFile('w')
- subprocess.call('diff -u -p %s %s > %s' % (oldprofile, newtemp.name, difftemp.name), shell=True)
+ subprocess.call('diff -u -p %s %s > %s' % (oldprofile, newtemp.name, difftemp.name), shell=True)
- newtemp.close()
- subprocess.call('less %s' % difftemp.name, shell=True)
- difftemp.close()
+ newtemp.close()
+ subprocess.call('less %s' % difftemp.name, shell=True)
+ difftemp.close()
def set_process(pid, profile):
# If process not running don't do anything
diff --git a/utils/apparmor/ui.py b/utils/apparmor/ui.py
index bfbde8c6..f25fff31 100644
--- a/utils/apparmor/ui.py
+++ b/utils/apparmor/ui.py
@@ -14,7 +14,6 @@
import sys
import re
import readline
-from apparmor.yasti import yastLog, SendDataToYast, GetDataFromYast
from apparmor.common import readkey, AppArmorException, DebugLogger
@@ -47,18 +46,11 @@ def UI_Info(text):
debug_logger.info(text)
if UI_mode == 'text':
sys.stdout.write(text + '\n')
- else:
- yastLog(text)
def UI_Important(text):
debug_logger.debug(text)
if UI_mode == 'text':
sys.stdout.write('\n' + text + '\n')
- else:
- SendDataToYast({'type': 'dialog-error',
- 'message': text
- })
- path, yarg = GetDataFromYast()
def get_translated_hotkey(translated, cmsg=''):
msg = 'PromptUser: ' + _('Invalid hotkey for')
@@ -105,15 +97,6 @@ def UI_YesNo(text, default):
continue # If user presses any other button ask again
else:
ans = default
-
- else:
- SendDataToYast({'type': 'dialog-yesno',
- 'question': text
- })
- ypath, yarg = GetDataFromYast()
- ans = yarg['answer']
- if not ans:
- ans = default
return ans
def UI_YesNoCancel(text, default):
@@ -160,14 +143,6 @@ def UI_YesNoCancel(text, default):
default = 'c'
else:
ans = default
- else:
- SendDataToYast({'type': 'dialog-yesnocancel',
- 'question': text
- })
- ypath, yarg = GetDataFromYast()
- ans = yarg['answer']
- if not ans:
- ans = default
return ans
def UI_GetString(text, default):
@@ -181,13 +156,6 @@ def UI_GetString(text, default):
string = ''
finally:
readline.set_startup_hook()
- else:
- SendDataToYast({'type': 'dialog-getstring',
- 'label': text,
- 'default': default
- })
- ypath, yarg = GetDataFromYast()
- string = yarg['string']
return string.strip()
def UI_GetFile(file):
@@ -196,29 +164,15 @@ def UI_GetFile(file):
if UI_mode == 'text':
sys.stdout.write(file['description'] + '\n')
filename = sys.stdin.read()
- else:
- file['type'] = 'dialog-getfile'
- SendDataToYast(file)
- ypath, yarg = GetDataFromYast()
- if yarg['answer'] == 'okay':
- filename = yarg['filename']
return filename
def UI_BusyStart(message):
debug_logger.debug('UI_BusyStart: %s' % UI_mode)
if UI_mode == 'text':
UI_Info(message)
- else:
- SendDataToYast({'type': 'dialog-busy-start',
- 'message': message
- })
- ypath, yarg = GetDataFromYast()
def UI_BusyStop():
debug_logger.debug('UI_BusyStop: %s' % UI_mode)
- if UI_mode != 'text':
- SendDataToYast({'type': 'dialog-busy-stop'})
- ypath, yarg = GetDataFromYast()
CMDS = {'CMD_ALLOW': _('(A)llow'),
'CMD_OTHER': _('(M)ore'),
@@ -302,13 +256,6 @@ class PromptQuestion(object):
arg = None
if UI_mode == 'text':
cmd, arg = self.Text_PromptUser()
- else:
- self.type = 'wizard'
- SendDataToYast(self)
- ypath, yarg = GetDataFromYast()
- if not cmd:
- cmd = 'CMD_ABORT'
- arg = yarg['selected']
if cmd == 'CMD_ABORT':
confirm_and_abort()
cmd = 'XXXINVALIDXXX'
@@ -447,25 +394,8 @@ def confirm_and_abort():
ans = UI_YesNo(_('Are you sure you want to abandon this set of profile changes and exit?'), 'n')
if ans == 'y':
UI_Info(_('Abandoning all changes.'))
- #shutdown_yast()
- #for prof in created:
- # delete_profile(prof)
sys.exit(0)
-def UI_ShortMessage(title, message):
- SendDataToYast({'type': 'short-dialog-message',
- 'headline': title,
- 'message': message
- })
- ypath, yarg = GetDataFromYast()
-
-def UI_LongMessage(title, message):
- SendDataToYast({'type': 'long-dialog-message',
- 'headline': title,
- 'message': message
- })
- ypath, yarg = GetDataFromYast()
-
def is_number(number):
try:
return int(number)
diff --git a/utils/apparmor/yasti.py b/utils/apparmor/yasti.py
deleted file mode 100644
index 180e7152..00000000
--- a/utils/apparmor/yasti.py
+++ /dev/null
@@ -1,106 +0,0 @@
-# ----------------------------------------------------------------------
-# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
-#
-# 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 re
-import sys
-try:
- import ycp
-except ImportError:
- # ycp isn't found everywhere.
- ycp = None
-
-from apparmor.common import error, DebugLogger
-
-# Set up UI logger for separate messages from YaST module
-debug_logger = DebugLogger('YaST')
-
-
-def setup_yast():
- # To-Do
- pass
-
-def shutdown_yast():
- # To-Do
- pass
-
-def yastLog(text):
- ycp.y2milestone(text)
-
-def SendDataToYast(data):
- debug_logger.info('SendDataToYast: Waiting for YCP command')
- for line in sys.stdin:
- ycommand, ypath, yargument = ParseCommand(line)
- if ycommand and ycommand == 'Read':
- debug_logger.info('SendDataToYast: Sending--%s' % data)
- ycp.Return(data)
- return True
- else:
- debug_logger.info('SendDataToYast: Expected \'Read\' but got-- %s' % line)
- error('SendDataToYast: didn\'t receive YCP command before connection died')
-
-def GetDataFromYast():
- debug_logger.inf('GetDataFromYast: Waiting for YCP command')
- for line in sys.stdin:
- debug_logger.info('GetDataFromYast: YCP: %s' % line)
- ycommand, ypath, yarg = ParseCommand(line)
- debug_logger.info('GetDataFromYast: Recieved--\n%s' % yarg)
- if ycommand and ycommand == 'Write':
- ycp.Return('true')
- return ypath, yarg
- else:
- debug_logger.info('GetDataFromYast: Expected Write but got-- %s' % line)
- error('GetDataFromYast: didn\'t receive YCP command before connection died')
-
-def ParseCommand(commands):
- term = ParseTerm(commands)
- if term:
- command = term[0]
- term = term[1:]
- else:
- command = ''
- path = ''
- pathref = None
- if term:
- pathref = term[0]
- term = term[1:]
- if pathref:
- if pathref.strip():
- path = pathref.strip()
- elif command != 'result':
- ycp.y2error('The first arguement is not a path. (%s)' % pathref)
- argument = None
- if term:
- argument = term[0]
- if len(term) > 1:
- ycp.y2warning('Superfluous command arguments ignored')
- return (command, path, argument)
-
-def ParseTerm(inp):
- regex_term = re.compile('^\s*`?(\w*)\s*')
- term = regex_term.search(inp)
- ret = []
- symbol = None
- if term:
- symbol = term.groups()[0]
- else:
- ycp.y2error('No term symbol')
- ret.append(symbol)
- inp = regex_term.sub('', inp)
- if not inp.startswith('('):
- ycp.y2error('No term parantheses')
- argref, err, rest = ycp.ParseYcpTermBody(inp)
- if err:
- ycp.y2error('%s (%s)' % (err, rest))
- else:
- ret += argref
- return ret

View File

@ -1,3 +1,14 @@
-------------------------------------------------------------------
Fri Jul 14 18:51:26 UTC 2017 - suse-beta@cboltz.de
- don't rely on implementation details for reload in %post
-------------------------------------------------------------------
Wed Jul 12 13:33:20 UTC 2017 - rgoldwyn@suse.com
- add JSON support. Required for FATE#323380.
(apparmor-yast-cleanup.patch, apparmor-json-support.patch)
-------------------------------------------------------------------
Sat Mar 25 21:42:10 UTC 2017 - suse-beta@cboltz.de

View File

@ -81,6 +81,10 @@ Patch10: upstream-changes-r3629..3648.diff
# 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 @@ SubDomain.
# 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 @@ export DISABLE_RESTART_ON_UPDATE="yes"
%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}