How to secure AWS credentials in frontend - amazon-web-services

I have created a static website which is hosted in S3.
Now I need to upload a file to another S3 bucket via that frontend.
For that I am using AWS library.
Problem is I have to give the AWS access keys to the AWS library.
As hardcoding the credentials is a bad practice, what can I do to securely pass the access keys to the AWS library?

Use AWS JavaScript SDK to call the sts:assumerole to get the temporary credentials that will be valid for certain time instead of hard-coding them in your code.
Once you get the Access key and secret key along with the SessionToken use them in AWS Library and the credential will be valid for 1 hour by default, if duration is not specified while calling assume role api.
Hope this helps

Related

AWS: Does my S3 bucket need a policy for files to be readable from my application?

I have a Laravel application that is hosted on AWS. I am using an S3 bucket to store files. I know that I have successfully connected to this bucket because when I upload files, they appear as I would expect inside the bucket's directories.
However, when I try to use the URL attached to the uploaded file to display it, I receive a 403 Forbidden error.
I have an IAM user set up named laravel which has the permission AmazonS3FullAccess applied to it, and I am using that key/secret.
I have the Object URL like so:
https://<BUCKET NAME>.s3.eu-west-1.amazonaws.com/<DIR>/<FILENAME>.webm
But if I try to access that either in my app (fed into an audio player) or just via the link directly, I get a 403. None of the tutorials I've followed to get this working involve Bucket Policies, but when I've googled the problems I'm having, Bucket Policy seems to come up.
Is there a single source of truth on how I am to do this? My AWS knowledge is very limited, but I am trying to get better!
When you request a URL of the form https://bucket.s3.amazonaws.com/dog/snoopy.png, that request is unauthenticated. Your S3 bucket policy does not allow unauthenticated access to the contents of the bucket so that request is denied with 403.
If you want your files to be downloadable by an unauthenticated/anonymous client then create an S3 bucket policy to allow that.
Alternatively, your server can create signed URLs and share those with the client.
Otherwise, your client's requests need to be authenticated, which means having correctly-permissioned credentials and using an AWS SDK.
Typically, back-end applications that you write that need access to data in S3 (or other AWS resources) would be given AWS credentials allowing the necessary access. If your back-end application runs in AWS then you would do that by launching the compute with an IAM role.
Typically, front-end applications would not have AWS credentials. Instead they would either authenticate to a back-end that then does work with AWS resources on their behalf. There are other options, however, such as AWS Amplify apps.

AWS IAM and java sdk service clients - How does credentials are generated using role associated with a service?

I am running java app on ECS fargate and have attached a role with the fargate task to perform s3 operations. From my java process i have started using DefaultCredentialsProviderChain.java from aws sdk to get the credentials and create s3 client. I am facing issues to understand below mentioned questions:
Which class in the chain (in DefaultCredentialsProviderChain.java) gets credentials (temporary key and secret access key) from the role associated ? And For how long these temp credentials are valid ?
Can i cache the s3 client created with credentials from DefaultCredentialsProviderChain.java so that on java service startup s3 client will be built once or s3 client needs to be created each and every time any s3 operation needs to be performed?
I followed below mentioned link but did not get my answers, Can anyone please help me to understand these queries.
https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/credentials.html#credentials-chain
Which class in the chain (in DefaultCredentialsProviderChain.java) gets credentials
As you have attached a runtime role, the AWS will provide a metadata service. The credential provider will use the service to fetch the runtime credentials. By default the runtime credentials are valid for one hour (as far I recall).
https://docs.aws.amazon.com/AmazonS3/latest/userguide/AuthUsingTempSessionToken.html
Can i cache the s3 client created with credentials
Yes you can. The credential provider keeps track of the session lifetime and refresh the token some time before expiration (as well - as far I remember).
This actually places some limits when creating a presigned url. The presigned url is valid only until the credentials are valid. So it may happen that you create a presigned url and the url will be valid shorter time than expected

AWS securing accessKeyId and secretAccessKey

I'm trying to make javascript access Amazon S3 bucket, and everything works as expected. I need to secure the javascript sothat I dont store the accessKeyId and secretAccessKey in code or TFS. Below is the bit which passess the access and secret keys.
AWS.config.update({
region: '--region-code-here--',
accessKeyId: '--keyhere--',
secretAccessKey: '--secretkey-here--'
});
const s3 = new AWS.S3();
//... more code...
According to amazon https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-browser.html, the suggested way is to Using Amazon Cognito Identity or Using web federated identity than hardcoded in the script. I find it hard to follow the amazon documentation in my S3 context.
Accessing S3 via javascript is part of a larger application, and I cannot prompt the user for separate credentials for the JS to access the S3 bucket.
Any tips very much appreciated. The ultimate goal is to secure the access key being hardcoded.
Assuming your JavaScript code is running in a web page, your app will not be able to access your S3 bucket unless it has credentials or you make the bucket public. Assuming you don't want to make the bucket public, you need to find a way to get credentials to the app.
Typically you would want to authenticate the user before you hand out credentials (because those credentials will be visible in the app) and you can do both with a dedicated server application. Or you can do this more easily with Cognito or WIF, which will authenticate the client and convert that into a set of credentials for a given IAM role. Or, of course, you could ask the user to supply AWS credentials, but I'm assuming that's not appropriate in this case.

AWS S3 Upload Using Signed URL

AWS provides SDKs on iOS and Android to upload to their servers yet you don't want your key exposed if it was decompiled. How do you prevent that? Is there a way to sign a URL on the backend and give it to the client so they can upload directly onto S3 Without exposing the key?
You can use Amazon STS (Security Token Service) to generate unique sign-in credentials that also expire automatically.
You can also control permissions on these temporary credentials obtained via STS (for example to allow only upload permissions in a certain S3 bucket).

accessing AWS S3 from a desktop app securely

I have data from multiple users inside a single S3 account. My desktop app has an authentication system which let the app know who the user is and which folder to access on S3. but the desktop app has the access code to the whole S3 folder.
somebody told me this is not secure since a hacker could break the request from the app to the S3 and use the credentials to download all the data.
Is this true? and if so how can I avoid it? (he said I need to a client server in the AWS cloud but this isn't clear to me... )
btw. I am using Boto python library to access S3.
thanks
I just found this:
Don't store your AWS secret key in the app. A determined hacker would be able to find it eventially. One idea is that you have a web service hosted somewhere whose sole purpose is to sign the client's S3 requests using the secret key, those requests are then relayed to the S3 service. Therefore you get your users to authenticate agaist your web service using credentials that you control. To re-iterate: the clients talk directly to S3, but get their requests "rubber-stamped"/approved by you.
I don't see S3 necessarily as a flat structure - if you use filesystem notation "folder/subfolder/file.ext" for the keys.
Vanity URLs are supported by S3 see http://docs.amazonwebservices.com/AmazonS3/2006-03-01/VirtualHosting.html - basically the URL "http://s3.amazonaws.com/mybucket/myfile.ext" becomes "http://mybucket.s3.amazonaws.com/myfile.ext" and you can then setup a CNAME in your DNS that maps "www.myname.com" to "mybucket.s3.amazonaws.com" which results in "http://www.myname.com/myfile.ext"
Perfect timing! AWS just announced a feature yesterday that's likely to help you here: Variables in IAM policies.
What you would do is create an IAM account for each of your users. This will allow you to have a separate access key and secret key for each user. Then you would assign a policy to your bucket that restricts access to a portion of the bucket, based on username. (The example that I linked to above has good example of this use case).