AWS REST Api as S3 proxy and accessing client specific bucket - amazon-web-services

I have created AWS API Gateway as S3 proxy as per guidelines here. So final url looks something like
http://api.exmaple.com/v1/{clientbucketname}/{key}
client will use their pre-assigned bucket name in the url. I understand that if API is authenticated using IAM user then API will have access to the bucket belongs to authenticated IAM user and can perform actions only on a particular client's bucket.
However my API is authenticated using API-KEY. Each client has their own API-KEY how do i tie API-KEY to S3 bucket so client A cannot access client B's bucket simply by changing the bucket name in the URL.

It is not possible without AWS_IAM authorization.
API Gateway uses the result of that authorization to locate the account, role and bucket.

Related

Amazon Cognito and Application specific authorization logic to access Amazon CloudFront content

I'd like to protect Amazon CloudFront content with my custom application specific authorization logic.
For example, for authentication purpose I may use Amazon Cognito and Amazon CloudFront with AWS Lambda#Edge approach which will inspect every incoming request to CloudFront and ensure that request has a valid JWT token.
But how about the authorization part?
According to the application business logic, every single authenticated user should not have the access to the same resources.
How and where to check that a user with a valid JWT token has the access (according to the application business logic) to the requested Amazon CloudFront content?
Should such authorization logic be included in the Lambda#Edge handler also?
Yeah, the Lambda#Edge can be used to authorize the user to access a resource behind CloudFront.
And the authorization can be done with the Amazon Cognito User Pool service.
You flow will be similar the following one:
Here is a example of how to this: Secure Your Static Website with AWS CloudFront and Lambda
Check this blogpost to understand more about this process: Authorization#Edge Protect your Amazon CloudFront content from being downloaded by unauthenticated users.

Sending email using AWS API without Secret Key and Access Key Id

I know close to nothing about AWS. But I want to use AWS SDK in my Springboot project to send email via SES. I am to send the emails as a delegate user, and all I have is the Identity user's ARN. I tried the code available on the AWS website and set X-SES-SOURCE-ARN header as the identity user's ARN, and I am getting Unable to load AWS credentials from any provider in the chain error. Do I need to add any sort of ACCESS-KEY-ID and SECRET-KEY?
You might be confusing IAM identity with email/domain identities.
IAM handles authorization for the API call (AWS sigv4).
SES identities are internal to the service and just represent an authorized sending email address or domain (one that has performed verification steps).
To make a successful call you need to have both of those:
An IAM principal with authorization for ses:SendEmail in the account.
A verified email or domain identity in the account that is passed as the source ARN in your API call.
If you are using sending authorization policies then things require a little more setup but is essentially the same.
You can add the accessKey and secretKey on a file named AwsCredentials.properties. Next, when you configure the AWS SES Client, you load that file, as in the following example with Cognito.
public AWSCognitoIdentityProvider getAmazonCognitoIdentityClient() {
ClasspathPropertiesFileCredentialsProvider propertiesFileCredentialsProvider = new ClasspathPropertiesFileCredentialsProvider();
return AWSCognitoIdentityProviderClientBuilder.standard().withCredentials(propertiesFileCredentialsProvider)
.withRegion(props.getRegion()).build();
}

How do you access an AWS Lambda with credentials using API Gateway?

I'm not clear on how to send credentials and IAM access to an API gateway. This seems clear:
There is the tutorial on AWS but this is not the way I wanted to access my API.
API Gateway example
As most would know, you put your AWS Key and Secret key in a configuration file that lives in .AWS on the userspace of the user but if you are using a website, for example, you won't have that. Is the idea that anytime a user access the API that you put that user in an anonymous group that has access to the .credentials file?
You are describing IAM authentication for API Gateways. For your of your web app to generate IAM credentials I would recommend using a Cognito Identity Pool Authenticated Role. The Cognito Identity Pool Authenticated Role Exchanges a JWT for the AWS IAM credentialsthat are used in API calls. Your users will first authenticate against the identity pool. The identity pool even allows for unauthenticated users that are using your registered app to generate credentials with permissions which you specify. This guide will show you how to generate these credentials in your code.
Alternatively you can use API Gateway Identity Pool Authorizer or API Gateway Lambda Authorizer to secure your API.

AWS API Gateway Security with a Custom Authoriser & AWS Service Integrations

When using API Gateway to proxy AWS services such as S3 works great.
However it would seem that security is an afterthought. The execution role that is used for AWS Service integration seems to leave open the integrated service when using a customer authorizer.
The Custom Authorizer in API Gateway returns a principalId (e.g. a userId) and an IAM policy document. How could one build an IAM policy for the execution role of the service integration which would require for example the userId/principalId to be in the path of an S3 object.
I.e. using a custom authorizer + S3 integration how do you secure object access to only a particular key space where the principalId is part of an object tag or path?
http://docs.aws.amazon.com/AmazonS3/latest/dev/object-tagging.html or http://docs.aws.amazon.com/AmazonCloudWatch/latest/events/policy-keys-cwe.html
I was having the same problem. Here is how I solved it with the path.
Assume user1 need to access their data and their space is
domain/user1/object1
domain/user1/object2
In the custom Authorizer you can return policy that the user can access only domain/user1/*. You can use any pattern you want and organize the storage to whatever namespace you want. If you want to expand namespace for multiple users you can do access to
domain/user1/*
domain/managers/*
And APIGateway will take care of the rest. If the user tries to access anything other than the above URL paths, the user will get 403 forbidden.
Followed the documentation from AWS and works perfectly,
http://docs.aws.amazon.com/apigateway/latest/developerguide/use-custom-authorizer.html
In Addition, if you want authentication I would recommend CloudFront signed URL and Cognito.

AWS Custom Authorization lambda to approve Api Gateway service proxy action?

I want to create an Api Gateway route which is connected via service proxy to s3.
Only authenticated and authorized users (from Cognito Userpool) which have a specific permission (which is stored in a DynamoDb table) should be able to upload the file.
Since I'm not using S3 as the service proxy and not lambda, is it ok to put the code checking against the Dynamodb in the Custom Authorizer lambda? (After the token has been verified and before sending the success callback).
The query is simple, based on the Cognito user unique Id, I check in a table that user if user is authorized to upload.
I wouldn't want the upload to be done via a lambda function since some files are big.
Thanks
You can also consider
Setup CloudFront infront of S3 bucket.
Using IAM authorization at API Gateway.
Write a Lambda endpoint which checks Cognito ID in request context against Dynamodb.
Return Signed URL from Lambda for authorized users to directly upload files to S3 from browser client.