AWS restrict access to S3 bucket to single Amazon Cognito user - amazon-cognito

I'd like to implement the following: a specific Cognito (authenticated) user must have access to a single S3 bucket.
What is the best way to achieve the above?
I have tried the following:
Create Cognito User Pool with App integration
Create Cognito Identity Pool, which creates a dedicated IAM role on autenticated users
My idea was to update the policy of the Identity-Pool-IAM role to impose restrictions on S3 buckets to specific users only. I would of course have to extend this policy every time I add a new Cognito user (no problem with this).
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"mobileanalytics:PutEvents",
"cognito-sync:*",
"cognito-identity:*"
],
"Resource": [
"*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::BUCKET_NAME"
],
"Condition": {
"StringLike": {
"cognito-identity.amazonaws.com:sub": "COGNITO_USER_SUB_UID"
}
}
}
]
}
AWS doesn't like the way the S3-related policy above is written. It returns:
This policy defines some actions, resources, or conditions that do
not provide permissions. To grant access, policies must have an action
that has an applicable resource or condition.
Question: am I taking the right approach? If so, what am I doing wrong? If not, how should I solve my (supposedly simple) requirement?
For whatever reason, all the examples I have found seem to restrict access to an S3 folder in a bucket rather than the bucket itself (see here or here).

Related

Grant cross account access to dynamodb table without using sts:AssumeRole

Essentially, I want an Iam role from AccountA to be able to manage a dynamodb table in AccountB, but the deployment that I am using does not support sts:AssumeRole (not my choice). I faced this same issue with an S3, but I was able to add an S3 bucket policy that allowed the Iam role from AccountB to access it (see below). Is there anything similar for dynamodb tables?
Thanks all :D
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::AccountB:role/iam-role-name"
},
"Action": "*",
"Resource": [
"arn:aws:s3:::bucket-name",
"arn:aws:s3:::bucket-name/*"
]
}
]
}
The only way that you can manage a table in another account is by assuming a role.
Unlike S3, DynamoDB does not support resource based access control. Unfortunately there are no simple workarounds as IAM is a security feature.

Amazon cognito Identity ID (sub) + S3 bucket name

I am currently working on a webApp to let authenticated users (by Cognito User Pool) to handle their own s3 bucket. In this way, I would like to use the following variable ${cognito-identity.amazonaws.com:sub} in order to dynamically name my s3 buckets.
This is what I am expecting about my s3 role linked to my authenticated users from my Cognito federated identities :
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::${cognito-identity.amazonaws.com:sub}/*"
]
}
]
}
The value of ${cognito-identity.amazonaws.com:sub} looks like "eu-west-2:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx", but I know S3 name cannot contain ":" special character...
Is there any workaround in order to dynamically name my s3 buckets based on each cognito Identity ID ?
Looking forward any tips/advices :)
As #Rasikh mentions in his comment, there are limits to the number of S3 buckets per account. 100 by default, although you can get that increased to a maximum of 1,000 by submitting a service limit request to AWS. However, the solution is not scalable to any number of users.
A more common pattern is to create just a single s3 bucket, and only give each authenticated user the permissions to access a certain prefix (path or folder) based on their cognito identity's sub property.
The following policy (taken from Example 2 of the Access Policy Examples) gives a cognito web identity s3:ListBucket permission, but only for their particular prefix, and the ability to get and put objects, but again only inside their prefix.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": ["s3:ListBucket"],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::mybucket"],
"Condition": {"StringLike": {"s3:prefix": ["${cognito-identity.amazonaws.com:sub}/*"]}}
},
{
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::mybucket/${cognito-identity.amazonaws.com:sub}/*"]
}
]
}
It's worth noting that this will only work for authenticated users, as unauthenticated users will get a different cognito identity, as thus a different sub, each time.

Where is policy of read/write AWS S3 for IAM user

I am adding a IAM user for read and write access to objects in AWS S3 bucket from React Native app. I plan to use signed URL to access the objects in a S3 bucket so the policy should be for programmatically access. The IAM user is created just for the purpose of read/write access to S3 bucket. When I open the existing policy to choose from, there are only 4 S3 related policy:
I can use the read only access. But I didn't find write access permission. Full access to the bucket seems to much to give. Also some of them has description of management console use and I am not sure if the policy could be used programmatically.
It appears that you are asking how to assign read and write permissions on a specific bucket to a specific user.
This can be done by attaching an inline policy to the IAM User. It would be something like:
{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Action":[
"s3:ListAllMyBuckets"
],
"Resource":"arn:aws:s3:::*"
},
{
"Effect":"Allow",
"Action":[
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource":"arn:aws:s3:::examplebucket"
},
{
"Effect":"Allow",
"Action":[
"s3:PutObject",
"s3:PutObjectAcl",
"s3:GetObject",
"s3:GetObjectAcl",
"s3:DeleteObject"
],
"Resource":"arn:aws:s3:::examplebucket/*"
}
]
}
Please note that some permissions are granted against the bucket (eg ListBucket) while some are granted within the bucket (eg GetBucket).
See: User Policy Examples - Amazon Simple Storage Service

Prevent access of S3 bucket for admin via console

I have some very highly confidential data that i want to store in s3 bucket.
I want to make policies ( bucket or iam whatever required) in such a way that no one ( not even admin) can read the contents of files in that bucket from aws console.
But i will have a program running on my host that needs to put and get data from that s3 bucket.
Also i will be using server side encryption of s3 but i can't use client side encryption of s3.
You are looking for something like this;
{
"Id": "bucketPolicy",
"Statement": [
{
"Action": "s3:*",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:iam::111111111111:user/USERNAME",
"arn:aws:iam::111111111111:role/ROLENAME"
]
},
"Resource": [
"arn:aws:s3:::examplebucket",
"arn:aws:s3:::examplebucket/*"
]
}
],
"Version": "2012-10-17"
}
For test purposes make sure you replace arn:aws:iam::111111111111:user/USERNAME with your user arn. So in case you lock out everybody you can at least perform actions on the bucket.
arn:aws:iam::111111111111:role/ROLENAME should be replaced by the role arn which is attached to your EC2 instance (I am assuming that is what you mean by host).

Getting AWS Lambda access to private S3 resource

We have been trying to crack an issue with resource permissions related to S3 and Lambda.
We have a root account which inturn has -
Account A - Bucket owner
Account B - Used to upload (through CORS) and give access to S3 images
ROLE L - We have a lambda function which assigned this role with Full S3 access
The buckets have access policy like below -
{
"Version": "2012-10-17",
"Id": "Policyxxxxxxxxx",
"Statement": [
{
"Sid": "Stmt44444444444",
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:iam::xxxxxxxxxxxx:user/account-A",
"arn:aws:iam::xxxxxxxxxxxx:role/role-L"
]
},
"Action": [
"s3:*",
],
"Resource": [
"arn:aws:s3:::bucket",
"arn:aws:s3:::bucket/*"
]
}
]
}
The issue -
The lambda is able to access S3 resource only if object ACL is set to Public/read-only. But Lambda fails when the resource is set to 'private'.
Bucket policy just gives access to the bucket. Is there a way to give Role L read access to the resource?
Objects stored in Amazon S3 buckets are private by default. There is no need to use a Deny policy unless you wish to override another policy that grants access to the content.
I would recommend:
Remove your Deny policy
Create an IAM Role for your AWS Lambda function and grant permission to access the S3 bucket within that role.
Feel free to add a Bucket Policy for normal use as appropriate, but that should not impact your Lambda function's access that is granted via the Role.