GoogleCloudPlatform / docker-credential-gcr

A Docker credential helper for GCR users
https://gcr.io
Apache License 2.0
289 stars 92 forks source link

Does this support Identity Federation from external accounts? #95

Closed Dermah closed 2 years ago

Dermah commented 3 years ago

Weird use case, but I'm trying to use docker-credential-gcr to authenticate docker client requests to us-docker.pkg.dev from an AWS instance that can generate Google credentials using Identity Federation.

From that documentation, I've used the command given (with the relevant variables replaced for my account):

gcloud iam workload-identity-pools create-cred-config \
    projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
    --service-account=SERVICE_ACCOUNT_EMAIL \
    --output-file=FILEPATH \
    --aws

This generates a JSON file that I thought could be used as the GOOGLE_APPLICATION_CREDENTIALS key:

{
  "type": "external_account",
  "audience": "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID",
  "subject_token_type": "urn:ietf:params:aws:token-type:aws4_request",
  "token_url": "https://sts.googleapis.com/v1/token",
  "credential_source": {
    "environment_id": "aws1",
    "region_url": "http://169.254.169.254/latest/meta-data/placement/availability-zone",
    "url": "http://169.254.169.254/latest/meta-data/iam/security-credentials",
    "regional_cred_verification_url": "https://sts.{region}.amazonaws.com?Action=GetCallerIdentity&Version=2011-06-15"
  },
  "service_account_impersonation_url": "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT_EMAIL:generateAccessToken"
}

When I set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the location of this key file and try to pull an image I get this error

$ docker pull us-docker.pkg.dev/PROJECT_NAME/REPOSITORY_NAME/IMAGE_NAME
Using default tag: latest
Error response from daemon: Get https://us-docker.pkg.dev/v2/PROJECT_NAME/REPOSITORY_NAME/IMAGE_NAME/manifests/latest: denied: Permission "artifactregistry.repositories.downloadArtifacts" denied on resource "projects/PROJECT_NAME/locations/us/repositories/REPOSITORY_NAME" (or it may not exist)

I'm assuming this is because docker-credential-gcr doesn't support "type": "external_account" JSON file keys:

$ echo us-docker.pkg.dev | docker-credential-gcr get
docker-credential-gcr/helper: could not retrieve GCR's access token: google: error getting credentials using GOOGLE_APPLICATION_CREDENTIALS environment variable: unknown credential type: "external_account"

Note I have been able to pull the above image on this AWS instance when I gave the helper a "type": "service_account" JSON file key for a service account downloaded from the console.

docker-credential-gcr seems to use golang.org/x/oauth2 version v0.0.0-20210817223510-7df4dd6e12ab, which is a high enough version to support identity federation to get the credentials. Am I doing something else wrong?

jonjohnsonjr commented 3 years ago

docker-credential-gcr seems to use golang.org/x/oauth2 version v0.0.0-20210817223510-7df4dd6e12ab, which is a high enough version to support identity federation to get the credentials.

Where do you see this? As far as I can tell, we're on a pretty old version of oauth2. I think we just need to update that.

Dermah commented 3 years ago

Ah yep my mistake. I don't do much go, so I misintepreted go's output when installing the binary:

$ go get -u github.com/GoogleCloudPlatform/docker-credential-gcr
go: downloading golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
...

You're right, the oauth2 library bundled here is older and doesn't support external_account https://github.com/GoogleCloudPlatform/docker-credential-gcr/blob/7307e104ebc758a766a5f954aef3c9050ac3f336/vendor/golang.org/x/oauth2/google/google.go#L92-L96

but the latest oauth2 library does

jonjohnsonjr commented 2 years ago

@Dermah I believe while moving over to go modules, we pulled in a new enough version of oauth2 for this to work now. Can you try the 2.1.0 release?

Dermah commented 2 years ago

I no longer have access to the environment where I was testing this, but it looks like the go modules would have enabled my use case. Thank you for this!