Cross account IAM roles for Kubernetes service account - s3 bucket - amazon-web-services

Hey im trying to cross account access for a role. i have 2 accounts: prod and non-prod.
and bucket in prod account, which im trying to write files to there from a non-prod role which is used as a service account in k8s cluster.
in prod account i configured:
a role with the following policy(read write access to the bucket):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ListObjectsInBucket",
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::test2"
]
},
{
"Sid": "AllObjectActions",
"Effect": "Allow",
"Action": "s3:*Object",
"Resource": [
"arn:aws:s3:::test2/*"
]
}
]
}
and the following trust:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::non-prod-AccountID:role/name-of-the-non-prod-role"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
in non prod i configured:
a role with the following policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::prod-Account-ID:role/prod-role-name"
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
and trust as follows:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::non-prod-accountID:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/1111111111111111111"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.us-east-1.amazonaws.com/id/1111111111111111111:sub":
"system:serviceaccount:name-space:name-of-the-service-account"
}
}
}
]
}
serviceAccount annotation is:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::non-prod-AccountID:role/non-prod-role-name
when running the command from inside the pod with the service account of the role in non-prod:
aws s3 cp hello.txt s3://test2/hello.txt
im having:
upload failed: ./hello.txt to s3://test2/hello.txt An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
by the way the cluster is in another account (devops account) if its related, surely added OIDC provider identity to both non-prod and prod accounts as identity provider.

