feat(registry): authenticate to private ECR with the AWS credential chain - #40
Merged
Conversation
…hain Destination registries were authenticated only through docker credential config, so ECR required a docker login that had already been performed in the runtime environment. The GitHub Action cannot satisfy that: it runs as a Docker container action, which does not receive the runner's ~/.docker/config.json, so credentials written by aws-actions/amazon-ecr-login on the host were invisible to it and every request failed with 401 Unauthorized. ECRKeychain recognises private ECR hosts by their registry host, reads the account and region from it, and calls ecr:GetAuthorizationToken through the standard AWS credential chain. Tokens are cached per account and region and refetched inside a five minute window before expiry, so a continuously running sync no longer needs an external refresh loop. An existing docker credential entry for the same registry still wins, which keeps explicit logins working. Public ECR is a separate service with a separate token API and is not covered. The Helm chart gains serviceAccount.annotations so a deployment can attach an IRSA role and drop dockerConfigSecret for ECR entirely.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Destination registries were authenticated only through docker credential config (
authn.DefaultKeychain), so an ECR destination required adocker loginperformed in the runtime environment.The GitHub Action cannot satisfy that. It runs as a Docker container action, and a container action does not receive the runner's
~/.docker/config.json; the runner mounts/github/homeasHOMEinstead. Credentials written byaws-actions/amazon-ecr-loginon the host are therefore invisible to the container, and every request fails:Reproduced on a live workflow before this change, and confirmed fixed there by routing the login through
DOCKER_CONFIGin the workspace.Change
ECRKeychainrecognises private ECR hosts by the registry host itself (<account>.dkr.ecr.<region>.amazonaws.com, including-fips, GovCloud, and the China partition), reads the account and region from it, and callsecr:GetAuthorizationTokenthrough the standard AWS credential chain: environment variables, shared config, IRSA, instance role.GenericRegistry) and the copy (crane.Copy), and it activates on the host, not ondestinations[].type, so a mistypedtypecannot silently disable it.public.ecr.aws) is a different service with a different token API and is not covered; documented as still needing adocker login.The Helm chart gains
serviceAccount.annotations, so a deployment can attach an IRSA role and dropdockerConfigSecretfor ECR entirely.Docs cover both halves of the original failure: ECR needs only
aws-actions/configure-aws-credentials, and GHCR/ACR/GCR logins needDOCKER_CONFIGpointed at the workspace so the container action can read them.Tests
internal/registry/ecr_test.go: host parsing (including hosts that merely embed an ECR host), delegation for non-ECR hosts, AWS token used when docker config is empty, docker config preferred when present, fallback when docker config errors, caching per account and region, refetch inside the expiry window, error message naming the registry and cause,user:passworddecoding with colons in the password.verify-syncerd(full tier) passes: static/build, helm, live Docker Hub to local registry sync with state skip, Slack failure notification, docker build.