Blame SOURCES/0007-Add-clevis-luks-report.patch

3700a9
From a85f50f789d69d9ca0a4096a64ac912f5967f97f Mon Sep 17 00:00:00 2001
3700a9
From: Sergio Correia <scorreia@redhat.com>
3700a9
Date: Sun, 10 May 2020 15:32:50 -0300
3700a9
Subject: [PATCH 7/8] Add clevis luks report
3700a9
3700a9
---
3700a9
 src/luks/clevis-luks-report         | 95 +++++++++++++++++++++++++++++
3700a9
 src/luks/clevis-luks-report-compare | 71 +++++++++++++++++++++
3700a9
 src/luks/clevis-luks-report-decode  | 59 ++++++++++++++++++
3700a9
 src/luks/clevis-luks-report-sss     | 53 ++++++++++++++++
3700a9
 src/luks/clevis-luks-report-tang    | 67 ++++++++++++++++++++
3700a9
 src/luks/clevis-luks-report.1.adoc  | 41 +++++++++++++
3700a9
 src/luks/meson.build                |  7 +++
3700a9
 7 files changed, 393 insertions(+)
3700a9
 create mode 100755 src/luks/clevis-luks-report
3700a9
 create mode 100755 src/luks/clevis-luks-report-compare
3700a9
 create mode 100755 src/luks/clevis-luks-report-decode
3700a9
 create mode 100755 src/luks/clevis-luks-report-sss
3700a9
 create mode 100755 src/luks/clevis-luks-report-tang
3700a9
 create mode 100644 src/luks/clevis-luks-report.1.adoc
