rpm-ostree/tests/vmcheck/test-autoupdate-check.sh
Jonathan Lebon bdf3cda8db Print CVEs fixed in available updates
One question I often have when looking at the output of `status -a`:

```
AvailableUpdate:
        Version: 29.20181202.0 (2018-12-02T08:37:50Z)
         Commit: dece5737a087d5c6038efdb86cb4512f867082ccfc6eb0fa97b2734c1f6d99c3
   GPGSignature: Valid signature by 5A03B4DD8254ECA02FDA1637A20AA56B429476B4
  SecAdvisories: FEDORA-2018-042156f164  Unknown    net-snmp-libs-1:5.8-3.fc29.x86_64
                 FEDORA-2018-87ba0312c2  Moderate   kernel-4.19.5-300.fc29.x86_64
                 FEDORA-2018-87ba0312c2  Moderate   kernel-core-4.19.5-300.fc29.x86_64
                 FEDORA-2018-87ba0312c2  Moderate   kernel-modules-4.19.5-300.fc29.x86_64
                 FEDORA-2018-87ba0312c2  Moderate   kernel-modules-extra-4.19.5-300.fc29.x86_64
                 FEDORA-2018-f467c36c2b  Moderate   git-core-2.19.2-1.fc29.x86_64
           Diff: 67 upgraded, 1 removed, 16 added
```

is "How serious and relevant are these advisories to me? How soon should
I reboot?". For the packages that I'm most familiar with, e.g. `kernel`
and `git-core`, I usually look up the advisory and check why it was
marked as a security update, mentioned CVEs, and how those affect me.

The updateinfo metadata includes a wealth of information that could be
useful here. In Fedora, CVEs treated by the security response team
result in RHBZs, which end up attached to the advisories and thus make
it into that metadata.

This patch tries to reduce friction in answering some of those questions
above by checking for those CVEs and printing a short description in the
output of `status -a`. Example:

```
AvailableUpdate:
        Version: 29.20181202.0 (2018-12-02T08:37:50Z)
         Commit: dece5737a087d5c6038efdb86cb4512f867082ccfc6eb0fa97b2734c1f6d99c3
   GPGSignature: Valid signature by 5A03B4DD8254ECA02FDA1637A20AA56B429476B4
  SecAdvisories: FEDORA-2018-042156f164  Unknown    net-snmp-libs-1:5.8-3.fc29.x86_64
                   CVE-2018-18065 CVE-2018-18066 net-snmp: various flaws [fedora-all]
                   https://bugzilla.redhat.com/show_bug.cgi?id=1637573
                 FEDORA-2018-87ba0312c2  Moderate   kernel-4.19.5-300.fc29.x86_64
                 FEDORA-2018-87ba0312c2  Moderate   kernel-core-4.19.5-300.fc29.x86_64
                 FEDORA-2018-87ba0312c2  Moderate   kernel-modules-4.19.5-300.fc29.x86_64
                 FEDORA-2018-87ba0312c2  Moderate   kernel-modules-extra-4.19.5-300.fc29.x86_64
                   CVE-2018-16862 kernel: cleancache: Infoleak of deleted files after reuse of old inodes
                   https://bugzilla.redhat.com/show_bug.cgi?id=1649017
                   CVE-2018-19407 kernel: kvm: NULL pointer dereference in vcpu_scan_ioapic in arch/x86/kvm/x86.c
                   https://bugzilla.redhat.com/show_bug.cgi?id=1652656
                 FEDORA-2018-f467c36c2b  Moderate   git-core-2.19.2-1.fc29.x86_64
                   CVE-2018-19486 git: Improper handling of PATH allows for commands to executed from current directory
                   https://bugzilla.redhat.com/show_bug.cgi?id=1653143
           Diff: 67 upgraded, 1 removed, 16 added
```

Including the CVE name and RHBZ link also makes it easier to look for
more details if desired.

Closes: #1695
Approved by: rfairley
2018-12-05 18:56:49 +00:00

