Skip to content

Instantly share code, notes, and snippets.

@mping
Last active September 25, 2023 15:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mping/0d253ba8aaca5332762eaa60b4987286 to your computer and use it in GitHub Desktop.
Save mping/0d253ba8aaca5332762eaa60b4987286 to your computer and use it in GitHub Desktop.
Generate certificates for mTLS with subjectAltNames
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = AU
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Some-State
organizationName = Organization Name (eg, company)
organizationName_default = Internet Widgits Pty Ltd
commonName = Common Name (eg, YOUR name)
commonName_default = testca
[v3_req]
basicConstraints = CA:true
keyUsage = critical, keyCertSign

Appendix: Generate certs

https://github.com/grpc/grpc-java/blob/master/testing/src/main/resources/certs/README

Valid test credentials:

The ca is self-signed:
openssl req -x509 -new -newkey rsa:2048 -nodes -keyout ca.key -out ca.pem \
  -config ca-openssl.cnf -days 3650 -extensions v3_req \
  -addext "subjectAltName = DNS:localhost,DNS:nginx"

When prompted for certificate information, everything is default.

client is issued by CA:
openssl genrsa -out client.key.rsa 2048 
openssl pkcs8 -topk8 -in client.key.rsa -out client.key -nocrypt
openssl req -new -key client.key -out client.csr

When prompted for certificate information, everything is default except the common name which is set to testclient.

openssl x509 -req -CA ca.pem -CAkey ca.key -CAcreateserial -in client.csr \
  -out client.pem -days 3650
server0 is issued by CA:
openssl genrsa -out server0.key.rsa 2048
openssl pkcs8 -topk8 -in server0.key.rsa -out server0.key -nocrypt
openssl req -new -key server0.key -out server0.csr

When prompted for certificate information, everything is default except the common name which is set to localhost

openssl x509 -req -CA ca.pem -CAkey ca.key -CAcreateserial -in server0.csr \
  -out server0.pem -days 3650 -extfile <(printf "subjectAltName=@alternate_names\n[ alternate_names ]\nDNS.1=localhost\nDNS.2=nginx")
MySQL requires a diff key format:
openssl rsa -in server0.key -out server0.key.rsa
Generate .pem and .bin files for private key
openssl pkcs8 -nocrypt -in client.key -out client.key.pem
openssl pkcs8 -topk8 -inform PEM -outform DER -in client.key.pem -out client.key.pem.bin -nocrypt
Clean up:
rm *.rsa; rm *.csr; rm ca.srl      
Verify
openssl s_client -CAfile ca.pem -cert client.pem -key client.key -showcerts -connect localhost:4318 
curl --cacert ca.pem --cert client.pem --key client.key localhost:4318
openssl x509 -noout -ext subjectAltName -in server0.pem

Be generous with perms because life is too short. In prod be strict.

;; in certs dir
chmod 644 *
Verify key matches cert

If you seem errors such as:

ERROR 2026 (HY000): SSL connection error: The certificate and the given key do not match.

it means the private key doesn't match the certificate. To verify:

❯ openssl rsa -noout -modulus -in server0.key | openssl md5
(stdin)= 8919698fe70ee10044ca5ff885a0e24f
                                  
❯ openssl x509 -noout -modulus -in server0.pem | openssl md5
(stdin)= 8919698fe70ee10044ca5ff885a0e24f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment