mirror of
https://github.com/containers/podman
synced 2024-10-20 17:23:30 +00:00
a9dbd2b3de
CI and system tests currently pull some images from docker.io. Eliminate that, by: - building a custom image containing much of what we need for testing; and - copying other needed images to quay.io (Reason: effective 2020-11-01 docker.io will limit the number of image pulls). The principal change is to create a new quay.io/libpod/testimage, using the new test/system/build-testimage script, instead of relying on quay.io/libpod/alpine_labels. We also switch to using a hardcoded :YYYYMMDD tag, instead of :latest, in an attempt to futureproof our CI. This image includes 'httpd' from busybox-extras, which we use in our networking test (previously we had to pull and run busybox from docker.io). The testimage can and should be extended as needed for future tests, e.g. adding test file content or other useful tools. For the '--pull' tests which require actually pulling from the registry, I've created an image with the same name but tagged :00000000 so it will never be pulled by default. Since this image is only used minimally, it's just busybox. Unfortunately there remain two cases we cannot solve in this tiny alpine-based image: 1) docker registry 2) systemd For those, I've (manually) run: podman pull [ docker.io/library/registry:2.7 | registry.fedoraproject.org/fedora:31 ] podman tag !$ quay.io/... podman push !$ ...and amended the calling tests accordingly. I've tried to make the the smallest reasonable diff, not the smallest possible one. I hope it's a reasonable tradeoff. Signed-off-by: Ed Santiago <santiago@redhat.com>
330 lines
11 KiB
Bash
330 lines
11 KiB
Bash
#!/usr/bin/env bats -*- bats -*-
|
|
#
|
|
# tests for podman login
|
|
#
|
|
|
|
load helpers
|
|
|
|
###############################################################################
|
|
# BEGIN one-time envariable setup
|
|
|
|
# Create a scratch directory; our podman registry will run from here. We
|
|
# also use it for other temporary files like authfiles.
|
|
if [ -z "${PODMAN_LOGIN_WORKDIR}" ]; then
|
|
export PODMAN_LOGIN_WORKDIR=$(mktemp -d --tmpdir=${BATS_TMPDIR:-${TMPDIR:-/tmp}} podman_bats_login.XXXXXX)
|
|
fi
|
|
|
|
# Randomly-generated username and password
|
|
if [ -z "${PODMAN_LOGIN_USER}" ]; then
|
|
export PODMAN_LOGIN_USER="user$(random_string 4)"
|
|
export PODMAN_LOGIN_PASS=$(random_string 15)
|
|
fi
|
|
|
|
# Randomly-assigned port in the 5xxx range
|
|
if [ -z "${PODMAN_LOGIN_REGISTRY_PORT}" ]; then
|
|
for port in $(shuf -i 5000-5999);do
|
|
if ! { exec 3<> /dev/tcp/127.0.0.1/$port; } &>/dev/null; then
|
|
export PODMAN_LOGIN_REGISTRY_PORT=$port
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Override any user-set path to an auth file
|
|
unset REGISTRY_AUTH_FILE
|
|
|
|
# END one-time envariable setup
|
|
###############################################################################
|
|
# BEGIN filtering - none of these tests will work with podman-remote
|
|
|
|
function setup() {
|
|
skip_if_remote "none of these tests work with podman-remote"
|
|
|
|
basic_setup
|
|
}
|
|
|
|
# END filtering - none of these tests will work with podman-remote
|
|
###############################################################################
|
|
# BEGIN first "test" - start a registry for use by other tests
|
|
#
|
|
# This isn't really a test: it's a helper that starts a local registry.
|
|
# Note that we're careful to use a root/runroot separate from our tests,
|
|
# so setup/teardown don't clobber our registry image.
|
|
#
|
|
|
|
@test "podman login [start registry]" {
|
|
AUTHDIR=${PODMAN_LOGIN_WORKDIR}/auth
|
|
mkdir -p $AUTHDIR
|
|
|
|
# Registry image; copy of docker.io, but on our own registry
|
|
local REGISTRY_IMAGE="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/registry:2.7"
|
|
|
|
# Pull registry image, but into a separate container storage
|
|
mkdir -p ${PODMAN_LOGIN_WORKDIR}/root
|
|
mkdir -p ${PODMAN_LOGIN_WORKDIR}/runroot
|
|
PODMAN_LOGIN_ARGS="--root ${PODMAN_LOGIN_WORKDIR}/root --runroot ${PODMAN_LOGIN_WORKDIR}/runroot"
|
|
# Give it three tries, to compensate for flakes
|
|
run_podman ${PODMAN_LOGIN_ARGS} pull $REGISTRY_IMAGE ||
|
|
run_podman ${PODMAN_LOGIN_ARGS} pull $REGISTRY_IMAGE ||
|
|
run_podman ${PODMAN_LOGIN_ARGS} pull $REGISTRY_IMAGE
|
|
|
|
# Registry image needs a cert. Self-signed is good enough.
|
|
CERT=$AUTHDIR/domain.crt
|
|
if [ ! -e $CERT ]; then
|
|
openssl req -newkey rsa:4096 -nodes -sha256 \
|
|
-keyout $AUTHDIR/domain.key -x509 -days 2 \
|
|
-out $AUTHDIR/domain.crt \
|
|
-subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=localhost"
|
|
fi
|
|
|
|
# Store credentials where container will see them
|
|
if [ ! -e $AUTHDIR/htpasswd ]; then
|
|
htpasswd -Bbn ${PODMAN_LOGIN_USER} ${PODMAN_LOGIN_PASS} \
|
|
> $AUTHDIR/htpasswd
|
|
|
|
# In case $PODMAN_TEST_KEEP_LOGIN_REGISTRY is set, for testing later
|
|
echo "${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS}" \
|
|
> $AUTHDIR/htpasswd-plaintext
|
|
fi
|
|
|
|
# Run the registry container.
|
|
run_podman '?' ${PODMAN_LOGIN_ARGS} rm -f registry
|
|
run_podman ${PODMAN_LOGIN_ARGS} run -d \
|
|
-p ${PODMAN_LOGIN_REGISTRY_PORT}:5000 \
|
|
--name registry \
|
|
-v $AUTHDIR:/auth:Z \
|
|
-e "REGISTRY_AUTH=htpasswd" \
|
|
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
|
|
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
|
|
-e REGISTRY_HTTP_TLS_CERTIFICATE=/auth/domain.crt \
|
|
-e REGISTRY_HTTP_TLS_KEY=/auth/domain.key \
|
|
$REGISTRY_IMAGE
|
|
}
|
|
|
|
# END first "test" - start a registry for use by other tests
|
|
###############################################################################
|
|
# BEGIN actual tests
|
|
# BEGIN primary podman login/push/pull tests
|
|
|
|
@test "podman login - basic test" {
|
|
run_podman login --tls-verify=false \
|
|
--username ${PODMAN_LOGIN_USER} \
|
|
--password-stdin \
|
|
localhost:${PODMAN_LOGIN_REGISTRY_PORT} <<<"${PODMAN_LOGIN_PASS}"
|
|
is "$output" "Login Succeeded!" "output from podman login"
|
|
|
|
# Now log out
|
|
run_podman logout localhost:${PODMAN_LOGIN_REGISTRY_PORT}
|
|
is "$output" "Removed login credentials for localhost:${PODMAN_LOGIN_REGISTRY_PORT}" \
|
|
"output from podman logout"
|
|
}
|
|
|
|
@test "podman login - with wrong credentials" {
|
|
registry=localhost:${PODMAN_LOGIN_REGISTRY_PORT}
|
|
|
|
run_podman 125 login --tls-verify=false \
|
|
--username ${PODMAN_LOGIN_USER} \
|
|
--password-stdin \
|
|
$registry <<< "x${PODMAN_LOGIN_PASS}"
|
|
is "$output" \
|
|
"Error: error logging into \"$registry\": invalid username/password" \
|
|
'output from podman login'
|
|
}
|
|
|
|
@test "podman login - check generated authfile" {
|
|
authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
|
|
rm -f $authfile
|
|
|
|
registry=localhost:${PODMAN_LOGIN_REGISTRY_PORT}
|
|
|
|
run_podman login --authfile=$authfile \
|
|
--tls-verify=false \
|
|
--username ${PODMAN_LOGIN_USER} \
|
|
--password ${PODMAN_LOGIN_PASS} \
|
|
$registry
|
|
|
|
# Confirm that authfile now exists
|
|
test -e $authfile || \
|
|
die "podman login did not create authfile $authfile"
|
|
|
|
# Special bracket form needed because of colon in host:port
|
|
run jq -r ".[\"auths\"][\"$registry\"][\"auth\"]" <$authfile
|
|
is "$status" "0" "jq from $authfile"
|
|
|
|
expect_userpass="${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS}"
|
|
actual_userpass=$(base64 -d <<<"$output")
|
|
is "$actual_userpass" "$expect_userpass" "credentials stored in $authfile"
|
|
|
|
|
|
# Now log out and make sure credentials are removed
|
|
run_podman logout --authfile=$authfile $registry
|
|
|
|
run jq -r '.auths' <$authfile
|
|
is "$status" "0" "jq from $authfile"
|
|
is "$output" "{}" "credentials removed from $authfile"
|
|
}
|
|
|
|
# Some push tests
|
|
@test "podman push fail" {
|
|
|
|
# Create an invalid authfile
|
|
authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
|
|
rm -f $authfile
|
|
|
|
wrong_auth=$(base64 <<<"baduser:wrongpassword")
|
|
cat >$authfile <<EOF
|
|
{
|
|
"auths": {
|
|
"localhost:${PODMAN_LOGIN_REGISTRY_PORT}": {
|
|
"auth": "$wrong_auth"
|
|
}
|
|
}
|
|
}
|
|
EOF
|
|
|
|
run_podman 125 push --authfile=$authfile \
|
|
--tls-verify=false $IMAGE \
|
|
localhost:${PODMAN_LOGIN_REGISTRY_PORT}/badpush:1
|
|
is "$output" ".*: unauthorized: authentication required" \
|
|
"auth error on push"
|
|
}
|
|
|
|
@test "podman push ok" {
|
|
# Preserve image ID for later comparison against push/pulled image
|
|
run_podman inspect --format '{{.Id}}' $IMAGE
|
|
iid=$output
|
|
|
|
destname=ok-$(random_string 10 | tr A-Z a-z)-ok
|
|
# Use command-line credentials
|
|
run_podman push --tls-verify=false \
|
|
--creds ${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS} \
|
|
$IMAGE localhost:${PODMAN_LOGIN_REGISTRY_PORT}/$destname
|
|
|
|
# Yay! Pull it back
|
|
run_podman pull --tls-verify=false \
|
|
--creds ${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS} \
|
|
localhost:${PODMAN_LOGIN_REGISTRY_PORT}/$destname
|
|
|
|
# Compare to original image
|
|
run_podman inspect --format '{{.Id}}' $destname
|
|
is "$output" "$iid" "Image ID of pulled image == original IID"
|
|
|
|
run_podman rmi $destname
|
|
}
|
|
|
|
# END primary podman login/push/pull tests
|
|
###############################################################################
|
|
# BEGIN cooperation with skopeo
|
|
|
|
# Skopeo helper - keep this separate, so we can test with different
|
|
# envariable settings
|
|
function _test_skopeo_credential_sharing() {
|
|
if ! type -p skopeo; then
|
|
skip "skopeo not available"
|
|
fi
|
|
|
|
registry=localhost:${PODMAN_LOGIN_REGISTRY_PORT}
|
|
|
|
run_podman login "$@" --tls-verify=false \
|
|
--username ${PODMAN_LOGIN_USER} \
|
|
--password ${PODMAN_LOGIN_PASS} \
|
|
$registry
|
|
|
|
destname=skopeo-ok-$(random_string 10 | tr A-Z a-z)-ok
|
|
echo "# skopeo copy ..."
|
|
run skopeo copy "$@" \
|
|
--format=v2s2 \
|
|
--dest-tls-verify=false \
|
|
containers-storage:$IMAGE \
|
|
docker://$registry/$destname
|
|
echo "$output"
|
|
is "$status" "0" "skopeo copy - exit status"
|
|
is "$output" ".*Copying blob .*" "output of skopeo copy"
|
|
is "$output" ".*Copying config .*" "output of skopeo copy"
|
|
is "$output" ".*Writing manifest .*" "output of skopeo copy"
|
|
|
|
echo "# skopeo inspect ..."
|
|
run skopeo inspect "$@" --tls-verify=false docker://$registry/$destname
|
|
echo "$output"
|
|
is "$status" "0" "skopeo inspect - exit status"
|
|
|
|
got_name=$(jq -r .Name <<<"$output")
|
|
is "$got_name" "$registry/$dest_name" "skopeo inspect -> Name"
|
|
|
|
# Now try without a valid login; it should fail
|
|
run_podman logout "$@" $registry
|
|
echo "# skopeo inspect [with no credentials] ..."
|
|
run skopeo inspect "$@" --tls-verify=false docker://$registry/$destname
|
|
echo "$output"
|
|
is "$status" "1" "skopeo inspect - exit status"
|
|
is "$output" ".*: unauthorized: authentication required" \
|
|
"auth error on skopeo inspect"
|
|
}
|
|
|
|
@test "podman login - shares credentials with skopeo - default auth file" {
|
|
if is_rootless; then
|
|
if [ -z "${XDG_RUNTIME_DIR}" ]; then
|
|
skip "skopeo does not match podman when XDG_RUNTIME_DIR unset; #823"
|
|
fi
|
|
fi
|
|
_test_skopeo_credential_sharing
|
|
}
|
|
|
|
@test "podman login - shares credentials with skopeo - via envariable" {
|
|
authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
|
|
rm -f $authfile
|
|
|
|
REGISTRY_AUTH_FILE=$authfile _test_skopeo_credential_sharing
|
|
rm -f $authfile
|
|
}
|
|
|
|
@test "podman login - shares credentials with skopeo - via --authfile" {
|
|
# Also test that command-line --authfile overrides envariable
|
|
authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
|
|
rm -f $authfile
|
|
|
|
fake_authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
|
|
rm -f $fake_authfile
|
|
|
|
REGISTRY_AUTH_FILE=$authfile _test_skopeo_credential_sharing --authfile=$authfile
|
|
|
|
if [ -e $fake_authfile ]; then
|
|
die "REGISTRY_AUTH_FILE overrode command-line --authfile!"
|
|
fi
|
|
rm -f $authfile
|
|
}
|
|
|
|
# END cooperation with skopeo
|
|
# END actual tests
|
|
###############################################################################
|
|
# BEGIN teardown (remove the registry container)
|
|
|
|
@test "podman login [stop registry, clean up]" {
|
|
# For manual debugging; user may request keeping the registry running
|
|
if [ -n "${PODMAN_TEST_KEEP_LOGIN_REGISTRY}" ]; then
|
|
skip "[leaving registry running by request]"
|
|
fi
|
|
|
|
run_podman --root ${PODMAN_LOGIN_WORKDIR}/root \
|
|
--runroot ${PODMAN_LOGIN_WORKDIR}/runroot \
|
|
rm -f registry
|
|
run_podman --root ${PODMAN_LOGIN_WORKDIR}/root \
|
|
--runroot ${PODMAN_LOGIN_WORKDIR}/runroot \
|
|
rmi -a
|
|
|
|
# By default, clean up
|
|
if [ -z "${PODMAN_TEST_KEEP_LOGIN_WORKDIR}" ]; then
|
|
rm -rf ${PODMAN_LOGIN_WORKDIR}
|
|
fi
|
|
|
|
# Make sure socket is closed
|
|
if { exec 3<> /dev/tcp/127.0.0.1/${PODMAN_LOGIN_REGISTRY_PORT}; } &>/dev/null; then
|
|
die "Socket still seems open"
|
|
fi
|
|
}
|
|
|
|
# END teardown (remove the registry container)
|
|
###############################################################################
|
|
|
|
# vim: filetype=sh
|