I try to log into my AWS ECR repository. This is my powershell script:
param(
[string]$profile,
[string]$ecr_name
)
$accountId = (aws sts get-caller-identity --query "Account" --output text --profile $profile)
$region = (aws configure get region --profile $profile)
$TAG = "latest"
$AccountUrl = "${accountId}.dkr.ecr.${region}.amazonaws.com"
Write-Host "LoginAttempt 1"
docker login --username AWS --password $(aws ecr get-login-password --region $region --profile $profile) $AccountUrl
Write-Host "LoginAttempt 2"
aws ecr get-login-password --region $region --profile $profile | docker login --username AWS --password-stdin $AccountUrl
Write-Host "LoginAttempt 3"
docker login --username AWS --password $(aws ecr get-login-password --region $region --profile $profile) $AccountUrl
When copy-pasting the code into a powershell termin, everything works. When running the code directly using this command:
powershell.exe -File file_location.ps1 --ecr_name yyy --profile xxx
I get this strange behavior:
LoginAttempt 1
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
LoginAttempt 2
Error response from daemon: login attempt to https://1234567890.dkr.ecr.eu-west-1.amazonaws.com/v2/ failed with status: 400 Bad Request
LoginAttempt 3
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
I am working on a Windows machine, the script is stored in utf8 with LF. For obvious security reasons i would prefer to pass the password using stdin.
Note:
The explanation below implies that pasting your code into an interactive session should equally fail in PowerShell (Core) 7.3- / Windows PowerShell, whereas you report it as working in your interactive sessions.
The only explanation I can think of is that perhaps you pasted into an interactive PowerShell 7.4+ session (where the problem doesn't arise), whereas your script-based attempt calls the Windows PowerShell CLI, powershell.exe
.
Your own attempt to provide the password to docker login
via stdin (--password-stdin
):
# OK in PowerShell (Core) 7.4+
aws ecr get-login-password --region $region --profile $profile |
docker login --username AWS --password-stdin $AccountUrl
should work as-is in PowerShell (Core) v7.4+, where data being piped between external (native) programs is now passed as-is, i.e. as raw byte data.
In v7.3.x-, as well as in Windows PowerShell, a workaround is required, because in these versions:
not only is the aws
output decoded into .NET strings and re-encoded based on the encoding stored in the $OutputEncoding
preference variable on piping to docker
crucially, a newline is invariably added to the original text if it doesn't end in one - this is what causes the login to fail.
The simplest workaround is to shell out to cmd /c
, because cmd.exe
's pipeline is and always has been a raw byte conduit, so the problem doesn't arise there:
# Workaround for PowerShell 7.3.x- and Windows PowerShell
cmd /c "aws ecr get-login-password --region $region --profile $profile | docker login --username AWS --password-stdin `"$AccountUrl`""
Note:
$region
and $profile
expand to values that don't require double-quoting in cmd.exe
; if so, use embedded double-quoting as I've done for $AccountUrl
above (scrolled out of view, because - unlike in PowerShell - only single-line commands are supported with cmd /c
).For additional background information, see this answer.