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.
Related
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.
lets say I have a on-premise application that needs to access various AWS services such as S3, Cloudwatch etc. What is the correct way to handle this authentication? I have read recommendations to create a new iam role and then distribute the AWS keys on the server that the application runs. But wouldn't this be very bad practice in case the keys gets stolen or exposed in some way? It would also be more work to rotate credentials for example. Is it possible to assign roles in some other ways or this is the correct way to do it? Isn't it better to assign roles or that isn't possible when not running the app in AWS?
Creat an IAM user with “Programmatic Access” only, which will provide you with a key and secret pair.
As a general rule, your application can use one set of credentials to get another, more privileged set of credentials. The app must be able to authenticate somehow so it needs some basic form of service account credentials to start with.
One way you can do this is to create an IAM user with minimal privileges. This IAM user is able to assume a specific IAM service role, but nothing else. That service role actually confers permissions to interact with S3, CloudWatch etc. Your application is configured with, or somehow securely retrieves, the credentials associated with the IAM user. Your application then uses these to call STS and assume the IAM service role, getting back short-lived STS credentials (access key, secret key, and session token). You should leverage the additional 'external ID' with the IAM role, as one more security factor.
Your application is also responsible for getting a new set of credentials before the existing set expires. You can do that in a number of ways, for example by using new STS credentials for every single request you make (so they never expire) or simply paying attention to the credentials expiration time and refreshing prior.
Also, read Temporary Credentials for Users in Untrusted Environments.
If your application is running on an Amazon EC2 instance and it is the only application on that instance, then:
Create an IAM Role
Assign the appropriate permissions to the Role
Assign the IAM Role to the EC2 instance
Any software running on the instance will automatically have access to credentials to access AWS. These credentials automatically rotate every 6 hours.
If you are not running on an EC2 instance:
Create an IAM User
Assign the appropriate permissions to the User
Generate credentials for the User (Access Key, Secret Key) and store them in a credentials file on the computer being used by the application
Any software running on the instance will automatically have access to these credentials to access AWS.
i'm a root user for my AWS account and i want to give my full root access to a particular user(user1 is my user which i created from my root account) "only for a particular region". The user can create new users, groups and also can access to all AWS services only in that region (ex: us-east-1).
is it possible to give an access to a user?
I tried in the JSON and visual editor also, but it is working only for EC2 but user need to access all the root admin permissions only in that particular region.
Thank you
It is only possible to restrict an IAM user/role to use a single region for EC2 service because there is no available condition key for other services. Also note that there are several services which are global e.g. IAM, Route53 etc.
Regardless of regions, there can only be one Root user in an account but you can create IAM users with administrator access which will have full access but to do certain tasks, you still need Root credentials (please refer to the comparison).
I am planning on a web page that creates an instance for an user using a specific AMI. Is there any AWS method to let the user approve my web application to do this using their credentials? (i. e. getting a secret token with certain privileges)
Similar to when you let a Facebook application have access to certain information of your profile. I am looking for a way to get a token from the user signed in so that I can create an instance for them.
I want to avoid the user the pain of doing all the manual steps of going to IAM, create a new user, get the token and then upload them to my site.
I looked into AWS Cognito but this doesn't seem to be what I am looking for.
Similar to when you let a Facebook application have access to certain information of your profile.
AWS and Facebook are not similar in any sense. Facebook is a web application. AWS something entirely different.
Facebook has users, but AWS has accounts, which in turn have users... but in AWS, don't need a user's permission to do things to resources -- what you actually need is an account's permission to do things to its resources, because resources are associated with the account, not the user.
I am looking for a way to get a token from the user signed in so that I can create an instance for them.
Users sign in to the AWS console. After this, there is no such concept as a user allowing an external application doing things under the "signed in" user's auspices.
The user has to have sufficient permissions to either create sufficiently-privileged temporary IAM credentials (such as with GetSessionToken or AssumeRole from the IAM API) and hand them over to you, or create an IAM user with sufficient privilege and hand the keys to that user over to you... or you provide them with the ARN of one of your IAM users, and your customer gives your user permission to perform the actions or assume a role in your customer's account, created for the purpose.
I want to avoid the user the pain of doing all the manual steps of going to IAM, create a new user, get the token and then upload them to my site.
That can't be avoided, by design... and, in any event, whatever exactly you are planning, your model seems flawed: it would only be a naïve user who would allow you to do this. I have accounts that are allowed to launch hundreds of instances concurrently. Does it make sense that I would allow a third party to have access to credentials that could run up a huge bill for me? (If AWS trusts a set of credentials to launch instances, then it trusts them to launch instances -- all the way up to the account's instance limits).
If you want a user to be able to launch an instance from your AMI, you can simply list it on the AWS Marketplace, or you can share the AMI with the user's account, or even just make the AMI public.
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.