From 3c41c52d7708ea1eefa26bca45188f064317357b Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Thu, 24 Jun 2021 11:09:37 -0400 Subject: [PATCH] Rework TPM usage in SUSE diskless For one, need to detect stale TPM value and clear them. For another, seal to PCR 15 and extend after unlock, so that the booted system is unable to retrieve the data from the TPM (e.g. a plain user by default is allowed to unseal data if there's no policy, so use a policy and extend the state away before boot) --- .../hooks/cmdline/10-confluentdiskless.sh | 103 ++++++++++++------ 1 file changed, 67 insertions(+), 36 deletions(-) diff --git a/confluent_osdeploy/suse15-diskless/initramfs/lib/dracut/hooks/cmdline/10-confluentdiskless.sh b/confluent_osdeploy/suse15-diskless/initramfs/lib/dracut/hooks/cmdline/10-confluentdiskless.sh index 2bd08f79..07843553 100644 --- a/confluent_osdeploy/suse15-diskless/initramfs/lib/dracut/hooks/cmdline/10-confluentdiskless.sh +++ b/confluent_osdeploy/suse15-diskless/initramfs/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 + 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 @@ -42,6 +68,27 @@ cat /tls/*.pem > /etc/confluent/ca.pem mkdir -p /var/lib/ca-certificates/ cat /tls/*.pem > /var/lib/ca-certificates/ca-bundle.pem 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) + 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..." @@ -62,44 +109,28 @@ if [[ $confluent_mgr == *%* ]]; then ifname=$(ip link |grep ^$ifidx:|awk '{print $2}') ifname=${ifname%:} fi -needseal=1 -oldumask=$(umask) -umask 0077 -for hdl in $(tpm2_getcap handles-persistent|awk '{print $2}'); do - unsealeddata=$(tpm2_unseal -Q -c $hdl) - if [[ $unsealeddata == "CONFLUENT_APIKEY:"* ]]; then - confluent_apikey=${unsealeddata#CONFLUENT_APIKEY:} - echo $confluent_apikey > /etc/confluent/confluent.apikey + +ready=0 +while [ $ready = "0" ]; do + get_remote_apikey + if [[ $confluent_mgr == *:* ]]; then + confluent_mgr="[$confluent_mgr]" fi + 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 -needseal=0 -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 - 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 - fi - needseal=1 -done -if [[ $confluent_mgr == *:* ]]; then - confluent_mgr="[$confluent_mgr]" -fi -if [ $needseal == 1 ]; then - tmpdir=$(mktemp -d) - cd $tmpdir - tpm2_createprimary -G ecc -Q --key-context=prim.ctx - (echo -n "CONFLUENT_APIKEY:";cat /etc/confluent/confluent.apikey) | tpm2_create -Q --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 - cd - - rm -rf $tmpdir -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