How to Push to Account Using ASSUME_ROLE in AWS ECR - amazon-web-services

What am I missing? Regardless of what syntax I try, pushing to AWS ECR always lands in the main / management AWS account. In the AWS console I can switch into that account with the appropriate role. Using Terraform I can set the assume_role.role_arn property to create resources in the correct account. However, no config or syntax for Docker and the AWS CLI seems to work. I'm clearly missing a step, property, or global option.
If I go the Terraform route, I can do anything I need. So, I know it should work ...
provider "aws" {
region = "us-gov-west-1"
shared_credentials_file = "~/.aws/credentials"
profile = "govcloud"
assume_role {
role_arn = "arn:aws-us-gov:iam::123456789012:role/Build_Administrator"
}
}
However, I would rather NOT use Terraform for such a simple task as pushing to ECR.
I've tried using the role_arn property in the ~/.aws/config and that doesn't work...
[govcloud]
region = us-gov-west-1
output = json
[govcloud-assume]
region = us-gov-west-1
output = json
role_arn=arn:aws-us-gov:iam::123456789012:role/Build_Administrator
In any other scenario, calling get-login-password / create-repository will leverage the current configured keys and will manipulate the configured account...
aws ecr get-login-password | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-gov-west-1.amazonaws.com
aws ecr create-repository --repository-name "complexapi" --image-tag-mutability MUTABLE
It feels as if there should be some type of global option to set the target account or role_arn, however no combination works...
aws ecr get-login-password --profile govcloud-assume --region us-gov-west-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-gov-west-1.amazonaws.com
aws ecr create-repository --profile govcloud-assume --region us-gov-west-1 --repository-name "complexapi" --image-tag-mutability MUTABLE
Update 1:
Feels like I'm getting closer. After setting the access key I can successfully call aws sts assume-role and return a Credentials object. Just don't know what to do with it yet.
Update 2:
STS was a waste of time and sent me down the wrong path. Don't go there. It's not needed and will pollute your local auth environment for the AWS CLI.

