github.com/containers/podman/v5@v5.1.0-rc1/test/system/150-login.bats (about)

     1  #!/usr/bin/env bats   -*- bats -*-
     2  #
     3  # tests for podman login
     4  #
     5  
     6  load helpers
     7  load helpers.network
     8  load helpers.registry
     9  
    10  ###############################################################################
    11  # BEGIN filtering - none of these tests will work with podman-remote
    12  
    13  function setup() {
    14      skip_if_remote "none of these tests work with podman-remote"
    15  
    16      basic_setup
    17      start_registry
    18  }
    19  
    20  # END   filtering - none of these tests will work with podman-remote
    21  ###############################################################################
    22  # BEGIN actual tests
    23  # BEGIN primary podman login/push/pull tests
    24  
    25  @test "podman login - basic test" {
    26      run_podman login --tls-verify=false \
    27                 --username ${PODMAN_LOGIN_USER} \
    28                 --password-stdin \
    29                 localhost:${PODMAN_LOGIN_REGISTRY_PORT} <<<"${PODMAN_LOGIN_PASS}"
    30      is "$output" "Login Succeeded!" "output from podman login"
    31  
    32      # Now log out
    33      run_podman logout localhost:${PODMAN_LOGIN_REGISTRY_PORT}
    34      is "$output" "Removed login credentials for localhost:${PODMAN_LOGIN_REGISTRY_PORT}" \
    35         "output from podman logout"
    36  }
    37  
    38  @test "podman login - with wrong credentials" {
    39      registry=localhost:${PODMAN_LOGIN_REGISTRY_PORT}
    40  
    41      run_podman 125 login --tls-verify=false \
    42                 --username ${PODMAN_LOGIN_USER} \
    43                 --password-stdin \
    44                 $registry <<< "x${PODMAN_LOGIN_PASS}"
    45      is "$output" \
    46         "Error: logging into \"$registry\": invalid username/password" \
    47         'output from podman login'
    48  }
    49  
    50  @test "podman login - check generated authfile" {
    51      authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
    52      rm -f $authfile
    53  
    54      registry=localhost:${PODMAN_LOGIN_REGISTRY_PORT}
    55  
    56      run_podman login --authfile=$authfile \
    57          --tls-verify=false \
    58          --username ${PODMAN_LOGIN_USER} \
    59          --password ${PODMAN_LOGIN_PASS} \
    60          $registry
    61  
    62      # Confirm that authfile now exists
    63      test -e $authfile || \
    64          die "podman login did not create authfile $authfile"
    65  
    66      # Special bracket form needed because of colon in host:port
    67      run jq -r ".[\"auths\"][\"$registry\"][\"auth\"]" <$authfile
    68      is "$status" "0" "jq from $authfile"
    69  
    70      expect_userpass="${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS}"
    71      actual_userpass=$(base64 -d <<<"$output")
    72      is "$actual_userpass" "$expect_userpass" "credentials stored in $authfile"
    73  
    74  
    75      # Now log out and make sure credentials are removed
    76      run_podman logout --authfile=$authfile $registry
    77  
    78      run jq -r '.auths' <$authfile
    79      is "$status" "0" "jq from $authfile"
    80      is "$output" "{}" "credentials removed from $authfile"
    81  }
    82  
    83  @test "podman login inconsistent authfiles" {
    84      ambiguous_file=${PODMAN_LOGIN_WORKDIR}/ambiguous-auth.json
    85      echo '{}' > $ambiguous_file # To make sure we are not hitting the “file not found” path
    86  
    87      run_podman 125 login --authfile "$ambiguous_file" --compat-auth-file "$ambiguous_file" localhost:5000
    88      assert "$output" =~ "Error: options for paths to the credential file and to the Docker-compatible credential file can not be set simultaneously"
    89  
    90      run_podman 125 logout --authfile "$ambiguous_file" --compat-auth-file "$ambiguous_file" localhost:5000
    91      assert "$output" =~ "Error: options for paths to the credential file and to the Docker-compatible credential file can not be set simultaneously"
    92  }
    93  
    94  @test "podman login - check with --config global option" {
    95      dockerconfig=${PODMAN_LOGIN_WORKDIR}/docker
    96      rm -rf $dockerconfig
    97  
    98      registry=localhost:${PODMAN_LOGIN_REGISTRY_PORT}
    99  
   100      run_podman --config $dockerconfig login \
   101          --tls-verify=false \
   102          --username ${PODMAN_LOGIN_USER} \
   103          --password ${PODMAN_LOGIN_PASS} \
   104          $registry
   105  
   106      # Confirm that config file now exists
   107      test -e $dockerconfig/config.json || \
   108          die "podman login did not create config $dockerconfig/config.json"
   109  
   110      # Special bracket form needed because of colon in host:port
   111      run jq -r ".[\"auths\"][\"$registry\"][\"auth\"]" <$dockerconfig/config.json
   112      is "$status" "0" "jq from $dockerconfig/config.json"
   113  
   114      expect_userpass="${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS}"
   115      actual_userpass=$(base64 -d <<<"$output")
   116      is "$actual_userpass" "$expect_userpass" "credentials stored in $dockerconfig/config.json"
   117  
   118      # Now log out and make sure credentials are removed
   119      run_podman --config $dockerconfig logout $registry
   120  
   121      run jq -r '.auths' <$dockerconfig/config.json
   122      is "$status" "0" "jq from $dockerconfig/config.json"
   123      is "$output" "{}" "credentials removed from $dockerconfig/config.json"
   124  }
   125  
   126  # Some push tests
   127  @test "podman push fail" {
   128  
   129      # Create an invalid authfile
   130      authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
   131      rm -f $authfile
   132  
   133      wrong_auth=$(base64 <<<"baduser:wrongpassword")
   134      cat >$authfile <<EOF
   135  {
   136      "auths": {
   137              "localhost:${PODMAN_LOGIN_REGISTRY_PORT}": {
   138                      "auth": "$wrong_auth"
   139              }
   140      }
   141  }
   142  EOF
   143  
   144      run_podman 125 push --authfile=$authfile \
   145          --tls-verify=false $IMAGE \
   146          localhost:${PODMAN_LOGIN_REGISTRY_PORT}/badpush:1
   147      is "$output" ".* checking whether a blob .* exists in localhost:${PODMAN_LOGIN_REGISTRY_PORT}/badpush: authentication required" \
   148         "auth error on push"
   149  }
   150  
   151  function _push_search_test() {
   152      # Preserve image ID for later comparison against push/pulled image
   153      run_podman inspect --format '{{.Id}}' $IMAGE
   154      iid=$output
   155  
   156      destname=ok-$(random_string 10 | tr A-Z a-z)-ok
   157      # Use command-line credentials
   158      run_podman push --tls-verify=$1 \
   159                 --format docker \
   160                 --cert-dir ${PODMAN_LOGIN_WORKDIR}/trusted-registry-cert-dir \
   161                 --creds ${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS} \
   162                 $IMAGE localhost:${PODMAN_LOGIN_REGISTRY_PORT}/$destname
   163  
   164      # Search a pushed image without --cert-dir should fail if --tls-verify=true
   165      run_podman $2 search --tls-verify=$1 \
   166                 --format "table {{.Name}}" \
   167                 --creds ${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS} \
   168                 localhost:${PODMAN_LOGIN_REGISTRY_PORT}/$destname
   169  
   170      # Search a pushed image without --creds should fail
   171      run_podman 125 search --tls-verify=$1 \
   172                 --format "table {{.Name}}" \
   173                 --cert-dir ${PODMAN_LOGIN_WORKDIR}/trusted-registry-cert-dir \
   174                 localhost:${PODMAN_LOGIN_REGISTRY_PORT}/$destname
   175  
   176      # Search a pushed image should succeed
   177      run_podman search --tls-verify=$1 \
   178                 --format "table {{.Name}}" \
   179                 --cert-dir ${PODMAN_LOGIN_WORKDIR}/trusted-registry-cert-dir \
   180                 --creds ${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS} \
   181                 localhost:${PODMAN_LOGIN_REGISTRY_PORT}/$destname
   182      is "${lines[1]}" "localhost:${PODMAN_LOGIN_REGISTRY_PORT}/$destname" "search output is destname"
   183  
   184      # Yay! Pull it back
   185      run_podman pull --tls-verify=$1 \
   186                 --cert-dir ${PODMAN_LOGIN_WORKDIR}/trusted-registry-cert-dir \
   187                 --creds ${PODMAN_LOGIN_USER}:${PODMAN_LOGIN_PASS} \
   188                 localhost:${PODMAN_LOGIN_REGISTRY_PORT}/$destname
   189  
   190      # Compare to original image
   191      run_podman inspect --format '{{.Id}}' $destname
   192      is "$output" "$iid" "Image ID of pulled image == original IID"
   193  
   194      run_podman rmi $destname
   195  }
   196  
   197  @test "podman push and search ok with --tls-verify=false" {
   198      _push_search_test false 0
   199  }
   200  
   201  @test "podman push and search ok with --tls-verify=true" {
   202      _push_search_test true 125
   203  }
   204  
   205  # END   primary podman login/push/pull tests
   206  ###############################################################################
   207  # BEGIN cooperation with skopeo
   208  
   209  # Skopeo helper - keep this separate, so we can test with different
   210  # envariable settings
   211  function _test_skopeo_credential_sharing() {
   212      if ! type -p skopeo; then
   213          skip "skopeo not available"
   214      fi
   215  
   216      registry=localhost:${PODMAN_LOGIN_REGISTRY_PORT}
   217  
   218      run_podman login "$@" --tls-verify=false \
   219                 --username ${PODMAN_LOGIN_USER} \
   220                 --password ${PODMAN_LOGIN_PASS} \
   221                 $registry
   222  
   223      destname=skopeo-ok-$(random_string 10 | tr A-Z a-z)-ok
   224      echo "# skopeo copy ..."
   225      run skopeo copy "$@" \
   226          --format=v2s2 \
   227          --dest-tls-verify=false \
   228          containers-storage:$IMAGE \
   229          docker://$registry/$destname
   230      echo "$output"
   231      is "$status" "0" "skopeo copy - exit status"
   232      is "$output" ".*Copying blob .*"     "output of skopeo copy"
   233      is "$output" ".*Copying config .*"   "output of skopeo copy"
   234      is "$output" ".*Writing manifest .*" "output of skopeo copy"
   235  
   236      echo "# skopeo inspect ..."
   237      run skopeo inspect "$@" --tls-verify=false docker://$registry/$destname
   238      echo "$output"
   239      is "$status" "0" "skopeo inspect - exit status"
   240  
   241      got_name=$(jq -r .Name <<<"$output")
   242      is "$got_name" "$registry/$destname" "skopeo inspect -> Name"
   243  
   244      # Now try without a valid login; it should fail
   245      run_podman logout "$@" $registry
   246      echo "# skopeo inspect [with no credentials] ..."
   247      run skopeo inspect "$@" --tls-verify=false docker://$registry/$destname
   248      echo "$output"
   249      is "$status" "1" "skopeo inspect - exit status"
   250      is "$output" ".*: authentication required" \
   251         "auth error on skopeo inspect"
   252  }
   253  
   254  @test "podman login - shares credentials with skopeo - default auth file" {
   255      if is_rootless; then
   256          if [ -z "${XDG_RUNTIME_DIR}" ]; then
   257              skip "skopeo does not match podman when XDG_RUNTIME_DIR unset; #823"
   258          fi
   259      fi
   260      _test_skopeo_credential_sharing
   261  }
   262  
   263  @test "podman login - shares credentials with skopeo - via envariable" {
   264      authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
   265      rm -f $authfile
   266  
   267      REGISTRY_AUTH_FILE=$authfile _test_skopeo_credential_sharing
   268      rm -f $authfile
   269  }
   270  
   271  @test "podman login - shares credentials with skopeo - via --authfile" {
   272      # Also test that command-line --authfile overrides envariable
   273      authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
   274      rm -f $authfile
   275  
   276      fake_authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
   277      rm -f $fake_authfile
   278  
   279      REGISTRY_AUTH_FILE=$authfile _test_skopeo_credential_sharing --authfile=$authfile
   280  
   281      if [ -e $fake_authfile ]; then
   282          die "REGISTRY_AUTH_FILE overrode command-line --authfile!"
   283      fi
   284      rm -f $authfile
   285  }
   286  
   287  @test "podman login -secret test" {
   288      secret=$(random_string 10)
   289      echo -n ${PODMAN_LOGIN_PASS} > $PODMAN_TMPDIR/secret.file
   290      run_podman secret create $secret $PODMAN_TMPDIR/secret.file
   291      secretID=${output}
   292      run_podman login --tls-verify=false \
   293               --username ${PODMAN_LOGIN_USER} \
   294               --secret ${secretID} \
   295               localhost:${PODMAN_LOGIN_REGISTRY_PORT}
   296      is "$output" "Login Succeeded!" "output from podman login"
   297      # Now log out
   298      run_podman logout localhost:${PODMAN_LOGIN_REGISTRY_PORT}
   299      is "$output" "Removed login credentials for localhost:${PODMAN_LOGIN_REGISTRY_PORT}" \
   300         "output from podman logout"
   301      run_podman secret rm $secret
   302  
   303      # test using secret id as --username
   304      run_podman secret create ${PODMAN_LOGIN_USER} $PODMAN_TMPDIR/secret.file
   305      run_podman login --tls-verify=false \
   306                 --secret ${PODMAN_LOGIN_USER} \
   307                 localhost:${PODMAN_LOGIN_REGISTRY_PORT}
   308      is "$output" "Login Succeeded!" "output from podman login"
   309      # Now log out
   310      run_podman logout localhost:${PODMAN_LOGIN_REGISTRY_PORT}
   311      is "$output" "Removed login credentials for localhost:${PODMAN_LOGIN_REGISTRY_PORT}" \
   312         "output from podman logout"
   313      run_podman secret rm ${PODMAN_LOGIN_USER}
   314  
   315      bogus_secret=$(random_string 10)
   316      echo -n ${bogus_secret} > $PODMAN_TMPDIR/secret.file
   317      run_podman secret create $secret $PODMAN_TMPDIR/secret.file
   318      secretID=${output}
   319      run_podman 125 login --tls-verify=false \
   320               --username ${PODMAN_LOGIN_USER} \
   321               --secret ${secretID} \
   322               localhost:${PODMAN_LOGIN_REGISTRY_PORT}
   323  
   324      is "$output" "Error: logging into \"localhost:${PODMAN_LOGIN_REGISTRY_PORT}\": invalid username/password" "output from failed podman login"
   325  
   326      run_podman secret rm $secret
   327  
   328  }
   329  
   330  @test "podman pull images with retry" {
   331      run_podman pull -q --retry 4 --retry-delay "10s" $IMAGE
   332      run_podman 125 pull -q --retry 4 --retry-delay "bogus" $IMAGE
   333      is "$output" 'Error: time: invalid duration "bogus"' "bad retry-delay"
   334  
   335      skip_if_remote "running a local registry doesn't work with podman-remote"
   336      start_registry
   337      authfile=${PODMAN_LOGIN_WORKDIR}/auth-$(random_string 10).json
   338      run_podman login --tls-verify=false \
   339                 --username ${PODMAN_LOGIN_USER} \
   340                 --password-stdin \
   341                 --authfile=$authfile \
   342                 localhost:${PODMAN_LOGIN_REGISTRY_PORT} <<<"${PODMAN_LOGIN_PASS}"
   343      is "$output" "Login Succeeded!" "output from podman login"
   344  
   345      image1="localhost:${PODMAN_LOGIN_REGISTRY_PORT}/test:1.0"
   346  
   347      run_podman tag $IMAGE $image1
   348      run_podman push --authfile=$authfile \
   349          --tls-verify=false $mid \
   350          $image1
   351      run_podman rmi $image1
   352      run_podman pull -q --retry 4 --retry-delay "0s" --authfile=$authfile \
   353          --tls-verify=false $image1
   354      assert "${output:0:12}" = "$PODMAN_TEST_IMAGE_ID" "First pull (before stopping registry)"
   355      run_podman rmi $image1
   356  
   357      # This actually STOPs the registry, so the port is unbound...
   358      pause_registry
   359      # ...then, in eight seconds, we start it again
   360      (sleep 8; unpause_registry) &
   361      run_podman 0+w pull -q --retry 4 --retry-delay "5s" --authfile=$authfile \
   362              --tls-verify=false $image1
   363      assert "$output" =~ "Failed, retrying in 5s.*Error: initializing.* connection refused"
   364      assert "${lines[-1]:0:12}" = "$PODMAN_TEST_IMAGE_ID" "push should succeed via retry"
   365      unpause_registry
   366  
   367      run_podman rmi $image1
   368  }
   369  
   370  @test "podman containers.conf retry" {
   371      skip_if_remote "containers.conf settings not set for remote connections"
   372      run_podman pull --help
   373      assert "$output" =~ "--retry .*performing pull \(default 3\)"
   374  
   375      run_podman push --help
   376      assert "$output" =~ "--retry .*performing push \(default 3\)"
   377  
   378      containersConf=$PODMAN_TMPDIR/containers.conf
   379      cat >$containersConf <<EOF
   380  [engine]
   381  retry=10
   382  retry_delay="5s"
   383  EOF
   384  
   385      CONTAINERS_CONF="$containersConf" run_podman pull --help
   386      assert "$output" =~ "--retry .*performing pull \(default 10\)"
   387      assert "$output" =~ "--retry-delay .*pull failures \(default \"5s\"\)"
   388  
   389      CONTAINERS_CONF="$containersConf" run_podman push --help
   390      assert "$output" =~ "--retry .*performing push \(default 10\)"
   391      assert "$output" =~ "--retry-delay .*push failures \(default \"5s\"\)"
   392  
   393      CONTAINERS_CONF="$containersConf" run_podman create --help
   394      assert "$output" =~ "--retry .*performing pull \(default 10\)"
   395      assert "$output" =~ "--retry-delay .*pull failures \(default \"5s\"\)"
   396  
   397      CONTAINERS_CONF="$containersConf" run_podman run --help
   398      assert "$output" =~ "--retry .*performing pull \(default 10\)"
   399      assert "$output" =~ "--retry-delay .*pull failures \(default \"5s\"\)"
   400  }
   401  
   402  # END   cooperation with skopeo
   403  # END   actual tests
   404  ###############################################################################
   405  
   406  # vim: filetype=sh