I have a user with read access on a bucket. Is there a way to authenticate with the users' credentials without using my secret key?
Something like (pseudo code):
auth = new S3Authentication(user, pass)
obj = S3::getObject(obj, auth)
Update
I discovered the solution to my own question. See below.
The original reason for asking this question was because I was operating under the assumption that the global access and security key needed to be use to generate the appropriate Authorization digest header.
This is not the case.
You can use Amazon's IAM to create a new key pair to use when authenticating. Here are the steps:
Create a new Group in IAM
Set the policy on the group to whatever you access you want users within this group to have. In my case, I just chose the S3 Read-Only policy template
Create a new user and put it in this group
Creating a new user will generate a new secret/access key specific to that user. You can use this pair to auth S3 transactions.
As an aside, you shouldn't need to mess with the bucket-specific permissions. In my case, I have no bucket permissions set (not even Authenticated users) and it works just fine.
Related
I read some questions and answers about my issue, but I still don't know the answer.
Can I use the userSub in AWS Cognito as primary key?
AWS Cognito: Difference between Cognito ID and sub, what should I use as primary key?
First, I will try to describe my case.
I want to create an application with spring boot as a resource server that uses oauth2. Then to save me some time with user management, I was hoping to use AWS Cognito since it allows me to create users as admin. I can set it up that it won't let other people sign up for themselves, which is crucial for me since my app will have restricted access; the admin will manage that.
Now to my question, which field of AWS Cognito can I use as the primary key for keeping user-specific data in my DB? I read that neither usernamenor sub is correct.
username can be changed, for example, and sub is globally unique, so it can't be restored. Is there any way to create a custom field where AWS Cognito will autogenerate UUID that I can use, and if I had to restore the user pool, I would have an option to set this field?
You can still go with username. If it is ever changed, just update your database to reflect this change.
You can also create a custom attributes in user pool. You can use that to store a self generated id. As for automatically generating this, you can have a post confirmation lambda trigger that will use adminUpdateUserAttributes to assign a unique id.
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 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.
I am new to AWS so not fully aware of its features.
I want to create an application running on EC2 instance which allows a user to login and upload a picture to a S3 bucket.
The user is created in through IAM in AWS, and assigned a policy to allow that specific user to only access that specific bucket.
However, in my code, I do not want to store the Access ID and the Secret key - which is assigned by AWS when I create my user due to Security issues i.e. in case someone gets access to them.
In order to solve this, my thoughts were to create my own login system, where I create a user (e.g. user = abc1, password = password1), and in the background the user and password will be equal to the access key and the secret ID without the user ever knowing them.
Is this a good way forward with this and how would I go ahead with it? Or is there a better way of doing this?
This is my recommendation:
Build your own login system (typical login/password(hashed) system), and assign an IAM user to the application itself (or the machine with a machine role), not the user, so the application (or machine) is the entity allowed to run the S3 operations. This way is easier to manage privileges.
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.