Skip to content

Commit

Permalink
tests: add apparmor prompting integration tests (#14518)
Browse files Browse the repository at this point in the history
* tests: add simple apparmor prompting integration tests

Signed-off-by: Oliver Calder <[email protected]>

* tests/lib/tools: correct tests.session exec usage statement

Since the `exec` argument handler includes a `break` statement, all
further arguments are treated as the command to run and potential
arguments to that command. Thus, the `-u`, `-p`, and `--` arguments
cannot occur after `exec`.

This commit changes the usage statement to reflect this, since all
existing tests use `tests.session [-u USER] [-p PID_FILE] exec <CMD>`
rather than `tests.session exec [-u USER] [-p PID_FILE] -- <CMD>`.

Since `--` is unused and cannot work with `exec` given the former's
`break` statement, remove the `--` argument.

Signed-off-by: Oliver Calder <[email protected]>

* tests: fix apparmor prompting integration tests

Signed-off-by: Oliver Calder <[email protected]>

* tests: add shellcheck exceptions for apparmor prompting tests

Signed-off-by: Oliver Calder <[email protected]>

* tests: add download file tests for apparmor prompting

Signed-off-by: Oliver Calder <[email protected]>

* tests: fix apparmor prompting tests script ownership

Signed-off-by: Oliver Calder <[email protected]>

* tests: add apparmor prompting rule timespan tests

Signed-off-by: Oliver Calder <[email protected]>

* tests: fix rule timeout in timespan deny test for apparmor prompting

Signed-off-by: Oliver Calder <[email protected]>

* tests: add apparmor prompting tests for explicit rule conflict

Signed-off-by: Oliver Calder <[email protected]>

* tests: move prompting scripted client invocation to main task and reduce sleeps

Signed-off-by: Oliver Calder <[email protected]>

* tests: add prompting tests for writes actioned by other pid

Signed-off-by: Oliver Calder <[email protected]>

* tests: make prompt actioned by other pid tests not block on dir lock

When creating a new file is blocked on a reply to a request prompt, the
directory in which the file will be created is locked from other writes.
Thus, we can't queue up multiple outstanding writes on files in the same
directory. Instead, we must write files in different directories in
order for this test to succeed.

Signed-off-by: Oliver Calder <[email protected]>

* tests: clarify comments around directory locking in prompting tests

Signed-off-by: Oliver Calder <[email protected]>

* tests: clarify apparmor prompting test comments and add debug rules

Signed-off-by: Oliver Calder <[email protected]>

* tests: add prompting tests for writing/reading existing files

Signed-off-by: Oliver Calder <[email protected]>

* tests: fix prompting tests which queue up creates and reply single

Signed-off-by: Oliver Calder <[email protected]>

* tests: address review comments on prompting integration tests

Signed-off-by: Oliver Calder <[email protected]>

* tests: fix unwanted shell expansion in apparmor prompting tests

Signed-off-by: Oliver Calder <[email protected]>

* tests: improve checks for snapd restart after enabling prompting

Signed-off-by: Oliver Calder <[email protected]>

* tests: prompting integration tests wait for particular client with test dir to terminate

Signed-off-by: Oliver Calder <[email protected]>

* tests: fix apparmor prompting pgrep, pkill, and NOMATCH usage

Signed-off-by: Oliver Calder <[email protected]>

* tests: fix bugs in prompting integration tests found by shellcheck

Signed-off-by: Oliver Calder <[email protected]>

* tests: fix prompting integration tests support check on older systems

Signed-off-by: Oliver Calder <[email protected]>

* tests: increase restart timeout after enabling apparmor prompting

Signed-off-by: Oliver Calder <[email protected]>

* tests: fix snapd restart check to actually re-check pid

Signed-off-by: Oliver Calder <[email protected]>

* tests: move apparmor prompting snap install client to execute with retry

Signed-off-by: Oliver Calder <[email protected]>

* tests: move apparmor prompting client snap install back to prepare

Signed-off-by: Oliver Calder <[email protected]>

* tests: adjust prompting download file tests now that rules may overlap

Now that #14538 has landed, rules
may overlap as long as their outcomes do not conflict. As such, the
download_file_defaults test case is no longer expected to fail.

Signed-off-by: Oliver Calder <[email protected]>

* tests: fix prompting test case where client expects error

Signed-off-by: Oliver Calder <[email protected]>

---------

Signed-off-by: Oliver Calder <[email protected]>
  • Loading branch information
olivercalder authored Oct 23, 2024
1 parent e2fe8b8 commit bcaa4e6
Show file tree
Hide file tree
Showing 36 changed files with 2,156 additions and 5 deletions.
6 changes: 1 addition & 5 deletions tests/lib/tools/tests.session
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash -e

show_help() {
echo "usage: tests.session exec [-u USER] [-p PID_FILE] [--] <CMD>"
echo "usage: tests.session [-u USER] [-p PID_FILE] exec <CMD>"
echo " tests.session prepare | restore [-u USER | -u USER1,USER2,...]"
echo " tests.session kill-leaked"
echo " tests.session dump"
Expand Down Expand Up @@ -32,10 +32,6 @@ main() {
pid_file="$2"
shift 2
;;
--)
shift
break
;;
kill-leaked)
action=kill-leaked
shift
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"version": 1,
"prompt-filter": {
"snap": "prompting-client",
"interface": "home",
"constraints": {
"path": "$BASE_PATH/.*"
}
},
"prompts": [
{
"prompt-filter": {
"constraints": {
"path": ".*/test1/file.txt",
"requested-permissions": [ "write" ]
}
},
"reply": null
},
{
"prompt-filter": {
"constraints": {
"path": ".*/test2/file.txt",
"requested-permissions": [ "write" ]
}
},
"reply": null
},
{
"prompt-filter": {
"constraints": {
"path": ".*/test3/file.txt",
"requested-permissions": [ "write" ]
}
},
"reply": null
},
{
"prompt-filter": {
"constraints": {
"path": ".*/test4/file.txt",
"requested-permissions": [ "write" ]
}
},
"reply": {
"action": "allow",
"lifespan": "forever",
"constraints": {
"path-pattern": "${BASE_PATH}/test?/file.txt",
"permissions": [ "write" ]
}
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/sh

# A test that replying with allow forever actions previous matching creates.
#
# When creating a new file is blocked on a reply to a request prompt, the
# directory in which the file will be created is locked from other writes.
# Thus, we can't queue up multiple outstanding file creations in the same
# directory. Instead, we must create files in different directories in order
# for this test to succeed. Reads and writes to already-existing files in a
# directory are not blocked by file creations pending replies in that same
# directory.

TEST_DIR="$1"
TIMEOUT="$2"
if [ -z "$TIMEOUT" ] ; then
TIMEOUT=10
fi

WRITABLE="$(snap run --shell prompting-client.scripted -c 'cd ~; pwd')/$(basename "$TEST_DIR")"
snap run --shell prompting-client.scripted -c "mkdir -p $WRITABLE"

for dir in test1 test2 test3 ; do
mkdir -p "${TEST_DIR}/${dir}"
name="${dir}/file.txt"
echo "Attempt to create $name in the background"
snap run --shell prompting-client.scripted -c "touch ${WRITABLE}/${dir}-started; echo $name is written > ${TEST_DIR}/${name}; touch ${WRITABLE}/${dir}-finished" &
if ! timeout "$TIMEOUT" sh -c "while ! [ -f '${WRITABLE}/${dir}-started' ] ; do sleep 0.1 ; done" ; then
echo "failed to start create of $name within timeout period"
exit 1
fi
done

for dir in test1 test2 test3 ; do
name="${dir}/file.txt"
echo "Check that create for $name has not yet finished"
if [ -f "${WRITABLE}/${dir}-finished" ] ; then
echo "create of $name finished before create for test4/file.txt started"
exit 1
fi
done

echo "Attempt to create test4/file.txt (for which client will reply)"
mkdir -p "${TEST_DIR}/test4"
snap run --shell prompting-client.scripted -c "echo test4/file.txt is written > ${TEST_DIR}/test4/file.txt"

# Wait for the client to write its result and exit
timeout "$TIMEOUT" sh -c "while pgrep -f 'prompting-client.scripted.*${TEST_DIR}' > /dev/null; do sleep 0.1; done"

for dir in test1 test2 test3 ; do
name="${dir}/file.txt"
echo "Check that create for $name has finished"
if ! [ -f "${WRITABLE}/${dir}-finished" ] ; then
echo "create of $name did not finish after client replied"
exit 1
fi
done

CLIENT_OUTPUT="$(cat "${TEST_DIR}/result")"

if [ "$CLIENT_OUTPUT" != "success" ] ; then
echo "test failed"
echo "output='$CLIENT_OUTPUT'"
exit 1
fi

for dir in test1 test2 test3 test4; do
name="${dir}/file.txt"
TEST_OUTPUT="$(cat "${TEST_DIR}/${name}")"
if [ "$TEST_OUTPUT" != "$name is written" ] ; then
echo "file creation failed for $name"
exit 1
fi
done
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
{
"version": 1,
"prompt-filter": {
"snap": "prompting-client",
"interface": "home",
"constraints": {
"path": "$BASE_PATH/.*"
}
},
"prompts": [
{
"prompt-filter": {
"constraints": {
"path": ".*/test1/file.txt",
"requested-permissions": [ "write" ]
}
},
"reply": null
},
{
"prompt-filter": {
"constraints": {
"path": ".*/test2/file.txt",
"requested-permissions": [ "write" ]
}
},
"reply": null
},
{
"prompt-filter": {
"constraints": {
"path": ".*/test3/file.txt",
"requested-permissions": [ "write" ]
}
},
"reply": null
},
{
"prompt-filter": {
"constraints": {
"path": ".*/test4/file.txt",
"requested-permissions": [ "write" ]
}
},
"reply": {
"action": "deny",
"lifespan": "forever",
"constraints": {
"path-pattern": "${BASE_PATH}/test?/file.txt",
"permissions": [ "write" ]
}
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/sh

# A test that replying with allow forever actions previous matching creates.
#
# When creating a new file is blocked on a reply to a request prompt, the
# directory in which the file will be created is locked from other writes.
# Thus, we can't queue up multiple outstanding file creations in the same
# directory. Instead, we must create files in different directories in order
# for this test to succeed. Reads and writes to already-existing files in a
# directory are not blocked by file creations pending replies in that same
# directory.

TEST_DIR="$1"
TIMEOUT="$2"
if [ -z "$TIMEOUT" ] ; then
TIMEOUT=10
fi

WRITABLE="$(snap run --shell prompting-client.scripted -c 'cd ~; pwd')/$(basename "$TEST_DIR")"
snap run --shell prompting-client.scripted -c "mkdir -p $WRITABLE"

for dir in test1 test2 test3 ; do
mkdir -p "${TEST_DIR}/${dir}"
name="${dir}/file.txt"
echo "Attempt to create $name in the background"
snap run --shell prompting-client.scripted -c "touch ${WRITABLE}/${dir}-started; echo $name is written > ${TEST_DIR}/${name}; touch ${WRITABLE}/${dir}-finished" &
if ! timeout "$TIMEOUT" sh -c "while ! [ -f '${WRITABLE}/${dir}-started' ] ; do sleep 0.1 ; done" ; then
echo "failed to start create of $name within timeout period"
exit 1
fi
done

for dir in test1 test2 test3 ; do
name="${dir}/file.txt"
echo "Check that create for $name has not yet finished"
if [ -f "${WRITABLE}/${dir}-finished" ] ; then
echo "create of $name finished before create for test4/file.txt started"
exit 1
fi
done

echo "Attempt to create test4/file.txt (for which client will reply)"
mkdir -p "${TEST_DIR}/test4"
snap run --shell prompting-client.scripted -c "echo test4/file.txt is written > ${TEST_DIR}/test4/file.txt"

# Wait for the client to write its result and exit
timeout "$TIMEOUT" sh -c "while pgrep -f 'prompting-client.scripted.*${TEST_DIR}' > /dev/null; do sleep 0.1; done"

for dir in test1 test2 test3 ; do
name="${dir}/file.txt"
echo "Check that create for $name has finished"
if ! [ -f "${WRITABLE}/${dir}-finished" ] ; then
echo "create of $name did not finish after client replied"
exit 1
fi
done

CLIENT_OUTPUT="$(cat "${TEST_DIR}/result")"

if [ "$CLIENT_OUTPUT" != "success" ] ; then
echo "test failed"
echo "output='$CLIENT_OUTPUT'"
exit 1
fi

for dir in test1 test2 test3 test4; do
name="${dir}/file.txt"
if [ -f "${TEST_DIR}/${name}" ] ; then
echo "file creation unexpectedly succeeded for $name"
exit 1
fi
done
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"version": 1,
"prompt-filter": {
"snap": "prompting-client",
"interface": "home",
"constraints": {
"path": "$BASE_PATH/.*"
}
},
"prompts": [
{
"prompt-filter": {
"constraints": {
"path": ".*/test1.txt",
"requested-permissions": [ "write" ]
}
},
"reply": {
"action": "allow",
"lifespan": "forever",
"constraints": {
"path-pattern": "${BASE_PATH}/test*",
"permissions": [ "write" ]
}
}
},
{
"prompt-filter": {
"constraints": {
"path": ".*/fail.txt",
"requested-permissions": [ "write" ]
}
},
"reply": {
"action": "deny",
"lifespan": "single",
"constraints": {
"path-pattern": "${BASE_PATH}/*",
"permissions": [ "write" ]
}
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/sh

# A test that replying with allow always allows multiple files which match the
# path pattern to be created, but doesn't allow other file creation.

TEST_DIR="$1"
TIMEOUT="$2"
if [ -z "$TIMEOUT" ] ; then
TIMEOUT=10
fi

for name in test1.txt test2.md fail.txt test3.pdf ; do
echo "Attempt to write $name"
snap run --shell prompting-client.scripted -c "echo $name is written > ${TEST_DIR}/${name}"
done

# Wait for the client to write its result and exit
timeout "$TIMEOUT" sh -c "while pgrep -f 'prompting-client.scripted.*${TEST_DIR}' > /dev/null; do sleep 0.1; done"

CLIENT_OUTPUT="$(cat "${TEST_DIR}/result")"

if [ "$CLIENT_OUTPUT" != "success" ] ; then
echo "test failed"
echo "output='$CLIENT_OUTPUT'"
exit 1
fi

for name in test1.txt test2.md test3.pdf ; do
TEST_OUTPUT="$(cat "${TEST_DIR}/${name}")"
if [ "$TEST_OUTPUT" != "$name is written" ] ; then
echo "file creation failed for $name"
exit 1
fi
done

if [ -f "${TEST_DIR}/fail.txt" ] ; then
echo "file creation unexpectedly succeeded for fail.txt"
exit 1
fi
Loading

0 comments on commit bcaa4e6

Please sign in to comment.