From 82ab56ebb4423bd9375b41b16e62e5725308d2ba Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Tue, 2 Jun 2020 16:05:44 -0400 Subject: [PATCH] Add boot encryption support to EL8 The stock profile should now encrypt if requested --- .../el8/profiles/default/kickstart | 6 ++++++ .../el8/profiles/default/scripts/post.sh | 4 +++- .../el8/profiles/default/scripts/pre.sh | 16 +++++++++++++++- .../el8/profiles/default/scripts/prechroot.sh | 1 + .../el8/profiles/default/scripts/tpm_luks.sh | 4 ++++ confluent_server/confluent/config/attributes.py | 10 ++++++++++ confluent_server/confluent/selfservice.py | 4 ++++ 7 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 confluent_osdeploy/el8/profiles/default/scripts/tpm_luks.sh diff --git a/confluent_osdeploy/el8/profiles/default/kickstart b/confluent_osdeploy/el8/profiles/default/kickstart index 3f94da2e..7e3999e4 100644 --- a/confluent_osdeploy/el8/profiles/default/kickstart +++ b/confluent_osdeploy/el8/profiles/default/kickstart @@ -17,6 +17,11 @@ # to the deployment target. %include /tmp/langinfo +# bootloader may be specified if crypted.grubpassword is set on +# a node. This will become a bootloader line if a password +# was specified +%include /tmp/grubpw + # The default partition scheme is applied to a single drive, using # the getinstalldisk script to make a best guess as to the most # appropriate device. See pre.sh and getinstalldisk to customize @@ -29,6 +34,7 @@ reboot %packages @^minimal-environment +clevis-dracut chrony rsync python3 diff --git a/confluent_osdeploy/el8/profiles/default/scripts/post.sh b/confluent_osdeploy/el8/profiles/default/scripts/post.sh index 80a6cd5e..f258b4b1 100644 --- a/confluent_osdeploy/el8/profiles/default/scripts/post.sh +++ b/confluent_osdeploy/el8/profiles/default/scripts/post.sh @@ -4,6 +4,9 @@ nodename=$(grep ^NODENAME /etc/confluent/confluent.info|awk '{print $2}') export mgr profile nodename . /etc/confluent/functions +if [ -f /tmp/cryptboot ]; then + run_remote tpm_luks.sh +fi # This script will execute in the installed system, but using the installer kernel prior to reboot. # This is an appropriate place to run post install activities that do not require the actual installed # kernel to run. For example adding drivers that would be needed for first boot to run cleanly. @@ -14,6 +17,5 @@ export mgr profile nodename # run_remote_python will use the appropriate python interpreter path to run the specified script # Add content as below: - # run_remote example.sh # run_remote_python example.py diff --git a/confluent_osdeploy/el8/profiles/default/scripts/pre.sh b/confluent_osdeploy/el8/profiles/default/scripts/pre.sh index 3d836845..8ee8a8a4 100644 --- a/confluent_osdeploy/el8/profiles/default/scripts/pre.sh +++ b/confluent_osdeploy/el8/profiles/default/scripts/pre.sh @@ -24,6 +24,12 @@ if [ "$rootpw" = null ]; then else echo "rootpw --iscrypted $rootpw" > /tmp/rootpw fi +grubpw=$(grep ^grubpassword /etc/confluent.deploycfg | awk '{print $2}') +if [ "$grubpw" = "null" ]; then + touch /tmp/grubpw +else + echo "bootloader --iscrypted --password=$grubpw" > /tmp/grubpw +fi for pubkey in /etc/ssh/ssh_host*key.pub; do certfile=${pubkey/.pub/-cert.pub} curl -f -X POST -H "CONFLUENT_NODENAME: $nodename" -H "CONFLUENT_APIKEY: $(cat /etc/confluent.apikey)" -d @$pubkey https://$mgr/confluent-api/self/sshcert > $certfile @@ -34,6 +40,14 @@ if [ -f "/run/install/cmdline.d/01-autocons.conf" ]; then consoledev=$(cat /run/install/cmdline.d/01-autocons.conf | sed -e 's!console=!/dev/!' -e 's/,.*//') tmux a <> $consoledev >&0 2>&1 & fi +cryptboot=$(grep ^encryptboot: /etc/confluent.deploycfg | awk '{print $2}') +LUKSPARTY='' +if [ "$cryptboot" == "bound" ]; then + LUKSPARTY="--encrypted --passphrase=$(cat /etc/confluent.apikey)" + echo $cryptboot >> /tmp/cryptboot +fi + + export mgr profile nodename curl -f https://$mgr/confluent-public/os/$profile/scripts/functions > /tmp/functions . /tmp/functions @@ -41,5 +55,5 @@ run_remote_python getinstalldisk if [ -e /tmp/installdisk ]; then echo clearpart --all --initlabel >> /tmp/partitioning echo ignoredisk --only-use $(cat /tmp/installdisk) >> /tmp/partitioning - echo autopart --nohome >> /tmp/partitioning + echo autopart --nohome $LUKSPARTY >> /tmp/partitioning fi diff --git a/confluent_osdeploy/el8/profiles/default/scripts/prechroot.sh b/confluent_osdeploy/el8/profiles/default/scripts/prechroot.sh index 9d326c6f..e4a319cb 100644 --- a/confluent_osdeploy/el8/profiles/default/scripts/prechroot.sh +++ b/confluent_osdeploy/el8/profiles/default/scripts/prechroot.sh @@ -12,6 +12,7 @@ export mgr profile nodename cp -a /etc/confluent /mnt/sysimage/etc cp /tmp/functions /mnt/sysimage/etc/confluent/ . /tmp/functions +cp /tmp/cryptboot /mnt/sysimage/tmp/ # Preserve the ssh setup work done for the installer # by copying into the target system and setting up diff --git a/confluent_osdeploy/el8/profiles/default/scripts/tpm_luks.sh b/confluent_osdeploy/el8/profiles/default/scripts/tpm_luks.sh new file mode 100644 index 00000000..a26fc5e6 --- /dev/null +++ b/confluent_osdeploy/el8/profiles/default/scripts/tpm_luks.sh @@ -0,0 +1,4 @@ +#!/bin/sh +cryptdisk=$(blkid -t TYPE="crypto_LUKS"|sed -e s/:.*//) +clevis luks bind -d $cryptdisk -k - tpm2 '{"pcr_bank": "sha256", "pcr_ids": "7"}' < /etc/confluent/confluent.apikey +cryptsetup luksRemoveKey $cryptdisk < /etc/confluent/confluent.apikey diff --git a/confluent_server/confluent/config/attributes.py b/confluent_server/confluent/config/attributes.py index b84f7847..8041b0fe 100644 --- a/confluent_server/confluent/config/attributes.py +++ b/confluent_server/confluent/config/attributes.py @@ -107,6 +107,16 @@ node = { 'crypted.selfapikey': { 'description': ('Crypt of api key for self api requests by node'), }, + 'deployment.encryptboot': { + 'description': ('Specify a strategy for encrypting the volume. Support ' + 'This setting is currently only enabled for ' + 'RedHat 8 and CentOS 8 profiles. If blank or unset, ' + 'no encryption is done. If set to "bound" then the OS ' + 'will freely decrypt so long as the same ' + 'Trusted Platform Module is available to decrypt the ' + 'volume'), + 'validvalues': ('bound', 'none', ''), + }, 'deployment.apiarmed': { 'description': ('Indicates whether the node authentication token interface ' 'is armed. If set to once, it will grant only the next ' diff --git a/confluent_server/confluent/selfservice.py b/confluent_server/confluent/selfservice.py index 897c53d1..4bbc7d3c 100644 --- a/confluent_server/confluent/selfservice.py +++ b/confluent_server/confluent/selfservice.py @@ -69,6 +69,10 @@ def handle_request(env, start_response): deployinfo = deployinfo.get(nodename, {}) profile = deployinfo.get( 'deployment.pendingprofile', {}).get('value', '') + ncfg['encryptboot'] = deployinfo.get('deployment.encryptboot', {}).get( + 'value', None) + if ncfg['encryptboot'] in ('', 'none'): + ncfg['encryptboot'] = None ncfg['profile'] = profile protocol = deployinfo.get('deployment.useinsecureprotocols', {}).get( 'value', 'never')