File: task.yaml

package info (click to toggle)
snapd 2.72-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 80,412 kB
  • sloc: sh: 16,506; ansic: 16,211; python: 11,213; makefile: 1,919; exp: 190; awk: 58; xml: 22
file content (119 lines) | stat: -rw-r--r-- 5,083 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
summary: Ensure that batch-reloading of AppArmor profiles works, including fallback.

details: |
    This test checks that apparmor profiles are re-generated on snapd startup in a batch,
    and that fallback logic of running apparmor parser for each individual snap takes
    over when the batch fails. This is tested by replacing /sbin/apparmor_parser with
    fake apparmor_parser.fake that fails when if multiple snaps are given (more than 10)
    at once, and otherwise succeeds and runs the real apparmor_parser.
    The test checks system log for transient errors reported by snapd for apparmor failures
    and then verifies apparmor cache to ensure expected profiles were created by fallback
    logic.

systems:
    - ubuntu-20.04-*
    - ubuntu-24.04-*

environment:
    VARIANT/changed: changed
    VARIANT/unchanged: unchanged
    AA_CACHE: /var/cache/apparmor/
    AA_PROFILES: /var/lib/snapd/apparmor/profiles/
    FAKE_LOG: /tmp/apparmor_parser.fake.log

prepare: |
    if not tests.info is-reexec-in-use; then
        tests.exec skip-test "The test uses apparmor from the snapd snap; not valid with no-reexec" && exit 0
    fi

    snap install test-snapd-content-plug test-snapd-tools
    snap install --edge test-snapd-curl
    cp /sbin/apparmor_parser /sbin/apparmor_parser.real
    echo > "$FAKE_LOG"

restore: |
    tests.exec is-skipped && exit 0

    mv /sbin/apparmor_parser.real /sbin/apparmor_parser
    rm -f "$FAKE_LOG"

debug: |
    tests.exec is-skipped && exit 0

    "$TESTSTOOLS"/journal-state get-log -a | grep apparmor_parser.fake
    cat "$FAKE_LOG" || true

execute: |
    tests.exec is-skipped && exit 0

    systemctl stop snapd.{service,socket}

    echo "Update system key"
    printf '{"version":1}' > /var/lib/snapd/system-key

    # snapd will execute the vendored apparmor-parser from the snapd snap
    echo "Replace apparmor parser from the snapd snap with a broken one"
    mount -o bind bin/apparmor_parser.fake /snap/snapd/current/usr/lib/snapd/apparmor_parser
    tests.cleanup defer umount /snap/snapd/current/usr/lib/snapd/apparmor_parser

    # remove all apparmor cached profiles so we can check they are recreated
    rm -f $AA_CACHE/snap* $AA_CACHE/*/snap*

    # "changed" variant requires source profiles on the disk to look different than the
    # ones generated on snapd restart, simulate this by appending a comment to them.
    # In both variants fake apparmor parser fails the same way, the difference is only
    # internal to snapd and it is a slightly different execution path in apparmor backend,
    # manifested in the log by "failed to batch-reload [variant] profiles.." that we match
    # further down.
    if [ "$VARIANT" = "changed" ]; then
        for profile in "$AA_PROFILES"/snap*; do
            echo "# forced profile change" >> "$profile"
        done
    fi
    systemctl start snapd.{socket,service}

    echo "Checking that apparmor profile cache has been populated"

    # note, the list is not exhaustive but is enough for the test and the journal check below
    expected_profiles="snap-update-ns.test-snapd-content-plug
    snap-update-ns.test-snapd-curl
    snap-update-ns.test-snapd-tools
    snap.test-snapd-content-plug.content-plug
    snap.test-snapd-curl.curl
    snap.test-snapd-tools.block
    snap.test-snapd-tools.cat
    snap.test-snapd-tools.cmd
    snap.test-snapd-tools.echo
    snap.test-snapd-tools.env
    snap.test-snapd-tools.fail
    snap.test-snapd-tools.head
    snap.test-snapd-tools.sh
    snap.test-snapd-tools.success"

    retry=50
    while true; do
        if [ $retry -le 0 ]; then
            echo "Expected AppArmor profiles not found in the cache directory."
            echo "Expected: $expected_profiles; Got:"
            cat profiles.out
            exit 1
        fi
        # apparmor cache is a forest on newer Ubuntu (e.g. 19.10), therefore use find
        find $AA_CACHE/ -name '*test-snapd*' -exec basename {} \; | sort > profiles.out
        echo "$expected_profiles" | diff profiles.out - && break
        sleep 1
        retry=$(( retry - 1 ))
    done

    # we're matching a single long log line (the invocation of apparmor_parser for batch-reload of
    # multiple profiles) where the order of arguments is not deterministic, therefore it's split
    # into multiple matches. We expect same profiles to always fail - we just don't know how
    # snapd ordered the arguments when executing apparmor_parser.
    MATCH "FAIL ON: .*/snap-update-ns.test-snapd-curl" < "$FAKE_LOG"
    MATCH "FAIL ON: .*/snap.test-snapd-curl.curl" < "$FAKE_LOG"
    MATCH "FAIL ON: .*/snap-update-ns.test-snapd-tools" < "$FAKE_LOG"
    MATCH "FAIL ON: .*/snap.test-snapd-tools.block" < "$FAKE_LOG"
    MATCH "FAIL ON: .*/snap.test-snapd-tools.cat" < "$FAKE_LOG"
    # sanity: make sure we got just one "FAIL ON:" line, meaning a single failed invocation of apparmor
    # parser when loading the batch.
    [ "$(grep -c "FAIL ON:" < "$FAKE_LOG")" = "1" ] || echo "Got more than one failed invocation of apparmor parser when reloading multiple profiles in a batch"