I am writing a user policy using AWS Cognito User Pools for an app that needs to be compatible with an old ad hoc user management system we had previously used on S3 with IAM while we move to a better user management model using Cognito.
The old system used arn:aws:s3:::[Our Bucket Name]/${aws:username}/* in the group policy to only allow a user access to objects using their username. I had thought that using the same username in Cognito would allow us to use a duplicate role policy allowing the Cognito users the same access, but according to this, the aws:username is not present for Cognito; that only has the aws:userid, which, if I am reading this right, is essentially a randomly generated unique string that has nothing to do with the username and so cannot be used for this purpose.
Is there any other way I can give the Cognito user access to a given IAM username's folder in S3 on the basis of the same name through a role policy? The only way I can think of is to make custom policies on a per-user basis, but I would prefer to keep changes to our existing user creation system to a minimum.
Short answer: don't mix IAM with Cognito. Write an app/service/api to provide the objects to the authorized user.
Long Answer: IAM is for admins or services of AWS. Do not mix it with the Cognito. Cognito is for storing and providing tokens to your users. You might ask how to provide the objects within bucket-name/user-test to user-test:
Store User Access Rights in S3: For each user have a bucket access-rights/user-test. It should conclude the user rights; for example you can have as a Json:
{
username: string,
access-bucket-name: string
}
Additional Service: You can have authentication service to check the user is authenticated (using Cognito), then based on the body of the token, get the username; and check its rights (first step) and the application should provide the object from the initial bucket the user wants to access.
Related
Is using an IdentityPool mandatory with AWS Cognito?
My use case:
My web app has users who can self-signup and will be added to the Cognito UserPool I have set up. I only want to provide access to my backend resources to authenticated users (ie., users belonging to an authenticatedRole IAM role). My requirement is simple enough that a single authenticated role suffices to handle my application's resource authorization requirements and I just want to deny access to all backend resources for non-authenticated users.
Is this possible with just the UserPool and if yes, how do I go about accomplishing this?
Note: I am using CDK to define my Infrastructure as code.
Using an identity pool is by no means mandatory with Cognito. It is completely on a use case basis. A few things to clarify here.
Userpool - For authentication
Identity Pool - For authorization.
Basically, if you want your end users to sign-up, sign-in, and then access AWS resources or make AWS API calls, then you would have to use an Identity pool. So let’s say you have a gaming application where the end user can sign in via FB, Google, or natively (username and password). This is authentication, and here we would be using a Cognito user pool. Now the user, is logged in and playing the game. They make a high score. This high score may need to be added to S3 or a DynamoDB table record for the user. For this, an identity pool is used. An identity pool will help you with vending temporary AWS credentials that the end user can use.
I believe in your use case the userpool should be sufficient. You can grant access to your resources by verifying the access token returned by Cognito for the end user.
I made a dashboard where users can upload files. I want to make it so that users can only have access to S3 urls that are files that they uploaded. How can I achieve this?
The users are application based, meaning they are, in my case, Django users.
Thanks! Anything helps!!
As this is entirely application based there are a few steps you could take to try and mitigate against accidental exposure.
Firstly organise your S3 folder structure in a way that uses prefixes for usernames, this way from a hierarchical point of view you can limit the scope of where users objects are stored. By prefix I mean the key might look like this users/$USERNAME/file.txt where $USERNAME is actually the users username.
You could enhance this in in your application by expanding to use Cognito, with a seperate user for every user you have created. When the user logs into your application you could also have the login occur via the Cognito user (this can be done programmatically).
With a successful login you'll be provided temporary credentials for IAM, all users can be assigned to a Cognito group which can have an IAM role attached. When you login it will assume this role, which allows some special properties to be supported in IAM.
By using ${cognito-identity.amazonaws.com:sub} you can actually limit the IAM permissions to only access that prefix of the S3 bucket. This moves responsibility from your application to Cognito and IAM.
More information about this is available in: Amazon S3: Allows Amazon Cognito Users to Access Objects in Their Bucket.
I have my enterprise Quicksight in place and with users using our company email to register an account (like john.doe#mycompany.com). We're using Gmail for business.
On the other hand we have developed another application backed by AWS Cognito user pool using Google as an identity provider, and since this is the same user base our intention was to use the same user pool for Quicksight access. In addition we will develop a Lambda that would synchronize Cognito user group association with Quicksight memberships if/when necessary.
I've followed the example described here https://aws.amazon.com/blogs/big-data/use-amazon-quicksight-federated-single-sign-on-with-amazon-cognito-user-pools/, but the problem is that even though I login as different users I get access to Quicksight via same IAM role. The Quicksight user associated with this role has a specific username starting with CognitoQuickSight1-AuthRole-KX4Y16... and email associated with the user I used to login the very first time.
Now I'm wondering if in this setup it's even possible to have different roles associated with different users so they can be differentiated on Quicksight side? Or is there any other way to achieve this?
I don't think you can assign QuickSight user specific permission on Federated users.
Some AWS services allows to use the user identity in the resource base IAM policy. For example S3 (to allow user to access only their 'directory' in a bucket) and DynamoBD (to allow user to only access item where their identity is the primary key).
According to https://docs.aws.amazon.com/quicksight/latest/user/security_iam_service-with-iam.html Quicksight does not support Resource based or Tag based policies.
I have an embedded device that requires the ability to write to S3. I want to avoid giving the embedded device an actual AWS IAMUser. I am looking at using Cognito to gain write access to S3.
I have a user pool with a group and one user (for now). The group has an attached policy which permits access to write to a certain S3 bucket. The pool is setup so that only admins can create new users. I have managed to authenticate the cognito user and have got access to refresh tokens and the idTokens. I am looking to use these tokens to write to my s3 bucket.
I am trying to follow trying to follow the documentation but am getting confused. I think i need a federated identity pool but i have no requirement for a public provider. I just want my cognito user group to write to s3.
Is there a simple solution to allow a cognito user to write to S3 without federated identities or if not do i require a back end to serve a token for a federated identity?
I have been using warrant https://github.com/capless/warrant to authenticate as so:
from warrant.aws_srp import AWSSRP
import boto3
client = boto3.client('cognito-idp')
aws = AWSSRP(username='<username>', password='<password>', pool_id='<pool>',
client_id='<clientid>', client=client)
tokens = aws.authenticate_user()
Any tips would be greatly appreciated!
You do need a federated identity pool. In the identity provider section you choose Cognito and enter your pool ID and pool client ID. Then, you need to provide the identity pool with authenticated and unauthenticated roles. You can use these roles to provide that S3 write access.
This is the default behavior for the identity provider setup. If you want the Role to come from the group that your user is in, you will need to set the Choose role from token option in the identity provider section under where you provided your pool and client id.
I was reading up per subject matter and has a query on what is the best practice to handle user's authorization to AWS resources.
Scenario:
A 2-tiers windows application that access to AWS S3 and dynamoDB.
There are 2 groups of users - Admin and Normal User. Admin has read + write access, and Normal User has just the read access.
I'm trying to see if I could avoid a 3-tiers design. At such, I would like to access AWS resources directly from my application. In another word, I do not access AWS resources thru web services (that could do my user authorization check there).
Design:
I uses Web Identity Federation (google) to authenticate user and uses STS to get temporary credentials.
I've created 2 IAM Roles - AdminRole (with write+read policy) and UserRole (with read policy).
At this point, my thoughts are stuck on what is the best practice and securely choose which role to assume from my application.
Solution 1:
Create a UserRole table in dynamoDb with UserId and Role attributes.
After user has authenticated with google, I'll check the UserRole table against the userid returned from google to get the role of this user. Assuming I've pre-setup all the user's roles in the table.
I do not want to hardcode or expose my AWS secret key onto my app, but for the above execution, I've created a secret key with a role and policy only to the [UserRole] table.
At this point, I would know which role to assume from my app when I get the temporary credential using STS.
However, with the above solution, I see that there is one security loophole. If someone is able to get hold of my application id used for my IAM role, and with some brute-force effort on my IAM roles' name, that person can easily gain temporary credential with AdminRole.
(added) Solution 2:
I create just 1 IAM role - GoogleUserRole
In the policy portion, I allow write access to admin user by using their Federated userid.
I'm still new with writing AWS policies, but I think I've read somewhere that I could have this fine-grained control to the specified user(s). This could be feasible if my users based are small, but not very feasible when my user base grows.
Welcome any thoughts and advises.
Thanks.