Aws-cli: aws ecr get-login should use --password-stdin if available

Created on 6 Oct 2017  ·  36Comments  ·  Source: aws/aws-cli

Currently, on Docker 17.07+, when evaling the output of aws ecr get-login, the following error message appears:

WARNING! Using --password via the CLI is insecure. Use --password-stdin.

It would be nice if aws ecr get-login could use --password-stdin if it's available. The workaround is to use get-authorization-token, but that involves everyone writing code, whereas --password-stdin is a good idea for everyone who'd ever use aws ecr get-login.

v2

Most helpful comment

This is more friendly for Windows (git bash) and related clients.

export _DOCKER_REPO="$(aws ecr get-authorization-token --output text  --query 'authorizationData[].proxyEndpoint')"
aws ecr get-login --no-include-email --region us-east-1 | awk '{print $6}' | docker login -u AWS --password-stdin $_DOCKER_REPO

Its also similar to @dsdenes but doesn't hardcode the repo

All 36 comments

So I realize getting the warning is not ideal, but the CLI is already using get-authorization-token under the hood. To use --password-stdin and preserve backwards compatibility by printing the command to run to stdout, the command would need to output:

echo <authorizaton-token> | docker login -u AWS  -e none https://123456789012.dkr.ecr.us-west-2.amazonaws.com --password-stdin

which defeats the purpose because the password is still getting printed out. Furthermore, the CLI would have to handle the proper redirection expressions based on the operating system it is being ran from. Is the main reason for this request to just ignore the warning?

When I referred to the get-authorization-token workaround, I meant a workaround where users essentially write an ecr get-login themselves, but one that pipes the output of get-authorization-token to docker login themselves -- I understand that ecr get-login is already using that functionality right now.

I imagine the warning is really about leaking the token in two places: process lists and shell history. I agree that echoing the bare token doesn't resolve either issue any more than passing it via -p is. Presumably there's no contract to what gets output other than "if you eval it with sh docker will be logged in to ECR", so presumably (assuming we can get that expression in a reasonable, cross-platform manner) an expression that itself uses ecr get-authorization-token instead of its output is fine. (I'd understand if e.g. it wouldn't be OK for the expression to do IO, but you have to log in to ECR so that part is moot). This would have the benefit of not leaking the token under any circumstances: not via process lists, and not via shell history.

echo $(aws ecr get-authorization-token --region eu-central-1 --output text --query 'authorizationData[].authorizationToken' | base64 -d | cut -d: -f2) | docker login -u AWS https://123456.dkr.ecr.eu-central-1.amazonaws.com --password-stdin

This is more friendly for Windows (git bash) and related clients.

export _DOCKER_REPO="$(aws ecr get-authorization-token --output text  --query 'authorizationData[].proxyEndpoint')"
aws ecr get-login --no-include-email --region us-east-1 | awk '{print $6}' | docker login -u AWS --password-stdin $_DOCKER_REPO

Its also similar to @dsdenes but doesn't hardcode the repo

@closedLoop Command works but make sure to include --region argument in the first line if not in us-east-1 or it will default to there.

Late to the party, but I was tired of seeing the login warning too 🙂

aws ecr get-login --no-include-email --region ${REGION} --profile ${PROFILE} | awk '{printf $6}' | docker login -u AWS ${REPOSITORY} --password-stdin

Docker seems to have made this a warning that now requires explicit input, meaning that aws-cli ecr get-login can no longer work in a script....

@rlees85 - did you try any of the suggestions above? get-login certainly _should_ work in scripts - I imagine that's the major use case for the command, anyhow.

[root@xps13 ~]# export AWS_PROFILE=<blah>
[root@xps13 ~]# systemctl start docker
[root@xps13 ~]# docker --version
Docker version 18.04.0-ce, build 3d479c0af6
[root@xps13 ~]# eval $(aws ecr get-login --region eu-west-1 --no-include-email)
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Are you sure you want to proceed? [y/N] 

Workaround: yes | eval $(aws ecr get-login --region eu-west-1 --no-include-email) but thats hacky

Actually I think this is unrelated to the issue/warning that this thread is about... my bad

For the record, this is less of an immediate issue because docker has reverted the prompt. See https://github.com/docker/cli/pull/1008.

It sounds like their long time plan is to re-introduce this prompt, so it still would probably be good for aws ecr get-login to switch to using --password-stdin.

Any idea about timeline for the fix of this issue?
When "aws ecr get-login" will output which uses --password-stdin instead of --password?

What if we introduce the --password-stdin flag at aws ecr get-login --password-stdin, that will solve the backward compatibility issue for older Docker folk. With this flag pass in, we'll generate the echo <auth> | docker login --passwrod-stdin ... version. Without it, we'll generate login normally with the -p option.

Generating an echo statement is not ideal, since it exposes the password in the process listing. The only way to do this securely is to just run docker login directly from the aws tool instead of relying on a user to copy & paste its output.

