How does logging into AWS ECR with podman work?

27 Nov 2024 09:44 aws ecr podman

If you want to use Amazon Elastic Container Registry (ECR) with podman, you’ll do something like this: aws ecr get-login-password ... | podman login .... How does that work?

aws ecr get-login-password

If you run aws ecr get-login-password, it will spit out a big chunk of base64-encoded JSON. You can recognise this because it starts with eyJ.

If we pipe that output to | base64 -d | jq, we get something like this:

{
  "payload": "qe...hw=",
  "datakey": "AQ..k=",
  "version": "2",
  "type": "DATA_KEY",
  "expiration": 1732743887
}

The payload and datakey values are opaque data. You can see this for the payload value:

% aws ecr get-login-password | base64 -d | jq -r '.payload' | base64 -d | file -
/dev/stdin: data

Interestingly, if you do the same for datakey, file (on macOS, at least) reports “Windows Precompiled iNF”. I suspect that it’s mistaken.

The expiration value is Unix epoch, in seconds. It’s 12 hours from when I ran the command. You can see the expiry by running the date command, as follows:

% date -d @1732743887
Wed Nov 27 21:44:47 GMT 2024

podman login

The actual content of the “login password” (it’s actually a token) is kinda irrelevant. It’s just something that we give to podman login (or docker login, but that’s a subject for another post) for later.

We pipe the output from aws ecr get-login-password to podman login, as follows:

aws ecr get-login-password --region eu-west-1 | podman login --username AWS --password-stdin "$ECR_REGISTRY"

The important part is the --password-stdin which tells podman login to read the password from stdin.

This is a security feature: We don’t want to pass it on the command line: sh # DON'T DO THIS! podman login --username AWS --password $(aws ecr get-login-password) If we did that, the password would be visible in the process list (in ps or /proc/PID/cmdline). Other users might be able to see it. So the convention is to pass it via stdin.

The registry is specified as $AWS_ACCOUNT.dkr.ecr.$AWS_REGION.amazonaws.com

podman login remembers the username (“AWS”) and password (the token) for later use of the given registry, when running podman push commands, for example.

By default, it stores the username and password in the ~/.config/containers/auth.json file, which looks like this (I’ve ellided the AWS registry name):

{
  "auths": {
    "[...].amazonaws.com": {
      "auth": "QV...0="
    }
  }
}

If we take that value (which is base64-encoded), we get back to our username/password pair from earlier:

% cat ~/.config/containers/auth.json | jq -r '.auths[].auth' | base64 -d
AWS:eyJ...
% cat ~/.config/containers/auth.json | jq -r '.auths[].auth' | base64 -d | cut -d: -f2 | base64 -d | jq
{
  "payload": "qe...
...etc.

Conclusion

All of which is to say: podman login is persisted to a file, and you can put it in a separate CI step.