cross account ssm start session - amazon-iam

Was trying to start a session[terminal] via ssm on an instance in another account. using command
aws ssm start-session --target i-yyyaf4692d801d1xx --region ap-south-1
but it was failing with response as "Target is not connected".
we get this response when the instance is usually not found in the inventory of Systems Manager. - which i can't add, as the instance is in another account
END Goal: I wish to use users created in Account A to be able to start sessions on instances on Account B. both part of the same organisation.
Also,
my user has appropriate permissions have verified it through IAM Simulator
it seems instance IDs are unique and associated to one account only.
the instance is accessible by local users in that account.
[update 9th Jan 2023]
Thanks for the responses, its clear that IAM Role[with assume role sts] suffices the request conditions.
But i was looking for some seamless method, where we dont need to generate temporary credentials and use them for access each time.
May be a script to do this task or something would do. As IAM Principal: Users need to generate temp creds manually which is not the case with IAM Roles

You need to delegate access between the accounts. You can do this by creating a role in the target account which is allowed to assumed by users in the other account.
Setup the access:
Create an IAM role with necessary IAM permissions to access the instances in the target account (account B)
Create a trust relationship on the role in the target account to trust the appropriate principals (users or roles) in the source account (account A).
Grant the appropriate principals (users or roles) in the the source account (account A) permission to call the sts assume-role API for the role in the target account (account B)
Use the access:
From your user profile or role in account A, call the sts assume-role API to obtain credentials for the role you created in account B.
Use the credentials returned by the sts assume-role call in order to call the API using the identity assumed in account B to access the resources.
See: cross-account IAM access for more details.

Related

As a management account/delegated admin in a AWS Organization, how to call AWS services for each member account in AWS SDK?

Say I set up a AWS organization from account 111111111111, and then I create/invite 2 accounts, 222222222222 and 33333333333. As soon as I enabled SCP, I see a FullAWSAccess Policy attached to all members. I am trying to update each account programmatically in AWS SDK, and not having to switch roles on Console each time. For example:
AWSOrganizations client = AWSOrganizationsClientBuilder.standard().build();
ListAccountsResult result = client.listAccounts(new ListAccountsRequest().withMaxResults(10))
result.getAccounts()
.stream()
.forEach(account -> {
// I am not sure what to do with below data
// account.getArn()
// account.getId()
})
Say I want each member to put a s3 object like so:
s3.putObject(..)
Do I need to assume a role (AWS creates a OrganizationAccountAccessRole role by default) for each member account and call AWS service? Or am I missing something?
Your assumption is correct, in order to execute actions in other member accounts you need to assume a role in that account first. AWS Organizations creates OrganizationAccountAccessRole in each newly created account, this role has a trust policy to trust the master account. So as long as you're authenticated to the master account with any role that has sts:AssumeRole action you can assume OrganizationAccountAccessRole in the target account and do the "needfuls".
As the best practise you should your own automation role in each account and a dedicated automation account. This automation role lets say "pipeline-role" will have limited permissions that can be assumed only from your automation account.
This way you're reducing the need to utilise your master account and also making this automation role only as powerful as your automation needs instead of using the full AdministratorAccess policy.

Can't grant cross-account access to a ECS task's role

Background:
I am trying to grant access for an ECS task in Account B to extract data from a DynamoDB table in Account A.
In theory, this works fine by: (1) creating a role in Account A that Account B is allowed assume (with a paired External ID), and then (2) granting that role access to the needed DynamoDB tables.
Problem:
When a process running in ECS assumes the ECS role (Account B), it creates a unique instance of that role, which apparently cannot be the target of a principal statement in the account. If I try granting access to the underlying role, that apparently has no affect.
Can I force ECS to use the original role, which I can grant as principal, rather an a temporary set which apparently can't then assume other roles?
The only workaround I can think of is to create a new user with programmatic API credentials, handoff those creds to the ECS task, and then then have the ECS task overrides it's own role with the one's belonging to the AWS key-pair. That's definitely an antipattern though, as far as I can tell, and it opens up the risk of those credentials being compromised.
Is there any way to do this without resorting to a manually created user and manually passed AWS creds?
Additional info:
I can grant to this principal arn:aws:iam::AcctB****:role/myrole but the ECS task is using this one at runtime: arn:aws:sts::AcctB****:assumed-role/myrole/45716b8c-40c8-4ca7-b346-1ff4ee94eb53.
Error message is: An error occurred (AccessDenied) when calling the AssumeRole operation: User: arn:aws:sts::AcctB****:assumed-role/myrole/45716b8c-40c8-4ca7-b346-1ff4ee94eb53 is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::AcctA****:role/ExternalRole
I faced the same situation and found a safe way to programmatically assume the role from an ECS task.
sts_client = boto3.client('sts')
identity = sts_client.get_caller_identity()
print(identity) # identity in account A
response = sts_client.assume_role(RoleArn=assume_role_arn, RoleSessionName=session_name)
session = boto3.Session(aws_access_key_id=response['Credentials']['AccessKeyId'],
aws_secret_access_key=response['Credentials']['SecretAccessKey'],
aws_session_token=response['Credentials']['SessionToken'])
The idea is to connect to account A, assume role from account B, init a session using temporary credentials and then init whatever client you need from that session.
external_client = session.client('sts')
identity = external_client.get_caller_identity()
print(identity) # identity in account B
This is more secure than creating a IAM user and share credentials between accounts because authentication is done internally.
Here you can find more information about how it works
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sts.html
Linking the following topic here: How to assume an AWS role from another AWS role?
TL;DR
Really make sure you don't have a typo, wrong name or external id in one of the policies.
ECS needs to assume your Task Role the same way you are trying to assume the role in Account B. This can't be changed. Even ECS tries to assume Account B role with assumed-role/... it works as expected when granted a principal with role/...