@wichert We would evaluate the command and run it instead of copy and paste it. For example:
$(aws ecr get-login --no-include-email --region us-east-1 --password-stdin)

I think that is the use case anyway, user want to generate that token and to be run at the same machine. I don't think this method is less secure than existing one?

The whole point of the change in docker login is to improve security by making sure the password is never exposed via the process list. If aws ecr get-login just invokes a shell with the password in the command line you are completely negating that improvement. What imho should happen is that aws ecr get-login just invokes docker login directly and passes the password via stdin. Anything that relies on evaluating the output of aws ecr will be insecure.

EDIT [2020/02/14]
Since #4874, piping the password into docker login --password-stdin is now possible!
Just use:

aws ecr get-login-password | docker login --username AWS --password-stdin https://<aws_account_id>.dkr.ecr.<region>.amazonaws.com

Presuming pipes are supported in the terminal, it seems to me there needn't be a need to use echo — just have a different aws ecr command/flag to only print the password, and pipe that to docker login --password-stdin:

# NOTE: --password-stdin IS HYPOTHETICAL! DO NOT EXPECT IT TO WORK

$ aws ecr get-login --no-include-email --region us-east-1 --password-stdin
aws ecr get-login --region us-east-1 --print-password-only | docker login -u AWS --password-stdin https://12345.dkr.ecr.us-east-1.amazonaws.com

$ aws ecr get-login --region us-east-1 --print-password-only
pCwnxiDQWSN1nx9uaphdzRK7dQHxZUSlzMKi4IViZOCvnAE9K1P0qJkH5UMISmbkJlrjut96yzPOb82Jpoc0BEvKeZUlXWtSX4JA

$ aws ecr get-login --region us-east-1 --print-password-only | docker login -u AWS --password-stdin https://12345.dkr.ecr.us-east-1.amazonaws.com
Login Succeeded

$ $(aws ecr get-login --no-include-email --region us-east-1 --password-stdin)
Login Succeeded

Presuming pipes are supported in the terminal, it seems to me there needn't be a need to use echo — just have a different aws ecr command/flag to only print the password, and pipe that to docker login --password-stdin:

$ aws ecr get-login --no-include-email --region us-east-1 --password-stdin
aws ecr get-login --region us-east-1 --print-password-only | docker login -u AWS --password-stdin https://12345.dkr.ecr.us-east-1.amazonaws.com

$ aws ecr get-login --region us-east-1 --print-password-only
pCwnxiDQWSN1nx9uaphdzRK7dQHxZUSlzMKi4IViZOCvnAE9K1P0qJkH5UMISmbkJlrjut96yzPOb82Jpoc0BEvKeZUlXWtSX4JA

$ aws ecr get-login --region us-east-1 --print-password-only | docker login -u AWS --password-stdin https://12345.dkr.ecr.us-east-1.amazonaws.com
Login Succeeded

$ $(aws ecr get-login --no-include-email --region us-east-1 --password-stdin)
Login Succeeded

I have been trying your fix but I am not sure I am proceeding correctly...?
I do aws ecr get-login --no-include-email --region eu-west-1 --password-stdin
and it returns Unknown options: --password-stdin
--print-password-only is unknows as well.

Have I missed steps before? Thanks!

this should be fine

pwd="$(aws ecr get-login --no-include-email --region us-east-1 | awk '{print $6}')"
docker login -u AWS --password "$pwd"

Using $pwd on the command-line would defeat the purpose, as the password would then be available for reading in /proc/N/cmdline. By passing it through a pipe, only the program emitting it (aws and awk) and the program reading it (docker) can see the password:

# one-liner
aws ecr get-login --no-include-email --region us-east-1 | awk '{print $6}' | docker login -u AWS --password-stdin $(aws ecr get-login --no-include-email --region us-east-1 | awk '{print $7}')

# long-form
cmd="aws ecr get-login --no-include-email --region us-east-1"
url=$($cmd | awk '{ print $7 }')
$cmd | awk '{ print $6 }' | docker login -u AWS --password-stdin $url

By the way, there is no flag in latest aws cli installed via pip

--print-password-only

This is completely broken by the way. How is this still not fixed?

To be clear, --print-password-only was just a suggestion; it's not a feature offered or supported by aws-cli, at time of writing.

Okay so I've had this problem. The CD tool we are using logged the warning as an error so no choice but to avoid it.

Here is what I have used with Powershell to push to AWS ECR:

First step to create the file

aws ecr get-login --no-include-email --region $region | Out-File -FilePath $FILEPATH

Second step to filter the file and just get the password.

-split @(Get-Content -Path $FILEPATH) | Select-Object -Index 5 | Out-File -FilePath $FILEPATH
cat $FILEPATH | docker login -u AWS --password-stdin ECR-URL

Hopefully this works. You will need the credentials (on aws configure) as well. It is however a very long process (I literally crashed through PS with this so there might be faster ways).

