The AARE class is meant to handle the internals of path AppArmor regexes
at various places / rule types (filename, signal peer etc.). The goal is
to use it in rule classes to hide all regex magic, so that the rule
class can just use the match() method.
If log_event is given (which means handing over a raw path, not a regex),
the given path is converted to a regex in convert_expression_to_aare().
(Also, the raw path is used in match().)
BTW: The reason for delaying re.compile to match() is performance - I'd
guess a logprof run calls match() only for profiles with existing log
events, so we can save 90% of the re.compile() calls.
The patch also includes several tests.
Acked-by: John Johansen <john.johansen@canonical.com>
In detail, this means:
- handle signal events in logparser.py
- "translate" those events in aa.py - from log (logparser.py readlog())
to prelog (handle_children()) to log_dict (collapse_log()) to
log_obj (ask_the_questions())
(yes, really! :-/ - needless to say that this is ugly...)
- finally ask the user about the signal in ask_the_questions()
Also add a logparser test to test-signal.py to ensure the logparser step
works as expected.
Note that the aa.py changes are not covered by tests, however they
worked in a manual test.
Acked-by: John Johansen <john.johansen@canonical.com>
As Kshitij mentioned, abstract methods should use NotImplementedError
instead of AppArmorBug.
While changing this, I noticed that __repr__() needs to be robust against
NotImplementedError because get_raw() is not available in BaseRule.
Therefore the patch changes __repr__() to catch NotImplementedError.
Of course the change to NotImplementedError also needs several
adjustments in the tests.
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
(long before branching off 2.10, therefore I'll also commit to 2.10)
It's pointless to keep a separate file for those tests - they integrate
well in test-signal.py.
After the move, test-signal_parse.py is empty and will be deleted.
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
This means:
- import the classes instead of RE_PROFILE_SIGNAL
- simplify signal rule parsing a lot
- drop the (now unused) functions parse_signal_rule() and write_signal_rules()
- change write_signal() to use the SignalRuleset class
Also drop the now unused Raw_Signal_Rule from rules.py.
Finally, drop most parser signal tests from the "known wrong results"
blacklist in test-parser-simple-tests.py because those tests succeed
with SignalRule.
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
The tests in test-signal_parse.py used aa.parse_signal_rule(), which is
based on Raw_Signal_Rule (= regex check + "just store it").
This patch changes the tests to test against SignalRule.get_clean().
Since get_clean() does some cleanups, the expected result slightly
differs from the original rule.
Finally switch to the AATest class and setup_all_loops() we use in most
tests.
Also change test-regex_matches.py to import RE_PROFILE_SIGNAL directly
from apparmor.regex instead of apparmor.aa (where it will vanish soon).
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
Those classes will be used to parse and handle signal rules.
They understand the (surprisingly complex) syntax of signal rules.
Note that get_clean() doesn't output superfluos things, so
signal ( send ) set = ( int ),
will become
signal send set=int,
Also add a set of tests (100% coverage :-) to make sure everything works
as expected.
This is a merged commit of the following patches:
- 07-add-SignalRule-and-SignalRuleset.diff
- 13-test-signal-compare_obj.diff
- 17-signal-rule-cleanup.diff
- 21-test-signal-rename-tests.diff
- 22-signal-rule-adjustments.diff
- 24-signal-rule-fix-error-message.diff
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
(all patches in this commit)
As a preparation for the SignalRule class, add a <details> match group
to RE_PROFILE_SIGNAL.
Also adjust test-regex_matches.py for the added group.
Note: RE_PROFILE_SIGNAL is only used in aa.py, and only matches[0..2]
are used. 0 and 1 are audit and allow/deny and 2 is and stays the whole
rule (except audit and allow/deny). Therefore no aa.py changes are
needed.
Acked-by: John Johansen <john.johansen@canonical.com> for trunk and 2.10
The last utils/test/Makefile change switched to using the in-tree
libapparmor by default (unless USE_SYSTEM=1 is given). However, I missed
to add the swig/python parts of libapparmor to PYTHONPATH, so the
system-wide LibAppArmor/__init__.py was always used.
This patch adds the in-tree libapparmor python module to PYTHONPATH.
I'm sorry for the interesting[tm] way to find out that path, but
a) I don't know a better / less ugly way and
b) a similar monster already works in libapparmor/swig/python/test/ ;-)
Acked-by: John Johansen <john.johansen@canonical.com> for 2.9 and trunk
(that also implies 2.10 ;-)
This makes print()ing a class object much more helpful - instead of
<apparmor.rule.network.NetworkRule object at 0x7f416b239e48>
we now get something like
<NetworkRule> network inet stream,
(based on get_raw())
A NetworkRuleset will be printed as (also based on get_raw())
<NetworkRuleset>
network inet stream,
allow network inet stream, # comment
</NetworkRuleset>
Also add tests to test-network.py to ensure that __repr__() works as
expected.
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
If a script contains a hashbang like
#! /usr/bin/perl -w
aa-autodep created a profile entry like
"/usr/bin/perl -w" ix,
which is obviously incorrect.
This patch fixes this (by using only the first part of the hashbang line)
and also adds some tests for it.
References: https://bugs.launchpad.net/apparmor/+bug/1505775
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
Bug: https://launchpad.net/bugs/1393979
Both create_new_profile() and handle_children() check if the given exec
target is a script and add permissions for the interpreter and a
matching abstraction.
This patch merges that into the get_interpreter_and_abstraction()
function and changes create_new_profile() and handle_children() to use
this function.
A nice side effect is that handle_children() now knows more abstractions
(its original list was incomplete).
The behaviour of create_new_profile() doesn't change.
Also add tests for get_interpreter_and_abstraction() to make sure it
does what we expect.
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
Bug: https://launchpad.net/bugs/1505775
These tests ensure that create_new_profile() sets the expected basic
permissions for scripts and non-script files.
Acked-by: John Johansen <john.johansen@canonical.com>
Also add support for the USE_SYSTEM variable, which means:
- test against the in-tree libapparmor and python modules by default
- test against the system libapparmor and python modules if USE_SYSTEM
is set
The old behaviour was a mix of both - it always used the in-tree python
modules and the system libapparmor.
For obvious reasons, you'll need to build libapparmor before running the
tests (unless you specify USE_SYSTEM=1 as parameter to make check).
Acked-by: John Johansen <john.johansen@canonical.com> for trunk and 2.9
Add a testcase that parses all tests in the parser/tst/simple_tests/
directory with parse_profile_data() to ensure that everything with valid
syntax is accepted, and that all tests marked as FAIL raise an
exception.
This already resulted in
- several patches to fix low-hanging fruits (including some bugs in the
parser simple_tests itsself)
- a list of tests that don't behave as expected. Those files get their
expected result reverted to make sure we notice any change in the
tools behaviour, especially changing to the really expected resulted.
This method also makes sure that the testcase doesn't report any of
the known failures.
- a 5% improvement in test coverage - mostly caused by nearly completely
covering parse_profile_data.
- addition of some missing testcased (as noticed by missing coverage),
for example several "rule outside of a profile" testcases.
As indicated above, the tools don't work as expected on all test
profiles - most of the failures happen on expected-to-fail tests that
pass parse_profile_data() without raising an exception. There are also
some tests failing despite valid syntax, often with rarely used syntax
like if conditions and qualifier blocks.
Most of the failing (generated) tests are caused by features not
implemented in the tools yet:
- validating dbus rules (currently we just store them without any parsing)
- checks for conflicting x permissions
- permissions before path ("r /foo,")
- 'safe' and 'unsafe' keywords for *x rules
- 'Pux' and 'Cux' permissions (which actually mean PUx and CUx, and get
rejected by the tools - ideally the generator script should create
PUx and CUx tests instead)
skip_startswith excludes several generated tests from being run. I know
that skip_startswith also excludes tests that would not fail, but the
generated filenames (especially generated_x/exact-*) don't have a
pattern that I could easily use to exclude less tests - and I'm not too
keen to add a list with 1000 single filenames ;-)
Acked-by: John Johansen <john.johansen@canonical.com>
With this addition, all globbing styles (as documented in apparmor.d(5))
are covered in the convert_regexp() tests.
Acked-by: Seth Arnold <seth.arnold@canonical.com>
The tests for convert_regexp() were hidden in common_test.py, where they
were never executed.
This patch moves them to the new file test-aare.py and also converts the
regex_tests.ini to a tests[] array to have the test data inside the test
file. (All tests from regex_tests.ini are in test-aare.py, and two tests
with prepended and appended path segments were added.)
Also add some tests that check the raw behaviour of convert_regexp() -
the tests "by example" are probably more useful and for sure more
readable ;-) but I want to have some examples of the converted regexes
available.
Acked-by <timeout>
logparser.py does a regex check on log lines as performance improvement
so that it only hands over lines that look like AppArmor events to
LibAppArmor parsing. Those regexes were incomplete and didn't cover all
log formats LibAppArmor accepts, with the end result of "overlooking"
events.
This patch splits off common parts of the regex, adds more regexes for
several log types and finally merges everything into one regex.
test-libapparmor-test_multi.py now also checks all test_multi log lines
against the regex to ensure logparser.py doesn't silently ignore events.
test-logparser.py gets adjusted to the merged RE_LOG_ALL regex.
Finally, add a new test that was posted on IRC to the test_multi set.
As already threatened nearly a month ago,
Acked by <timeout> for trunk and 2.9
This testcase will parse all libraries/libapparmor/testsuite/test_multi
tests and compare the result with the *.out files.
It also include a "ToDo list" of keywords that are not yet supported in
the python code - those are typically related to rule types not
supported in the tools yet (dbus, signal etc.).
An interesting special case are exec events with network details:
testcase01.in, testcase12.in, testcase13.in
which might be hand-made, invalid logs, but nobody remembers ;-)
Acked-by <timeout>
Profile name and attachment can contain variables, so the
RE_PROFILE_START regex should accept it.
(Note: the variable content isn't checked.)
Also add some tests with variables.
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
- allow only a specific set of time units
- optionally allow whitespace between rlimit value and unit
- move check for invalid time units to time_to_int()
Also update the tests:
- add several tests with whitespace between value and unit
- change a test that used the (now invalid) "1m" to "1min"
- change the time_to_int() tests to use 'us' as default unit, and add
a test with 'seconds' as default unit
Acked-by: Steve Beattie <steve@nxnw.org>
Thanks to a bug in the apparmor.d manpage, NetworkRule rejected rules
that contained only TYPE (for example "network stream,"). A bugreport on
IRC and some testing with the parser showed that this is actually
allowed, so NetworkRule should of course allow it.
Note: not strip()ing rule_details is the easiest way to ensure we have
whitespace in front of the TYPE in TYPE-only rules, which is needed by
the RE_NETWORK_DETAILS regex.
Also adjust the tests to the correct behaviour.
Acked-by: Steve Beattie <steve@nxnw.org>
RlimitRule accidently used 'ms' (milliseconds) as default unit for
rttime rules, but rttime without unit means 'us' (microseconds). This
patch fixes this.
Also add some tests with 'us' as unit, and two more to cover terribly
invalid corner cases (and to improve test coverage by 2 lines ;-)
Acked-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
Change minitools tests to use AATest and work inside a tmpdir.
This results in lots of changes ('./profiles' -> self.profile_dir,
local_profilename -> self.local_profilename etc.) and also moves some
code from the global area to AASetup().
Also drop the no longer needed clean_profile_dir() and add linebreaks
in assert* calls with a long error message specified.
Acked-by: Steve Beattie <steve@nxnw.org>
The function is basically a wrapper around a regex, so regex.py is a
much better home.
While on it, rename the regex to RE_INCLUDE, change it to named matches,
use RE_EOL to handle comments and compile it outside the function, which
should result in a (small) performance improvement.
Also rewrite re_match_include(), let it check for empty include
filenames ("#include <>") and let it raise AppArmorException in that
case.
Finally, adjust code calling it to the new location, and add some tests
for re_match_include()
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
Change hat declarations ("^hat,") are no longer supported (see previous
patch for details). Therefore remove support for writing them.
This also means to completely remove the 'declared' flag, which was only
needed for hat declarations, and was (after the previous patch) always
set to False.
Also add a hat to the cleanprof_test.{in,out} test profile to make sure
aa-cleanprof doesn't break hats, and a hat declaration with the same
name to make sure it gets removed and doesn't break the "real" hat.
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
After switching to winbindd as test profile, comments about the ntpd
profile don't make sense anymore ;-)
The patch also includes some whitespace fixes.
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
Acked-by: Steve Beattie <steve@nxnw.org>
This time we only have 98% coverage (some missing and partial) because
I didn't find corner cases that raise some exceptions ;-)
Acked-by: Steve Beattie <steve@nxnw.org>
Change minitools_test.py to use the winbind instead of the ntpd profile
for testing. The tests broke because the ntpd profile has the
attach_disconnected flag set now, and therefore didn't match the
expected flags anymore.
Also replace the usage of filecmp.cmp() in the cleanprof test with
reading the file and using assertEqual - this has the advantage that we
get a full diff instead of just "files differ".
Note: The aa-cleanprof test is still failing because of a bug in
tools.py, but will be fixed by the next patch.
See https://bugs.launchpad.net/apparmor/+bug/1416346 for details.
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
This allows to run minitools_test.py as non-root user.
Also add a check that only creates the force-complain directory if it
doesn't exist yet.
Note: With this patch applied, there are still 4 failing tests, probably
caused by changes in the profiles that are used in the tests.
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
The function will return the 'Exec Condition' and the 'Target Profile'
as nice list to use in aa-logprof (once we have support for
change_profile in logparser.py) and aa-mergeprof.
Also add some tests to ensure the correct result.
Acked-by: Steve Beattie <steve@nxnw.org>
BaseRule:
- add logprof_header() - sets the 'Qualifier' (audit, allow/deny) header
if a qualifier is specified, calls logprof_header_localvars() and then
returns an array of headers to display in aa-logprof and aa-mergeprof
- add logprof_header_localvars() - dummy function that needs to be
implemented in the child classes
NetworkRule: add logprof_header_localvars() - adds 'Network Family'
and 'Socket Type' to the headers
CapabilityRule: add logprof_header_localvars() - adds 'Capability' to
the headers
Also change aa-mergeprof to use rule_obj.logprof_header() for network
and capability rules. This means deleting lots of lines (that moved to
the *Rule classes) and also deleting the last differences between
capabiltiy and network rules.
Finally add tests for the newly added functions.
Acked-by: Steve Beattie <steve@nxnw.org>
Also implement handling for the special capability value '__ALL__' in
severity.py, which is used for 'capability,' rules (aa-mergeprof might
need to display the severity for such a rule).
Finally, add some tests for severity() in test-capability.py and a test
for '__ALL__' in test-severity.py.
Acked-by: Steve Beattie <steve@nxnw.org>
severity() will, surprise!, return the severity of a rule, or
sev_db.NOT_IMPLEMENTED if a *Rule class doesn't implement the severity()
function.
Also add the NOT_IMPLEMENTED constant to severity.py, and a test to
test-baserule.py that checks the return value in BaseRule.
Acked-by: Steve Beattie <steve@nxnw.org>
I decided to use a "small" solution for now, which basically means
s/unittest.TestCase/AATest/, cleanup of some setUp() and renaming the
remaining setUp() functions to AASetup().
This doesn't mean an instant win (like in test-severity.py), but allows
to add tests with a tests[] array.
Acked-by: Steve Beattie <steve@nxnw.org>
To be able to distinguish between severity 10 and unknown severity,
change AASetup to specify 'unknown' as default rank, and change the
expected result to 'unknown' where it's expected.
Also change the "expected rank %d" to "%s" because it can be a string
now, and add a test that contains directories with different severity
in one variable.
After these changes, handle_variable_rank() errors out with
TypeError: unorderable types: str() > int()
so fix it by
- initializing rank with the default rank (instead of none)
- explicitely check that rank and rank_new are != the default rank before
doing a comparison
A side effect is another bugfix - '@{HOME}/sys/@{PROC}/overcommit_memory'
is severity 4, not 10 or unknown (confirmed by reading severity.db).
Acked-by: Steve Beattie <steve@nxnw.org>
This simplifies test-severity.py a lot:
- lots of test functions are replaced with tests[] arrays
- tempdir handling and cleanup is now done automagically
Even if test-severity.py shrunk by 65 lines, all tests are still there.
There's even an addition - SeverityTestCap now additionally verifies the
result of rank_capability().
Acked-by: Steve Beattie <steve@nxnw.org>
Add a check to parse_profile_data() to detect if a file contains two
profiles with the same name.
Note: Two profiles with the same name, but in different files, won't be
detected by this check.
Also add basic tests to ensure that a valid profile gets parsed, and two
profiles with the same name inside the same file raise an exception.
(Sidenote: these simple tests improve aa.py coverage from 9% to 12%,
which also confirms the function is too long ;-)
Acked-by: Steve Beattie <steve@nxnw.org>
Add writeTmpfile() to AATest to write a file into the tmpdir. If no
tmpdir exists yet, automatically create one.
createTmpdir() is a separate function so that it's possible to manually
create the tmpdir (for example, if a test needs an empty tmpdir).
Also add a tearDown() function to delete the tmpdir again. This function
calls self.AATeardown() to avoid the need for super() in child classes.
Finally, simplify AaTestWithTempdir in test-aa.py to use createTmpdir()
and add an example for AATeardown() to test-example.py.
Acked-by: Steve Beattie <steve@nxnw.org>
It did this in the old 2.8 code, but didn't in 2.9.x (first there was a
broken hat regex, then I commented out the hat handling to avoid
breakage caused by the broken regex).
This patch makes sure the hat flags get set when setting the flags for
the main profile.
Also change RE_PROFILE_HAT_DEF to use more named matches
(leadingwhitespace and hat_keyword). Luckily all code that uses the
regex uses named matches already, which means adding another (...) pair
doesn't hurt.
Finally adjust the tests:
- change _test_set_flags to accept another optional parameter
expected_more_rules (used to specify the expected hat definition)
- add tests for hats (with '^foobar' and 'hat foobar' syntax)
- add tests for child profiles, one of them commented out (see below)
Remaining known issues (also added as TODO notes):
- The hat and child profile flags are *overwritten* with the flags used
for the main profile. (That's well-known behaviour from 2.8 :-/ but we
have more flags now, which makes this more annoying.)
The correct behaviour would be to add or remove the specified flag,
while keeping other flags unchanged.
- Child profiles are not handled/changed if you specify the 'program'
parameter. This means:
- 'aa-complain smbldap-useradd' or 'aa-complain /usr/sbin/smbldap-useradd'
_will not_ change the flags for the nscd child profile
- 'aa-complain /etc/apparmor.d/usr.sbin.smbldap-useradd' _will_ change
the flags for the nscd child profile (and any other profile and
child profile in that file)
Even with those remaining issues (which need bigger changes in
set_profile_flags() and maybe also in the whole flags handling), the
patch improves things and fixes the regression from the 2.8 code.
Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9
(might get re-used later ;-)
Also add two tests for profile names not starting with / - the quoted
version wasn't catched as invalid before, so this change is actually
also a bugfix.
Acked-by: Steve Beattie <steve@nxnw.org> for trunk and 2.9.
Add setUp() to AATest that sets "self.maxDiff = None" (unlimited).
This gives us unlimited array diffs everywhere where AATest is used.
Also rename several setUp() functions in test-regex_matches.py to
AASetup() to avoid that the shiny new AATest setUp() gets overwritten.
Acked-by: Steve Beattie <steve@nxnw.org>
As requested by Steve, also add an example AASetup() to test-example.py.
Replace usage of RE_PROFILE_CAP and RE_PROFILE_NETWORK with
CapabilityRule.match() and NetworkRule.match() calls.
This also means aa.py doesn't need to import those regexes anymore.
As a side effect of this change, test-regex_matches.py needs a small
fix because it imported RE_PROFILE_CAP from apparmor.aa instead of
apparmor.regex.
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Add match() and _match() class methods to rule classes:
- _match() returns a regex match object for the given raw_rule
- match() converts the _match() result to True or False
The primary usage is to get an answer to the question "is this raw_rule
your job?". (For a moment, I thought about naming the function
*Rule.myjob() instead of *Rule.match() ;-)
My next patch will change aa.py to use *Rule.match() instead of directly
using RE_*, which will make the import list much shorter and hide
another implementation detail inside the rule classes.
Also change _parse() to use _match() instead of the regex, and add some
tests for match() and _match().
Acked-by: Seth Arnold <seth.arnold@canonical.com>
Add utils/test/test-network.py with tests for NetworkRule and
NetworkRuleset.
The tests are hopefully self-explaining, so let me just mention the most
important things:
- I started to play with namedtuple, which looks very useful (see "exp")
- the test loops make the tests much more readable (compare with
test-capability.py!) and make it easy to add some more tests
- 100% coverage :-)
Acked-by: Kshitij Gupta <kgupta8592@gmail.com>
Implement in-profile de-duplication in BaseRuleset (currently affects
"only" CapabilityRuleset, but will also work for all future *Ruleset
classes).
Also change 'deleted' to be a simple counter and add some tests that
verify the in-profile deduplication.
Acked-by: Seth Arnold <seth.arnold@canonical.com>