Kubernetes pull private external amazon ECR images - amazon-web-services

I have an Amazon account with a K8S cluster which is able to pull images from the same account's ECR repository.
But, my company have another account with another ECR repository. How can I pull image from this "external" ECR repository ?
I'am also a Rancher user and I used to do this by installing a special container (https://github.com/rancher/rancher-ecr-credentials) which does the job.
Is there something equivalent for Kubernetes?
Thanks for your precious help

Since you already have this setup for pulling images from the same account, you can do this with IAM policy level or ECR permissions, in your other AWS account set up a policy specifying the AWS account number (where k8s is) that will be able to pull images
For example grant pull permissions in the ECR Permissions tab
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "k8s-aws-permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::aws_account_number:root"
},
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability"
]
}
]
}

Related

Pulling image from AWS ECR repository without AWS credentials

I need to pull docker images from on premise. However, I don't have access to AWS keys to be able to perform such an action against a private repository. How can I pull ECR images without AWS authentication? I've noticed ECR public repository, however, I still need some level of restriction to protect the repos contents.
Yes, you can authenticate temporarily. As document pointed;
You can use temporary security credentials to make programmatic requests for AWS resources using the AWS CLI or AWS API (using the AWS SDKs). The temporary credentials provide the same permissions as long-term security credentials, such as IAM user credentials.
Reference : https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html
Also, If there is no way to succeed the authentication this way or any other way,
You can use public registries + registry policies. You can ALLOW certain IPs/services/users to reach your registry. Example registry policy is below;
{
"Version": "2012-10-17",
"Id": "ECRPolicyId1",
"Statement": [
{
"Sid": "IPAllow",
"Effect": "Deny",
"Principal": "*",
"Action": "ecr:*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
1.2.3.4/32,
2.3.4.5/32
]
},
"IpAddress": {
"aws:SourceIp": "0.0.0.0/0"
}
}
}
]
}

AWS Allow Cross-account EKS Cluster to Pull Images from ECR

Summary:
I'm looking to enable EKS nodes to pull images from an ECR registry from a different AWS project. I created an "AllowPull" policy in the desired ECR repository and set the principal of the policy to the ARN of the EKS cluster role, but node is unable to pull the image.
How should the policy be formulated in order to allow all nodes in an EKS cluster to pull from a cross-account ECR repository?
Attempt Details:
The ECR registry recourse name is:
arn:aws:ecr:us-east-2:226427918358:repository/external-pull-test
The EKS cluster that needs to pull the images has the following role attached:
arn:aws:iam::02182452XXXX:role/aws-dev-eks-cluster-crpiXXXX091410594876160000000c
The external ECR registry has the following policy JSON:
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "AllowPull",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::02182452XXXX:role/aws-dev-eks-cluster-crpiXXXX091410594876160000000c"
},
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:BatchGetImage",
"ecr:DescribeImages",
"ecr:DescribeRepositories",
"ecr:GetDownloadUrlForLayer"
]
}
]
}
The pod ImagePullBackOff error specifies that the user attempting to authenticate with the registry is this assumed role:
arn:aws:sts::02182452XXXX:assumed-role/aws-dev-eks-cluster-crpiXXXX091410594876160000000c/i-0ea4f53b6dfdcxxxx
Environment:
Kubernetes: v1.16.15-eks-e1a842
Additional Details:
Using the ARN of my user principal (cross-account) in the policy did allow me to pull images using docker locally. Using the ARN of the assumed role did enable the node to pull the image, but my understanding is that configuring the policy with a particular assumed role won't guarentee that the cluster nodes can consistently pull from the registry.
Another method is click on the "external-pull-test" repo on the ECR console, on the left panel under "Repositories" click on "Permissions", then click on "Edit" on the top right. You can add the account ID that needs to pull from this repo at "AWS account IDs". Check the permitted actions at the bottom "Actions" drop down box. "Save" and you should be able to pull.

AWS permissions for Fargate and SSM

