
Automating Certificate Generation for Distributed Splunk
Splunk is a distributed computing environment once a certain level of data ingestion is achieved, so having multiple systems communicating with each other is quite common. Even if the amount of data being ingested is small and there is only one Splunk server in the environment, you still have users and administrators connecting via browser to Splunkweb. Plus, you have the communication of your Universal Forwarders with your deployment server and your indexers. Having this communication secured is important, and one of the primary ways this is accomplished in Splunk is through the use of SSL certificates.
The process of managing your certificates is one that can easily become tedious. In this blog post, I will be discussing a solution to make the creation and management of certificates for many systems at once a bit less painful.
Quick note
This article won’t be about why you should use SSL certificates or even a comprehensive guide on how to implement certificates in Splunk. If you’re looking for that guide, I highly recommend jumping over to Adam’s blog post for those details. Instead, I want to focus on how tedious it is to create certificates for many systems at once.
How the need for automation came about
If your organization has a certificate management system that handles creating everything from scratch, this won’t be as useful. Most customers I have experience with, however, have an internal process that involves sending the internal PKI administrator a set of certificate signing requests (CSR), one for each system.
Managing this process isn’t difficult if you have only one server, like I previously mentioned, but when building a new distributed Splunk infrastructure from the ground up, it often requires a number of individual components, such as search heads, indexers, deployment servers, cluster masters, and hopefully also a monitoring console.
If you’re working from a Windows workstation, you won’t necessarily have the tools installed locally to do this, so certificates tend to be created on the Splunk system itself–likely running on Linux.
If you’re trying to satisfy all of the recent requirements in browsers for modern certificates, an important one from a few years ago is that both Chrome and Firefox no longer pay attention to the commonName (CN) of the certificate for hostname matching. Now they use the X.509 version 3 Subject Alternative Name (SAN). The difficulty here is that until OpenSSL 1.1.1–which is not available on any recent RHEL distro, but which does show up in Ubuntu starting with version 18.04–there is no good way to specify the SAN on the command line. As a result, it is common to update the OpenSSL configuration file (openssl.cnf) on each system to contain the correct details.
When you’re talking about dozens of systems, we’ve now come back around to how tedious this can be to do.
My simple solution for quick and accurate CSRs
Eliminating tedium and bringing consistency to any kind of process is a good thing, so I set out to make this easier. I wanted this to work with as many versions of OpenSSL as possible, including the “openssl” command from LibreSSL on macOS. This requirement unfortunately makes using the new “addext” feature in OpenSSL 1.1.1 not possible.
After some Googling and much trial and error, I finally found that when you supply the configuration file to the openssl binary, instead of just giving a filename, you can redirect the output of a subshell as a file descriptor rather than having the OpenSSL binary open the file and read it itself. This allows us to inject extra configuration on the CLI without ever modifying the original OpenSSL configuration file.
Now that we can create keys and CSRs with only the CLI, my thoughts turned quickly toward scripting this to avoid having to write out all of these commands. Additionally, there is no need to create each CSR separately on each system. We are no longer relying on configuration files, so we can create all of the signing requests on one system.
To make this as easy and portable as possible, the script–which you can also find on GitHub–has a few variables at the top to configure things rather than relying on a configuration file or some other separate input.
# Instructions:
# 1. Fill out the lists of hosts and aliases as necessary below
# 2. Fill out the key size and subject template for the cert details
# 3. Switch to a new directory and run the script. All of the files
# are created in the current working directory
# Host table. Use the header line below to fill this out. Don’t
# forget to remove the example hosts
# FQDN:Local IP:Any NAT IP or vanity names separated by commas
HOSTS=’
splunksh1.example.com:192.0.2.1:splunk.example.com,192.168.20.1
splunkes1.example.com:192.0.2.2:splunkes.example.com
splunkix1.example.com:192.0.2.3:
‘
# Key size, this should be at least 2048, but 4096 is better.
keysize=4096
# Subject Template. This must end with “CN=”
subjTmpl=’/C=US/ST=Ohio/L=Independence/O=Hurricane Labs/OU=Splunk/CN=’
### STOP. Everything else below here is the code.
openssl=`which openssl`
if [ -z “$openssl” ]; then
echo “You must run this on a host with OpenSSL/LibreSSL CLI tools installed.”
exit 1;
fi
for hoststr in $HOSTS; do
IFS=: read -ra host <<<"$hoststr" IFS=. read -ra fqdn <<<"${host[0]}" IFS=, read -ra aliases <<<"${host[2]}" echo "### ${fqdn[0]}" subjAltName="DNS:${host[0]},DNS:${fqdn[0]},IP:${host[1]}" for alias in $aliases; do echo "$alias" | egrep -q '^[0-9.]+$' if [ "$?" -eq "0" ]; then subjAltName="${subjAltName},IP:${alias}" else subjAltName="${subjAltName},DNS:${alias}" fi done openssl req -new -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nextendedKeyUsage=serverAuth,clientAuth\nsubjectAltName=${subjAltName}")) -extensions SAN -reqexts SAN -out ${fqdn[0]}.csr -subj "$subjTmpl${host[0]}/" -nodes -newkey rsa:${keysize} -keyout ${fqdn[0]}.keydone
Using the example hosts in the table above and sticking an echo in front of openssl, we can see how the script turns that table of hosts into the commands:
Notice when echo is used with our subshell redirection, we end up with a reference to the dev filename of the file descriptor, which is file descriptor 63 (/dev/fd/63
). OpenSSL reads from this file descriptor rather than creating a new one attached to the configuration file that would normally be passed into the option, e.g. /etc/ssl/openssl.cnf
.
Conclusion
Using this method, the process of securing Splunk’s web communication becomes a much less daunting task. If you haven’t taken the time to set up your own certificates, I hope this script is the final push you need to get it completed. Happy Secure Splunking!
The post Automating Certificate Generation for Distributed Splunk appeared first on Hurricane Labs.
*** This is a Security Bloggers Network syndicated blog from Hurricane Labs authored by Brian T Glenn. Read the original post at: http://feedproxy.google.com/~r/HurricaneLabsEngineeringNotes/~3/iGoMYWN1Ci0/