Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New scenario with keylime tenant in container #405

Merged
merged 1 commit into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
135 changes: 132 additions & 3 deletions Library/test-helpers/lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,38 @@
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"
Dismissed Show dismissed Hide dismissed
else
keylime_tenant $TENANT_CMD
fi
}

true <<'=cut'
=pod

=head2 limeStartIMAEmulator

Start the keylime IMA Emulator.
Expand Down Expand Up @@ -1187,7 +1219,7 @@

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
Expand All @@ -1204,7 +1236,6 @@
return 1
}


true <<'=cut'
=pod

Expand Down Expand Up @@ -1240,7 +1271,7 @@

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
Expand All @@ -1257,6 +1288,45 @@
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
Expand Down Expand Up @@ -2426,6 +2496,65 @@
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.
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
Dismissed Show dismissed Hide dismissed

#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
Dismissed Show dismissed Hide dismissed
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