3700a9
3700a9
diff --git a/src/luks/clevis-luks-report b/src/luks/clevis-luks-report
3700a9
new file mode 100755
3700a9
index 0000000..f047256
3700a9
--- /dev/null
3700a9
+++ b/src/luks/clevis-luks-report
3700a9
@@ -0,0 +1,95 @@
3700a9
+#!/usr/bin/bash -e
3700a9
+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
3700a9
+#
3700a9
+# Copyright (c) 2018 Red Hat, Inc.
3700a9
+# Author: Radovan Sroka <rsroka@redhat.com>
3700a9
+#
3700a9
+# This program is free software: you can redistribute it and/or modify
3700a9
+# it under the terms of the GNU General Public License as published by
3700a9
+# the Free Software Foundation, either version 3 of the License, or
3700a9
+# (at your option) any later version.
3700a9
+#
3700a9
+# This program is distributed in the hope that it will be useful,
3700a9
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3700a9
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3700a9
+# GNU General Public License for more details.
3700a9
+#
3700a9
+# You should have received a copy of the GNU General Public License
3700a9
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
3700a9
+#
3700a9
+
3700a9
+. clevis-luks-common-functions
3700a9
+
3700a9
+SUMMARY="Report any key rotation on the server side"
3700a9
+
3700a9
+if [ "$1" == "--summary" ]; then
3700a9
+    echo "$SUMMARY"
3700a9
+    exit 0
3700a9
+fi
3700a9
+
3700a9
+function usage_and_exit () {
3700a9
+    echo >&2
3700a9
+    echo "Usage: clevis luks report [-qr] -d DEV -s SLOT" >&2
3700a9
+    echo >&2
3700a9
+    echo -e "  -q\t Quiet mode" >&2
3700a9
+    echo -e "  -r\t Regenerate luks metadata with \"clevis luks regen -d DEV -s SLOT\"" >&2
3700a9
+    echo >&2
3700a9
+    echo "$SUMMARY" >&2
3700a9
+    echo >&2
3700a9
+    exit "$1"
3700a9
+}
3700a9
+
3700a9
+while getopts "hd:s:rq" o; do
3700a9
+    case "$o" in
3700a9
+    d) DEV="$OPTARG";;
3700a9
+    h) usage_and_exit 0;;
3700a9
+    r) ROPT="regen";;
3700a9
+    s) SLT="$OPTARG";;
3700a9
+    q) QOPT="quiet";;
3700a9
+    *) usage_and_exit 1;;
3700a9
+    esac
3700a9
+done
3700a9
+
3700a9
+### get luks metadata
3700a9
+
3700a9
+if [ -z "$DEV" ]; then
3700a9
+    echo "Did not specify a device!" >&2
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+if [ -z "$SLT" ]; then
3700a9
+    echo "Did not specify a slot!" >&2
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+if ! DATA_CODED=$(clevis_luks_read_slot "${DEV}" "${SLT}"); then
3700a9
+    # Error message was already displayed by clevis_luks_read_slot(),
3700a9
+    # at this point.
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+EXE="$(findexe clevis-luks-report-decode)"
3700a9
+RESULT="$($EXE "${DATA_CODED}")"
3700a9
+
3700a9
+if [ -n "$RESULT" ]; then
3700a9
+    echo "$RESULT"
3700a9
+    echo "Report detected that some keys were rotated."
3700a9
+    if [ -z "$QOPT" ]; then
3700a9
+        if [ -z "$ROPT" ]; then
3700a9
+            read -r -p "Do you want to regenerate luks metadata with \"clevis luks regen -d $DEV -s $SLT\"? [ynYN] " ans < /dev/tty
3700a9
+            [[ "$ans" =~ ^[yY]$ ]] && ROPT="regen"
3700a9
+        fi
3700a9
+    fi
3700a9
+else
3700a9
+    exit 0
3700a9
+fi
3700a9
+
3700a9
+if [ "$ROPT" = "regen" ]; then
3700a9
+    EXE="$(findexe clevis-luks-regen)"
3700a9
+    exec "$EXE" -d "$DEV" -s "$SLT"
3700a9
+else
3700a9
+    if [ -n "${RESULT}" ]; then
3700a9
+        # Keys were rotated.
3700a9
+        exit 1
3700a9
+    fi
3700a9
+fi
3700a9
diff --git a/src/luks/clevis-luks-report-compare b/src/luks/clevis-luks-report-compare
3700a9
new file mode 100755
3700a9
index 0000000..2ba5132
3700a9
--- /dev/null
3700a9
+++ b/src/luks/clevis-luks-report-compare
3700a9
@@ -0,0 +1,71 @@
3700a9
+#!/usr/bin/bash -e
3700a9
+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
3700a9
+#
3700a9
+# Copyright (c) 2018 Red Hat, Inc.
3700a9
+# Author: Radovan Sroka <rsroka@redhat.com>
3700a9
+#
3700a9
+# This program is free software: you can redistribute it and/or modify
3700a9
+# it under the terms of the GNU General Public License as published by
3700a9
+# the Free Software Foundation, either version 3 of the License, or
3700a9
+# (at your option) any later version.
3700a9
+#
3700a9
+# This program is distributed in the hope that it will be useful,
3700a9
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3700a9
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3700a9
+# GNU General Public License for more details.
3700a9
+#
3700a9
+# You should have received a copy of the GNU General Public License
3700a9
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
3700a9
+#
3700a9
+
3700a9
+SUMMARY="Compare two sets of keys"
3700a9
+
3700a9
+if [ "$1" == "--summary" ]; then
3700a9
+    echo "$SUMMARY"
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+if [ -z "$1" ]; then
3700a9
+    echo "$0 missing the first argument!"
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+if [ -z "$2" ]; then
3700a9
+    echo "$0 missing the second argument!"
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+ADV_KEYS="$1" # keys from advertisement
3700a9
+LUKS_KEYS="$2" # keys from luks metadata
3700a9
+
3700a9
+### iterate over adv keys and make thumbprints
3700a9
+CNT=0
3700a9
+declare -a ADV_KEYS_ARRAY
3700a9
+while res="$(jose fmt -j- -g keys -g"$CNT" -o- <<< "$ADV_KEYS")"; do
3700a9
+    thp="$(echo "$res" | jose jwk thp -i-)"
3700a9
+    ADV_KEYS_ARRAY["$CNT"]="$thp"
3700a9
+    CNT=$(( CNT + 1 ))
3700a9
+done
3700a9
+
3700a9
+CNT=0
3700a9
+while key="$(jose fmt -j- -g keys -g"$CNT" -o- <<< "$LUKS_KEYS")"; do
3700a9
+    thp="$(echo "$key" | jose jwk thp -i-)"
3700a9
+
3700a9
+    FOUND=0
3700a9
+    for k in "${ADV_KEYS_ARRAY[@]}"
3700a9
+    do
3700a9
+        if [ "$k" = "$thp" ]; then
3700a9
+            FOUND=1
3700a9
+            break
3700a9
+        fi
3700a9
+    done
3700a9
+
3700a9
+    if [ "$FOUND" -eq "0" ]; then
3700a9
+        echo "Key \"$thp\" is not in the advertisement and was probably rotated!"
3700a9
+        echo "$key"
3700a9
+        echo
3700a9
+    fi
3700a9
+    CNT=$(( CNT + 1 ))
3700a9
+done
3700a9
+
3700a9
+exit 0
3700a9
diff --git a/src/luks/clevis-luks-report-decode b/src/luks/clevis-luks-report-decode
3700a9
new file mode 100755
3700a9
index 0000000..f39d1e9
3700a9
--- /dev/null
3700a9
+++ b/src/luks/clevis-luks-report-decode
3700a9
@@ -0,0 +1,59 @@
3700a9
+#!/usr/bin/bash -e
3700a9
+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
3700a9
+#
3700a9
+# Copyright (c) 2018 Red Hat, Inc.
3700a9
+# Author: Radovan Sroka <rsroka@redhat.com>
3700a9
+#
3700a9
+# This program is free software: you can redistribute it and/or modify
3700a9
+# it under the terms of the GNU General Public License as published by
3700a9
+# the Free Software Foundation, either version 3 of the License, or
3700a9
+# (at your option) any later version.
3700a9
+#
3700a9
+# This program is distributed in the hope that it will be useful,
3700a9
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3700a9
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3700a9
+# GNU General Public License for more details.
3700a9
+#
3700a9
+# You should have received a copy of the GNU General Public License
3700a9
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
3700a9
+#
3700a9
+
3700a9
+. clevis-luks-common-functions
3700a9
+
3700a9
+SUMMARY="Decode luks header"
3700a9
+
3700a9
+if [ "$1" == "--summary" ]; then
3700a9
+    echo "$SUMMARY"
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+if [ -z "$1" ]; then
3700a9
+    echo "$0 missing the first argument!"
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+DATA_CODED="$1"
3700a9
+
3700a9
+if DATA_CODED="$(jose jwe fmt -i- <<< "$DATA_CODED")"; then
3700a9
+    DATA_CODED="$(jose fmt -j- -g protected -u- <<< "$DATA_CODED")"
3700a9
+    DATA_DECODED="$(jose b64 dec -i- <<< "$DATA_CODED")"
3700a9
+else
3700a9
+    echo "Error decoding JWE protected header!" >&2
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+### get pin and url
3700a9
+
3700a9
+if ! PIN="$(jose fmt -j- -g clevis -g pin -u- <<< "$DATA_DECODED")" || [ -z "$PIN" ]; then
3700a9
+    echo "Pin wasn't found in luks metadata!" >&2
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+if ! CONTENT="$(jose fmt -j- -g clevis -g "$PIN" -o- <<< "$DATA_DECODED")" || [ -z "$CONTENT" ]; then
3700a9
+    echo "Content wasn't found!" >&2
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+EXE="$(findexe clevis-luks-report-"$PIN")"
3700a9
+
3700a9
+exec "$EXE" "$CONTENT"
3700a9
diff --git a/src/luks/clevis-luks-report-sss b/src/luks/clevis-luks-report-sss
3700a9
new file mode 100755
3700a9
index 0000000..1dba4c1
3700a9
--- /dev/null
3700a9
+++ b/src/luks/clevis-luks-report-sss
3700a9
@@ -0,0 +1,53 @@
3700a9
+#!/bin/bash -e
3700a9
+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
3700a9
+#
3700a9
+# Copyright (c) 2018 Red Hat, Inc.
3700a9
+# Author: Radovan Sroka <rsroka@redhat.com>
3700a9
+#
3700a9
+# This program is free software: you can redistribute it and/or modify
3700a9
+# it under the terms of the GNU General Public License as published by
3700a9
+# the Free Software Foundation, either version 3 of the License, or
3700a9
+# (at your option) any later version.
3700a9
+#
3700a9
+# This program is distributed in the hope that it will be useful,
3700a9
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3700a9
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3700a9
+# GNU General Public License for more details.
3700a9
+#
3700a9
+# You should have received a copy of the GNU General Public License
3700a9
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
3700a9
+#
3700a9
+
3700a9
+. clevis-luks-common-functions
3700a9
+
3700a9
+SUMMARY="SSS report plugin"
3700a9
+
3700a9
+if [ "$1" == "--summary" ]; then
3700a9
+    echo "$SUMMARY"
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+if [ -z "$1" ]; then
3700a9
+    echo "$0 missing the first argument!" >&2
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+CONTENT="$1" # sss content
3700a9
+
3700a9
+CNT=0
3700a9
+while DATA_CODED="$(jose fmt -j- -g jwe -g"$CNT" -u- <<< "$CONTENT")"; do
3700a9
+    if [ -z "$DATA_CODED" ]; then
3700a9
+        CNT=$(( CNT + 1 ))
3700a9
+        continue # in some cases it can be empty string
3700a9
+    fi
3700a9
+
3700a9
+    EXE="$(findexe clevis-luks-report-decode)"
3700a9
+    if ! $EXE "$DATA_CODED"; then
3700a9
+        echo "Failed" >&2
3700a9
+        exit 1
3700a9
+    fi
3700a9
+
3700a9
+    CNT=$(( CNT + 1 ))
3700a9
+done
3700a9
+
3700a9
+exit 0
3700a9
diff --git a/src/luks/clevis-luks-report-tang b/src/luks/clevis-luks-report-tang
3700a9
new file mode 100755
3700a9
index 0000000..07f2a72
3700a9
--- /dev/null
3700a9
+++ b/src/luks/clevis-luks-report-tang
3700a9
@@ -0,0 +1,67 @@
3700a9
+#!/usr/bin/bash -e
3700a9
+# vim: set tabstop=8 shiftwidth=4 softtabstop=4 expandtab smarttab colorcolumn=80:
3700a9
+#
3700a9
+# Copyright (c) 2018 Red Hat, Inc.
3700a9
+# Author: Radovan Sroka <rsroka@redhat.com>
3700a9
+#
3700a9
+# This program is free software: you can redistribute it and/or modify
3700a9
+# it under the terms of the GNU General Public License as published by
3700a9
+# the Free Software Foundation, either version 3 of the License, or
3700a9
+# (at your option) any later version.
3700a9
+#
3700a9
+# This program is distributed in the hope that it will be useful,
3700a9
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3700a9
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
3700a9
+# GNU General Public License for more details.
3700a9
+#
3700a9
+# You should have received a copy of the GNU General Public License
3700a9
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
3700a9
+#
3700a9
+
3700a9
+. clevis-luks-common-functions
3700a9
+
3700a9
+SUMMARY="Tang report plugin"
3700a9
+
3700a9
+if [ "$1" == "--summary" ]; then
3700a9
+    echo "$SUMMARY"
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+if [ -z "$1" ]; then
3700a9
+    echo "$0 missing the first argument!"
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+CONTENT="$1"
3700a9
+
3700a9
+### Get the advertisement
3700a9
+if ! URL="$(jose fmt -j- -g url -u- <<< "$CONTENT")" || [ -z "$URL" ]; then
3700a9
+    echo "URL was not found!" >&2
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+if ! jws="$(curl -sfg "$URL/adv")"; then
3700a9
+    echo "Unable to fetch advertisement: $URL/adv!" >&2
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+if ! TANG_KEYS="$(jose fmt -j- -Og payload -SyOg keys -AUo- <<< "$jws")"; then
3700a9
+    echo "Advertisement is malformed!" >&2
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+### Check advertisement validity
3700a9
+ver="$(jose jwk use -i- -r -u verify -o- <<< "$TANG_KEYS")"
3700a9
+if ! jose jws ver -i "$jws" -k- -a <<< "$ver"; then
3700a9
+    echo "Advertisement is missing signatures!" >&2
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+if ! LUKS_KEYS="$(jose fmt -j- -g adv -o- <<< "$CONTENT")" || [ -z "$LUKS_KEYS" ]; then
3700a9
+    echo "LUKS keys from LUKS metadata were not found!" >&2
3700a9
+    exit 1
3700a9
+fi
3700a9
+
3700a9
+EXE="$(findexe clevis-luks-report-compare)"
3700a9
+
3700a9
+exec "$EXE" "$TANG_KEYS" "$LUKS_KEYS"
3700a9
diff --git a/src/luks/clevis-luks-report.1.adoc b/src/luks/clevis-luks-report.1.adoc
3700a9
new file mode 100644
3700a9
index 0000000..cf42afe
3700a9
--- /dev/null
3700a9
+++ b/src/luks/clevis-luks-report.1.adoc
3700a9
@@ -0,0 +1,41 @@
3700a9
+CLEVIS-LUKS-REPORT(1)
3700a9
+=====================
3700a9
+:doctype: manpage
3700a9
+
3700a9
+
3700a9
+== NAME
3700a9
+
3700a9
+clevis-luks-report - Reports whether a pin bound to a LUKS1 or LUKS2 volume has been rotated
3700a9
+
3700a9
+== SYNOPSIS
3700a9
+
3700a9
+*clevis luks report* -d DEV -s SLT
3700a9
+
3700a9
+== OVERVIEW
3700a9
+
3700a9
+The *clevis luks report* command checks a given slot of a LUKS device and reports whether the pin bound to it
3700a9
+-- if any -- has been rotated.
3700a9
+
3700a9
+== OPTIONS
3700a9
+
3700a9
+* *-d* _DEV_ :
3700a9
+  The bound LUKS device
3700a9
+
3700a9
+* *-s* _SLT_ :
3700a9
+  The slot or key slot number for the pin to be verified
3700a9
+
3700a9
+* *-q* :
3700a9
+  Quiet mode. If used, we will not prompt whether to regenerate data with *clevis luks regen*
3700a9
+
3700a9
+* *-r* :
3700a9
+  Regenerates LUKS metadata with *clevis luks regen -d DEV -s SLOT*
3700a9
+
3700a9
+== EXAMPLE
3700a9
+
3700a9
+    Check whether the pin bound to slot 1 in /dev/sda1 has been rotated:
3700a9
+
3700a9
+    # clevis luks report -d /dev/sda1 -s 1
3700a9
+
3700a9
+== SEE ALSO
3700a9
+
3700a9
+link:clevis-luks-regen.1.adoc[*clevis-luks-regen*(1)]
3700a9
diff --git a/src/luks/meson.build b/src/luks/meson.build
3700a9
index f21388d..ee588c3 100644
3700a9
--- a/src/luks/meson.build
3700a9
+++ b/src/luks/meson.build
3700a9
@@ -47,6 +47,13 @@ if libcryptsetup.found() and luksmeta.found() and pwmake.found()
3700a9
 
3700a9
   bins += join_paths(meson.current_source_dir(), 'clevis-luks-regen')
3700a9
   mans += join_paths(meson.current_source_dir(), 'clevis-luks-regen.1')
3700a9
+
3700a9
+  bins += join_paths(meson.current_source_dir(), 'clevis-luks-report')
3700a9
+  bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-compare')
3700a9
+  bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-decode')
3700a9
+  bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-sss')
3700a9
+  bins += join_paths(meson.current_source_dir(), 'clevis-luks-report-tang')
3700a9
+  mans += join_paths(meson.current_source_dir(), 'clevis-luks-report.1')
3700a9
 else
3700a9
   warning('Will not install LUKS support due to missing dependencies!')
3700a9
 endif
3700a9
-- 
3700a9
2.18.4
3700a9