I'm trying to create some infrastructure for a service I am building on AWS using AWS Fargate. I'm using SSM as a value store for some of my application configuration, so I need both the regular permissions for Fargate as well as additional permissions for SSM. However, after banging my head against this particular wall for a while, I've come to the conclusion that I just don't understand AWS IAM in general or this problem in particular, so I'm here for help.
The basis of my IAM code comes from this tutorial; the IAM code is actually not in that tutorial but rather in this file in the github repo linked to that tutorial. I presume I need to retain that STS permission for something although I'm not entirely sure what.
I've converted the IAM code from the tutorial into a JSON document because I find JSON easier to work with than the Terraform native thing. Here's what I've come up with. It doesn't work. I would like to know why it doesn't work and how to fix it. Please ELI5 (explain like I'm 5 years old) because I know nothing about this.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:GetParameters",
"secretsmanager:GetSecretValue",
"kms:Decrypt",
"sts:AssumeRole"
],
"Principal": {
"Service": ["ecs-tasks.amazonaws.com"]
}
}
]
}
At a minimum, your ECS task should have below permissions:
Ability to assume a role
Resource level permissions
In the example, you have referred, An IAM Role is created with the following:
A trust relationship is attached. <-- To enable ECS task to assume an IAM role
AWS managed policy AmazonECSTaskExecutionRolePolicy is attached. <-- Resource permissions
So, in order to retrieve the SSM parameter values, add below resource permissions.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:Describe*",
"ssm:Get*",
"ssm:List*"
],
"Resource": [
"arn:aws:ssm:*:*:parameter/{your-path-hierarchy-to-parameter}/*"
]
}
]
}
If your Secrets uses KMS, then grant necessary kms permissions (kms:Decrypt). Refer specifying-sensitive-data for reference.

How to access AWS ECR from another account's EC2 instance?

