SSL for company internal services
If you are using SSL in the wild you’ll probably generate your certificate on letsencrypt.org and all is pretty much taken care of.
But what if you have an internal HAProxy serving requests on the 192.168.x.x scope? Or you have an internal Spring Boot webapp that you also want to secure? As the servers will not be accessible by the outside world, you will not be able to generate a certificate for them. Don’t let that stop you. It’s trivial to generate your own certificates and install them in company resources including iOS devices.
The suggested path is to create an internal Certificate Authority (CA) and add that source of trust to all the machines that will be accessing the services secured.
Bird’s eye view of the process:
Authority: will act as the source of trust for all certificates you sign. You will have to install the Authority on every single machine/phone you’ll want.
- Generate a private key for a Certificate Authority (CA)
- Generate a Certificate for the Certificate Authority (CA)
- Install Certificate Authority on Windows
- Install Certificate Authority on iOS
Client: we can issue private keys for all our projects inside our network. Those private keys will be validated by our own generated and installed authority.
- Generate a private key for the client
- Generate a Certificate Sign Request (CSR)
- Have CA sign the CSR thus generating the client Certificate
- Merge the client certificate and the CA certificate into a pkcs12 file which is read by Spring
Install OpenSSL
First things first, install OpenSSL. If you are on a Linux machine you can use the distro repository and do something like apt-get install openssl
but if you are on windows things are a little trickier. OpenSSL states on their Wiki the following binary distributions by third parties. It’s always a risk to install software from sources you don’t trust, and you could compile OpenSSL on your machine, but I personally used https://indy.fulgan.com/SSL.
You can then just unzip the files into any folder and use the openssl.exe
from there.
You must also create a configuration file, can be called openssl.cnf
. In it’s most basic form it can take just the following variables:
# minimum config for openssl # conf for the `req` command, notice that it reads values from dn_prompt [req] distinguished_name = dn_prompt prompt = yes # the only three required, you'll be prompted to change values [dn_prompt] commonName = Common Name commonName_default = Your Project Name countryName = Country Name countryName_default = UK localityName = City localityName_default = London
Generate Certificate Authority
We start by generating a private key for the authority:
openssl genrsa -des3 -out ca_key.key 2048
And we then generate two certificates. Notice that the config value should point to wherever you placed your openssl.cnf
file. Also notice that we used 1825 days, 5 year as it’s a round number. Any other value will do. But on certificates Apple enforces tighter limits which we cover bellow.
openssl req -config c:\openssl.cnf -x509 -new -nodes -key ca_key.key -sha256 -days 1825 -out ca_cert.pem openssl req -config c:\openssl.cnf -x509 -new -nodes -key ca_key.key -sha256 -days 1825 -out ca_cert.crt
You now have three files. The ca_key.key
(private key) and the ca_cert.pem
and ca_cert.crt
which are the certificate files for your certificate authority.
Install on Windows: Click the ca_cert.crt
file on Windows and follow screen instructions. Then click Start -> Run -> certmgr.msc
. It will open the Windows Certificate Manager. You will find the certificate you installed under “Intermediate Certification Authorities”. You’ll want to drag that file to “Trusted Root Certification Authorities”. This can be done as a non admin user.
Install on iOS: Email the ca_key.pem
file to yourself. Open the email on iOS using the Apple Mail App. Follow the instructions and certificate will be installed. To uninstall you can go to Settings -> General -> Profile. After proper installation iOS requires a second step for you to trust the certificate, you must go to Settings -> General -> About -> Certificate Trust Settings and Enable Full Trust For Root Certificate.
Done. That’s all there is about generating a proper local CA.
Generate Certificates for services
Start by generating a private key for the service/site/etc.
openssl genrsa -des3 -out service1_key.key 2048
Generate a CSR (Certificate Sign Request):
openssl req -new -key service1_key.key -out service1_sign_request.csr
Now that we have the website key and the certificate sign request we need to create an external file with the names/ip’s for which such certificate will be valid. Create a file called service1_config.ext with the following info:
authorityKeyIdentifier=keyid,issuer basicConstraints=CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment subjectAltName = @alt_names # you can have both DNS and IP; listed a few just as an example [alt_names] DNS.1 = localhost DNS.2 = mywebsite DNS.3 = mywebsite.local IP.1 = 10.1.1.3 IP.2 = 127.0.0.1
Now we’ll use the CA certificate and private key together with the CSR (Certificate Sign Request) and the config file to generate a proper certificate for the website. Since iOS 13 Apple only allows a max of 825 days on certificates so that’s what we’ll use, also notice that Apple just recently announced that limit going down to 398 days so you may need to adjust accordingly depending on when you read this.
openssl x509 -req -in service1_sign_request.csr -CA ca_cert.pem -CAkey ca_key.key -CAcreateserial -out service1.crt -days 825 -sha256 -extfile service1_config.ext
You’ll now have the following files:
ca_key.key - certificate authority private key ca_key.pem - certificate authority certificate pem format ca_key.crt - certificate authority certificate crt format service1_key.key - website private key service1_sign_request.csr - website certificate sign request service1_config.ext - website config file for openssl sign request service1.crt - website certificate crt format
The one that matters, since CA Authority is already installed in all the devices is the certificate service1.crt
.
Spring Boot or HAProxy
Spring Boot uses PKC12
files.
HAProxy uses pem
files.
Let’s create both those files:
# PCK12 (Public-Key Cryptography Standards 12) openssl pkcs12 -export -in ca_key.crt -inkey ca_key.key -in service1.crt -inkey service1_key.key -name service1 -out service1.p12 # pem (Privacy Enhanced Mail Certificate file) openssl pkcs12 -in service1.p12 -nodes -out service1.pem
Spring Boot – edit application.properties and insert something like this:
server.ssl.key-store-type=PKCS12 # The path to the keystore containing the certificate, place it src/main/resources server.ssl.key-store=classpath:service1.p12 # The password used to generate the certificate server.ssl.key-store-password=PASSWORD-USED # The alias mapped to the certificate (the -name service1 on the last command) server.ssl.key-alias=service1 # force SSL security.require-ssl=true
HAProxy – edit config file and insert something like this:
frontend service1 bind 10.1.1.3:443 ssl crt /etc/ssl/certs/service1.pem default_backend service1_web_servers
And that’s it, SSL for internal projects without the warning “this site is insecure” or “certificate not valid” error messages.
Things that may be useful:
Remove password from private key:
If you’re planing on running some services, like HTCondor, you may need to have private decrypted keys. This can easily be achieved by running:
openssl rsa -in [my_private.key] -out [my_private.key]
Inspect Private Keys, CSR’s, CRT’s and PKCS’s:
At any point you may need to inspect any of these. Commands below:
# inspect a CSR (Certificate Signing Request) openssl req -text -noout -verify -in [my.csr] # inspect a private key openssl rsa -in [my_private.key] -check # inspect a CRT (Certificate) openssl x509 -in [my.crt] -text -noout # inspect a PKCS12 openssl pkcs12 -info -in [keyStore.p12]