[apparmor] [PATCH] json support for tools (logprof and genprof)
Goldwyn Rodrigues
rgoldwyn at suse.de
Tue Feb 28 02:39:39 UTC 2017
From: Goldwyn Rodrigues <rgoldwyn at suse.com>
This adds JSON support for tools in order to be able to talk to
other utilities such as Yast.
The json is one per line, in order to differentiate between multiple
records. This is based on work presented by Christian Boltz some time
back.
Signed-off-by: Goldwyn Rodrigues <rgoldwyn at suse.com>
---
utils/aa-genprof | 4 ++
utils/aa-logprof | 7 ++++
utils/apparmor/ui.py | 110 +++++++++++++++++++++++++++------------------------
3 files changed, 70 insertions(+), 51 deletions(-)
diff --git a/utils/aa-genprof b/utils/aa-genprof
index 3fe72bb..296db1b 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=_('provide output in json format'))
args = parser.parse_args()
+if args.json:
+ aaui.UI_mode = 'json'
+
profiling = args.program
profiledir = args.dir
diff --git a/utils/aa-logprof b/utils/aa-logprof
index 05ebbd9..711fc62 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,14 @@ 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=_('provide the output in json format'))
args = parser.parse_args()
+if args.json:
+ aaui.UI_mode = 'json'
+else:
+ aaui.UI_mode = 'text'
+
profiledir = args.dir
logmark = args.mark or ''
diff --git a/utils/apparmor/ui.py b/utils/apparmor/ui.py
index bfbde8c..fe8a9c5 100644
--- a/utils/apparmor/ui.py
+++ b/utils/apparmor/ui.py
@@ -1,5 +1,7 @@
# ----------------------------------------------------------------------
# Copyright (C) 2013 Kshitij Gupta <kgupta8592 at gmail.com>
+# Copyright (C) 2017 Christian Boltz <apparmor at 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,10 +13,12 @@
# GNU General Public License for more details.
#
# ----------------------------------------------------------------------
+
+import json
import sys
import re
import readline
-from apparmor.yasti import yastLog, SendDataToYast, GetDataFromYast
+from apparmor.yasti import SendDataToYast, GetDataFromYast
from apparmor.common import readkey, AppArmorException, DebugLogger
@@ -26,7 +30,10 @@ _ = init_translation()
debug_logger = DebugLogger('UI')
# The operating mode: yast or text, text by default
-UI_mode = 'text'
+try:
+ UI_mode
+except NameError:
+ UI_mode = 'text'
# If Python3, wrap input in raw_input so make check passes
if not 'raw_input' in dir(__builtins__): raw_input = input
@@ -47,18 +54,18 @@ def UI_Info(text):
debug_logger.info(text)
if UI_mode == 'text':
sys.stdout.write(text + '\n')
- else:
- yastLog(text)
+ elif UI_mode == 'json':
+ jsonout = {'info': text}
+ sys.stdout.write(json.dumps(jsonout, sort_keys=False, separators=(',', ': ')) + '\n')
+ #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()
+ elif UI_mode == 'json':
+ jsonout = {'important': text}
+ sys.stdout.write(json.dumps(jsonout, sort_keys=False, separators=(',', ': ')) + '\n')
def get_translated_hotkey(translated, cmsg=''):
msg = 'PromptUser: ' + _('Invalid hotkey for')
@@ -106,14 +113,13 @@ def UI_YesNo(text, default):
else:
ans = default
- else:
- SendDataToYast({'type': 'dialog-yesno',
- 'question': text
- })
- ypath, yarg = GetDataFromYast()
- ans = yarg['answer']
- if not ans:
- ans = default
+ elif UI_mode == 'json':
+ jsonout = {'dialog': 'yesno', 'text': text, 'default': default}
+ sys.stdout.write(json.dumps(jsonout, sort_keys=False, separators=(',', ': ')) + '\n')
+ ans = 'XXXINVALIDXXX'
+ while ans not in ['y', 'n']:
+ ans = getkey()
+
return ans
def UI_YesNoCancel(text, default):
@@ -160,14 +166,13 @@ 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
+ elif UI_mode == 'json':
+ jsonout = {'dialog': 'yesnocancal', 'text': text, 'default': default}
+ sys.stdout.write(json.dumps(jsonout, sort_keys=False, separators=(',', ': ')) + '\n')
+ ans = 'XXXINVALIDXXX'
+ while ans not in ['y', 'n', 'c']:
+ ans = getkey()
+
return ans
def UI_GetString(text, default):
@@ -181,44 +186,34 @@ 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']
+ elif UI_mode == 'json':
+ jsonout = {'dialog': 'getstring', 'text': text, 'default': default}
+ sys.stdout.write(json.dumps(jsonout, sort_keys=False, separators=(',', ': ')) + '\n')
+
+ string = raw_input('\n' + text)
+
return string.strip()
def UI_GetFile(file):
- debug_logger.debug('UI_GetFile: %s' % UI_mode)
+ debug_logger.debug('UI_Mode: %s' % UI_mode)
filename = None
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']
+ elif UI_mode == 'json':
+ jsonout = {'dialog': 'getfile', 'text': file['description']}
+ sys.stdout.write(json.dumps(jsonout, sort_keys=False, separators=(',', ': ')) + '\n')
+ filename = raw_input('\n')
+
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()
+ #if UI_mode == 'text':
+ UI_Info(message)
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'),
@@ -300,7 +295,7 @@ class PromptQuestion(object):
def promptUser(self, params=''):
cmd = None
arg = None
- if UI_mode == 'text':
+ if UI_mode == 'text' or UI_mode == 'json':
cmd, arg = self.Text_PromptUser()
else:
self.type = 'wizard'
@@ -377,6 +372,15 @@ class PromptQuestion(object):
function_regexp += ')$'
ans = 'XXXINVALIDXXX'
+ hdict = dict()
+ jsonprompt = {
+ 'title': title,
+ 'headers': hdict,
+ 'explanation': explanation,
+ 'options': options,
+ 'menu_items': menu_items,
+ }
+
while not re.search(function_regexp, ans, flags=re.IGNORECASE):
prompt = '\n'
@@ -388,6 +392,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'
@@ -405,7 +410,10 @@ class PromptQuestion(object):
prompt += ' / '.join(menu_items)
- sys.stdout.write(prompt + '\n')
+ if UI_mode == 'json':
+ sys.stdout.write(json.dumps(jsonprompt, sort_keys=False, separators=(',', ': ')) + '\n')
+ elif UI_mode == 'text':
+ sys.stdout.write(prompt + '\n')
ans = getkey().lower()
--
2.10.2
More information about the AppArmor
mailing list