Skip to content

Instantly share code, notes, and snippets.

@StanAngeloff
Last active October 11, 2022 19:37
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save StanAngeloff/d598116aadc0dc922c05 to your computer and use it in GitHub Desktop.
Save StanAngeloff/d598116aadc0dc922c05 to your computer and use it in GitHub Desktop.
Generate RabbitMQ self-signed certificate authority, server and client certificates.

RabbitMQ SSL

$ make [HOSTNAME=`hostname`] export
# See http://www.rabbitmq.com/ssl.html
#
# (c) Stan Angeloff / http://www.gnu.org/licenses/agpl-3.0.html
SHELL := /bin/bash
HOSTNAME ?= $(shell hostname)
PASSPHRASE ?= $(shell cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
PASSPHRASE_FILE = $(HOSTNAME)/.passphrase
CLIENT_NAME ?= client-1
# ---------------------------------------------------------------------------------------------------------------------
.PHONY: $(HOSTNAME)
$(HOSTNAME): $(HOSTNAME)/ca
$(PASSPHRASE_FILE):
@mkdir -p $(@D)
@echo '$(PASSPHRASE)' > $@
$(HOSTNAME)/ca: $(HOSTNAME)/ca/cacert.pem $(HOSTNAME)/ca/cacert.cer $(HOSTNAME)/server/cert.pem $(HOSTNAME)/server/keycert.p12 $(HOSTNAME)/$(CLIENT_NAME)/cert.pem $(HOSTNAME)/$(CLIENT_NAME)/keycert.p12
$(HOSTNAME)/ca/certs:
mkdir -p $@
$(HOSTNAME)/ca/private:
mkdir -p $@
chmod 0750 $@
$(HOSTNAME)/ca/serial:
echo 01 > $@
$(HOSTNAME)/ca/index.txt:
touch $@
$(HOSTNAME)/ca/openssl.cnf: $(HOSTNAME)/ca/certs $(HOSTNAME)/ca/private $(HOSTNAME)/ca/serial $(HOSTNAME)/ca/index.txt openssl.cnf.template
cat $(lastword $^) | sed -e 's/$$HOSTNAME/$(HOSTNAME)/g' -e 's/$$CLIENT_NAME/$(CLIENT_NAME)/g' > $@
$(HOSTNAME)/ca/cacert.pem: $(HOSTNAME)/ca/openssl.cnf
openssl req -x509 -config $< -newkey rsa:2048 -days 3650 -out $@ -outform PEM -subj /CN=$(HOSTNAME)/ -nodes
$(HOSTNAME)/ca/cacert.cer: $(HOSTNAME)/ca/cacert.pem
openssl x509 -in $< -out $@ -outform DER
$(HOSTNAME)/server $(HOSTNAME)/$(CLIENT_NAME):
mkdir $@
.SECONDARY: $(HOSTNAME)/server/key.pem $(HOSTNAME)/$(CLIENT_NAME)/key.pem
$(HOSTNAME)/%/key.pem: $(HOSTNAME)/%
openssl genrsa -out $@ 2048
.SECONDARY: $(HOSTNAME)/server/req.pem $(HOSTNAME)/$(CLIENT_NAME)/req.pem
$(HOSTNAME)/%/req.pem: $(HOSTNAME)/%/key.pem
openssl req -new -key $< -out $@ -outform PEM -subj /CN=$(HOSTNAME)/O=$(shell basename $(@D))/ -nodes
$(HOSTNAME)/%/cert.pem: $(HOSTNAME)/ca/openssl.cnf $(HOSTNAME)/%/req.pem
openssl ca -config $(firstword $^) -in $(lastword $^) -out $@ -notext -batch -extensions $(shell basename $(@D))_ca_extensions
$(HOSTNAME)/%/keycert.p12: $(HOSTNAME)/%/key.pem $(PASSPHRASE_FILE) $(HOSTNAME)/%/cert.pem
openssl pkcs12 -export -out $@ -in $(lastword $^) -inkey $(firstword $^) -passout file:$(PASSPHRASE_FILE)
# ---------------------------------------------------------------------------------------------------------------------
.PHONY: export
export: $(HOSTNAME)
mkdir $(HOSTNAME)/export
mkdir $(HOSTNAME)/export/ca
mkdir $(HOSTNAME)/export/ca/private
mkdir $(HOSTNAME)/export/server
mkdir $(HOSTNAME)/export/$(CLIENT_NAME)
cp $(HOSTNAME)/ca/cacert.pem $(HOSTNAME)/export/ca/
cp $(HOSTNAME)/ca/private/cakey.pem $(HOSTNAME)/export/ca/private/
cp $(HOSTNAME)/server/key.pem $(HOSTNAME)/server/cert.pem $(HOSTNAME)/export/server/
cp $(HOSTNAME)/$(CLIENT_NAME)/key.pem $(HOSTNAME)/$(CLIENT_NAME)/cert.pem $(HOSTNAME)/export/$(CLIENT_NAME)/
cat $(HOSTNAME)/ca/openssl.cnf | sed -e 's!$(HOSTNAME)/ca!ca!g' > $(HOSTNAME)/export/ca/openssl.cnf
[ ca ]
default_ca = $HOSTNAME
[ $HOSTNAME ]
dir = $HOSTNAME/ca
certificate = $dir/cacert.pem
database = $dir/index.txt
new_certs_dir = $dir/certs
private_key = $dir/private/cakey.pem
serial = $dir/serial
default_crl_days = 7
default_days = 3650
default_md = sha256
policy = $HOSTNAME_policy
x509_extensions = certificate_extensions
[ $HOSTNAME_policy ]
commonName = supplied
stateOrProvinceName = optional
countryName = optional
emailAddress = optional
organizationName = optional
organizationalUnitName = optional
domainComponent = optional
[ certificate_extensions ]
basicConstraints = CA:false
[ req ]
default_bits = 2048
default_keyfile = $HOSTNAME/ca/private/cakey.pem
default_md = sha256
prompt = yes
distinguished_name = root_ca_distinguished_name
x509_extensions = root_ca_extensions
[ root_ca_distinguished_name ]
commonName = $HOSTNAME
[ root_ca_extensions ]
basicConstraints = CA:true
keyUsage = keyCertSign, cRLSign
[ $CLIENT_NAME_ca_extensions ]
basicConstraints = CA:false
keyUsage = digitalSignature
extendedKeyUsage = 1.3.6.1.5.5.7.3.2
[ server_ca_extensions ]
basicConstraints = CA:false
keyUsage = keyEncipherment
extendedKeyUsage = 1.3.6.1.5.5.7.3.1
@doniz
Copy link

doniz commented Aug 9, 2019

Maybe you could share a template file of openssl.cnf ? :)

@StanAngeloff
Copy link
Author

Maybe you could share a template file of openssl.cnf ? :)

Done.

@michaelklishin
Copy link

RabbitMQ's own test suites use tls-gen, as do several client libraries. On behalf of the RabbitMQ core team I'd recommend using that instead of a yet another DIY version.

This example uses a shorter key extension list which can affect cipher suite negotiation.
tls-gen produces certificates that include all extensions known to be relevant to RabbitMQ (or, well, Erlang's TLS implementation).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment