From 8bba82b95a1ec76f9b25752ebc019a745f39c6c5 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. Add also new lime func for timeout cmd. --- Library/test-helpers/Dockerfile.tenant | 7 + Library/test-helpers/lib.sh | 135 ++++++++++++++- .../main.fmf | 28 +++ .../test.sh | 159 ++++++++++++++++++ 4 files changed, 326 insertions(+), 3 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..31510a3b --- /dev/null +++ b/Library/test-helpers/Dockerfile.tenant @@ -0,0 +1,7 @@ +FROM quay.io/centos/centos:stream9 +RUN \ + rm -f /etc/yum.repos.d/centos.repo && \ + curl -o /etc/yum.repos.d/c9s.repo 'https://raw.githubusercontent.com/RedHat-SP-Security/keylime-tests/main/tools/c9s.repo' && \ + cat /etc/yum.repos.d/* && \ + dnf install -y keylime-tenant which && \ + dnf clean all diff --git a/Library/test-helpers/lib.sh b/Library/test-helpers/lib.sh index 1cd907b5..fad74969 100644 --- a/Library/test-helpers/lib.sh +++ b/Library/test-helpers/lib.sh @@ -620,6 +620,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=$@ + + if [ -n "$limeconKeylimeTenantCmd" ]; then + $limeconKeylimeTenantCmd "$TENANT_CMD" "$limeconTenantVolume" + else + keylime_tenant $TENANT_CMD + fi +} + +true <<'=cut' +=pod + =head2 limeStartIMAEmulator Start the keylime IMA Emulator. @@ -1187,7 +1219,7 @@ limeWaitForAgentStatus() { local START=$SECONDS for I in `seq $TIMEOUT`; do - timeout $TIMEOUT keylime_tenant -c status -u $UUID &> $OUTPUT + limeTimeoutCommand $TIMEOUT "limeKeylimeTenant -c status -u $UUID" &> $OUTPUT AGTSTATE=$(cat "$OUTPUT" | grep "^{" | tail -1 | jq -r ".[].operational_state") if echo "$AGTSTATE" | grep -E -q "$STATUS"; then cat $OUTPUT @@ -1204,7 +1236,6 @@ limeWaitForAgentStatus() { return 1 } - true <<'=cut' =pod @@ -1240,7 +1271,7 @@ limeWaitForAgentRegistration() { local START=$SECONDS for I in `seq $TIMEOUT`; do - timeout $TIMEOUT keylime_tenant -c regstatus -u $UUID &> $OUTPUT + limeTimeoutCommand $TIMEOUT "limeKeylimeTenant -c regstatus -u $UUID" &> $OUTPUT REGSTATE=$(cat $OUTPUT | grep "^{" | jq -r ".[].operational_state") if [ "$REGSTATE" == "Registered" ]; then cat $OUTPUT @@ -1257,6 +1288,45 @@ limeWaitForAgentRegistration() { return 1 } +true <<'=cut' +=pod + +=head2 limeTimeoutCommand + +Function stop command via SIGTERM after specified amount of time. + + limeTimeoutCommand TIMEOUT COMMAND + +=over + +=item + + TIMEOUT - Maximum time in seconds to wait + +=item COMMAND + +Specify command which have timeout. + +=back + +=cut + +limeTimeoutCommand() { + local TIMEOUT="$1"; + local COMMAND="$2"; + grep -qP '^\d+$' <<< $TIMEOUT + + ( + $COMMAND & + child=$! + trap -- "" SIGTERM + ( + sleep $TIMEOUT + kill $child 2> /dev/null + ) & + wait $child + ) +} # ~~~~~~~~~~~~~~~~~~~~ # Install @@ -2426,6 +2496,65 @@ limeconRunSystemd() { true <<'=cut' =pod +=head2 limeconRunTenant + +Tenant container run via podman with specified parameters. + + limeconRunTenant NAME TAG IP NETWORK TENANT_CMD MOUNT_DIR + +=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 + +Keylime tenant command in container + +=item MOUNT_DIR + +Path of mount dir. + +=back + +Returns 0. + +=cut + +limeconRunTenant() { + + local NAME=$1 + local TAG=$2 + local IP=$3 + local NETWORK=$4 + local TENANT_CMD=$5 + local MOUNT_DIR=$6 + local MOUNT_TENANT="--volume=/etc/keylime/:/etc/keylime/" + + if [ -d cv_ca ]; then + MOUNT_TENANT="$PWD/cv_ca:/var/lib/keylime/cv_ca/:z $MOUNT_TENANT" + fi + + podman run --volume $MOUNT_DIR --volume $MOUNT_TENANT --name $NAME --net $NETWORK --ip $IP $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..004dfaf1 --- /dev/null +++ b/container/functional/keylime_all_in_container-basic-attestation/test.sh @@ -0,0 +1,159 @@ +#!/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 + +[ -n "$REGISTRY" ] || REGISTRY=quay.io + +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 + + # Pull or build verifier container + TAG_VERIFIER="verifier_image" + if [ -n "$VERIFIER_IMAGE" ]; then + rlRun "limeconPullImage $REGISTRY $VERIFIER_IMAGE $TAG_VERIFIER" + else + rlRun "limeconPrepareImage ${VERIFIER_DOCKERFILE} ${TAG_VERIFIER}" + fi + + # Pull or build registrar container + TAG_REGISTRAR="registrar_image" + if [ -n "$REGISTRAR_IMAGE" ]; then + rlRun "limeconPullImage $REGISTRY $REGISTRAR_IMAGE $TAG_REGISTRAR" + else + rlRun "limeconPrepareImage ${REGISTRAR_DOCKERFILE} ${TAG_REGISTRAR}" + fi + + #build tenant container + TAG_TENANT="tenant_image" + rlRun "limeconPrepareImage ${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 keylime_verifier /etc/keylime" + 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 keylime_registrar /etc/keylime $(realpath ./cv_ca)" + rlRun "limeWaitForRegistrar 8891 $IP_REGISTRAR" + + CONT_TENANT="tenant_container" + # define limeconKeylimeTenantCmd so that the keylime container can be used by limeWaitForAgentStatus etc. + limeconKeylimeTenantCmd="limeconRunTenant $CONT_TENANT localhost/$TAG_TENANT $IP_TENANT $CONT_NETWORK_NAME" + limeconTenantVolume="$PWD/:/workdir/:z" + + #setup of agent + TAG_AGENT="agent_image" + CONT_AGENT="agent_container" + rlRun "limeconPrepareImage ${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 $TESTDIR keylime_agent $PWD/confdir_$CONT_AGENT $(realpath ./cv_ca)" + rlRun -s "limeWaitForAgentRegistration $AGENT_ID" + rlPhaseEnd + + rlPhaseStartTest "Add keylime agent" + rlRun "limeKeylimeTenant -v $IP_VERIFIER -t $IP_AGENT -u $AGENT_ID --runtime-policy /workdir/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 +