summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/system/150-login.bats339
1 files changed, 339 insertions, 0 deletions
diff --git a/test/system/150-login.bats b/test/system/150-login.bats
new file mode 100644
index 000000000..9c9593311
--- /dev/null
+++ b/test/system/150-login.bats
@@ -0,0 +1,339 @@
+#!/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 ${PODMAN_LOGIN_PASS} \
+ localhost:${PODMAN_LOGIN_REGISTRY_PORT}
+ 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 "x${PODMAN_LOGIN_PASS}" \
+ $registry
+ 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