cosign: cosign sign does not use local image registry credentials

Question

I’m trying to sign a container image that I pushed to docker.io. This seems simple enough:

$ cosign sign -key cosign.key docker.io/adambkaplan/ruby-ex

However, when trying to pull the image, cosign does not appear to use my local credentials. Instead cosign appears to do the following:

  1. Try to GET the root of the container registry
  2. With the UNAUTHORIZED response, then it requests a “pull” scoped token
  3. After receiving the token, it then tries to pull the container image. For whatever reason the token is invalid, and the pull fails.

I was able to verify that my ~/.docker/config.json contains valid auth credentials for docker.io, and that I can pull images using those credentials with my container engine (podman).

This could be related to #337.

Here’s the debug output:

cosign -d sign -key cosign.key docker.io/adambkaplan/ruby-ex
2021/08/27 10:46:56 --> GET https://index.docker.io/v2/
2021/08/27 10:46:56 GET /v2/ HTTP/1.1
Host: index.docker.io
User-Agent: Go-http-client/1.1
Accept-Encoding: gzip


2021/08/27 10:46:56 <-- 401 https://index.docker.io/v2/ (201.76705ms)
2021/08/27 10:46:56 HTTP/1.1 401 Unauthorized
Content-Length: 87
Content-Type: application/json
Date: Fri, 27 Aug 2021 14:46:56 GMT
Docker-Distribution-Api-Version: registry/2.0
Strict-Transport-Security: max-age=31536000
Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io"

{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":null}]}

2021/08/27 10:46:56 --> GET https://auth.docker.io/token?scope=repository%3Aadambkaplan%2Fruby-ex%3Apull&service=registry.docker.io [body redacted: basic token response contains credentials]
2021/08/27 10:46:56 GET /token?scope=repository%3Aadambkaplan%2Fruby-ex%3Apull&service=registry.docker.io HTTP/1.1
Host: auth.docker.io
User-Agent: go-containerregistry/v0.6.0
Accept-Encoding: gzip


2021/08/27 10:46:57 <-- 200 https://auth.docker.io/token?scope=repository%3Aadambkaplan%2Fruby-ex%3Apull&service=registry.docker.io (179.251563ms) [body redacted: basic token response contains credentials]
2021/08/27 10:46:57 HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json
Date: Fri, 27 Aug 2021 14:46:56 GMT
Strict-Transport-Security: max-age=31536000


2021/08/27 10:46:57 --> GET https://index.docker.io/v2/adambkaplan/ruby-ex/manifests/latest
2021/08/27 10:46:57 GET /v2/adambkaplan/ruby-ex/manifests/latest HTTP/1.1
Host: index.docker.io
User-Agent: go-containerregistry/v0.6.0
Accept: application/vnd.docker.distribution.manifest.v1+json,application/vnd.docker.distribution.manifest.v1+prettyjws,application/vnd.docker.distribution.manifest.v2+json,application/vnd.oci.image.manifest.v1+json,application/vnd.docker.distribution.manifest.list.v2+json,application/vnd.oci.image.index.v1+json
Authorization: <redacted>
Accept-Encoding: gzip


2021/08/27 10:46:57 <-- 401 https://index.docker.io/v2/adambkaplan/ruby-ex/manifests/latest (43.68461ms)
2021/08/27 10:46:57 HTTP/1.1 401 Unauthorized
Content-Length: 162
Content-Type: application/json
Date: Fri, 27 Aug 2021 14:46:57 GMT
Docker-Distribution-Api-Version: registry/2.0
Strict-Transport-Security: max-age=31536000
Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:adambkaplan/ruby-ex:pull",error="insufficient_scope"

{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"repository","Class":"","Name":"adambkaplan/ruby-ex","Action":"pull"}]}]}

2021/08/27 10:46:57 --> GET https://auth.docker.io/token?scope=repository%3Aadambkaplan%2Fruby-ex%3Apull&service=registry.docker.io [body redacted: basic token response contains credentials]
2021/08/27 10:46:57 GET /token?scope=repository%3Aadambkaplan%2Fruby-ex%3Apull&service=registry.docker.io HTTP/1.1
Host: auth.docker.io
User-Agent: go-containerregistry/v0.6.0
Accept-Encoding: gzip


2021/08/27 10:46:57 <-- 200 https://auth.docker.io/token?scope=repository%3Aadambkaplan%2Fruby-ex%3Apull&service=registry.docker.io (38.934215ms) [body redacted: basic token response contains credentials]
2021/08/27 10:46:57 HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json
Date: Fri, 27 Aug 2021 14:46:57 GMT
Strict-Transport-Security: max-age=31536000


