From a8e152cc4a127f992b50281b4eda489bdc22b669 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Thu, 24 Jun 2021 12:04:10 -0400 Subject: [PATCH] Switch TPM strategy on RedHat diskless Switch to thte same approach as used in suse: -Try to unseal any persistent handles -If that works, try to use it on network -If it didn't work, clear that handle -When an api key is retrieved, then seal it to pcr 15 -When it's all done, extend pcr15 to prevent the OS from being able to unseal --- .../hooks/cmdline/10-confluentdiskless.sh | 89 ++++++++++++++----- imgutil/el8/dracut/install | 6 +- 2 files changed, 70 insertions(+), 25 deletions(-) diff --git a/confluent_osdeploy/el8-diskless/initramfs/usr/lib/dracut/hooks/cmdline/10-confluentdiskless.sh b/confluent_osdeploy/el8-diskless/initramfs/usr/lib/dracut/hooks/cmdline/10-confluentdiskless.sh index ea433356..d0d4b790 100644 --- a/confluent_osdeploy/el8-diskless/initramfs/usr/lib/dracut/hooks/cmdline/10-confluentdiskless.sh +++ b/confluent_osdeploy/el8-diskless/initramfs/usr/lib/dracut/hooks/cmdline/10-confluentdiskless.sh @@ -1,3 +1,29 @@ +get_remote_apikey() { + while [ -z "$confluent_apikey" ]; do + /opt/confluent/bin/clortho $nodename $confluent_mgr > /etc/confluent/confluent.apikey + if grep ^SEALED: /etc/confluent/confluent.apikey > /dev/null; then + # we don't support remote sealed api keys anymore + echo > /etc/confluent/confluent.apikey + fi + confluent_apikey=$(cat /etc/confluent/confluent.apikey) + if [ -z "$confluent_apikey" ]; then + echo "Unable to acquire node api key, set deployment.apiarmed=once on node '$nodename', retrying..." + sleep 10 + else + tmpdir=$(mktemp -d) + cd $tmpdir + tpm2_startauthsession --session=session.ctx + tpm2_policypcr -Q --session=session.ctx --pcr-list="sha256:15" --policy=pcr15.sha256.policy + tpm2_createprimary -G ecc -Q --key-context=prim.ctx + (echo -n "CONFLUENT_APIKEY:";cat /etc/confluent/confluent.apikey) | tpm2_create -Q --policy=pcr15.sha256.policy --public=data.pub --private=data.priv -i - -C prim.ctx + tpm2_load -Q --parent-context=prim.ctx --public=data.pub --private=data.priv --name=confluent.apikey --key-context=data.ctx + tpm2_evictcontrol -Q -c data.ctx + tpm2_flushcontext session.ctx + cd - + rm -rf $tmpdir + fi + done +} root=1 rootok=1 netroot=confluent @@ -41,6 +67,27 @@ cat /tls/*.pem > /etc/confluent/ca.pem mkdir -p /etc/pki/tls/certs cat /tls/*.pem > /etc/pki/tls/certs/ca-bundle.crt TRIES=0 +oldumask=$(umask) +umask 0077 +tpmdir=$(mktemp -d) +cd $tpmdir +lasthdl="" +for hdl in $(tpm2_getcap handles-persistent|awk '{print $2}'); do + tpm2_startauthsession --policy-session --session=session.ctx + tpm2_policypcr -Q --session=session.ctx --pcr-list="sha256:15" --policy=pcr15.sha256.policy + unsealeddata=$(tpm2_unseal --auth=session:session.ctx -Q -c $hdl 2>/dev/null) + tpm2_flushcontext session.ctx + if [[ $unsealeddata == "CONFLUENT_APIKEY:"* ]]; then + confluent_apikey=${unsealeddata#CONFLUENT_APIKEY:} + echo $confluent_apikey > /etc/confluent/confluent.apikey + if [ -n "$lasthdl" ]; then + tpm2_evictcontrol -c $lasthdl + fi + lasthdl=$hdl + fi +done +cd - +rm -rf $tpmdir touch /etc/confluent/confluent.info cd /sys/class/net echo -n "Scanning for network configuration..." @@ -61,32 +108,28 @@ if [[ $confluent_mgr == *%* ]]; then ifname=$(ip link |grep ^$ifidx:|awk '{print $2}') ifname=${ifname%:} fi -needseal=1 -oldumask=$(umask) -umask 0077 -while [ -z "$confluent_apikey" ]; do - /opt/confluent/bin/clortho $nodename $confluent_mgr > /etc/confluent/confluent.apikey - if grep ^SEALED: /etc/confluent/confluent.apikey > /dev/null; then - needseal=0 - sed -e s/^SEALED:// /etc/confluent/confluent.apikey | clevis-decrypt-tpm2 > /etc/confluent/confluent.apikey.decrypt - mv /etc/confluent/confluent.apikey.decrypt /etc/confluent/confluent.apikey + +ready=0 +while [ $ready = "0" ]; do + get_remote_apikey + if [[ $confluent_mgr == *:* ]]; then + confluent_mgr="[$confluent_mgr]" fi - confluent_apikey=$(cat /etc/confluent/confluent.apikey) - if [ -z "$confluent_apikey" ]; then - echo "Unable to acquire node api key, no TPM2 sealed nor fresh token available, retrying..." - sleep 10 + tmperr=$(mktemp) + curl -sSf -H "CONFLUENT_NODENAME: $nodename" -H "CONFLUENT_APIKEY: $confluent_apikey" https://$confluent_mgr/confluent-api/self/deploycfg > /etc/confluent/confluent.deploycfg 2> $tmperr + if grep 401 $tmperr > /dev/null; then + confluent_apikey="" + if [ -n "$lasthdl" ]; then + tpm2_evictcontrol -c $lasthdl + fi + confluent_mgr=${confluent_mgr#[} + confluent_mgr=${confluent_mgr%]} + else + ready=1 fi + rm $tmperr done -if [[ $confluent_mgr == *:* ]]; then - confluent_mgr="[$confluent_mgr]" -fi -if [ $needseal == 1 ]; then - sealed=$(echo $confluent_apikey | clevis-encrypt-tpm2 {}) - if [ ! -z "$sealed" ]; then - curl -sf -H "CONFLUENT_NODENAME: $nodename" -H "CONFLUENT_APIKEY: $confluent_apikey" -d $sealed https://$confluent_mgr/confluent-api/self/saveapikey - fi -fi -curl -sf -H "CONFLUENT_NODENAME: $nodename" -H "CONFLUENT_APIKEY: $confluent_apikey" https://$confluent_mgr/confluent-api/self/deploycfg > /etc/confluent/confluent.deploycfg +tpm2_pcrextend 15:sha256=2fbe96c50dde38ce9cd2764ddb79c216cfbcd3499568b1125450e60c45dd19f2 umask $oldumask autoconfigmethod=$(grep ipv4_method /etc/confluent/confluent.deploycfg |awk '{print $2}') if [ "$autoconfigmethod" = "dhcp" ]; then diff --git a/imgutil/el8/dracut/install b/imgutil/el8/dracut/install index 25b5a962..1649589c 100644 --- a/imgutil/el8/dracut/install +++ b/imgutil/el8/dracut/install @@ -1,6 +1,8 @@ -dracut_install /usr/bin/clevis-encrypt-tpm2 /usr/bin/clevis-decrypt-tpm2 /usr/bin/jose /usr/bin/mktemp +dracut_install mktemp dracut_install /lib64/libtss2-tcti-device.so.0 -dracut_install /usr/bin/tpm2_create /usr/bin/tpm2_pcrread /usr/bin/tpm2_createpolicy /usr/bin/tpm2_createprimary /usr/bin/tpm2_load /usr/bin/tpm2_unseal +dracut_install tpm2_create tpm2_pcrread tpm2_createpolicy tpm2_createprimary +dracut_install tpm2_load tpm2_unseal tpm2_getcap tpm2_evictcontrol +dracut_install tpm2_pcrextend tpm2_policypcr tpm2_flushcontext tpm2_startauthsession dracut_install curl openssl tar cpio gzip lsmod ethtool xz lsmod ethtool dracut_install modprobe touch echo cut wc bash netstat uniq grep ip hostname dracut_install awk egrep dirname expr sort