Hello,

I played a bit with our shiny new json interface in aa-logprof.

While doing that, I learned that grabbing stdout and simulating stdin 
isn't easy and/or underdocumented. I finally found
    http://www.python-course.eu/pipes.php
It has a very nice and working "Bidirectional Pipes" example which I
used as a base for the code below.

The next thing I noticed out is that aa-logprof simply ends - there isn't
any "end" message, so for now, I have to catch EOFError. Is this 
acceptable, or should we introduce a formal "end" message in json?
Note that such an "end" message could be slightly tricky because there's
more than one way how aa-logprof finishes (no events, aborting, all
events handled and logs saved, crashing with an exception, ...)


That said - here is a proof of concept for testing the aa-logprof json 
interface. I tested it with file events, and I'm quite sure it will 
break when an exec event appears ;-)

Also note that I only tested with py3.


import os, sys

def do_logprof():
    import apparmor.aa as apparmor
    import apparmor.ui as aaui

    aaui.set_json_mode()
    # apparmor.profile_dir = apparmor.get_full_path(profiledir)
    apparmor.set_logfile('./audit.log')

    apparmor.init_aa()
    apparmor.loadincludes()
    apparmor.do_logprof_pass('')

def logprof_driver():
    if not 'raw_input' in dir(__builtins__): raw_input = input

    fh = open("guesser.log","w")

    while True:
        try:
            res = raw_input()
            fh.write(res + "\n")
        except EOFError:
            return

        if 'promptuser' in res:
            if "Changed Local Profiles" in res:
                print('{"dialog": "promptuser", "selected": 0, "response_key": 
"r"}')
                fh.write('*** logprof_driver printed r (abort)\n')
            else:
                print('{"dialog": "promptuser", "selected": 0, "response_key": 
"a"}')
                fh.write('*** logprof_driver printed a\n')
        elif 'yesno' in res:
            print('{"dialog": "yesno", "response_key": "y"}')

        sys.stdout.flush()


stdin  = sys.stdin.fileno() # usually 0
stdout = sys.stdout.fileno() # usually 1

parentStdin, childStdout  = os.pipe()
childStdin,  parentStdout = os.pipe()
pid = os.fork()
if pid:
    # parent process
    os.close(parentStdin)
    os.close(parentStdout)
    os.dup2(childStdin,  stdin)
    os.dup2(childStdout, stdout)
    logprof_driver()
else:
    # child process
    os.close(childStdout)
    os.close(childStdin)
    os.dup2(parentStdin,  stdin)
    os.dup2(parentStdout, stdout)
    do_logprof()



You probably noticed that the answer selection is, well, quite limited ;-)
The final version will have a list of expected input and output.

I'm also thinking about implementing a "json log" in aa-logprof because
writing these lists of expected input and output manually is probably an
annoying task. Just running aa-logprof normally and having all the input
and output as json afterwards would be easier ;-)



Note: you'll need an utils/test/.coveragerc - otherwise you'll end up 
with a "Can't combine arc data with line data" error when trying to 
create a coverage report (from what I found, coverage options given on
the commandline don't survive the fork()).

# cat .coveragerc 
[run]
branch = True
parallel = True
concurrency = multiprocessing


Speaking about coverage - running _only_ the above proof of concept 
results in:
- 29% coverage of aa.py  (that means more than 1000 lines are covered!)
- 51% coverage of ui.py

I also compared "make coverage html" with and without the above POC:
- aa.py: 40% -> 48%
- ui.py: 11% -> 52%


As always - feedback and better code are welcome ;-)


Regards,

Christian Boltz
-- 
Lass es mich so ausdrücken, Du hast einem mutmaßlichen Anfänger auf
die Frage "Wie lasse ich ein Auto an?", mit einer Erklärung wie er
die Zündung kurzschließt geantwortet :-)
[Ralf Corsepius in suse-programming]

Attachment: signature.asc
Description: This is a digitally signed message part.

-- 
AppArmor mailing list
AppArmor@lists.ubuntu.com
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to