diff --git a/utils/aa-genprof b/utils/aa-genprof index 21988cdeb..ab62aedc8 100755 --- a/utils/aa-genprof +++ b/utils/aa-genprof @@ -72,12 +72,13 @@ parser.add_argument('-j', '--json', action="store_true", help=_('Input and Outpu parser.add_argument('--configdir', type=str, help=argparse.SUPPRESS) args = parser.parse_args() -if args.json: - aaui.set_json_mode() - profiling = args.program apparmor.init_aa(confdir=args.configdir, profiledir=args.dir) + +if args.json: + aaui.set_json_mode(apparmor.cfg) + apparmor.set_logfile(args.file) aa_mountpoint = apparmor.check_for_apparmor() diff --git a/utils/aa-logprof b/utils/aa-logprof index 4513e35fd..37f3e937a 100755 --- a/utils/aa-logprof +++ b/utils/aa-logprof @@ -31,13 +31,13 @@ parser.add_argument('-j', '--json', action='store_true', help=_('Input and Outpu parser.add_argument('--configdir', type=str, help=argparse.SUPPRESS) args = parser.parse_args() -if args.json: - aaui.set_json_mode() - logmark = args.mark or '' apparmor.init_aa(confdir=args.configdir, profiledir=args.dir) +if args.json: + aaui.set_json_mode(apparmor.cfg) + apparmor.set_logfile(args.file) aa_mountpoint = apparmor.check_for_apparmor() diff --git a/utils/apparmor/ui.py b/utils/apparmor/ui.py index 1163404ab..185ee4458 100644 --- a/utils/apparmor/ui.py +++ b/utils/apparmor/ui.py @@ -33,14 +33,20 @@ debug_logger = DebugLogger('UI') ARROWS = {'A': 'UP', 'B': 'DOWN', 'C': 'RIGHT', 'D': 'LEFT'} UI_mode = 'text' +jsonlog = None def write_json(jsonout): - print(json.dumps(jsonout, sort_keys=False, separators=(',', ': '))) + jtxt = json.dumps(jsonout, sort_keys=False, separators=(',', ': ')) + + if jsonlog: + jsonlog.write('o ' + jtxt + '\n') + + print(jtxt) sys.stdout.flush() -def set_json_mode(): +def set_json_mode(cfg): """ Currently this is only used by aa-genprof and aa-logprof, while e.g. aa-status generates its own JSON output. @@ -50,8 +56,14 @@ def set_json_mode(): Current known consumers of the JSON output: - YaST + + The cfg parameter expects the parsed logprof.conf aka apparmor.aa.cfg. """ - global UI_mode + global UI_mode, jsonlog + + if int(cfg['settings'].get('json_log', False)): + jsonlog = NamedTemporaryFile('w', prefix='aa-jsonlog-', delete=False, encoding='utf-8') + UI_mode = 'json' jsonout = {'dialog': 'apparmor-json-version', 'data': '2.12'} write_json(jsonout) @@ -67,6 +79,10 @@ def set_text_mode(): # for the dialog type def json_response(dialog_type): string = input('\n') + + if jsonlog: + jsonlog.write('i ' + string + '\n') + rh = json.loads(string.strip()) if rh["dialog"] != dialog_type: raise AppArmorException('Expected response %s got %s.' % (dialog_type, string)) diff --git a/utils/logprof.conf b/utils/logprof.conf index fd804c0ab..64d3f6f1e 100644 --- a/utils/logprof.conf +++ b/utils/logprof.conf @@ -35,6 +35,10 @@ # files. custom_includes = + # When called with --json, log all input and output to a tempfile (/tmp/aa-jsonlog-*) + # Only enable for debugging. + # Note that aa-logprof will not display any hint that aa-jsonlog-* gets written. + json_log = 0 [qualifiers] # things will be painfully broken if bash has a profile diff --git a/utils/test/test-aa-cli-bootstrap.py b/utils/test/test-aa-cli-bootstrap.py index 206445260..b784e7564 100644 --- a/utils/test/test-aa-cli-bootstrap.py +++ b/utils/test/test-aa-cli-bootstrap.py @@ -61,7 +61,7 @@ class AACliBootstrapTest(AATest): self.assertEqual(sys.stdout.getvalue(), 'Test string\n') def test_aa_ui_info_json(self): - aaui.set_json_mode() + aaui.set_json_mode({'settings': {}}) sys.stdout.getvalue() aaui.UI_Info('Test string') self.assertEqual(