What is the preferred way of using AWS (specifical

2020-06-06 04:23发布

问题:

Adding the AWS access key and secret key directly in app code is definitely not a good approach, primarily because the app resides on the users device (unlike server side code), and can be reverse engineered to get the credentials, which can then be misused.

Though I find this information everywhere, but am unable to find a definitive solution to this problem. What are my options? I read about the token vending machine architecture for temporary credentials, but I am not convinced that it is any better. If I can reverse engineer the secret key, then I can reverse engineer the code which requests for temporary credentials. And once I have a set of temporary credentials to access S3, I am as good as if I had the key. I can request the temporary credentials again and again, even if they expire pretty quickly. To summarize, if an app can do something, I can do the same as a malicious user. If anything, the TVM can be a bit better at management (rotating credentials, and changing key in case of breach, etc.). Please note we can put the same access restrictions on the secret key, as we plan to do in case of TVM temporary credentials.

Additionally, if Amazon doesn't want people to use the secret key directly in the App, why don't they block it in their SDK, and enforce TVM or the correct solution. If you will leave a path, people are going to use it. I read several articles like these, and wonder why?: http://blog.rajbala.com/post/81038397871/amazon-is-downloading-apps-from-google-play-and

I am primarily from web background, so my understanding of this may be a bit flawed. Please help me understand if this is better, and whether there is a perfect (or may be good) solution available to this problem.

PS: Is there a rails implementation of TVM?

回答1:

Embedding S3 keys in App code is very risky. Anyone can easily get that key from your app code (no reverse engineering or high skill set required), even if that is stored encrypted it is still compromised just that someone need to try harder (depending on how do you encrypt).

I hope that you understand the advantages of using temporary credentials to access Amazon (S3 etc) resources (mainly security + some others like no app update etc). I think you are more confused about the process to get the temporary credentials from TVM and how that is safer than embedding keys in code.

Every client using TVM first need to register with the TVM server implementation hosted by you. The communication between App (using TVM client) and TVM server is over SSL.

First the app register with TVM by providing UUID and a secret key. Please note that the secret key is not embedded in App code (which I think is main reason for your confusion) but generated randomly (using SecRandomCopyBytes which generates an array of cryptographically secure random bytes) at the time of registration (and hex encoded).

Once the device is registered successfully with TVM, the client TVM store the generated UDID and secret key in a storage called Keychain in iOS and Shared Preferences in Android. The keychain in iOS is the shared storage provided by iOS to securely (encrypted) store information (mainly keys, password etc).

After registration and UDID/Secret Key storage, App can get the token from TVM by sending the UDID, cryptographic signature, and a timestamp. The cryptographic signature is an HMAC hash generated from the timestamp using the secret key. The TVM can use the UDID to lookup the secret key and uses it to verify the signature. The TVM then responds by sending back temporary credentials, which are encrypted using the secret key (uses AES). The application decrypts the temporary credentials using the key and can then use them to access any AWS services for which the temporary credentials are authorized. Eventually, the expiration time of these temporary credentials will be reached, at which point the application can get the fresh temporary credentials, if required.



回答2:

I am not sure how signed URLs relate to TVM, because I don't understand the concepts 100% but signed URLs really solved the problem for me. I needed a mechanism that would feed web app and mobile app data without allowing for misuse of the credentials. Putting the key in the code is indeed a very bad idea as it may generate a huge bill for the company.

After 3 days of extensive research, I found a simple and, what seems to be, a reliable and relatively safe solution: signed URLs. The idea is, that a very light-weight back-end can generate a temporary URL that will grant the user access to the specific resource for a limited time. So the idea is simple:

  • the user asks our back-end with a Rest call that he wants a specific resource

  • the back-end is already authorized with AWS S3

  • the back-end generates a temporary URL for the user and sends it in the Rest response

  • the user uses the URL to fetch the data directly from the AWS

A plug-and-play Python implementation can be found here and with a slight modification that I had to use: here.

Of course one more thing to figure out would be how do we authorize the user before we know that we can grant it the URL but that's another pair of shoes.



回答3:

You should ideally use Cognito Identity for achieving this along with appropriate policies. It should be used with S3TransferUtility and S3TransferManager in iOS and Android SDKs. That would allow for background uploads and downloads as well. Cognito vends temporary credentials for access to AWS resources and is free. Also, you could federate it using UserPools or providers like Google, Facebook if you want secure access.

Thanks, Rohan