How to Use Kong ACME Plugin
One of my viewers requested me to talk about Kong’s ACME plugin. I did not cover this plugin because function-wise it is quite limited. If you are running Kong on Kubernetes, I suggest you to use cert-manager instead to handle TLS certificate. You can find my related post here.
As there is no other choice if you are using Kong on VM or docker, I decide to write this post to help you use this plugin.
Before we start, we need to understand where certificates are stored. Kong supports storing certificate in a few places. Although you can store your certificate in memory, you really should store your certificate in a database. If you are using a DB-backed instance, you can choose to store your certificate in kong database
Preparation
Prerequisite :
Kong running with DB or Redis.
You can find plugin documentation here.
First of all, you MUST include lua_ssl_trusted_certificate
to start Kong. This is critical otherwise you will get below error when kong requests certificate.
1 | 2021/08/13 01:34:46 [error] 27#0: *10433 [kong] handler.lua:109 failed to update certificate: acme directory request failed: 20: unable to get local issuer certificate, context: ngx.timer, client: 218.215.244.189, server: 0.0.0.0:8443 |
I am using kong:2.5-ubuntu
image so I can use "KONG_LUA_SSL_TRUSTED_CERTIFICATE=system"
to start Kong as below.
Secondly, you must expose Kong proxy at port 80. Kong ACME plugin only supports HTTP-01 validation which requires this port to be opened.
Here is an example:
1 | docker run --detach --name kong \ |
As you can see I am using a postgres database in my deployment and expose port 80 and 443.
If you want to know more about kong deployment on docker, please check this post.
Thirdly, you should know what type of private key to use and which CA you want to request your certificate from. To know more about using different type of certificate key and CA, please check this post.
Usage Example
Create a service
You don’t need a realy service or route for creating certificate requests. We will create a dummy service and route for that. 65535 is used here just to avoid conflicts with existing services.
1 | curl --request POST \ |
Create Route
/.well-known/acme-challenge
is the required location for HTTP-01 validation.
1 | curl --request POST \ |
Enable ACME plugin
I am using the simpliest configuration here. As you can see I use config.storage=kong
which stores the certificate in database.
1 | curl --request POST \ |
Optional: Enable ACME Plugin with Redis
If you are using dbless deployment, you can use redis to store your certificate. In below example, my redis is in the same network as kong and its host name is redis-demo
, password is A-SUPER-STRONG-DEMO-PASSWORD
.
config.domains=demo.your.domain.name
can be configured asconfig.domains=*.your.domain.name
which means the users agree ACME plugin to request certificate for<ANYTHING>.your.domain.name
. This is not the common name nor SAN on the certificate created. This option is more of telling ACME plugin which domain(s) it is supposed to request certificates for. If the domain name on your certificate request is not covered here, ACME plugin won’t request certificate for it.
1 | curl --request POST \ |
Create Certificate
Now that we have everything setup, we can request our certificate. Kong ACME plugin only supports single domain certificate which means each FQDN has its own certificate.
You can either use the proxy endpoint to trigger certificate creation
1 | curl https://mydomain.com -k |
or Admin API endpoint
1 | curl http://localhost:8001/acme -d host=mydomain.com |
If you want to do a test run before requesting the real certificate
1 | curl http://localhost:8001/acme -d host=mydomain.com -d test_http_challenge_flow=true |
You should get your certiifcate pretty soon if everything goes well.
That’s all I want to cover today and I hope you find it useful.
See you on the next one.