Check IAM permissions of caller in AWS Lambda - amazon-web-services

I have dozens of services each requiring access to their corresponding secret in AWS Secrets Manager.
I have implemented a solution of granular permissions to IAM roles of services so that each can access only their credentials. This creates neatly a least access pattern to services.
I want to implement an AWS Lambda to abstract away access to Secrets Manager secrets. If I have only one Lambda (per environment), how can I check that the IAM role invoking the lambda has permissions to access a particular secret? So to exclude the case of a service requesting access to another service's credentials.
I can always create one lambda per service and assign permissions to each service to only invoke their lambda (which only accesses the corresponding secret), but this seems quite inelegant...

Related

AWS boto3 user vs role

I am trying to follow best practices, but the documentation is not clear to me. I have a python script running locally that will move some files from my local drive to S3 for processing. Lambda picks it up from there and does the rest. So far I set up an AWS User for this process, and connected it to a "policy" that only has access to the needed resources.
Next step is to move my scripts to a docker container in my local server. But I thought best practice would be to use a Role with policies, instead of a User with policies. However, according to this documentation... in order to AssumeRole... I have to first be signed in as a user.
The calls to AWS STS AssumeRole must be signed with the access key ID
and secret access key of an existing IAM user or by using existing temporary
credentials such as those from another role. (You cannot call AssumeRole
with the access key for the root account.) The credentials can be in
environment variables or in a configuration file and will be discovered
automatically by the boto3.client() function.
So no matter what, I'll need to embed my user credentials into my docker image (or at least a separate secrets file)
If that is the case, then it seems adding a "Role" in the middle between the User and the Policies seems completely useless and redundant. Can anyone confirm or correct?
Roles and policies are for services running in AWS environments. For a Role you define a Trust Policy. The Trust Policy defines what principal (User, Role, AWS Service etc.) can assume it. You also define the permissions that the principal which assumes it has to access AWS services.
For services running inside AWS (EC2, Lambda, ECS), it is always possible to select an IAM role, which will be assumed by your service. This way your application will always get temporary credentials corresponding to the IAM role and you should never use an AWS Access Key Id and Secret.
However, this isn't possible for services running locally or outside of AWS environment. For your Docker container running locally, the only real option would be to create an Access Key ID and Secret and copy it there. There are still some things you can do to keep your account secure:
Follow the least privilege principal. Create a policy that provides access to only the absolutely required resources.
Create a user (programmatic access only) and add the policy. Use AWS Access Key ID and Secret of this user for your Docker container.
Make sure that the AWS Credentials are rotated regularly.
Make sure that the secrets aren't committed in source control, prefer a secrets file or a Vault system than environmental variables.

What are the benefits of sharing an IAM role instead of a IAM key?

I'm told sharing IAM roles with third parties is more secure than sharing IAM keys. Currently we limit IAM keys with IP filters, many conditions on access control.
Why would sharing IAM roles be better. My understanding is they can use their role to assume privilege for a time limited period from something like the boto3 api. But if they can assume the role without limit, how is there a security benefit over a key?
First, as you mentioned, the short-lived session credentials used by a role limits the time that compromised credentials can be used.
Second, with an IAM user, any time the third party needs to access resources in your account, they must posses the access key and secret key of your IAM user. If they want to access resources from your account from an EC2 instance, they need to have a way to securely push the keys to the EC2 instance. If they want to access resources from a Lambda, they need to make the keys available to the Lambda. If they want to access resources from a mobile device, they need to push the credentials to the mobile device (where they are more difficult to secure, let alone rotate).
Managing these credentials is not only additional work for the third party, but also additional risk for you. The long-lived credentials for your IAM user are now being passed around by a third party.
Using an IAM role instead, you can allow the third party to access resources without passing your credentials around. An EC2 instance can avoid handling your credentials using EC2 instance roles. Lambda, similarly, can avoid handling your credentials by using execution roles. On a mobile device, there is Cognito.
To grant an external party access to the AWS resources owned by you, you have following options:
[WORST APPROACH] You create an IAM user (say, Foo) and grant it the required permissions and then share the same with the external parties. This is obviously the worst approach as now you have no segregation between who is making calls to your resources because in effect, it is always Foo who is calling you.
You let your clients create IAM users in their own accounts and then whitelist them in your resource's policy. This works, given that your resource supports resource-level policies (S3 and API Gatewaydo). Now, even if they do support resource-level policies, now it is an overhead for you to whitelist all such users created by all your clients, which can access the resource.
You create an IAM role, grant it capabilities (in terms of IAM policies) to access your resource and then whitelist your clients' IAM users to assume that role. This will be your way of saying that "this role is capable of accessing my resource and if you can assume this role, so do you". Moreover, this also prevents you from sharing the credentials as AWS STS does all that work in generating the temporary credentials for you.

