KeyChest is being integrated with Let’s Encrypt more tightly, it now has its first integration hook for Certbot. It registers domains using self-registered API keys and creates dormant accounts for you simply to confirm.
KeyChest has had a RESTful API for quite some time. Once we decided to integrate KeyChest via a certbot hook, I realized that we needed something much simpler. The question was whether we can do network requests from Linux scripts without unnecessary dependencies.
It turns out it can be done using a virtual device, which is available in some widely used Linux shells. The simplest Linux code now looks like this:
exec 3<> "/dev/tcp/keychest.net/10023"
echo -e "command add domain keychest.net apikey 28a7e10-1fea" >&3
echo "$(dd bs=1000 count=1 <&3 2>/dev/null)"
This piece of code works in most popular Linux shells (bash, ksh, …) and it now works with KeyChest as well. We can now also share the first renew hook – you just copy it to a certbot folder (e.g., “/etc/letsencrypt/renewal-hooks/post” ) and that’s all to it.
The new API follows the same principles as the original one – the main goal is to simplify the integration even for automatically spawn virtual servers or containers without any unnecessary configuration. This means:
- new API clients can connect and register the first time they connect to the internet;
- a random API key can be requested from KeyChest – no need for platform-dependent generators of random strings;
- networking – no need for curl or other networking tools; a simple TCP abstractions in bash shell.
What drives the design of KeyChest interfaces is simplifying the distributed part of the integration. While this may mean some additional CPU load, it saves your time.
Let’s Encrypt Integration with Certbot
The simplest integration with certbot is via its “renewal-hooks” folders. One can add a number of shell scripts, which will be called during certbot’s “renew” command. You can use command line parameters to specify additional hooks with any of the certbot calls, but being able to just copy a file to the right location is much less intrusive.
The downside is, that certbot is far from easy for “enterprise” environment. It doesn’t provide any information provided as command line parameters, nor other variables it either loads or computes as part of its processing.
As a result, we decided to extract domains from certificate requests from log files, just like we extract your email support from certbot configuration. The email is however more interesting.
You can get our KeyChest integration script for certbot from GitLab:
https://gitlab.com/keychest/certbot-hooks
At the moment, there are four options to define the email for KeyChest integration:
- a primary email can be set inside the script – it can be identical for all your copies of certbot;
- the script tries to find an email from Let’s Encrypt account meta data;
- it will take an email from a file (/etc/letsencrypt/renewal-hooks/) keychest_apikey;
- a random email address is generated within the “@keychest.net” is created for each new instance automatically
These options allow exploring a range of possible integration scenarios and provide a background to develop the most suitable approach that will scale with your needs.
Using Network API Using Linux Shells
KeyChest offers just three API calls providing for a flexible integration into end-to-end monitoring.
- Request an API key – this is an optional function providing clients a way to generate random string to uniquely identify them;
- Claim API key – this call binds a new API key to an email address so it can be managed from within KeyChest;
- Add domain – this method adds a new domain to an API key;
Our script is using a simple, dependency-free means for network communication available in Linux shells. It uses an abstraction for TCP connections, namely
/dev/tcp/<url>/<port>
e.g.: /dev/tcp/keychest.net/10023
We can simply open a connection (or file descriptor), which can be then used to read and/or write from the remote server. Requesting an API key looks like this:
TCP_DEV="/dev/tcp/keychest.net/10023"
exec 3<> "$TCP_DEV"
echo -ne "command apikey" >&3
RESPONSE=$(dd bs=1000 count=1 <&3 2>/dev/null | head -l 1)
echo $RESPONSE # this will return "data 28a7e10-1fea…"
Each API call is a single line, which contains a sequence of pairs key and value. The keys can be in random order. The response consists of one or two lines:
- data – if there’s any data to return
- status – consisting of a string (ok/error), numerical code (200 for ok), and a human readable string.
An example of an API call adding a new domain would be (assuming a connection “3” is already open:
echo -ne "command add apikey 28a7e10-1fea… domain keychest.net" >&3
I hope you will find this useful. Any questions, get in touch – [email protected]. We’d also be happy to pull your changes, versions, improvements!