Search code examples
google-compute-enginegcloudgoogle-container-registry

Access google container registry without the gcloud client


I have a CoreOS docker host that I want to start running containers on, but when trying to use the docker command to fetch the image from the google container private registry (https://cloud.google.com/tools/container-registry/), I get a 403. I did some searching, but I'm not sure how to attach authentication (or where to generate the user+pass bundle to use with the docker login command).

Has anybody had any luck pulling from the google private containers? I can't install the gcloud command because coreos doesn't come with python, which is a requirement

docker run -p 80:80 gcr.io/prj_name/image_name
Unable to find image 'gcr.io/prj_name/image_name:latest' locally
Pulling repository gcr.io/prj_name/image_name
FATA[0000] HTTP code: 403

Update: after getting answers from @mattmoor and @Jesse:

The machine that I'm pulling from does have devaccess

curl -H 'Metadata-Flavor: Google' http://metadata.google.internal./computeMetadata/v1/instance/service-accounts/default/scopes
https://www.googleapis.com/auth/bigquery
https://www.googleapis.com/auth/cloud-platform
https://www.googleapis.com/auth/compute
https://www.googleapis.com/auth/datastore
----> https://www.googleapis.com/auth/devstorage.read_only
https://www.googleapis.com/auth/logging.admin
https://www.googleapis.com/auth/sqlservice.admin
https://www.googleapis.com/auth/taskqueue
https://www.googleapis.com/auth/userinfo.email

Additionally, I tried using the _token login method

jenkins@riskjenkins:/home/andre$ ACCESS_TOKEN=$(curl -H 'Metadata-Flavor: Google' 'http://metadata.google.internal./computeMetadata/v1/instance/service-accounts/default/token' | cut -d'"' -f 4)
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   142  100   142    0     0  14686      0 --:--:-- --:--:-- --:--:-- 15777
jenkins@riskjenkins:/home/andre$ echo $ACCESS_TOKEN
**************(redacted, but looks valid)
jenkins@riskjenkins:/home/andre$ docker login -e [email protected] -u _token -p $ACCESS_TOKEN http://gcr.io
Login Succeeded
jenkins@riskjenkins:/home/andre$ docker run gcr.io/prj_name/image_name
Unable to find image 'gcr.io/prj_name/image_name:latest' locally
Pulling repository gcr.io/prj_name/image_name
FATA[0000] HTTP code: 403

Solution

  • The Google Container Registry authentication scheme is to simply use:

    username: '_token'
    password: {oauth access token}
    

    On Google Compute Engine you can login without gcloud with:

    $ METADATA=http://metadata.google.internal./computeMetadata/v1
    $ SVC_ACCT=$METADATA/instance/service-accounts/default
    $ ACCESS_TOKEN=$(curl -H 'Metadata-Flavor: Google' $SVC_ACCT/token \
        | cut -d'"' -f 4)
    $ docker login -e [email protected] -u '_token' -p $ACCESS_TOKEN https://gcr.io
    

    Update on {asia,eu,us,b}.gcr.io

    To access a repository hosted in a localized repository, you should login to the appropriate hostname in the above docker login command.

    Update on quotes around _token

    As of docker version 1.8, docker login requires the -u option to be in qoutes or start with a letter.

    Some diagnostic tips...

    Check that you have the Cloud Storage scope via:

    $ curl -H 'Metadata-Flavor: Google' $SVC_ACCT/scopes
    ...
    https://www.googleapis.com/auth/devstorage.full_control
    https://www.googleapis.com/auth/devstorage.read_write
    https://www.googleapis.com/auth/devstorage.read_only
    ...
    

    NOTE: "docker pull" requires "read_only", but "docker push" requires "read_write".

    To give this robot access to a bucket in another project, there are a few steps.

    First, find out the VM service account (aka robot)'s identity via:

    $ curl -H 'Metadata-Flavor: Google' $SVC_ACCT/email
    [email protected]
    

    Next, there are three important ACLs to update:

    1) Bucket ACL (needed to list objects, etc)

    PROJECT_ID=correct-answer-42
    [email protected]
    gsutil acl ch -u $ROBOT:R gs://artifacts.$PROJECT_ID.appspot.com
    

    2) Bucket Default ACL (template for future #3)

    gsutil defacl ch -u $ROBOT:R gs://artifacts.$PROJECT_ID.appspot.com
    

    3) Object ACLs (only needed when the bucket is non-empty)

    gsutil -m acl ch -R -u $ROBOT:R gs://artifacts.$PROJECT_ID.appspot.com
    

    Part of why this isn't in our official documentation yet is that we want a better high-level story for it, but tl;dr we respect GCS ACLs.