2021/08/27 10:46:57 --> GET https://index.docker.io/v2/adambkaplan/ruby-ex/manifests/latest
2021/08/27 10:46:57 GET /v2/adambkaplan/ruby-ex/manifests/latest HTTP/1.1
Host: index.docker.io
User-Agent: go-containerregistry/v0.6.0
Accept: application/vnd.docker.distribution.manifest.v1+json,application/vnd.docker.distribution.manifest.v1+prettyjws,application/vnd.docker.distribution.manifest.v2+json,application/vnd.oci.image.manifest.v1+json,application/vnd.docker.distribution.manifest.list.v2+json,application/vnd.oci.image.index.v1+json
Authorization: <redacted>
Accept-Encoding: gzip


2021/08/27 10:46:57 <-- 401 https://index.docker.io/v2/adambkaplan/ruby-ex/manifests/latest (40.460773ms)
2021/08/27 10:46:57 HTTP/1.1 401 Unauthorized
Content-Length: 162
Content-Type: application/json
Date: Fri, 27 Aug 2021 14:46:57 GMT
Docker-Distribution-Api-Version: registry/2.0
Strict-Transport-Security: max-age=31536000
Www-Authenticate: Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:adambkaplan/ruby-ex:pull",error="insufficient_scope"

{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"repository","Class":"","Name":"adambkaplan/ruby-ex","Action":"pull"}]}]}

error: signing docker.io/adambkaplan/ruby-ex: getting remote image: GET https://index.docker.io/v2/adambkaplan/ruby-ex/manifests/latest: UNAUTHORIZED: authentication required; [map[Action:pull Class: Name:adambkaplan/ruby-ex Type:repository]]

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 29 (12 by maintainers)

Most upvoted comments

Hi, had auth issues (I use podman instead of docker), the following was a workaround for me:

cat ${XDG_RUNTIME_DIR}/containers/auth.json > ~/.docker/config.json

My two cents: auth.json (podman) or config.json (docker) must contain an entry with authentications for https://index.docker.io/v1/ otherwise the authentication seems to fail. I have solved it by adding an extra entry like so (trailing / needed):

{
        "auths": {
                "docker.io": {
                        "auth": "redacted"
                },
                "https://index.docker.io/v1/": {
                        "auth": "redacted"
                }
        }
}

I found out that if the registry URL is index.docker.io go-containerregistry uses the full url when looking for creds.

In my case, I discovered that this .docker/config.json results in authentication failure:

{"auths":{"https://index.docker.io":{"auth":"<redacted>"}}}

But this one results in success:

{"auths":{"https://index.docker.io/v1/":{"auth":"<redacted>"}}}

Interestingly the authentication failure when /v1 is not appended clearly shows that /v2/ is attempted by default:

main.go:46: error during command execution: GET https://index.docker.io/v2/myrepo/curl/manifests/latest: UNAUTHORIZED: authentication required; [map[Action:pull Class: Name:myrepo/curl Type:repository]]

Any use of buildah, podman, skopeo based tools where the credentials are stored in a different location than ~/.docker, seems to have cosign not recognise the use of a different container build tool and it’s already authenticated information creds.

@tommyreilly you’re right, it only supports docker’s behavior right now.

If we end up supporting some alternative to Docker’s configuration and authentication scheme, it should be one we maintain. I think documenting our docker mimicry and prescribing a manual way of setting things up for automation should suffice for now

I assume the issue is that cosign expects a Docker daemon with a default config (or env vars set).

Not a daemon, just the normal docker config file behavior; i.e. $HOME/.docker/config.json but it can be overridden by DOCKER_CONFIG. If Snap is moving this around but not setting that environment variable, I’d argue it’s a bug in Snap?

or to implement the registry API and support e.g. cosign registry login directly.

There’s not really a registry API for logging in. We could support a login command, but it just manipulates a local configuration file and wouldn’t support configuring credential helpers…

I think the cosign tool and docs could probably do a better job describing how auth works, regardless.

I’m hitting this same issue when trying to integrate cosign into our teams CI flow. Any use of buildah, podman, skopeo based tools where the credentials are stored in a different location than ~/.docker, seems to have cosign not recognise the use of a different container build tool and it’s already authenticated information creds.

As these tools are commonly used in automated flows, it would be great if anyone has any ideas to work round the current situation.