Respecting an API key with Amazon's API Gateway - amazon-web-services

I'm learning serverless applications. I've created a simple Lambda that I've confirmed is working via Paw/curl.
Next I completed the API Gateway tasks of:
create a POST Resource that requires an API key
create beta and test Stages
create the API key
create a Usage Plan
associate the API key with the Usage Plan
associate the Usage Plan with the test Stage
I expect requests with the x-api-key Header to work, and those without to be denied. But I observe all requests continue to successfully finish regardless of that Header's presence.
I've recreated individual API Gateway steps and eventually the process as a whole, to no avail. Any clue of what I've missed?

I'm not seeing anything that screams of a problem. This blog walks through doing the same thing, but it results in a 403 when calling without the key. Any chance it's something simple, like you changed the "API key required" flag and didn't deploy again?

Related

Delay in using API Key added to API Usage Plan with AWS Cognito

Description
My application uses cognito user pools for identity management and cognito authorizer on API Gateway.
Once the user signs in (using aws amplify), a lambda function is triggered, which generates an API Key, adds it to the API Usage Plan against the cognito user and also adds it in a custom field in cognito.
Using the custom field (which is the API Key), I want to call an API endpoint (configured on the gateway with cognito authorizer).
Problem
Upon user signup/login, I get the custom field which is the API Key on client side and then immediately, I call an endpoint passing the key in headers (x-api-key).
But, the API Gateway takes time to recognise the API Key from the usage plan (and shows the error "Unable to find the key in Usage Plan" in cloudwatch logs).
Hence, on immediate use, it throws CORS error (which isn't actually the right error, because I've configured cross-origin header to *). The actual reason might be the one seen in cloudwatch logs.
After a delay of around 25-30 seconds, I am able to access the API Endpoint without any error.
I am unable to figure out what am I doing wrong and why is it taking time for API Gateway to populate the API key internally?
I've read about issues (Api Gateway Api Key immediate use upon creation giving forbidden) and (How long should I wait after applying an AWS IAM policy before it is valid?) earlier and they state that it's due to the globally distributed nature and hence the delay.
But, for others the delay is between 3-5 seconds, while in my case it's 25-30 seconds which is my main concern as it causes the user to wait until the API's are accessible on the page in my application.
What is the workaround or solution to this, and is my approach of this whole mechanism is correct or am I missing something?

Attaching a usage plan to a public Api Gateway Endpoint

For learning purposes, I have developed a front-end application in Angular with AWS as back-end.
As this is a didactic project, I must prevent any possible costs explosion. Overall, for what concerns API Gateway calls.
At the moment, I have a single public GET endpoint for providing the information to the public homepage in the front-end.
I need to attach a usage plan to this endpoint for limiting the maximum number of calls to this endpoint. For example, max 10000 calls/week.
I already tried with an API-KEY:
Created the Usage Plan with "Quota: 10,000 requests per week"
Created the API KEY connected to the Usage Plan
Connected the API KEY to the authentication method of the endpoint
It works, but in this way I need to hard code the API KEY on the front-end.
I know that hard coding sensitive information on the front-end is a bad practice, but I thought that in this case the API KEY is needed only for connecting a Usage Plan, not for securing private information or operations. So I'm not sure if in this case it should be acceptable or not.
Is this solution safe, or could the same API KEY be used for other malicious purposes?
Are there any other solutions?
To add to the other answer, API Keys are not Authorization Tokens.
API Keys associated with Usage Plans are sent to the gateway on the x-api-key header (by default).
Tokens used by authorizers live on the standard Authorization header.
Use API Keys to set custom throttling and quotas for a particular caller, but you still need an Authorizer on any secure endpoints.
You can optionally set an API Key to be returned from the Authorizer when using a custom authorizer to be applied to the Usage Plan, which prevents you from having to distribute keys to clients in addition to their secrets.
APIG Key Source Docs
As the documentation says, generally you wouldn't want to rely on a hardcoded API key for authentication.
In addition, based on the information you provided, the usage plan limits are tied to the use by the user of the API key. So you could also set up throttling on the account or stage itself.
Finally, if it's possible, you could set up security group rules on your server or access control lists on your vpc that is serving your front end so that not everyone can access it.
Other ideas are to shut down the API gateway when you aren't using it and also rotate the API key frequently.
Obviously none of these are going to be enough if this were hosting sensitive information or doing anything remotely important. But as long as the only information in the client side is that API Key to access the API Gateway and that API Gateway itself doesn't interact with anything sensitive that's probably enough for a learning project.
But you should do all of this at your own risk as for all you know I'm the person who's going to try to hack you ;)