If you're getting the error An error occurred (InvalidIdentityToken) when calling the AssumeRoleWithWebIdentity operation: No OpenIDConnect provider found in your account for $oidc_url when trying to cross-account assume roles, but you can assume roles in your cluster account normally, here's some points:
EKS ACCOUNT
Create a ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: $sa_name
namespace: $eks_ns
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::$resource_account_id:role/$role_name
Annotate your deployment
spec.template.spec:
serviceAccountName: $sa_name
Get info about your cluster OIDC Provider
aws iam get-open-id-connect-provider --open-id-connect-provider-arn arn:aws:iam::$eks_cluster_account_id:oidc-provider/$oidc_provider
3.1. The output will be like:
{
"Url": "...",
"ClientIDList": ["..."],
"ThumbprintList": ["..."],
"CreateDate": "...",
"Tags": [...]
}
3.2. Take note of the outputs (Url and ThumbprintList specially)
RESOURCE ACCOUNT
Add the provider (if you don`t have it already), using the output from your cluster account
aws iam create-open-id-connect-provider --url $oidc_url --client-id-list sts.amazonaws.com --thumbprint-list $oidc_thumbprint
This should be enought to the mentioned error stop. If you now get An error occurred (AccessDenied) when calling the AssumeRoleWithWebIdentity operation: Not authorized to perform sts:AssumeRoleWithWebIdentity, you're problably using the $eks_cluster_account_id on Principal.Federated, instead of $resource_account_id created on the previous step. So, make sure you're using the ARN from the IP that is assigned to the resource account, not the cluster account.
Create a role and a policy to access your resources with following trusted entities policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::$resource_account_id:oidc-provider/$oidc_provider"
},
"Action": "sts:AssumeRoleWithWebIdentity"
}
]
}
Also, there's no need to have two roles. One is enough.

Related

IAM role doesn't work when used on pod level but works on EKS worker node level

I already have an existing service account with IAM role that is currently able to pull in secrets in my application pod - so I know this is setup correctly.
However, I also want to give additional s3 policies to the same service account that will enable my pod to write and read to s3 bucket, but this fails to work as I get 403 forbidden error?
I'm able to exec into my pod and run aws s3 ls s3://my-bucket and can see the contents of my s3 bucket and can also push to the bucket from within the pod (which tells me the service account has been configured correctly), but strangely I can't do this from the actual application UI due to this 403 forbidden error message? I know the service account is still being used because it's still pulling in the secrets fine but fails to use the additional s3 policies.
I should also note that when I attach the exact same policy on the EKS worker node level the application works fine and this 403 s3 error goes away but doesn't work when using service account. Any ideas on what this could be?
My bucket isn't using any encryption at this stage.
Trust relationship for IAM role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<account-num>:oidc-provider/oidc.eks.eu-west-1.amazonaws.com/id/<oidc-num>"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.eu-west-1.amazonaws.com/id/<oidc-num>:sub": "system:serviceaccount:<app-namespace>:<service-account>"
}
}
}
]
}
IAM policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": "secretsmanager:GetSecretValue",
"Resource": [
"arn:aws:secretsmanager:eu-west-1:<account>:secret:<secret>"
]
},
{
"Sid": "",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:PutLifecycleConfiguration",
"s3:ListBucket",
"s3:GetObject",
"s3:GetLifecycleConfiguration",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::bucket/*",
"arn:aws:s3:::bucket"
]
}
]
}
Service account is annotated with IAM role
kubectl describe sa service-account
Name: service-account
Namespace: app-namespace
Labels: app.kubernetes.io/managed-by=Helm
Annotations: eks.amazonaws.com/role-arn: arn:aws:iam::account:role/IAM-role-to-attach
meta.helm.sh/release-name: release
meta.helm.sh/release-namespace: app-namesapce
Image pull secrets: <none>
Mountable secrets: secret
Tokens: token
Events: <none>

Dynamodb Cross-account put_item

I have two AWS accounts (account A, and account B). Account A has an EC2 instance, and that instance wants to do a put item to a dynamodb located in account B.
Since it is cross-account access, I created an IAM role on account B to allow account A to do put_item, an IAM role on account A to assume that role and attached the IAM role on the EC2 instance
When I run my program, I get an error message saying that I am trying to use the assume role to put an item to a table that in the same account. (in my code i just sepcified the Account B table name)
It seems that the instance doesn’t realize that the table is on account B even I have the assumerole setup. What am I missing here?
I have also verified that I can put item using AWS CLI (after performing the STS call).
Is there any Java API that I can to specify which dynamodb arn that I want to put the item to?
Error message:
User: arn:aws:sts::ACCOUNT_A:assumed-role/Assume-role/INSTANCE_ID is not authorized to perform: dynamodb:PutItem on resource: arn:aws:dynamodb:us-east-1:ACCOUNT_A:table/TABLE_NAME (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: AccessDeniedException)
Policy on account A:
{
"Version": "2012-10-17",
"Statement": [ {
"Effect": "Allow",
"Action": [ "sts:AssumeRole", "sts:GetFederationToken" ],
"Resource": "arn:aws:iam::AccountA:role/PutItem" },
{ "Effect": "Allow",
"Action": [ "sts:DecodeAuthorizationMessage", "sts:GetAccessKeyInfo", "sts:GetCallerIdentity" ],
"Resource": "*" } ]
}
Policy on Account B:
{
"Version": "2012-10-17",
"Statement": [ {
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [ "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:UpdateTable" ],
"Resource": "arn:aws:dynamodb:region:accB:table/table name" },
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "dynamodb:*",
"Resource": "*" } ]
}

AWS CloudWatch Cross-Account Logging with EC2 Instance Profile

When I originally setup CloudWatch, I created an EC2 Instance Profile to automatically grant access to write to the account's own CloudWatch service. Now, I would like to consolidate the logs from several accounts into a central account.
I'd like to implement a simplified architecture that is based on Centralized Logging on AWS. However, these logs will feed an on-premise ELK stack, so I'm only trying to implement the components outlined in red. I would like to solve this without the use of Kinesis.
Either the CloudWatch Agent (CWAgent) doesn't support assuming a role or I can't wrap my mind around how to craft the EC2 Instance Profile to allow the CWAgent to assume a role in a different account.
Logging Target (AWS Account 111111111111)
IAM LogStreamerRole:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::999999999999:role/EC2CloudWatchLoggerRole"
]
},
"Action": "sts:AssumeRole",
"Condition": {}
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": [
"arn:aws:logs:*:*:*"
]
}
]
}
Logging Source (AWS Account 999999999999)
IAM Instance Profile Role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::111111111111:role/LogStreamerRole"
}
]
}
The CWAgent is producing the following error:
/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log:
2018-02-12T23:27:43Z E! CreateLogStream / CreateLogGroup with log group name Linux/var/log/messages stream name i-123456789abcdef has errors. Will retry the request: AccessDeniedException: User: arn:aws:sts::999999999999:assumed-role/EC2CloudWatchLoggerRole/i-123456789abcdef is not authorized to perform: logs:CreateLogStream on resource: arn:aws:logs:us-west-2:999999999999:log-group:Linux/var/log/messages:log-stream:i-123456789abcdef
status code: 400, request id: 53271811-1234-11e8-afe1-a3c56071215e
It is still trying to write to its own CloudWatch service, instead of to the central CloudWatch service.
From the logs, I see that the instance profile is used.
arn:aws:sts::999999999999:assumed-role/EC2CloudWatchLoggerRole/i-123456789abcdef
Just add the following to the /etc/awslogs/awscli.conf to assume the LogStreamerRole role.
role_arn = arn:aws:iam::111111111111:role/LogStreamerRole
credential_source=Ec2InstanceMetadata

Datadog AWS integration for multiple aws account

I have two AWS account , I was able to set AWS integration for the first account using Terraform, but when I try to create AWS integration for my second account I am having an error.
I have created a role with in-line policy and we do not have a cross account set up.
! Datadog is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::xxxxxxxxxx:role/DatadogAWSIntegrationRole. See http://docs.datadoghq.com/integrations/aws/
Trust Relationship:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::xxxxxxxxxxxx:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "xxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}
]
}
Can anyone please guide me how to solve this error?
The role arn:aws:iam::xxxxxxxxxx:role/DatadogAWSIntegrationRole also has to have permission to assume the role on the other account.
You'll have to update the DatadogAWSIntegrationRole on the primary account to include:
{
"Version": "2012-10-17",
"Statement": [
...
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::xxxxxxxxxxxx:role/AssumedRoleForDataDogInOtherAccount"
}
]
}

AWS Code Commit Cross Account IAM Roles

I have two AWS accounts:
DEV: 111111111111
PROD: 999999999999
I created an a code commit repo in the prod account called prodRepo.
What I want to do is allow an ec2 instance on the DEV and PROD account to have read-only access to this repo. So git clone, git pull, etc...
I can do this easily on my PROD account using the following IAM instance profile called codecommit-tester
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"codecommit:BatchGetRepositories",
"codecommit:Get*",
"codecommit:GitPull",
"codecommit:List*"
],
"Resource": "arn:aws:codecommit:us-east-1:999999999999:prodRepo"
}
]
}
The Trust Relationship policy is:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
}
Then I use the aws credentials helpers in the git config to perform read-only git operations without having to store credentials on my machine (it gets the credentials for code commit from the instance metadata).
$ cat ~/.gitconfig
[credential]
helper = !aws codecommit credential-helper $#
UseHttpPath = true
The problem I am having is creating an the IAM policy/role on the DEV account to do the same thing as the PROD account. Here is what I tried.
I edited the Trust Relationship on the PROD account to trust the DEV account:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:root"
},
"Action": "sts:AssumeRole"
}
}
Now I think this means the DEV account can assume this role. On the DEV account I created these IAM policies attached to a role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"codecommit:BatchGetRepositories",
"codecommit:Get*",
"codecommit:GitPull",
"codecommit:List*"
],
"Resource": "arn:aws:codecommit:us-east-1:999999999999:prodRepo"
}
]
}
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::999999999999:role/codecommit-tester"
}
}
I use the credentials helper on the DEV account after launching an ec2 instance using this IAM instance profile and I get this error when performing a git clone:
$ git clone https://git-codecommit.us-east-1.amazonaws.com/v1/repos/prodRepo
Cloning into 'prodRepo'...
fatal: unable to access 'https://git-codecommit.us-east-1.amazonaws.com/v1/repos/prodRepo/': The requested URL returned error: 403
So what did I miss in the IAM roles/policies on the DEV to make this work?
I think you don't need iam role in dev which you mention (On the DEV account I created these IAM policies attached to a role) .... have not tried with instance cross account assume role..
but if you can create new IAM role in prod account with
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::999999999999:role/codecommit-tester"
}
]
}
and trust relation would be something like
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:root"
},
"Action": "sts:AssumeRole"
}
and just assume new IAM ARN in dev ec2 role.