How to give cloudfront or any resource access to another account role

I have a cloudfront, let's say in Account A and I want to access this cloudfront from a build server which is in another AWS account let's say in Account B with IAM Role.
How to give a IAM role access(Account B) to that cloudfront which is in Account A.
Note: Please consider Role not IAM user.
Overview of Managing Access Permissions to Your CloudFront Resources
An AWS account owns the resources that are created in the account,
regardless of who created the resources. Specifically, the resource
owner is the AWS account of the principal entity (that is, the root
account, an IAM user, or an IAM role) that authenticates the resource
creation request.
The following examples illustrate how this works:
Attach a permissions policy to a role (grant cross-account
permissions) – You can grant permissions to perform CloudFront actions
to a user that was created in another AWS account. To do so, you
attach a permissions policy to an IAM role, and then you allow the
user in the other account to assume the role. The following example
explains how this works for two AWS accounts, account A and account B:
Account A administrator creates an IAM role and attaches to the role a
permissions policy that grants permissions to create or access
resources that are owned by account A.
Account A administrator attaches a trust policy to the role. The trust
policy identifies account B as the principal that can assume the role.
Account B administrator can then delegate permissions to assume the
role to users or groups in account B. This allows users in account B
to create or access resources in account A.
For more information about how to delegate permissions to users in
another AWS account, see Access Management in the IAM User Guide.

What is exactly "Assume" a role in AWS?

Question
What does exactly "Assume" a role mean in AWS and where is the definitive definition provided?
Background
Assuming a role is frequently used and trying to understand the definition and what it actually means.
I suppose when a principal (IAM user, application running in an EC2 instance, etc which invokes an action to access AWS resource(s)) needs to invoke an action to access an AWS resource:
AWS (API? or some Authorisation runtime in AWS?) identifies the roles which the principal can be granted. e.g. if an EC2 user is specified to execute the assume-role API call and run an application which accesses an AWS resources in an EC2 instance to which IAM profile is attached, then:
All the IAM roles from the EC2 IAM profile
IAM roles and policies requested in the assume-role call
IAM roles which the EC2 user is granted
AWS finds a role from the roles which has the policy (action, resource) that allows the principle to do the action on the resource.
AWS switches the role of the principle to the role identified.
When the step 3 has happened, it is said "the principal has assumed the role". Is this correct?
Research
Using IAM Roles
Before an IAM user, application, or service can use a role that you created, you must grant permissions to switch to the role. You can use any policy attached to one of an IAM user's groups or to the user itself to grant the necessary permissions.
Assuming a Role
AssumeRole
Using IAM Roles
Using an IAM Role to Grant Permissions to Applications Running on Amazon EC2 Instances
Assuming a role means asking Security Token Service (STS) to provide you with a set of temporary credentials -- role credentials -- that are specific to the role you want to assume. (Specifically, a new "session" with that role.)
You can optionally include a policy with this request, which will serve to limit the permissions of the temporary credentials to only a subset of what the role's policies would have allowed.
You then use these credentials to make further requests. These credentials look similar to IAM user credentials with an access-key-id and secret, but the access key begins with ASIA instead of AKIA and there's a third element, called the security token, which must be included in requests signed with the temporary credentials.
When you make requests with these temporary credentials, you have the permissions associated with the role, and not your own (if you have one) because you have taken on a new identity. CloudTrail can be used to trace the role credentials back to the user who assumed the role, but otherwise the service is unaware of who is using the credentials.
tl;dr: Assuming a role means obtaining a set of temporary credentials which are associated with the role and not with the entity that assumed the role.
AWS (API? or some Authorisation runtime in AWS?) identifies the roles which the principal can be granted.
No. You specify the role you want to assume.
When "you" are code running on an EC2 instance, and the instance has an instance role, the EC2 infrastructure actually calls assume-role on behalf of the instance, and you can fetch the temporary credentials from the instance metadata service. These credentials are accessible only from within the instance, but they are not stored on the instance.
When running a Lambda function, the Lambda infrastructure contacts STS and places your temporary credentials in environment variables. Again, these credentials are accessible to the function, without being stored inside the function.
In either case, you could call assume role with these credentials and assume a different role, but that should not be necessary in most environments.
e.g. if an EC2 user is specified to execute the assume-role API call and run an application which accesses an AWS resources in an EC2 instance to which IAM profile is attached, then:
AWS has no awareness of EC2 users. Instance roles are accessible to everything running on the instance.
All the IAM roles from the EC2 IAM profile
An instance profile can only include one role.
IAM roles and policies requested in the assume-role call
You request to assume exactly one role. You do not need to request a policy -- you only specify a policy if you want the temporary credentials to have fewer privileges than the role credentials would allow. This might be something you would do if you needed code running in an untrusted place -- such as code in a browser or an app -- to be able to sign requests with credentials.
AWS finds a role from the roles which has the policy (action, resource) that allows the principle to do the action on the resource.
No. As noted above, you ask for a specific role when you call assume-role.
AWS switches the role of the principle to the role identified.
No. You make the switch by using the temporary credentials provided.
I have created the following diagram for myself to understand what is exactly assume a role in AWS. Hopefully, you will also find it helpful.
In the diagram, I put it in 3 steps:
Prepare the roles (ExecutionRole and AssumedRole)
Create a Lambda Function on Account A (in your case it is EC2)
Execute the LambdaFunction.
The diagram uses cross-account as an example, if it is within the same account step 1.3 is not required.
Typically, you use AssumeRole within your account or for cross-account access.
...
Users in the same account as the role do not need explicit permission to assume the role. Source: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html
When step 3 has happened, it is said: "the principal has assumed the
role". Is this correct?
The steps you mentioned in assuming a role are correct.
Here the important point is the IAM role's Trust Relationship configuration where you grant each of the IAM user, application, or service to assume the role. That is where you grant the permission to assume the particular role.
This is important in many aspects, where it controls who can assume the role and it is important to provide not only least access to the role but also grant the least amount of entities who can assume the role.

