The Serverless Framework makes coding, deploying, and maintaining serverless functions a breeze. That's a great set of characteristics, but what about security? Well, securing API endpoints is straightforward, too.
This post shows you how to secure your AWS Lambda endpoints in three steps.
- Add
apiKey
property toserverless.yml
- Copy the key that is returned after deployment
- Use the key as your
x-api-key
header in your API requests
The apiKey
Property
Generating an api key is as simple as adding an additional property to your serverless.yml
file. Under provider
, add the apiKey
property and list the names of api keys you want generated (lines 7-8 below).
provider:
name: aws
runtime: python3.6 # This could be any runtime
stage: dev
region: us-west-1
apiKeys:
- celery_${opt:stage}
- anotherKey_${opt:stage}
Notice the ${opt:stage}
part of the keys. This syntax is how you use variables in serverless.yml
. It takes the stage
and inserts it where the variable syntax is placed. When you deploy to dev
, the celery key is celery_dev
. When you deploy to production
the key is celery_production
.
This isn't a requirement, but it's a good idea to include if you're deploying to multiple environments. A key name can only be used once in a project, so if your dev
deployment uses the key name celery
, then celery
can't be used for your production deployment. You'll get an error saying the key name is already in use. Using the syntax above (lines 7-8) circumvents these naming issues.
Additionally, you can assign different requesters different keys (e.g. some use the celery
key, others use the anotherKey
key) if you want to keep track of where your requests are coming from.
Retrieving the apiKey
Value
After deployment, the following information is returned:
Serverless: Stack update finished...
Service Information
service: my-lambda-service
stage: dev
region: us-west-1
stack: update-account-columns-dev
apiKeys:
celery_qa: KrdJFKaodifhoae76asdfkj987dfliIdaffiD
anotherKey_qa: dsAfJaodifhoae76asdfkj987dfliiuehfns6
endpoints:
POST - https://dkfj7dkfh7.execute-api.us-west-1.amazonaws.com/dev/
functions:
my_lambda: my-lambda-service-dev-my_lambda
If you've already deployed, and need this information again, run sls info -s <dev/qa/stage/production/whatevs>
from the root of your serverless project. For example, to get the info above, I could run sls info -s dev
.
Lines 7-9 above show two api keys, and their values. You'll need to use one of these values to get through to your endpoint.
Using the x-api-key
Header
Using the API key is no more difficult than adding a header to your request. Specifically, you need to add an x-api-key
header.
Below you'll find two examples. The first in Python using the requests
package. The second in Node.js using the new r2
package (which is Mikeal Rogers's – the creator of request
– latest http library)
Python using requests.
import requests
headers = {
"x-api-key": "KrdJFKaodifhoae76asdfkj987dfliIdaffiD"
}
my_profile = requests.get(
"https://your-api/dev", headers=headers)
print(my_profile.content)
Node using r2.
const r2 = require("r2");
const headers = {
"x-api-key": "dsAfJaodifhoae76asdfkj987dfliiuehfns6"
};
const myProfile = () => {
return r2.get("https://your-api/dev", {
headers
}).response;
};
myProfile()
.then(res => res.json())
.then(json => console.log(json));
Conclusion
API keys are not a complete security solution, but are a great start to securing your endpoints. And, by all means, using API keys to secure your endpoints is much better than no security at all!
For more on security, check out this great overview of different security strategies, including a discussion of use-cases for API keys.