If I call api gateway apis from a ec2 instance with role, can AWS automatically handle the IAM authorization?

I want to call api gateway from our own backend which is a ECS cluster, and I want to use IAM authorization, is there any way to not manually sign the request using Access Key and Secret Key?
For example when Lambda call KMS to decrypt environment variables, no need to configure the AWS SDK. Wondering if there's similar thing for API gateway.
It is definitely possible, even more - it's a security best practice. You can assign IAM roles to all computing services of AWS: Lambda, EC2, ECS, Beanstalk etc. On ECS you can assign IAM roles to your tasks.
It gives a great benefit, which is well described in official docs:
Benefits of Using IAM Roles for Tasks
Credential Isolation: A container can only retrieve credentials for the IAM role that is defined in the task definition to which it belongs; a container never has access to credentials that are intended for another container that belongs to another task.
Authorization: Unauthorized containers cannot access IAM role credentials defined for other tasks.
Auditability: Access and event logging is available through CloudTrail to ensure retrospective auditing. Task credentials have a context of taskArn that is attached to the session, so CloudTrail logs show which task is using which role.
This link will help you: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html

How do I send an email through SES with temporary SES-specific credentials?

This page shows how to send an email using SES. The example works by reading the credentials from ~/.aws/credentials, which are the root (yet "shared"??) credentials.
The documentation advises in various places against using the root credentials.
Acquiring temporary credentials
using roles is mentioned as an option, yet assume_role() is not defined for SES client objects.
How do I send an email through SES with temporary SES-specific credentials?
Update
The context for my question is an application running on an EC2 instance.
There are a few pieces to this.
First you need an IAM policy. You can use one of the built-in policies, such as AmazonSESFullAccess or you can create your own. The holder of a particular policy will be able to access the resources and actions defined in the policy. You can create this policy manually, or work through the AWS console and it will walk you through it. IAM --> Policies --> Create Policy
Secondly, you will need a role. Also, easily done in the console. IAM --> Roles --> Create role. Trusted entity is AWS service. Highlight EC2. In the next screen, select the policy you want to associate with this role. This is the policy you created above. If your EC2 already has a role, then you can add the IAM policy to this role. Assigning an IAM policy to a role, is what they refer to as a trust policy.
Now any code that runs on your EC2 instance will be able to send messages to your SES service. The EC2 assumes the role assigned to it. And the SES policy is defined for that role. This will allow EC2 to get temporary credentials (behind the scenes).
The back story is as follows. Any API call to an AWS service needs to have a key and secret. When you make API calls from your local computer, you may use your personal key and secret (or even root ones). When you need to make API calls from another service, you do not have that key and secret. It would not be secure or practical to store the credentials on an EC2. Or even worse, in an S3 bucket. That is why AWS came up with the Role concept. Roles can request temporary credentials from an internal service called Simple Token Service (STS). A role is attached to an EC2 instance for example. And if the right policy is attached to that role, the EC2 instance can request to get temporary credentials to make an API call to another service. All of this happens behind the scenes.
Two options...
You could create IAM User credentials with the appropriate permissions and put them in the ~./aws/credentials file. Then your application will find them and use them to connect with Amazon SES.
Or, your application could use a set of IAM User credentials to call assume_role() (which is an IAM command). This will return a set of temporary credentials that could be used with Amazon SES. However, if you are going to provide a set of credentials that will be used to call assume_role(), then you may as well just use those credentials directly with Amazon SES.
An IAM User can be used for people OR applications.

How to put an app on the AWS Marketplace that requires S3 resources

I have an application on an EC2 Instance that I wish to put on the AWS Marketplace. The application uses AmazonS3 and on startup requires users to enter an Access Key, Secret Key, and a BucketName. It then uses the Accekey, and secretkey to create a bucket (specified by BucketName). However, this isn't allowed on the AWS Marketplace.
However, for AWS Marketplace,we require application authors to use AWS
Identity and Access Management (IAM) roles and do not permit the use
of access or secret keys.
Question
I am confused as to how to get around this and still put my AMI on the AWS Marketplace. My goal is for users to create their own S3 buckets in their own AWS Environments.
Your customers can create AWS IAM roles with access to the required resources (S3 buckets), and allow your account to use those roles.
The reasoning behind this mechanism is that your customers can follow the principle of least privilege and limit access to very specific resources and actions on those resources (instead of providing unsecured / root access to their entire account)