Which AWS account gets billed when using AWS STS?

I am looking to use AWS STS to access resources from another AWS account owned by another team.
say, AWS Account A trying to access AWS Account B.
basically the steps I am following:
1. Create a user in Account A
2. Create Role in Account B with the necesaary permissions
3. Add assume role permissions for user in Account A
4. Use User credentials to get temporary credentials for Account B.
5. Use temp credentials on Account B.
But, after reading through a ton of AWS docs, I am unable to figure out which account gets billed for the cross account API calls?
When you use AssumeRole to grant access to another Amazon account (account B), your identity switches to the other account with the username being the role name that you assumed.
The only cross account API being called will be AssumeRole. After this succeeds you will be using the APIs using account B's temporary credentials that were returned from AssumeRole.
All ownership, billing, etc. will be the same as if you had originally logged into account B as a normal IAM user except for the user name.
CloudTrail records STS type calls such as AssumeRole and logs all authenticated API requests. Once AssumeRole succeeds, your activity (using the temporary credentials) will be logged by CloudTrail in account B. This assumes of course that CloudTrail is enabled.
This link will give you more details into the user identity that AWS uses when using AssumeRole.
CloudTrail userIdentity Element
When you create a role for cross-account access, you establish trust from the account that owns the role and the resources (trusting account) to the account that contains the users (trusted account). To do this, you specify the trusted account number as the Principal in the role's trust policy. That allows potentially any user in the trusted account to assume the role. To complete the configuration, the administrator of the trusted account must give specific groups or users in that account permission to switch to the role.
Link
As everyone has mentioned a user from the account A is just assuming a role in account B to temporary access resources in account B,ownership stays still and the owner pays for the resources he owns. In this case it is the account B who pays. STS is the service being used to assume a role and is part of IAM.
The following was taken from IAM FAQ.
Q: How do I assume an IAM role?
You assume an IAM role by calling the AWS Security Token Service (STS) AssumeRole APIs (in other words, AssumeRole, AssumeRoleWithWebIdentity, and AssumeRoleWithSAML). These APIs return a set of temporary security credentials that applications can then use to sign requests to AWS service APIs.
Q: How many IAM roles can I assume?
There is no limit to the number of IAM roles you can assume, but you can only act as one IAM role when making requests to AWS services.
Q: Who can use IAM roles?
Any AWS customer can use IAM roles.
Q: How much do IAM roles cost?
IAM roles are free of charge. You will continue to pay for any resources a role in your AWS account consumes.