Would be nice to get rid of this warning. Sure there are work arounds but they are larger than my entire build script so it adds a lot of clutter.

If all you want to do is get rid of the warning, just do this:
$(aws ecr get-login --no-include-email --region us-east-1) 2>/dev/null

Lots of misunderstanding here.

Point 1: (https://github.com/aws/aws-cli/issues/2875#issuecomment-415668165)

If you are worried about seeing the warning,

it's because you should be worried about what aws-cli is doing

Putting passwords into shell commands is BAD, BAD, BAD, BAD, BAD. By invoking aws ecr get-login,

You have just now LEAKED the password in plaintext to every single user on the system.

(Unless you are are using exotic configurations like mounting /proc with hidepid)

Developers suggesting hiding stderr or suggesting passing it as shell args to other commands like echo are sticking their collective head in the sand, caring more for untroubled logs than for security. See Passing Passwords.


Point 2: It's currently possible to pass the password from AWS CLI to docker in a secure way (https://github.com/aws/aws-cli/issues/2875#issuecomment-342821099) though it's ugly and requires other tools (cut, awk).

I'm in no position to be casting stones, but it's surprising AWS has left this security issue unaddressed for almost two years.

Does this official helper address the concerns voiced in this issue?

https://github.com/awslabs/amazon-ecr-credential-helper

I was unaware of that. It is indeed a suitable method. It uses docker's credStore/credHelpers interface.

Docker invokes the docker-credential-ecr-login executable and the executable produces on stdout

{
    "Username": "george",
    "Secret": "passw0rd"
}

In fact, it would be convenient if the AWS CLI itself offered this interface, so there wasn't separate install. amazon-ecr-credential-helper has several install methods, but none of them are the pip install used by AWS CLI :/

If you take a look at the README, it even mentions (as it is with other helpers) that Docker will automatically pick up any credentials required for ECR repositories without having to store or pass any usernames or passwords in the future.

I’d call that a win-win :)

@pauldraper I reckon if it’s easy enough to install it doesn’t matter to most users (which, in this case, at least for me, it is!)

Indeed using credHelpers is the best way.

Apparently amazon-ecr-credential-helper only has Ubuntu packages for non-LTS Ubuntu versions :/

So I did the same thing with a four-line script.

/usr/local/bin/docker-credential-ecr-login

#!/bin/sh
grep -q 'dkr.ecr.[^.]\+.amazonaws.com' - || exit
aws --output text ecr get-authorization-token --query authorizationData[0].authorizationToken \
  | base64 --decode \
  | sed -e 's/:/", "Secret":"/' -e 's/^/{"Username":"/' -e 's/$/"}/'

~/.docker/config

{"credsStore": "ecr-login"}

Now docker pull and docker push without an extra steps.

https://gist.github.com/pauldraper/b74a24f869b0acbc3bd488d67f9a53b4

Yesterday's release (v1.17.10) included a new command aws ecr get-login-password which performs the needed conversion to format the password for docker. For a more detailed write-up see: https://github.com/aws/containers-roadmap/issues/735.

We also removed ecr get-login in favor of ecr get-login-password in v2 as well. We recommend using the ecr get-login-password going forward. Closing issue.

The following works for me:

aws --region ${aws_region} ecr get-login-password \
    | docker login \
        --password-stdin \
        --username AWS \
        "${aws_account_id}.dkr.ecr.${aws_region}.amazonaws.com"

Ref.: https://github.com/aws/aws-cli/issues/4962#issuecomment-586486939, credit to @matthew-russo!

Or an even more automatic version where your account id is already detected using credentials (Replace us-east-1 with relevant region):

$ aws ecr get-login-password --region us-east-1 \
    | docker login \
        --password-stdin \
        --username AWS \
        "$(aws sts get-caller-identity --query Account --output text).dkr.ecr.us-east-1.amazonaws.com"

None of the above solutions are working for me, so far I've tried various iterations of the aws ecr get-login-password in a Docker image.

For ex:

 aws ecr get-login-password --region us-west-2 | docker login --password-stdin --username AWS "$(aws sts get-caller-identity --query Account --output text).dkr.ecr.us-west-2.amazonaws.com"

Results in:

Unable to locate credentials. You can configure credentials by running "aws configure".
Error: Cannot perform an interactive login from a non TTY device

Vast majority of the time I'm encountering this error: no basic auth credentials but I'm only facing this error once I'm at the last step trying to push the image:

- eval $(aws ecr get-login-password --region us-west-2 | docker login --password-stdin --username AWS "$(aws sts get-caller-identity --query Account --output text).dkr.ecr.us-west-2.amazonaws.com")
- docker build -t $IMAGE_NAME .
- docker tag <ecr_repo>:<tag> <image_uri>
- docker push <image_uri>
Was this page helpful?
0 / 5 - 0 ratings