From e4aed56f9f6158bdb4e5426434a7b7962acfcc46 Mon Sep 17 00:00:00 2001 From: Patrik Koncity Date: Mon, 3 Jul 2023 16:46:48 +0200 Subject: [PATCH] New scenario with keylime tenant in container New scenario with keylime tenant in container. Add new limecon function which prepare, build and manage tenant container. --- Library/test-helpers/Dockerfile.tenant | 2 + Library/test-helpers/lib.sh | 110 +++++++++++-- .../main.fmf | 28 ++++ .../test.sh | 149 ++++++++++++++++++ plans/upstream-keylime-swtpm-dev.fmf | 1 + 5 files changed, 279 insertions(+), 11 deletions(-) create mode 100644 Library/test-helpers/Dockerfile.tenant create mode 100644 container/functional/keylime_all_in_container-basic-attestation/main.fmf create mode 100755 container/functional/keylime_all_in_container-basic-attestation/test.sh diff --git a/Library/test-helpers/Dockerfile.tenant b/Library/test-helpers/Dockerfile.tenant new file mode 100644 index 00000000..49c48d35 --- /dev/null +++ b/Library/test-helpers/Dockerfile.tenant @@ -0,0 +1,2 @@ +FROM quay.io/centos/centos:stream9 +RUN dnf install -y keylime-tenant util-linux-core which && dnf clean all diff --git a/Library/test-helpers/lib.sh b/Library/test-helpers/lib.sh index 2e0ec3c2..618b05d5 100644 --- a/Library/test-helpers/lib.sh +++ b/Library/test-helpers/lib.sh @@ -612,6 +612,38 @@ limeStopAgent() { true <<'=cut' =pod +=head2 limeKeylimeTenant + +Run the keylime tenant on localhost or in container with specified tenant commands. + + limeKeylimeTenant TENANT_CMD + +=over + +=item + + TENANT_CMD - Set of commands which tenant run. + +=back + +Returns 0 when the stop was successful, non-zero otherwise. + +=cut + +limeKeylimeTenant() { + + local TENANT_CMD=$1 + + if [ -n "$limeconKeylimeTenantCmd" ]; then + limeconRunTenant $limeconKeylimeTenantCmd "$TENANT_CMD" + else + keylime_tenant $TENANT_CMD + fi +} + +true <<'=cut' +=pod + =head2 limeStartIMAEmulator Start the keylime IMA Emulator. @@ -1166,12 +1198,12 @@ limeWaitForAgentStatus() { [ -n "$3" ] && TIMEOUT=$3 for I in `seq $TIMEOUT`; do - keylime_tenant -c status -u $UUID &> $OUTPUT - if grep -E -q "\"operational_state\": \"$STATUS\"" $OUTPUT; then + limeKeylimeTenant "-c status -u $UUID" &> $OUTPUT + if grep -E -q "\"operational_state\": \"$STATUS\"" $OUTPUT; then cat $OUTPUT - rm $OUTPUT - return 0 - fi + rm $OUTPUT + return 0 + fi sleep 1 done cat $OUTPUT @@ -1179,7 +1211,6 @@ limeWaitForAgentStatus() { return 1 } - true <<'=cut' =pod @@ -1214,12 +1245,12 @@ limeWaitForAgentRegistration() { [ -n "$2" ] && TIMEOUT=$2 for I in `seq $TIMEOUT`; do - keylime_tenant -c regstatus -u $UUID &> $OUTPUT - if grep -q "Agent $UUID exists on registrar" $OUTPUT; then + limeKeylimeTenant "-c regstatus -u $UUID" &> $OUTPUT + if grep -q "Agent $UUID exists on registrar" $OUTPUT; then cat $OUTPUT - rm $OUTPUT - return 0 - fi + rm $OUTPUT + return 0 + fi sleep 1 done cat $OUTPUT @@ -2217,6 +2248,63 @@ limeconRunSystemd() { true <<'=cut' =pod +=head2 limeconRunTenant + +Tenant container run via podman with specified parameters. + + limeconRunTenant NAME TAG IP NETWORK TENANT_CMD + +=item NAME + +Set name of container. + +=item TAG + +Name of image tag. + +=item IP + +IP address of container. + +=item NETWORK + +Name of used podman network. + +=item TENANT_CMD + +Name of used podman network. + +=back + +Returns 0. + +=cut + +limeconRunTenant() { + + local NAME=$1 + local TAG=$2 + local IP=$3 + local NETWORK=$4 + local TENANT_CMD=$5 + local MOUNT_TENANT="--volume=/etc/keylime/:/etc/keylime/" + + if [ -d cv_ca ]; then + MOUNT_TENANT="--volume $PWD/cv_ca:/var/lib/keylime/cv_ca/:z $MOUNT_TENANT" + fi + if [ -f "policy.json" ]; then + MOUNT_TENANT="--volume $PWD/policy.json:/policy.json:z $MOUNT_TENANT" + fi + + podman run --name $NAME --net $NETWORK --ip $IP $MOUNT_TENANT localhost/$TAG keylime_tenant $TENANT_CMD + sleep 3 + limeconStop "tenant_container" + +} + +true <<'=cut' +=pod + =head2 limeconRunVerifier Container run via podman with specified parameters. diff --git a/container/functional/keylime_all_in_container-basic-attestation/main.fmf b/container/functional/keylime_all_in_container-basic-attestation/main.fmf new file mode 100644 index 00000000..770976d1 --- /dev/null +++ b/container/functional/keylime_all_in_container-basic-attestation/main.fmf @@ -0,0 +1,28 @@ +summary: Tests basic keylime attestation scenario for all keylime component in containers +description: | + Running agents,verifier and registrar and tenant in containers. + Every container uses certificates generated by keylime verifier. + Build container image for agent, verifier,registrar and tenant. + Starts verifier, registrar in container. + Setup agent conf for agent. + Run container with agent. + Register agent by verifier. + Verify registration of agent by one shot tenant container. + Verifiers that container passed with agent attestation. + Do changes in scripts monitored by agent and confirm that agent fail attestation accordingly. + All actions are verified by one shot tenant container. +contact: Patrik Koncity +tag: + - container +component: + - keylime +test: ./test.sh +framework: beakerlib +require: + - yum + - podman + - nmap +recommend: + - keylime +duration: 10m +enabled: true \ No newline at end of file diff --git a/container/functional/keylime_all_in_container-basic-attestation/test.sh b/container/functional/keylime_all_in_container-basic-attestation/test.sh new file mode 100755 index 00000000..c74b6b02 --- /dev/null +++ b/container/functional/keylime_all_in_container-basic-attestation/test.sh @@ -0,0 +1,149 @@ +#!/bin/bash +# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +#Machine should have /dev/tpm0 or /dev/tpmrm0 device +AGENT_ID="d432fbb3-d2f1-4a97-9ef7-75bd81c00000" + +[ -n "$DOCKERFILE_VERIFIER" ] || DOCKERFILE_VERIFIER=Dockerfile.upstream.c9s +[ -n "$DOCKERFILE_REGISTRAR" ] || DOCKERFILE_REGISTRAR=Dockerfile.upstream.c9s +[ -n "$DOCKERFILE_AGENT" ] || DOCKERFILE_AGENT=Dockerfile.upstream.c9s +[ -n "$DOCKERFILE_TENANT" ] || DOCKERFILE_TENANT=Dockerfile.upstream.c9s + + +rlJournalStart + + rlPhaseStartSetup "Do the keylime setup" + rlRun 'rlImport "./test-helpers"' || rlDie "cannot import keylime-tests/test-helpers library" + rlAssertRpm keylime + # update /etc/keylime.conf + limeBackupConfig + CONT_NETWORK_NAME="container_network" + IP_VERIFIER="172.18.0.4" + IP_REGISTRAR="172.18.0.8" + IP_AGENT="172.18.0.12" + IP_TENANT="172.18.0.16" + #create network for containers + rlRun "limeconCreateNetwork ${CONT_NETWORK_NAME} 172.18.0.0/16" + + #prepare verifier container + rlRun "limeUpdateConf verifier ip $IP_VERIFIER" + rlRun "limeUpdateConf verifier registrar_ip $IP_REGISTRAR" + #for log purposes, when agent fail, we need see verifier log, that attestation failed + rlRun "limeUpdateConf verifier log_destination stream" + + # prepare registrar container + rlRun "limeUpdateConf registrar ip $IP_REGISTRAR" + + # tenant + rlRun "limeUpdateConf tenant require_ek_cert False" + rlRun "limeUpdateConf tenant verifier_ip $IP_VERIFIER" + rlRun "limeUpdateConf tenant registrar_ip $IP_REGISTRAR" + + #need to setup configuration files + + #build verifier container + TAG_VERIFIER="verifier_image" + rlRun "limeconPrepareImage ${limeLibraryDir}/${DOCKERFILE_VERIFIER} ${TAG_VERIFIER}" + + #build registrar container + TAG_REGISTRAR="registrar_image" + rlRun "limeconPrepareImage ${limeLibraryDir}/${DOCKERFILE_REGISTRAR} ${TAG_REGISTRAR}" + + #build tenant container + TAG_TENANT="tenant_image" + rlRun "limeconPrepareImage ${limeLibraryDir}/${DOCKERFILE_TENANT} ${TAG_TENANT}" + + # if TPM emulator is present + if limeTPMEmulated; then + # start tpm emulator + rlRun "limeStartTPMEmulator" + rlRun "limeWaitForTPMEmulator" + rlRun "limeCondStartAbrmd" + # start ima emulator + rlRun "limeInstallIMAConfig" + rlRun "limeStartIMAEmulator" + fi + sleep 5 + + #mandatory for access agent containers to tpm + rlRun "chmod o+rw /dev/tpmrm0" + + #run verifier container + CONT_VERIFIER="verifier_container" + rlRun "limeconRunVerifier $CONT_VERIFIER $TAG_VERIFIER $IP_VERIFIER $CONT_NETWORK_NAME" + rlRun "limeWaitForVerifier 8881 $IP_VERIFIER" + #wait for generating of certs + sleep 5 + rlRun "podman cp $CONT_VERIFIER:/var/lib/keylime/cv_ca/ ." + + #run registrar container + CONT_REGISTRAR="registrar_container" + rlRun "limeconRunRegistrar $CONT_REGISTRAR $TAG_REGISTRAR $IP_REGISTRAR $CONT_NETWORK_NAME" + rlRun "limeWaitForRegistrar 8891 $IP_REGISTRAR" + + CONT_TENANT="tenant_container" + # define limeconKeylimeTenantCmd so that the keylime container can be used by limeWaitForAgentStatus etc. + limeconKeylimeTenantCmd="$CONT_TENANT $TAG_TENANT $IP_TENANT $CONT_NETWORK_NAME" + + #setup of agent + TAG_AGENT="agent_image" + CONT_AGENT="agent_container" + rlRun "limeconPrepareImage ${limeLibraryDir}/${DOCKERFILE_AGENT} ${TAG_AGENT}" + rlRun "limeUpdateConf agent registrar_ip '\"$IP_REGISTRAR\"'" + rlRun "limeconPrepareAgentConfdir $AGENT_ID $IP_AGENT confdir_$CONT_AGENT" + + # create some scripts + TESTDIR=$(limeCreateTestDir) + rlRun "echo -e '#!/bin/bash\necho This is good-script1' > $TESTDIR/good-script1.sh && chmod a+x $TESTDIR/good-script1.sh" + rlRun "echo -e '#!/bin/bash\necho This is good-script2' > $TESTDIR/good-script2.sh && chmod a+x $TESTDIR/good-script2.sh" + # create allowlist and excludelist + rlRun "limeCreateTestPolicy ${TESTDIR}/*" + + rlRun "limeconRunAgent $CONT_AGENT $TAG_AGENT $IP_AGENT $CONT_NETWORK_NAME $PWD/confdir_$CONT_AGENT $TESTDIR" + rlRun -s "limeWaitForAgentRegistration $AGENT_ID" + rlPhaseEnd + + rlPhaseStartTest "Add keylime agent" + rlRun "limeKeylimeTenant '-v $IP_VERIFIER -t $IP_AGENT -u $AGENT_ID --runtime-policy policy.json -f /etc/hosts -c add'" + rlRun -s "limeWaitForAgentStatus $AGENT_ID 'Get Quote'" + rlRun -s "limeKeylimeTenant '-c cvlist'" + rlAssertGrep "{'code': 200, 'status': 'Success', 'results': {'uuids':.*'$AGENT_ID'" "$rlRun_LOG" -E + rlPhaseEnd + + rlPhaseStartTest "Running allowed scripts should not affect attestation" + rlRun "${TESTDIR}/good-script1.sh" + rlRun "${TESTDIR}/good-script2.sh" + rlRun "tail /sys/kernel/security/ima/ascii_runtime_measurements | grep good-script1.sh" + rlRun "tail /sys/kernel/security/ima/ascii_runtime_measurements | grep good-script2.sh" + rlRun "sleep 5" + rlRun -s "limeWaitForAgentStatus $AGENT_ID 'Get Quote'" + rlPhaseEnd + + rlPhaseStartTest "Fail keylime agent" + rlRun "echo -e '#!/bin/bash\necho boom' > $TESTDIR/bad-script.sh && chmod a+x $TESTDIR/bad-script.sh" + rlRun "$TESTDIR/bad-script.sh" + rlRun "sleep 5" + rlRun "podman logs verifier_container | grep \"keylime.verifier - WARNING - Agent d432fbb3-d2f1-4a97-9ef7-75bd81c00000 failed, stopping polling\"" + rlRun -s "limeWaitForAgentStatus $AGENT_ID '(Failed|Invalid Quote)'" + rlPhaseEnd + + rlPhaseStartCleanup "Do the keylime cleanup" + limeconSubmitLogs + rlRun "limeconStop registrar_container verifier_container agent_container" + rlRun "limeconDeleteNetwork $CONT_NETWORK_NAME" + #set tmp resource manager permission to default state + rlRun "chmod o-rw /dev/tpmrm0" + if limeTPMEmulated; then + rlRun "limeStopIMAEmulator" + rlRun "limeStopTPMEmulator" + rlRun "limeCondStopAbrmd" + fi + limeExtendNextExcludelist "$TESTDIR" + limeSubmitCommonLogs + limeClearData + limeRestoreConfig + rlPhaseEnd + +rlJournalEnd + diff --git a/plans/upstream-keylime-swtpm-dev.fmf b/plans/upstream-keylime-swtpm-dev.fmf index 7a416b48..e7c87802 100644 --- a/plans/upstream-keylime-swtpm-dev.fmf +++ b/plans/upstream-keylime-swtpm-dev.fmf @@ -7,6 +7,7 @@ environment+: DOCKERFILE_AGENT: Dockerfile.upstream.c9s DOCKERFILE_VERIFIER: Dockerfile.upstream.c9s DOCKERFILE_REGISTRAR: Dockerfile.upstream.c9s + DOCKERFILE_TENANT: Dockerfile.upstream.c9s discover: how: fmf