grunt-aws-apigateway
A grunt plugin to easily configure and deploy AWS API Gateway.
Scope
AWS API Gateway configuration through the web console takes lot of mouse clicks and is error prone. This grunt plugin allows you to script and automatically deploy your API Gateway configuration.
Install
npm install grunt-aws-apigateway --save-dev
Usage
The following usage example could look a bit verbose at a first glance. However, AWS API Gateway setup is pretty complex and the following resources
structure tries to map as much close as possible the AWS API, in order to provide the same degree of flexibility.
grunt.initConfig({
apigateway_deploy: {
options: {
accessKeyId: "key",
secretAccessKey: "secret",
region: "us-east-1"
},
default: {
restApiId: "xxx",
deployment: {
stageName: "prod"
},
resources: {
"/users": {
methods: {
GET: {
integration: {
type: "AWS",
uri: "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:xxx:function:getUsers/invocations",
integrationHttpMethod: "POST",
requestTemplates: {
"application/json": JSON.stringify({
"filter": "$input.params('filter')"
})
}
},
responses: {
200: {
responseModels: {
"application/json": "Empty"
}
},
400: {
selectionPattern: "error code: 400",
responseTemplates: {
"application/json": JSON.stringify({"error": "$input.path('$.errorMessage')"})
}
}
}
}
}
}
}
}
}
});
grunt.loadNpmTasks('grunt-aws-apigateway');
grunt.registerTask(
"deploy-api",
"Deploy the API Gateway config",
["apigateway_deploy"]
);
Features
What you can do:
- Create API resources
- Configure resource's Method Request, Integration Request, Method Response, Integration Response
- Deploy API changes to a stage
What you can't do:
One time configuration you should do by hand:
- Create a new API
- Create stages (once created, the plugin will deploy the API to the configured stage)
- Create an IAM user with the policy required to deploy your API
- Add permission to each Lambda function will get invoked by API Gateway (in case you're integration API Gateway with AWS Lambda functions). Troubleshooting section explains how to do it.
NOTE: to ease the development of this plugin, each run deletes all resources and re-creates them. This means that it doesn't apply differential changes and if you've already created some resources that are not part of plugin configuration, you will loose it at the first run. In other words, make sure the plugin configuration contains all resources of your API.
Configuration
The plugin config is made of 3 required properties:
restApiId
(your API Gateway id)resources
deployment
resources
The resources
property contains the configuration of all your API Resources. Resources are organized in a tree, the path must start with a /
and each resource's full path is built concatenating together all parent resources paths.
Example - create /tweets/trends
resource:
{
resources: {
"/tweets": {
"/trends": {}
}
}
}
Each resource can have zero or more methods. For each method you must define a request and response integration (ie. a AWS Lambda function).
Example - add GET
method to /tweets/trends
resource:
{
resources: {
"/tweets": {
"/trends": {
methods: {
GET: {
authorizationType: "NONE",
apiKeyRequired: false,
integration: { },
responses: { }
}
}
}
}
}
}
The resource's Integration Request config must contain the integration type
and uri
, along with other optional settings (ie. requestTemplates
).
Example - integrate a lambda function to GET /tweets/trends
:
integration: {
type: "AWS",
uri: "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:xxx:function:getUsers/invocations",
integrationHttpMethod: "POST",
credentials: undefined,
requestParameters: {},
cacheNamespace: undefined,
cacheKeyParameters: [],
requestTemplates: {
"application/json": JSON.stringify({
"filter": "$input.params('filter')"
})
}
}
The resource's Integration Response config is a map whose keys are the status codes, and the value is the configuration for each status code.
Example - integrate 200
and 400
response codes:
responses: {
200: {
responseModels: {
"application/json": "Empty"
},
responseParameters: {},
responseTemplates: {}
},
400: {
selectionPattern: "error code: 400",
responseParameters: {},
responseTemplates: {
"application/json": JSON.stringify({"error": "$input.path('$.errorMessage')"})
}
}
}
deployment
The last step of apigateway_deploy
is to deploy all the changes to a stage. The configuration of this phase is made through the deployment
property. stageName
is the only required property.
{
deployment: {
stageName: "prod",
cacheClusterEnabled: false,
cacheClusterSize: "1G"
description: "",
stageDescription: "",
variables: []
}
}
Options
options.region
AWS region where you would like to deploy your API.
options.accessKeyId
and options.secretAccessKey
If you prefer to use hardcoded AWS credentials, you should both set accessKeyId
and secretAccessKey
.
options.credentialsJSON
If you prefer to use AWS credentials stored in a JSON file, you should set the JSON file path here.
options.profile
If you prefer to use a specific AWS credentials profile you can set it here.
Troubleshooting
"Internal server error" due to "Invalid permissions on Lambda function"
This error occurs when you didn't add permission to run the Lambda function from the API Gateway service. To fix it, run the following command:
$ aws lambda add-permission --function-name "<your function name>" --action "lambda:InvokeFunction" --principal "apigateway.amazonaws.com" --source-arn "<your api gateway endpoint arn>" --statement-id "522028352"
Example:
aws lambda add-permission --function-name "getUsers" --action "lambda:InvokeFunction" --principal "apigateway.amazonaws.com" --source-arn "arn:aws:execute-api:us-east-1:123456789:abcdefg/*/GET/users" --statement-id "522028352"
Contributing
You're very welcome to contribute to this pluging, in case you spot any bug, or to add some missing features (ie. create models). Please do your best to:
- Keep the coding style
- Keep your code as much clean (and readable) as possible
License
MIT