Generate a certificate for Squid using Ansible

Hi,

I’m currently writing an Ansible playbook to automate the installation of a router & transparent proxy running Rocky Linux. I already have this configuration running in our local school, though I’ve done the installation by hand. I’ve documented everything on my tech blog, step by step.

At one point I have to create a certificate like this:

# openssl req -new -newkey rsa:4096 -sha256 -days 3650 -nodes -x509 \
  -extensions v3_ca -keyout certificat.pem -out certificat.pem
Generating a RSA private key
.......................++++
.........++++
writing new private key to 'certificat.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]: FR
State or Province Name (full name) []: Gard
Locality Name (eg, city) [Default City]: Montpezat
Organization Name (eg, company) [Default Company Ltd]: Microlinux
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []: squidbox.sandbox.lan
Email Address []: info@microlinux.fr

And then I have to convert this into DER format:

# openssl x509 -in certificat.pem -outform DER -out certificat.der

I don’t know how to go about this with Ansible. There seem to be several certificate-related Ansible modules out there, but I don’t know which one to choose.

So far I managed to translate pretty much everything in my Squid setup into an Ansible playbook. Right now I have a bit of a roadblock with these two steps. I’d be thankful for a little help here.

Cheers,

Niki

You can pass parameters to openssl so it doesn’t prompt the user for anything when creating a new certificate.
Searching for “openssl new certificate non-interactive” online will point you to various solutions using parameters like “-subject” “-passin” and “-passout”.

There is also the detail that openssl req creates CSR (Certificate Signing Request) that must then be signed by CA to get the actual certificate. Once CA returns (public and private parts of) certificate, they need to be deployed.

Perhaps one should delegate the CSR creation to the “Ansible control host”?

1 Like

The Ansible control host is the same here, since I’m using ansible-pull on this machine.

if you know how to execute your scripts on a remote host from ansible, then you can create non-interactive actions there with these commands:

Generate a CA privet key and Certificate ( valid for 9999 days)

openssl req -nodes -new -x509 -keyout CA_key.pem -out CA_cert.pem -days 9999 -config CA.cnf

Generate web server secret key and CSR

openssl req -sha256 -nodes -newkey rsa:2048 -keyout localhost_key.pem -out localhost.csr -config localhost.cnf

Create certificate and sign it by own certificate authority (valid 730 days )

openssl x509 -req -days 730 -in localhost.csr -CA CA_cert.pem -CAkey CA_key.pem -CAcreateserial -out localhost_cert.pem -extensions req_ext -extfile localhost.cnf


This localhost.cnf:
[req]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = req_ext
x509_extensions = v3_req
prompt = no
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment

[req_distinguished_name]
countryName = UA
stateOrProvinceName = Kyiv
localityName = Kyiv
organizationName = Certificate signed by my CA
commonName = xxx.firma.my.ua

[req_ext]
subjectAltName = @alt_names

[v3_req]
subjectAltName = @alt_names

[alt_names]
IP.1 = 10.51.51.10
IP.2 = 127.0.0.1
DNS.1 = localhost
DNS.2 = localhost.localdomain
DNS.3 = xxx.firma.my.ua


this is CA.cnf file:
[ req ]
prompt = no
distinguished_name = req_distinguished_name

[ req_distinguished_name ]
C = UA
ST = Kyiv DC
L = Kyiv
O = MY Certificate Authority Local Center
OU = ITDep
CN = xxx.firma.my.ua
emailAddress = root@xxx.firma.my.ua