Skip to content

Commit

Permalink
New scenario with keylime tenant in container
Browse files Browse the repository at this point in the history
New scenario with keylime tenant in container.
Add new limecon function which prepare, build
and manage tenant container.
  • Loading branch information
Koncpa committed Sep 5, 2023
1 parent 63bbd0a commit f75a51e
Show file tree
Hide file tree
Showing 4 changed files with 311 additions and 3 deletions.
7 changes: 7 additions & 0 deletions Library/test-helpers/Dockerfile.tenant
Original file line number Diff line number Diff line change
@@ -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
120 changes: 117 additions & 3 deletions Library/test-helpers/lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
limeconRunTenant "$limeconKeylimeTenantCmd" "$TENANT_CMD" "$limeconTenantVolume"

Check warning

Code scanning / shellcheck

limeconTenantVolume is referenced but not assigned. Warning test

limeconTenantVolume is referenced but not assigned.
else
keylime_tenant $TENANT_CMD
fi
}

true <<'=cut'
=pod
=head2 limeStartIMAEmulator
Start the keylime IMA Emulator.
Expand Down Expand Up @@ -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

Check notice

Code scanning / shellcheck

Expressions don't expand in single quotes, use double quotes for that. Note test

Expressions don't expand in single quotes, use double quotes for that.
AGTSTATE=$(cat "$OUTPUT" | grep "^{" | tail -1 | jq -r ".[].operational_state")
if echo "$AGTSTATE" | grep -E -q "$STATUS"; then
cat $OUTPUT
Expand All @@ -1204,7 +1236,6 @@ limeWaitForAgentStatus() {
return 1
}


true <<'=cut'
=pod
Expand Down Expand Up @@ -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

Check notice

Code scanning / shellcheck

Expressions don't expand in single quotes, use double quotes for that. Note test

Expressions don't expand in single quotes, use double quotes for that.
REGSTATE=$(cat $OUTPUT | grep "^{" | jq -r ".[].operational_state")
if [ "$REGSTATE" == "Registered" ]; then
cat $OUTPUT
Expand All @@ -1257,6 +1288,45 @@ limeWaitForAgentRegistration() {
return 1
}

true <<'=cut'
=pod
=head2 limeTimeoutCommand
Function stop command vi 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

(
eval "$COMMAND" &
child=$!
trap -- "" SIGTERM
(
sleep $TIMEOUT
kill $child 2> /dev/null
) &
wait $child
)
}

# ~~~~~~~~~~~~~~~~~~~~
# Install
Expand Down Expand Up @@ -2426,6 +2496,50 @@ limeconRunSystemd() {
true <<'=cut'
=pod
=head2 limeconRunTenant
Tenant container run via podman with specified parameters.
limeconRunTenant PODMAN_CMD TENANT_CMD MOUNT_DIR
=item PODMAC_CMD
Setup of starting container.
=item TENANT_CMD
Keylime tenant command in container
=item MOUNT_DIR
Path of mount dir.
=back
Returns 0.
=cut

limeconRunTenant() {

local PODMAN_CMD=$1
local TENANT_CMD=$2
local MOUNT_DIR=$3
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

podman run $MOUNT_DIR $MOUNT_TENANT $PODMAN_CMD keylime_tenant $TENANT_CMD
sleep 3
limeconStop "tenant_container"

}

true <<'=cut'
=pod
=head2 limeconRunVerifier
Container run via podman with specified parameters.
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>
tag:
- container
component:
- keylime
test: ./test.sh
framework: beakerlib
require:
- yum
- podman
- nmap
recommend:
- keylime
duration: 10m
enabled: true
Original file line number Diff line number Diff line change
@@ -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="--name $CONT_TENANT --net $CONT_NETWORK_NAME --ip $IP_TENANT localhost/$TAG_TENANT"

Check warning

Code scanning / shellcheck

limeconKeylimeTenantCmd appears unused. Verify use (or export if used externally). Warning test

limeconKeylimeTenantCmd appears unused. Verify use (or export if used externally).
limeconTenantVolume="--volume $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

0 comments on commit f75a51e

Please sign in to comment.