Calling api gateway returns 403 and error about api key within CI but is fine outside of CI (Codebuild)

Using Cloudformation I have created an API Gateway and Usage Plan and then use the CLI/SDK to create an API Key. All this happens within our CI process. Then we test that the api returns the correct results (using dredd), however it fails with the following error:
API Key **********************************Rp9Mjh not authorized because method 'GET /bookings' requires API Key and API Key is not associated with a Usage Plan for API Stage XXXX/Prod: No Usage Plan found for key and API Stage
When I test the key outside of Codebuild (ie postman) it works fine.
Could somebody offer a suggestion of what could be wrong as I'm not sure why the exact same request fails from within Codebuild but runs fine outside.
Adding a sleep in the buildspec has fixed this. Apparently when api gateway generates the key its not available straight away.

AWS API Gateway: How to achieve continuous delivery?

I'm building an API using AWS API Gateway and AWS Lambda. I would like to achieve continuous delivery for this API. The path I've chosen to do it is to use CloudFormation through AWS CodePipeline. I've managed to to it for another project using Lambdas (without API Gateway), it works perfectly and it is really pleasant to use.
The issue I'm facing when deploying is that the Lambdas are properly updated but not the API definition. From what I understand, the AWS::ApiGateway::Deployment are immutable resources which means that for each deployment of the API I need to create a new AWS::ApiGateway::Deployment resource. This is not practical at all because for each of this AWS::ApiGateway::Deployment I have a new Invoke URL. This is not acceptable since I would have to either change my DNS record to the newly deployed API invoke URL or ask our API users to change the URL in their applications.
What I would like is to be able to change the API definition and the Lambdas implementations without my API users having to change anything in their applications.
How can I achieve this behavior?
I created a tutorial to highlight my issue. You can find it at: https://github.com/JonathanGailliez/aws-api-gateway-lambda-example
As per: https://forums.aws.amazon.com/thread.jspa?messageID=789869&#789869
joey-aws says:
We are currently in the process of rolling out a solution which
addresses this exact problem. In the meantime, a common workaround
would be to update something small, such as a "description" field
which could then be used to "trigger" an API Gateway deployment when
updating the CloudFormation stack.
I'll update this answer and the example repo once it's rolled out.
You could run a Cloudformation update from the command line or in the AWS console. This would change the API definitions and any lambda code without changing the unique id to access your gateway.
The other option is to put your API behind a custom domain name and then you could keep deploy a new API or stage and switch over the custom domain mapping when you are ready. The users wouldn't recognize any change.
A way to achieve that is by leveraging existing frameworks like
AWS SAM
Serverless
Claudia
I was able to achieve this by using CloudFormation template generated by troposphere and boto3 api in Python as follows:
Split the template into two parts
API definition, Method(s), IAM roles, ApiKey and Lambda (a)
Deployment, UsagePlan and UsagePlanKey (b)
Once changed Lambda code is zipped up and uploaded to S3 using boto3 api
Stack (b) is deleted
Stack (a) is updated with new resource id for the GET method connected to lambda
Stack (b) is created anew
Steps 3, 4, 5 are performed using CloudFormation boto3 api with blocking until completed.
Most importantly after all steps are done ApiKey value and stage Invoke URL remain the same, running updated Lambda code as tested with curl.
Note: it may take additional 30-60s for API to become fully functional after CloudFormation update is completed.

Inconsistent behavior AWS API gateway . Getting a 403 for an API that was working

I have a few API that have been working for a while. All of them are secured with an API key. For some reason all of them have stopped working and are throwing a 403,Error from cloudfront. None of them have any caching mechanism enabled. When I test my Lambda function via AWS console for these API endpoints, things work. In an attempt to recreate the issue, I pointed one of my test api endpoints to the lambda function without API keys. And that worked. Then I added API keys to the API and re-deployed it. Funnily enough, I was able to Postman them without passing x-api-key header. For this test API end point the response for Cache is X-Cache →Miss from cloudfront.
There is No difference in the setup for the my original API/test API. This behavior is inconsistent and without it my app function at all.
There was an update that was rolled out that affected a small number of customers using API Keys. Unfortunately it seems like you were one of the customers affected. We believe we have corrected the issue and you should no longer see 403s from your API when using a valid API Key.
Note: The reason you see CloudFront headers is that API Gateway creates a CloudFront distribution for each api.
Just regenerate your key and it should work as expected.