title: docker push to gcr.io fails with "denied: Token exchange failed for project"
body: <p>I've discovered a flow that works through GCP console but not through the <code>gcloud</code> CLI.</p>
  
  <h2>Minimal Repro</h2>
  
  <p>The following bash snippet creates a fresh GCP project and attempts to push an image to gcr.io, but fails with "access denied" even though the user is project owner:</p>
  
  <pre><code>gcloud auth login
  
  PROJECT_ID="example-project-20181120"
  gcloud projects create "$PROJECT_ID" --set-as-default
  gcloud services enable containerregistry.googleapis.com
  gcloud auth configure-docker --quiet
  
  mkdir ~/docker-source &amp;&amp; cd ~/docker-source
  git clone https://github.com/mtlynch/docker-flask-upload-demo.git .
  
  LOCAL_IMAGE_NAME="flask-demo-app"
  GCR_IMAGE_PATH="gcr.io/${PROJECT_ID}/flask-demo-app"
  docker build --tag "$LOCAL_IMAGE_NAME" .
  docker tag "$LOCAL_IMAGE_NAME" "$GCR_IMAGE_PATH"
  docker push "$GCR_IMAGE_PATH"
  </code></pre>
  
  <p><strong>Result</strong></p>
  
  <pre><code>The push refers to repository [gcr.io/example-project-20181120/flask-demo-app]
  02205dbcdc63: Preparing
  06ade19a43a0: Preparing
  38d9ac54a7b9: Preparing
  f83363c693c0: Preparing
  b0d071df1063: Preparing
  90d1009ce6fe: Waiting
  denied: Token exchange failed for project 'example-project-20181120'. Access denied.
  </code></pre>
  
  <p>The system is Ubuntu 16.04 with the latest version of gcloud <a href="https://gist.github.com/mtlynch/40ebf89e39890b71d738ee4fcf1c3a17#file-gistfile1-txt" rel="nofollow noreferrer">225.0.0, as of this writing</a>. The account I auth'ed with <a href="https://gist.github.com/mtlynch/40ebf89e39890b71d738ee4fcf1c3a17#file-gistfile2-txt" rel="nofollow noreferrer">has role <code>roles/owner</code></a>.</p>
  
  <h1>Inconsistency with GCP Console</h1>
  
  <p>I notice that if I follow the same flow through GCP Console, I can <code>docker push</code> successfully:</p>
  
  <ol>
  <li>Create a new GCP project via GCP Console</li>
  <li>Create a service account with <code>roles/owner</code> via GCP Console</li>
  <li>Download JSON key for service account</li>
  <li>Enable container registry API via GCP Console</li>
  <li><code>gcloud auth activate-service-account --key-file key.json</code></li>
  <li><code>gcloud config set project $PROJECT_ID</code></li>
  <li><code>gcloud auth configure-docker --quiet</code></li>
  <li><code>docker tag "$LOCAL_IMAGE_NAME" "$GCR_IMAGE_PATH" &amp;&amp; docker push "$GCR_IMAGE_PATH"</code></li>
  </ol>
  
  <p><strong>Result</strong>: Works as expected. Successfully pushes docker image to gcr.io.</p>
  
  <h1>Other attempts</h1>
  
  <p>I also tried using <code>gcloud auth login</code> as my @gmail.com account, then using that account to create a service account with gcloud, but that gets the same <code>denied</code> error:</p>
  
  <pre><code>SERVICE_ACCOUNT_NAME=test-service-account
  gcloud iam service-accounts create "$SERVICE_ACCOUNT_NAME"
  KEY_FILE="${HOME}/key.json"
  gcloud iam service-accounts keys create "$KEY_FILE" \
    --iam-account "${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com"
  gcloud projects add-iam-policy-binding "$PROJECT_ID" \
    --member "serviceAccount:${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \
    --role roles/owner
  gcloud auth activate-service-account --key-file="${HOME}/key.json"
  
  docker push "$GCR_IMAGE_PATH"
  </code></pre>
  
  <p><strong>Result</strong>: <code>denied: Token exchange failed for project 'example-project-20181120'. Access denied.</code></p>