How to setup API keys for AWS API Gateway using SAM templateMon, 30 Sep 2019
At first you could think it is pretty simple, however it is not. Once again AWS documentation is a bit incomplete. Therefore I decided to write a quick guide to save you a couple of hours of desperation and depression.
So first problem, as today, 2019-09-29, SAM does not support API keys directly. Therefore one alternative is to use swagger definition securityDefinitions
and
x-amazon-apigateway-api-key-source
The second problem is that you cannot use an API key alone, it must be associated with an API usage plan.In our swagger definition we should add the following lines of code:
x-amazon-apigateway-api-key-source: HEADER
securityDefinitions:
MyApiKey:
type: "apiKey"
name: "x-api-key"
in: "header"
paths:
your/path:
get:
security:
- MyApiKey: []
Now let's create our API key directly from our template:
MyApiKey:
Type: AWS::ApiGateway::ApiKey
Properties:
Enabled: true
After finish, you should deploy your application, for the purpose of automation I have created a simple script to deploy any template (Cloudformation or SAM) directly from the command line. After deploying let's test our end point without authentication.
curl -X GET https://my-endpoint
Execute the command and, hopefully, you should receive this message: {"message":"Forbidden"}
.
Now let's try with the API key. To grab it, just log into the AWS console and navigate to API Gateway, then click on "API keys", select your key and under "API key" click on show. Copy it and paste it on the following script.
curl --header "x-api-key: <your api key>" -X GET https://my-endpoint
The key must be placed on the x-api-key
header. Execute the script and you should receive this message: {"message":"Forbidden"}
Wait what?! Yes, this is an expected behavior and it took me some research to finally get an answer. So what is going on here? Well, when you setup an API key, you must also associate it with a usage plan. So let us create a plan with SAM template by adding two more resources: the first is the plan itself, the second is the association with the API key that we previously created.
APIUsagePlan:
Type: AWS::ApiGateway::UsagePlan
Properties:
ApiStages:
- ApiId: !Ref MyApi
Stage: !Ref Environment
ApiUsagePlanKey:
Type: AWS::ApiGateway::UsagePlanKey
Properties:
KeyId:!Ref MyApiKey
KeyType: API_KEY
UsagePlanId: !Ref APIUsagePlan
Now let's deploy again and test it. Finally this time the response should be 200. I really hope I saved you couple of hours of work by writing this post. If you have any comments or suggestions, feel free to contact me at [email protected] or visit my site.
Cheers!