282 lines
10 KiB
Bash
Executable File

#!/bin/bash
#
# Copyright (C) 2018 Jonathan Lebon
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
set -euo pipefail
. ${commondir}/libtest.sh
. ${commondir}/libvm.sh
set -x
# Prepare an OSTree repo with updates
vm_ostreeupdate_prepare
# ok, we're done with prep, now let's rebase on the first revision and install a
# bunch of layered packages
vm_build_rpm layered-cake version 2.1 release 3
vm_build_rpm layered-enh
vm_build_rpm layered-sec-none
vm_build_rpm layered-sec-low
vm_build_rpm layered-sec-crit
vm_build_rpm layered-constant # this one we won't update
vm_rpmostree rebase vmcheckmote:vmcheck \
--install layered-cake \
--install layered-enh \
--install layered-sec-none \
--install layered-sec-low \
--install layered-sec-crit \
--install layered-constant
vm_cmd systemctl is-active ostree-finalize-staged.service
vm_reboot
vm_rpmostree status -v
vm_assert_status_jq \
'.deployments[0]["origin"] == "vmcheckmote:vmcheck"' \
'.deployments[0]["version"] == "v1"' \
'.deployments[0]["packages"]|length == 6' \
'.deployments[0]["packages"]|index("layered-cake") >= 0'
echo "ok prep"
# start it up again since we rebooted
vm_start_httpd ostree_server $REMOTE_OSTREE 8888
vm_rpmostree cleanup -m
# make sure that off means off
vm_change_update_policy off
vm_rpmostree status | grep 'AutomaticUpdates: disabled'
vm_rpmostree upgrade --trigger-automatic-update-policy > out.txt
assert_file_has_content out.txt "Automatic updates are not enabled; exiting"
# check we didn't download any metadata (skip starting dir)
vm_cmd find /var/cache/rpm-ostree | tail -n +2 > out.txt
if [ -s out.txt ]; then
cat out.txt && assert_not_reached "rpmmd downloaded!"
fi
echo "ok disabled"
# runs --check and --preview, verifies rc matches what we expect, and capturing
# output for a following assert_output
assert_check_preview_rc() {
local expected_rc=$1; shift
local rc=0
vm_rpmostree upgrade --check > out.txt || rc=$?
assert_streq $rc $expected_rc
vm_rpmostree upgrade --preview > out-verbose.txt || rc=$?
assert_streq $rc $expected_rc
}
# check that --check/--preview still works
assert_check_preview_rc 77
assert_file_has_content out.txt "No updates available."
assert_file_has_content out-verbose.txt "No updates available."
echo "ok --check/--preview no updates"
# ok, let's test out check
vm_change_update_policy check
vm_rpmostree status | grep 'AutomaticUpdates: check'
# build an *older version* and check that we don't report an update
vm_build_rpm layered-cake version 2.1 release 2
cursor=$(vm_get_journal_cursor)
vm_cmd systemctl start rpm-ostreed-automatic.service
vm_wait_content_after_cursor $cursor 'Txn AutomaticUpdateTrigger.*successful'
vm_rpmostree status -v > out.txt
assert_not_file_has_content out.txt "AvailableUpdate"
# And check the unit name https://github.com/projectatomic/rpm-ostree/pull/1368
vm_get_journal_after_cursor $cursor journal.txt
assert_file_has_content journal.txt 'client(id:cli.*unit:rpm-ostreed-automatic.service'
rm -f journal.txt
# build a *newer version* and check that we report an update
vm_build_rpm layered-cake version 2.1 release 4
vm_rpmostree upgrade --trigger-automatic-update-policy
vm_rpmostree status > out.txt
assert_file_has_content out.txt "AvailableUpdate"
assert_file_has_content out.txt "Diff: 1 upgraded"
assert_not_file_has_content out.txt "SecAdvisories"
vm_rpmostree status -v > out.txt
assert_file_has_content out.txt "Upgraded: layered-cake 2.1-3 -> 2.1-4"
# make sure we don't report ostree-based stuff somehow
! grep -A999 'AvailableUpdate' out.txt | grep "Version"
! grep -A999 'AvailableUpdate' out.txt | grep "Timestamp"
! grep -A999 'AvailableUpdate' out.txt | grep "Commit"
echo "ok check mode layered only"
# confirm no filelists were fetched
vm_cmd find /var/cache/rpm-ostree -iname '*filelists*' > out.txt
if [ -s out.txt ]; then
cat out.txt && assert_not_reached "Filelists were downloaded!"
fi
echo "ok no filelists"
# now add some advisory updates
vm_build_rpm layered-enh version 2.0 uinfo VMCHECK-ENH
vm_build_rpm layered-sec-none version 2.0 uinfo VMCHECK-SEC-NONE
vm_rpmostree upgrade --trigger-automatic-update-policy
vm_rpmostree status > out.txt
assert_file_has_content out.txt "SecAdvisories: 1 unknown severity"
vm_rpmostree status -v > out.txt
assert_file_has_content out.txt \
"SecAdvisories: VMCHECK-SEC-NONE Unknown layered-sec-none-2.0-1.x86_64"
assert_not_file_has_content out.txt "VMCHECK-ENH"
assert_output() {
assert_file_has_content out.txt \
"SecAdvisories: 1 unknown severity, 1 low, 1 critical"
assert_file_has_content out-verbose.txt \
"SecAdvisories: VMCHECK-SEC-NONE Unknown layered-sec-none-2.0-1.x86_64" \
" VMCHECK-SEC-LOW Low layered-sec-low-2.0-1.x86_64" \
" VMCHECK-SEC-CRIT Critical layered-sec-crit-2.0-1.x86_64" \
"CVE-43-21 vuln5" \
"http://example.com/vuln5" \
"CVE-87-65 CVE-21-09 vuln7" \
"http://example.com/vuln7"
assert_not_file_has_content out-verbose.txt \
"layered-constant 1.0-1 -> 1.0-1" \
"vuln6" "JUNK" "vuln8"
# make sure any future call doesn't forget to create fresh ones
rm -f out.txt out-verbose.txt
}
# now add all of them
vm_build_rpm layered-sec-low version 2.0 uinfo VMCHECK-SEC-LOW
vm_build_rpm layered-sec-crit version 2.0 uinfo VMCHECK-SEC-CRIT
vm_uinfo add-ref VMCHECK-SEC-CRIT 5 http://example.com/vuln5 "CVE-43-21 vuln5"
vm_uinfo add-ref VMCHECK-SEC-CRIT 6 http://example.com/vuln6 "CVE-43-21 vuln6"
vm_uinfo add-ref VMCHECK-SEC-CRIT 7 http://example.com/vuln7 "CVE-87-65 CVE-21-09 vuln7"
vm_uinfo add-ref VMCHECK-SEC-CRIT 8 http://example.com/vuln8 "CVE-12-JUNK CVE-JUNK vuln8"
vm_rpmostree upgrade --trigger-automatic-update-policy
vm_rpmostree status > out.txt
vm_rpmostree status -v > out-verbose.txt
assert_output
echo "ok check mode layered only with advisories"
# check we see the same output with --check/--preview
# clear out cache first to make sure they start from scratch
vm_rpmostree cleanup -m
vm_cmd systemctl stop rpm-ostreed
assert_check_preview_rc 0
assert_output
echo "ok --check/--preview layered pkgs check policy"
# check that --check/--preview still works even with policy off
vm_change_update_policy off
vm_rpmostree cleanup -m
vm_cmd systemctl stop rpm-ostreed
vm_rpmostree status | grep 'AutomaticUpdates: disabled'
assert_check_preview_rc 0
assert_output
echo "ok --check/--preview layered pkgs off policy"
# ok now let's add ostree updates in the picture
vm_change_update_policy check
vm_ostreeupdate_create v2
vm_rpmostree upgrade --trigger-automatic-update-policy
# make sure we only pulled down the commit metadata
if vm_cmd ostree checkout vmcheckmote:vmcheck --subpath /usr/share/rpm; then
assert_not_reached "Was able to checkout /usr/share/rpm?"
fi
assert_output2() {
vm_assert_status_jq \
'.["cached-update"]["origin"] == "vmcheckmote:vmcheck"' \
'.["cached-update"]["version"] == "v2"' \
'.["cached-update"]["ref-has-new-commit"] == true' \
'.["cached-update"]["gpg-enabled"] == false'
# we could assert more json here, though how it's presented to users is
# important, and implicitly tests the json
assert_file_has_content out.txt \
"SecAdvisories: 1 unknown severity, 1 low, 1 critical" \
'Diff: 10 upgraded, 1 downgraded, 1 removed, 1 added'
assert_file_has_content out-verbose.txt \
"VMCHECK-SEC-NONE Unknown base-pkg-sec-none-2.0-1.x86_64" \
"VMCHECK-SEC-NONE Unknown layered-sec-none-2.0-1.x86_64" \
"VMCHECK-SEC-LOW Low base-pkg-sec-low-2.0-1.x86_64" \
"CVE-12-34 vuln1" \
"http://example.com/vuln1" \
"CVE-56-78 CVE-90-12 vuln3" \
"http://example.com/vuln3" \
"VMCHECK-SEC-LOW Low layered-sec-low-2.0-1.x86_64" \
"VMCHECK-SEC-CRIT Critical base-pkg-sec-crit-2.0-1.x86_64" \
"VMCHECK-SEC-CRIT Critical layered-sec-crit-2.0-1.x86_64" \
"CVE-43-21 vuln5" \
"http://example.com/vuln5" \
"CVE-87-65 CVE-21-09 vuln7" \
"http://example.com/vuln7" \
'Upgraded: base-pkg-enh 1.0-1 -> 2.0-1' \
' base-pkg-foo 1.4-7 -> 1.4-8' \
'Downgraded: base-pkg-bar 1.0-1 -> 0.9-3' \
'Removed: base-pkg-baz-1.1-1.x86_64' \
'Added: base-pkg-boo-3.7-2.11.x86_64'
assert_not_file_has_content out-verbose.txt \
"layered-constant 1.0-1 -> 1.0-1" \
"vuln2" "JUNK" "vuln4" \
"vuln6" "JUNK" "vuln8" \
# make sure any future call doesn't forget to create fresh ones
rm -f out.txt out-verbose.txt
}
vm_rpmostree status > out.txt
vm_rpmostree status -v > out-verbose.txt
assert_output2
echo "ok check mode ostree"
# check that we get similar output with --check/--preview
assert_check_preview_rc 0
assert_output2
echo "ok --check/--preview base pkgs check policy"
vm_change_update_policy off
vm_rpmostree cleanup -m
vm_cmd systemctl stop rpm-ostreed
assert_check_preview_rc 0
assert_output2
echo "ok --check/--preview base pkgs off policy"
assert_default_deployment_is_update() {
vm_assert_status_jq \
'.deployments[0]["origin"] == "vmcheckmote:vmcheck"' \
'.deployments[0]["version"] == "v2"' \
'.deployments[0]["packages"]|length == 6' \
'.deployments[0]["packages"]|index("layered-cake") >= 0'
vm_rpmostree db list $(vm_get_pending_csum) > list.txt
assert_file_has_content list.txt 'layered-cake-2.1-4.x86_64'
}
# now let's upgrade and check that it matches what we expect
# (but start from scratch to check that vanilla `upgrade` also builds the cache)
vm_rpmostree cleanup -m
vm_cmd systemctl stop rpm-ostreed
vm_rpmostree upgrade
vm_rpmostree status > out.txt
vm_rpmostree status -v > out-verbose.txt
# we should have printed as part of the pending deployment
assert_not_file_has_content out.txt "Available update"
assert_not_file_has_content out-verbose.txt "Available update"
assert_output2
assert_default_deployment_is_update
echo "ok upgrade"