With AWS CloudFormation it is easy to deploy your applications with AWS Elastic Container Service. However, if you
want to provide access to your applications through the Kong API Gateway, you are left with one additional step in the
deployment process: configuring the Kong gateway. This complicates the deployment process for ECS applications.
With the Custom CloudFormation Resources for the Kong API Gateway we can deploy both the application
and the Kong API Gateway configuration in one go!
The Custom Resources allow you to configure Kong APIs, Plugins, Consumers, ACL and credentials. The resources also allow
you to specify a JWT token to be generated and passed with each request to Kong.
How do I add a Kong API?
It is quite easy: you specify a CloudFormation resource of type Custom::KongAPI:
"SampleApi": {
"Type": "Custom::KongAPI",
"Properties": {
"API" : {
"name": "headers",
"uris": [ "/headers" ],
"upstream_url": "https://httpbin.org",
"strip_uri": false
},
"AdminURL": "https://kong:8001",
"ServiceToken": { "Fn::Join": [ ":", [ "arn:aws:lambda", { "Ref": "AWS::Region" }, { "Ref": "AWS::AccountId" }, "function:binxio-cfn-kong-provider" ]]}
}
}
The API
object takes all of the properties as defined by add-api.
If you need to access the api-id in your cloudformation module, you can reference attribute id
.
{ "Fn::GetAtt": [ "SampleApi", "id" ]}
How do I add a Kong Plugin?
You specify a CloudFormation resource of type Custom::KongPlugin, as follows:
"KeyAuthPlugin": {
"Type": "Custom::KongPlugin",
"Properties": {
"Plugin" : {
"name": "key-auth",
"api_id": { "Fn::GetAtt": [ "SampleApi", "id" ] },
},
"AdminURL": "https://kong:8001",
"ServiceToken": { "Fn::Join": [ ":", [ "arn:aws:lambda", { "Ref": "AWS::Region" }, { "Ref": "AWS::AccountId" }, "function:binxio-cfn-kong-provider" ]]}
}
}
the Plugin
object takes all properties as defined by add-plugin.
If you leave out the api_id
, you will configure a global plugin. If you add a consumer_id
you will configure
the plugin for the the specified consumer. If you add both, it will be for that consumer on that api.
If you need to access the plugin-id in your cloudformation module, you can reference attribute id
.
{ "Fn::GetAtt": [ "KeyAuthPlugin", "id" ]}
How do I add a Kong Consumer?
You specify a CloudFormation resource of type Custom::KongConsumer, as follows:
"KongConsumer": {
"Type": "Custom::KongConsumer",
"Properties": {
"Consumer" : {
"username": "kong-admin",
},
"AdminURL": "https://kong:8001",
"ServiceToken": { "Fn::Join": [ ":", [ "arn:aws:lambda", { "Ref": "AWS::Region" }, { "Ref": "AWS::AccountId" }, "function:binxio-cfn-kong-provider" ]]}
}
}
The Consumer
object takes all of the properties as defined by add-consumer.
If you need to access the consumer-id in your cloudformation module, you can reference attribute id
.
{ "Fn::GetAtt": [ "KongConsumer", "id" ]}
How do I add a Consumer to a ACL group?
You specify a CloudFormation resource of type Custom::KongACL, as follows:
"KongACL": {
"Type": "Custom::KongACL",
"Properties": {
"ACL" : {
"group": "admin",
"consumer_id": {"Fn::GetAtt": [ "KongConsumer", "id" ]}
},
"AdminURL": "https://kong:8001",
"ServiceToken": { "Fn::Join": [ ":", [ "arn:aws:lambda", { "Ref": "AWS::Region" }, { "Ref": "AWS::AccountId" }, "function:binxio-cfn-kong-provider" ]]}
}
}
The ACL
object takes all of the properties as defined by the ACL plugin in associating-consumers
How do I add to Credentials to a Consumer?
You specify a CloudFormation resource of type Custom::KongCredential, as follows:
"KongConsumerApiKey": {
"Type": "Custom::KongCredential",
"DependsOn": "KongConsumer",
"Properties": {
"PluginName": "key-auth",
"Credential": {
"consumer_id": { "Fn::GetAtt": [ "KongConsumer", "id" ] },
"key": "66471684-6BDF-4F11-868F-B513CC391520"
},
"AdminURL": "https://kong:8001",
"ServiceToken": { "Fn::Join": [ ":", [ "arn:aws:lambda", { "Ref": "AWS::Region" }, { "Ref": "AWS::AccountId" }, "function:binxio-cfn-kong-provider" ]]}
}
}
The Credential
object takes all of the properties as defined by plugin.
How do authenticate the Kong API requests?
You can add the object JWT
to any of the custom resources, providing the issuer name and the Name of a Parameter in the Parameter Store. This parameter should contain the RSA private key with which the JWT token is to be signed. The generated token will be passed on the authentication
header.
"KongConsumerApiKey": {
"Type": "Custom::Kong..."
"Properties": {
"JWT": {
"Issuer": "admin",
"PrivateKeyParameterName": "/kong/admin/private-key"
}
....
}
}
Installation
To install these custom resources, clone cfn-kong-provider from git, and type:
cd cfn-kong-provider
aws cloudformation create-stack
--capabilities CAPABILITY_IAM
--stack-name cfn-kong-provider
--template-body file://cloudformation/cfn-resource-provider.json
aws cloudformation wait stack-create-complete --stack-name cfn-kong-provider
If you want the provider to connect to a Kong API gateway which is only accessible from within a VPC, specify the parameters
AppVPC
, PrivateSubnets
and DefaultSecurityGroup
.
--parameters
ParameterKey=AppVPC,ParameterValue=vpid-id
ParameterKey=PrivateSubnets,ParameterValue=subnet-id1,subnet-id2
ParameterKey=DefaultSecurityGroup,ParameterValue=sg-id
This CloudFormation template will use our pre-packaged provider from s3://binxio-public-{{region}}/lambdas/cfn-kong-provider-latest.zip
.
Demo
For the demo to work, we need a deployed Kong API Gateway that is accessible from the Internet. If you do
not have one, type:
aws cloudformation create-stack --stack-name kong-environment
--template-body file://cloudformation/kong.json
--parameters ParameterKey=KongKeyName,ParameterValue=#insert-your-key-name-here#
aws cloudformation wait stack-create-complete --stack-name kong-environment
ADMIN_URL=$(aws --output text --query 'Stacks[*].Outputs[?OutputKey==<code>AdminURL].OutputValue'
cloudformation describe-stacks --stack-name kong-environment)
Note that it will create an entire Kong setup, including a VPC, loadbalancers and a Postgres Database. Do not forget to clean up
afterwards.
aws cloudformation create-stack --stack-name cfn-kong-provider-demo
--template-body file://cloudformation/demo-stack.json
--parameters ParameterKey=AdminURL,ParameterValue=$ADMIN_URL
aws cloudformation wait stack-create-complete --stack-name cfn-kong-provider-demo
To validate the result, set the environment variable ADMIN_URL
to point to your Kong API admin port and type:
curl $ADMIN_URL/apis/header-api
curl $ADMIN_URL/apis/header-api/plugins
curl $ADMIN_URL/consumers/johndoe
curl $ADMIN_URL/consumers/johndoe/acls
curl $ADMIN_URL/consumers/johndoe/basic-auth
curl $ADMIN_URL/consumers/johndoe/key-auth
Conclusion
By using the Kong Custom CloudFormation providers you can deploy both the application and the Kong API configuration for that
application in a single CloudFormation template, simplifying the deployment process.
If you have any questions, do not hesitate to contact me.