I'm writing a web app to layer some tools on top of our AWS account. I want to limit access to this web app to only those who have the appropriate access. I'm not really sure what to check (maybe which group they're in?) and how to check it (short of submitting dry-run calls to "test" their credentials?)
The flow would be something like..
User navigates to this page
Specifies what they want to do (via some prewritten scripts)
The page prompts them for a user/password associated with their AWS account
Execute the script (which will have access to do everything from start/stop EC2 to creating new ECS task definitions, modifying Route53, etc.)
What's the best way to validate that the user hitting my web app actually has permissions to execute these calls? Is there a SDK option to pass in credentials with calls, or create a credential object of some sort and test that?
A specific example of the SDK that I want to use is http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/ECS.html#registerTaskDefinition-property
AWS Cognito lets you specify separate roles for anonymous and authenticated users, with the policies you define for accessing other services: http://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html
In this broadcast we went through implementing a javascript example: https://www.twitch.tv/videos/132010411
Related
We plan to build a web client (Angular) for our project. Our Backend will be a lot of google cloud run services. How can we make sure that these services can only be called by this web application?
I understand that there are Service Account, which I can use to limit access to Cloud Run services, but how do I do that in a purely JavaScript application and without a logged in user. I just want to authenticate the application not the user.
Any advise or samples?
TL;DR: The application authentication and authorization level is managed by service account. But putting a service account key file in your Javascript app (and thus viewable by any user in their browser) is useless because your secret becomes public!
With Cloud Run, you have 2 mode: private and public
If public, no security, all the requests go to your Cloud Run service
If private, Google Front End check the identity of the requester and if they have the run.invoker permission. If so, the request pass through, else it's blocked.
For being authenticated, today, you need a service account. If you aren't on Google Cloud Platform (here in the browser of the users for example), you need a service account key file. But, if you put it in your website, it's not secure because anyone can take it and use it outside your website.
So, today, you can't do this: Either your Cloud Run is public, without any check, or private with authentication (and IAM authorization)
But, soon, at least in 2020 I hope, you should be able to put a load balancer in front of Cloud Run and to activate IAP on it. Thus, the users will be authenticated thanks to their Google account authentication cookie (SSO). However, in private mode in your browser, the user will be asked for being authenticated before going to the website. It's not authentication free, it's just authentication not manage by your own.
This is what I am trying to accomplish: I have a static website hosted with Firebase Hosting and it has a Google Forms Form. Upon clicking the submit button, I want to also send the user an email confirming that we received the form. I have written a Firebase function using an HTTP endpoint. However, that endpoint is exposed to the public. Is there any way I can protect this function? I know that we can do an auth verification with a logged-in user but I don't need the visitor to create an account to submit the form.
Thank you!
HTTP triggers deployed by the Firebase CLI are always accessible to anyone with an internet connection. The only access control is provided by Google Cloud to restrict access by IAM, which is not going to be helpful to you here.
What you should do instead is protect the endpoint to be accessible only by users signed in with Firebase Authentication. There are plenty of examples of this.
How to protect firebase Cloud Function HTTP endpoint to allow only Firebase authenticated users?
Callable functions also make it easy to check if the end user is authenticated at the time of the call.
Another possibility might be, to use req.headers["x-forwarded-for"] in order to compare the request's source IP address. It's not exactly a domain-check, because TCP/IP does not know about the DNS, but it still could be combined with a reverse lookup (or simply a list of IP address/es). It depends on the scenario (what the function actually does), because this would also work while not being authenticated. It is from where vs. who ...be aware the another Firebase hosting on the same IP address could not be told apart, but it would rule out direct access from the client-side .
Wondering if it's possible to have a webapp upload a file (userid.input.json) to Amazon S3, which triggers a lambda function that reads the file, does some processing, and saves the result as another (userid.output.json).
However userid.output.json should not be immediately accessible to the web application. The webapplication has to complete a Stripe payment and once the payment completes, the web application can access the (userid.output.json) file on amazon s3.
Before I ask how, I figured I'd first ask if this this scenario can be facilitated / architected on AWS?
Approach
Note that this is an update to the question based on more research. It looks like Amazon Cognito will be the perfect tool for signing in users and tying their user credentials to an IAM role that can read and write to S3 buckets.
So once the user is signed in through Amazon Cognito and has the proper credentials then their files can be uploaded to an S3 bucket and processed by a lambda. The result is then written to the same bucket.
Now earlier I suggested writing to a sealed bucket and having a Stripe webhook trigger moving the result from the sealed bucket to an accessible bucket. But it seems this is necessary, per the indication in the answer provided by #Snickers3192.
Once the stripe payment completes the webapp can set a boolean that is used to control access to the output and that completes the cycle?
Part of the rational for having a hidden bucket was that someone might pull the credentials out of the browser and execute them in a different script. I assume this is impossible (Famous last words :) ), but just in case I wrote a follow up question here.
In other words the credentials that are pulled into the client post signin with Amazon Cognito cannot be used to executed scripts outside of the application context?
Approach Part 2
Per my follow up questions it does not appear that relying on state within the webapp for making security decisions is good enough, as someone can probably figure out a way to get the token authentication token and manipulate the applications API directly using a client other than the core app.
So now I'm thinking about it like this:
1) Write the result to the sealed bucket (Processing Lambda)
2) Have the Stripe webhook update the users a transaction record in the users profile indicating payment paid = true (Stripe Lambda)
3) Create another lambda that has access rights to the sealed bucket but will return results only if paid=true. (Access Result Lambda)
So since Stripe is tied to an IAM user that is allowed to update the Application user profile and set paid=true and the sealed bucket can only be accessed by lambda that first checks if paid=true before returning the result, I believe that should guarantee security.
If anyone has a simpler approach please let me know.
This really is more a question of where you want to put the security, which in AWS there are many options, in your application logic which could mean:
Lambda/Webapp
S3 policies
IAM roles/groups
These decisions are usually dictated by where your identity store is kept, and also if you want to keep the notion of AWS users VS. users of your app. My preference is to keep these two pools separate, in that security logic like this is kept in the webapp/lambda and AWS security only deals with what rights developers have to the environment as well as what rights applications themselves have.
This means the webapp can always access the input and output buckets, but it keeps a record in a database somewhere (or makes use of your payment system API) who has paid and who hasn't paid and uses that information to deny or grant access to users. IMO this is a more modular design, and it enables you to lock down your AWS account better and is more clear to developers where security is located. In addition if you do go with IAM/S3 it will be more difficult to run and debug locally.
EDIT: After all your comments and additional security concerns you may also want to consider emailing a short lived URL link to the processed file, so that a user needs both email access as well as knowing their credentials to the application. This will mean even if your access token is stolen at the browser level, without the email access a hacker still can't get the processed file. If you want to be EXTREME SECURITY CORE, have the link that not only is authentication required, but also MFA so that they need to enter in a code which is constantly refreshing as you should have setup for your AWS account when you login.
I'm by no means a security expert but just follow best practices and do your due diligence and you will meet security expectations.
I'm newbie to Facebook Graph API and Facebook JavaScript SDK but I'd like to know some things:
Is there any way to put my Access Token in a Open Source application without actually showing it? I'm using GitHub and for security purposes I'd like to make it private.
Can I show my user information without asking the users to Authenticate themselves?
Where in Facebook Developers App can I allow more "scopes" to share publicly? For example, user_photos, user_posts, user_likes, user_status, etc...
These "scopes" that Facebook allows by default are actually the information I'm getting from the user while I'm Authenticating them right?
Just to clarify what I'm trying to do, I want to share things about my Facebook Account through the Facebook Graph API in the gh-pages branch on GitHub, but I don't like the idea of having to authenticate every single user that has access to the page.
I'd like to make my user information public, but don't want to show my access token, because it's Open Source and it can get dangerous eventually.
If you'd like to see my repository and have a better understanding of the project. You can access https://github.com/iszwnc/rye
If I recap:
you don't want to share your app access token (good!),
you don't want your users to authenticate.
Basically, you can't hide your token and let your users query Facebook directly. You need some server-side code on a machine that would be the only one reaching Facebook. Your server would play the role of an interface between Facebook and your users. So you will have to:
do the API calls from a server using server-side code (i.e. Node.js),
save the information you want in a database. This is optional but better to avoid the same information to be retrieved multiple times, thus avoiding your future 100 users to (voluntarily or not) reach your app API limit.
let the users query your server using some client-side code (i.e. AngularJS) in order to retrieve what you and only you know (remember, you own the token).
About Github, don't share your token on it. People can generate their own token if they want to run your app. Here are several suggestions:
Add your token to an environment variable which you can set just before launching the app (don't forget to mention that in your README),
Add your token to a file:
Create a credentials.js file that contains an empty token:
// Please use your own token
var APP_TOKEN = '';
Commit the file to Github,
Have a .gitignore file that contains the credentials.js,
var APP_TOKEN = 'now-you-can-put-your-token-here';
Good luck with your project, it looks exciting :-)
I want to create a client-side (server-less) application using the AWS SDK for JavaScript in the Browser. All intended users of the tool have individual IAM users and access to the AWS Web Console.
I want all API calls to be executed in the context of individual IAM users, so they are subject to each user's individual permissions, and so that I can see who did what in CloudTrail.
Since no kind of browser local storage should be trusted with persistent credentials, I cannot simply let the user enter his secret access key once and keep it.
However I guess I could request the user's access key id and secret access key on the beginning of each session, then call STS GetSessionToken with it, and only store the resulting temporary security credentials in the session storage and use that for all following SDK usage.
Of course it would be much nicer for users to be able to log in with their IAM user and password instead of their long and cryptic access key (think of mobile devices...).
Is there any kind of federated login option for IAM users (redirecting them to the AWS IAM login page), or a way to call the STS API with username and password?
Ideally, what you want is login via IAM user/password combination. As far as I am aware (and also see this) there is no standard way of doing this.
In one of my projects, I've simulated online login using HTTP client. If you can get the session token with that, that could work for you. But it does not support MFA, and is relying on the internals of the AWS authentication implementation which might change without warnings.