mirror of
https://github.com/containers/podman
synced 2024-10-21 01:34:37 +00:00
9ecf8e13dc
Great timing: this new test collided against #5268, which added a warning about using command-line --password. CI is now going to fail all over. Fix: rework test to use --password-stdin. Am doing so only in the places where output string is checked; other instances can keep using '--password xxx' because it's simpler. Signed-off-by: Ed Santiago <santiago@redhat.com>
340 lines
12 KiB
Bash
340 lines
12 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
|
|
|
|
# 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:2 ||
|
|
run_podman ${PODMAN_LOGIN_ARGS} pull registry:2 ||
|
|
run_podman ${PODMAN_LOGIN_ARGS} pull registry:2
|
|
|
|
# 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
|
|
run_podman ${PODMAN_LOGIN_ARGS} run --rm \
|
|
--entrypoint htpasswd registry:2 \
|
|
-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:2
|
|
}
|
|
|
|
# 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" {
|
|
# ARGH! We can't push $IMAGE (alpine_labels) to this registry; error is:
|
|
#
|
|
# Writing manifest to image destination
|
|
# Error: Error copying image to the remote destination: Error writing manifest: Error uploading manifest latest to localhost:${PODMAN_LOGIN_REGISTRY_PORT}/okpush: received unexpected HTTP status: 500 Internal Server Error
|
|
#
|
|
# Root cause: something to do with v1/v2 s1/s2:
|
|
#
|
|
# https://github.com/containers/skopeo/issues/651
|
|
#
|
|
run_podman pull busybox
|
|
|
|
# Preserve its ID for later comparison against push/pulled image
|
|
run_podman inspect --format '{{.Id}}' busybox
|
|
id_busybox=$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} \
|
|
busybox 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 busybox
|
|
run_podman inspect --format '{{.Id}}' $destname
|
|
is "$output" "$id_busybox" "Image ID of pulled image == busybox"
|
|
|
|
run_podman rmi busybox $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" {
|
|
skip "skopeo does not yet support REGISTRY_AUTH_FILE; #822"
|
|
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
|