To assume a role using the AWS CLI with ECR, you must use the --profile property within your scripts and structure the ~/.aws/config with two properties together: role_arn and source_profile
The ~/.aws/config requires both the main account and the sub-account you wish to work with. This sub-account contains the role you wish to assume with the ARN is maintained in its role_arn property. The profile of the sub-account is what you will reference in your scripts however the config must also point back to the source_profile which will maintain the actual credentials:
[default]
region = us-gov-west-1
output = json
[profile gov-mgmt]
region = us-west-1
output = json
[profile gov-staging]
role_arn = arn:aws-us-gov:iam::123456789123:role/BuildBoxRole
source_profile = gov-mgmt
region = us-gov-west-1
Your ~/.aws/credentials file then contains the keys for the main account:
[gov-mgmt]
aws_access_key_id = ABCDEFGHIJKLMNOPQRST
aws_secret_access_key = abcdefghijklmnopqrstuvwxyz1234567890ab12
Once in place, your commands will reference the profile containing the role you wish to assume (the target account) and, where needed, you use that account ID. In the example of the get-login-password command, the AWC CLI is passed the --profile property using the name of the sub-account. Docker will receive the resulting password from the AWS CLI and directly reference the sub-account by number.
For example, here are the commands to create the AWS ECR repository in the sub-account (note both the sub-account ID is used as well as the name of that account's profile):
aws ecr get-login-password --profile gov-staging | docker login \
--username AWS \
--password-stdin 123456789123.dkr.ecr.us-gov-west-1.amazonaws.com
aws ecr create-repository \
--profile gov-staging \
--repository-name "complexapi" \
--image-tag-mutability MUTABLE
... and the commands needed to push an image into the sub-account's registry with both the latest tag and a proper version number:
docker tag fredlackey/complexapi:0.0.0 \
123456789012.dkr.ecr.us-gov-west-1.amazonaws.com/complexapi:0.0.0
docker tag fredlackey/complexapi:0.0.0 \
123456789012.dkr.ecr.us-gov-west-1.amazonaws.com/complexapi:latest
aws ecr get-login-password \
--profile gov-staging | docker login \
--username AWS \
--password-stdin 123456789012.dkr.ecr.us-gov-west-1.amazonaws.com
docker push 123456789012.dkr.ecr.us-gov-west-1.amazonaws.com/complexapi:0.0.0
docker push 123456789012.dkr.ecr.us-gov-west-1.amazonaws.com/complexapi:latest

Related

Getting access denied error while pulling image from AWS ECR

I have two AWS profiles associated with different accounts configured on my machine as shown below.
[profile staging]
sso_start_url = https://xxxxxxxxxx.awsapps.com/start
sso_region = us-west-2
sso_account_id = xxxxxxxxxxxxx
sso_role_name = staging
region = us-west-2
output = json
[profile dev]
region = us-east-1
output = json
I am looking to pull a docker image from ECR which is present in account (A) corresponding to the staging profile
However, when I am trying to pull the image it is trying with my dev profile which doesn't have access to the repo in account (A)
Following are the commands
aws ecr get-login-password --region eu-west-2 | docker login --username AWS --password-stdin xxxxxxxxxxxx.dkr.ecr.eu-west-2.amazonaws.com
Login Succeeded
docker pull xxxxxxxxxxxx.dkr.ecr.eu-west-2.amazonaws.com/sample-image:latest
Getting access denied error for "arn:aws:iam::XXXXXXXXXXXXX:user\iam-user" which is associated to my dev profile
Please suggest what could be the issue.
As mentioned by jordanm in the comments above, answer is to use --profile option while using the command as shown below
aws ecr get-login-password --region eu-west-2 --profile=staging | docker login --username AWS --password-stdin xxxxxxxxxxxx.dkr.ecr.eu-west-2.amazonaws.com

How to source AWS credentials profile from .aws/credentials for aws cli

I have the following programmatic access credentials for AWS in my .aws/credentials file.
how to specify which credentials to use for AWS cli commands? and verify which credentials are being used?
To verify:
AWS_PROFILE=amplify aws sts get-caller-identity
# OR
aws sts get-caller-identity --profile amplify
The same to run commands:
AWS_PROFILE=default aws eks --region .......
# OR
aws eks --region ....... --profile default

I cant push Docker image to AWS ecr

I'm trying to push a Docker image from Dockerfile built to AWS ECR but when run this command:
$ aws ecr get-login-password --region eu-west-1 | docker login --username AWS --password-stdin 477629773586.dkr.ecr.eu-west-1.amazonaws.com
appears the error:
An error occurred (AccessDeniedException) when calling the
GetAuthorizationToken operation: User:
arn:aws:iam::477629773586:user/albertosanmartin is not authorized to
perform: ecr:GetAuthorizationToken on resource: * Error: Cannot
perform an interactive login from a non TTY device
I have installed and configured those files:
~/.aws/configure:
[default]
...
[mrthink]
region = eu-west-1
output = json
~/.aws/credentials
[default]
...
[mrthink]
aws_access_key_id = ****
aws_secret_access_key = ****
Seems to the command api get other user "albertosanmartin"
Anybody could help me please ?
Thanks in advance.
If you have your credentials configured under mrthink profile name in ~/.aws/credentials you need to pass the --profile param to the aws cli
$ aws --profile mrthink ecr get-login-password \
--region eu-west-1 |\
docker login --username AWS \
--password-stdin 477629773586.dkr.ecr.eu-west-1.amazonaws.com
The user arn:aws:iam::477629773586:user/albertosanmartin doesnt have access to ECR
You can double-check your credentials via sts get-caller-identity call if they are which you want to use.

How to iterate through multiple AWS accounts?

Consider an AWS organization with 50+ accounts. Each account has a role created that allows read-only access to the EC2 service - named "EC2ReadAccess" - and a trust relationship with the master(/management) account. A single IAM user in the master account has a policy applied to allow it to assume the role in every single account.
I would like to be able to iterate through all the accounts in order to retrieve all the EC2 instances, using the unique IAM user. I know that running a CLI command against all the accounts at once is out of the question. Leaving aside cycling through the regions in each account, which has been discussed extensively, is there an elegant solution for doing this?
One hack that comes to mind is to programmatically build the credentials file so that it contains a profile for each account. Each profile, in turn, will be "linked" to the profile of the IAM user (as described here), and have the account id within the role updated for each entry. An example below:
[user1]
aws_access_key_id=<key_id>
aws_secret_access_key=<secret_key>
[marketing]
role_arn = arn:aws:iam::123456789012:role/EC2ReadAccess
source_profile = user1
[dev]
role_arn = arn:aws:iam::234567890123:role/EC2ReadAccess
source_profile = user1
...
[prod]
role_arn = arn:aws:iam::345678901234:role/EC2ReadAccess
source_profile = user1
Running the CLI command - in this case aws ec2 describe-instances - can be accompanied by the --profile parameter in order to cycle through all the profiles present in the credentials file. The region can be cycled through within another loop. So a list of commands to be issued, generated programmatically beforehand, could look something like:
aws ec2 describe-instances --profile marketing --region us-east-1
aws ec2 describe-instances --profile marketing --region us-east-2
...
aws ec2 describe-instances --profile marketing --region sa-east-1
aws ec2 describe-instances --profile dev --region us-east-1
aws ec2 describe-instances --profile dev --region us-east-2
...
aws ec2 describe-instances --profile dev --region sa-east-1
...
aws ec2 describe-instances --profile prod --region us-east-1
aws ec2 describe-instances --profile prod --region us-east-2
...
aws ec2 describe-instances --profile prod --region sa-east-1
Is there a better way of doing this? Am I missing something obvious here?
Don't use the CLI to do this. If you're able to "programmatically build the credentials file", then you should be able to write a program that does the following for every child account:
Assumes the administrator role for that account.
Invokes the DescribeInstances API call.
Do whatever you want with the information
You don't indicate what programming language(s) you're familiar with, but here's some Python that I use to create an SDK client with the standard "OrganizationalAccountAccessRole" in a child account:
def create_boto_resource(account, region, resource_type):
creds = assumeRole(account)
return boto3.resource(resource_type,
region_name=region,
aws_access_key_id=creds['AccessKeyId'],
aws_secret_access_key=creds['SecretAccessKey'],
aws_session_token=creds['SessionToken'])
def assumeRole(account, role_name='OrganizationAccountAccessRole', duration=900):
stsClient = boto3.client('sts')
request = {}
request['RoleArn'] = f"arn:aws:iam::{account}:role/{role_name}"
request['RoleSessionName'] = 'DESCRIPTIVE_TEXT_HERE'
request['DurationSeconds'] = duration
return stsClient.assume_role(**request)['Credentials']
This code actually creates a Boto resource object, which is a simplified API that's supported for EC2 and a few other services. Here's and example of using the resource API to create an instance iterator.
Another way to attack this kind of problem might be via Systems Manager Inventory and Querying inventory data from multiple Regions and accounts.

AWS ECR Repository - How to copy images from one account and push to another account

I have two accounts - Account A and Account B. In account A, I have a policy with a user from account B can interact with Account A. I have a repository in both accounts. Account B doesn't have a policy set ( Not sure if I need a policy for Account A to interact with it).
My question is how do I push ecr images from Account A into Account B. I would like a copy of Account A image into Account B. Is this possible.
This is not a currently supported feature of ECR so you would need to perform the following steps to migrate from one account to another:
aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <aws_account_id>.dkr.ecr.<region>.amazonaws.com - Run this for the source account
docker pull $SOURCE_IMAGE:$VERSION - Pull the latest tag down to your local
docker tag $SOURCE_IMAGE:$VERSION $TARGET_IMAGE:$VERSION - Tag a new image based on the original source image
aws ecr get-login-password --region <region> | docker login --username AWS --password-stdin <aws_account_id>.dkr.ecr.<region>.amazonaws.com - Run this for the target account
docker push $TARGET_IMAGE:$VERSION - Push the docker image upto the target ECR account.
If you want to move all repositry from particularly region to another account (Destination account) then use below script.
It will list all repo from Account A
Pull an image from an account A one by one
Create Repo in Account B
Tag image
push image to account B
#!/bin/bash
TARGET_ACCOUNT_REGION="us-west-2"
DESTINATION_ACCOUNT_REGION="us-west-2"
DESTINATION_ACCOUNT_BASE_PATH="123456.dkr.ecr.$DESTINATION_ACCOUNT_REGION.amazonaws.com/"
REPO_LIST=($(aws ecr describe-repositories --query 'repositories[].repositoryUri' --output text --region $TARGET_ACCOUNT_REGION))
REPO_NAME=($(aws ecr describe-repositories --query 'repositories[].repositoryName' --output text --region $TARGET_ACCOUNT_REGION))
for repo_url in ${!REPO_LIST[#]}; do
echo "star pulling image ${REPO_LIST[$repo_url]} from Target account"
docker pull ${REPO_LIST[$repo_url]}
# Create repo in destination account, remove this line if already created
aws ecr create-repository --repository-name ${REPO_NAME[$repo_url]}
docker tag ${REPO_LIST[$repo_url]} $DESTINATION_ACCOUNT_BASE_PATH/${REPO_NAME[$repo_url]}
docker push $DESTINATION_ACCOUNT_BASE_PATH/${REPO_NAME[$repo_url]}
done
Make sure you already obtain login token for both account or add these command in the script.
aws ecr get-login-password --region $TARGET_ACCOUNT_REGION | docker login --username AWS --password-stdin ${REPO_LIST[$repo_url]}
# destination account login, make sure profile set for accoutn destination
aws ecr get-login-password --region $DESTINATION_ACCOUNT_REGION --profile destination_account | docker login --username AWS --password-stdin ${REPO_LIST[$repo_url]}
aws-cli-cheatsheet
Or you can use one of them
AWS cross-region replication
Cross account replication
Amazon ECR uses registry settings to configure features at the
registry level. The private registry settings are configured
separately for each Region. Currently, the only registry setting is
the replication setting, which is used to configure cross-Region and
cross-account replication of the images in your repositories
cross Region/account Replication feature in AWS
AWS has launched CRR (Cross Region Replication) and CAR (cross account replication)Click here for more info
AWS ECR Cross Region/Account Replication Feature allows replication of NEW objects. If you had an existing repository and wanted to replicate all its objects to another region/account Chris's answer is still the right one.
More Details: https://docs.aws.amazon.com/AmazonECR/latest/userguide/replication.html#replication-considerations