I have two accounts, a1 and a2.
I have an EC2 instance in a1, a1.ec2. It assumes some role in that account, a1.r. This role has full access to all ECR actions.
Now, I have an image registry (ECR) in a2 and would like to be able to access it from a1.ec2.
So, I ssh into that instance and in order to test the access I run
aws ecr describe-repositories --region <my-region> --registry-id <id of a2>
But I get the error
An error occurred (AccessDeniedException) when calling the DescribeRepositories operation: User: arn:aws:sts::<id of a1>:assumed-role/a1.r/i-075fad654b998275c is not authorized to perform: ecr:DescribeRepositories on resource: arn:aws:ecr:*:*:repository/*
However, this permission is indeed granted to the role a1.r. I verified this by being able to access an ECR in a1 just fine.
Also, the ECR I like to access has the following permission policies, so I make sure that the trouble is not caused by the ECR of a2:
{
"Sid": "new statement",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<id of a1>:root"
},
"Action": "*"
},
{
"Sid": "new statement",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<id of a1>:role/a1.r"
},
"Action": "*"
}
I had a look at https://serverfault.com/questions/897392/ecr-cross-account-pull-permissions where the solution appears to be to create cross-account roles. Although I could create such a role a2.cross-acc-r, I cannot figure out how I can assume that role for the the aws ecr cli commands. I do not want the EC2 instance to assume that role, as it resides in a different account (not even sure if that is possible at all).
Am I lacking something basic regarding how AWS IAM works?
If you want to pull and push images from one account's EC2 instance into another account's ECR, and do not need the full aws ecr CLI functionality, you can do so through docker.
For example, if you want your Jenkins to push built images into ECRs based on the targeted environment (production, staging) residing in different AWS accounts.
Doing so via docker is documented at https://aws.amazon.com/premiumsupport/knowledge-center/secondary-account-access-ecr/
Put simply, in the ECR repository, you grant the other account the needed permissions.
Then you get a temporary authentication token to authorize docker towards ECR via:
$(aws ecr get-login --registry-ids <account ID> --region <your region> --no-include-email)
After this, you can use docker pull and docker push to access it.
I had a look at https://serverfault.com/questions/897392/ecr-cross-account-pull-permissions where the solution appears to be to create cross-account roles. Although I could create such a role a2.cross-acc-r, I cannot figure out how I can assume that role for the aws ecr CLI commands. I do not want the EC2 instance to assume that role, as it resides in a different account (not even sure if that is possible at all).
You can do that by following the steps below:
In account A, I created a role (e.g RoleForB) to trust account B, and attach to the before created role an IAM policy to allow it to perform some read operations in the account A. e.g ReadOnlyAccess
In account B, I created a role (e.g AssumeRoleInA) and attach a policy to allow it to assume the role that is created in account A.
In account B Associate to your EC2 instance ec2-profile the IAM role (AssumeRoleInA) which was created in step 2.
In account B login into this EC2 instance to assume the role in Account A using the command aws sts assume-role --role-arn "arn:aws:iam::Account_A_ID:role/RoleForB" --role-session-name "EC2FromB".
In account B EC2 terminal when the command is step 4. finished, you can see the access key ID, secret access key, and session token from wherever you've routed it, in our case stdout either manually or by using a script. You can then assign these values to environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN)
So Let’s check the configurations mentioned above step by step but with some mode detail:
As before presented in account A, it builds the trust to account B by creating the role named RoleForB and attaching ReadOnlyAccess permission to it.
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::Account_B_ID:root"},
"Action": "sts:AssumeRole"
}
}
In account B, create a role named AssumeRoleInA then attach the corresponding policy to allow it to assume the role named RoleForB in account A.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": [
"arn:aws:iam::Account_A_ID:role/RoleForB"
]
}
]
}
In account B, create a new EC2 instance (if it does not exists yet), and associate it's ec2-profile with the IAM role named AssumeRoleInA.
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": {"Service": "ec2.amazonaws.com"},
"Action": "sts:AssumeRole"
}
}
In account B login into this EC2 instance to assume the role in Account A using the command:
aws sts assume-role --role-arn "arn:aws:iam::Account_A_ID:role/RoleForB" --role-session-name "EC2FromB"`
You need to setup a trust relationship between your account a1 and a2.
From your a2 Console, go to IAM service, create a new role:
1) Trusted Entity: Another AWS Account (input account a1's ID)
2) Policy: AmazonEC2ContainerRegistryPowerUser (or others that meet your requirement)
From your a2 Console, go to ECR service, you need to edit your permission:
{
"Sid": "new statement",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<id of a1>:root"
},
"Action": "*"
},
{
"Sid": "new statement",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<id of a2>:role/a2.r"
},
"Action": "*"
}
}

AWS ECS Fargate pull image from a cross account ECR repo

I have 2 AWS accounts:
- account A that has an ECR repo.
- account b that has an ECS cluster running Fargate.
I have created a "cross-account" role in account A with trust relations to account B, also I have attached the "AmazonEC2ContainerRegistryPowerUser" policy to this role.
I gave access to the ECR repository in account A by adding account B's id and the "cross-account" role to the repository policy.
I attached a policy to the fargate "TaskExecutionRole" allowing fargate to assume the "cross-account" role.
When trying to deploy a Fargate task in account B with a reference to an image in account A I'm getting a 500 error.
Fargate will not automatically assume a cross-account role. Fortunately, you do not need to assume a role in another account in order to pull images from that account's ECR repository.
To enable cross-account access to an image in ECR, add access for account B in account A's repository (by setting the repository policy), and then specify a TaskExecutionRole in account B that has permissions to pull from ECR ("ecr:GetDownloadUrlForLayer", "ecr:BatchGetImage", "ecr:BatchCheckLayerAvailability").
For example, set a repository policy on the repository in account A like the following:
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "AllowCrossAccountPull",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT_B_ID:root"
},
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchCheckLayerAvailability",
"ecr:BatchGetImage"
]
}
]
}
Then, set your TaskExecutionRole in account B to have a policy like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage"
],
"Resource": "*"
}
]
}
Alternately, you can use the managed policy AmazonECSTaskExecutionRolePolicy for your TaskExecutionRole instead of defining your own.