Generating certificates using keytool that include Subject Alternate Names
I needed certificates that work with both localhost and kafka hostname. Therefore, just adding a common name of CN=localhost
wouldn’t cut it anymore. Here’s the following steps in a Makefile to
-
generate a certificate authority (CA)
-
generate a private key and certificate
-
create a certificate signed request (CSR)
-
get the CSR signed by the CA
-
load the CA into the keystore
-
load the signed CSR into the keystrore
-
list the results
Makefile
PASSWORD=123456
ALIAS=server
SAN="SAN=DNS:kafka,DNS:localhost,IP:127.0.0.1"
ssl:
@echo "Create host Certificate Authority (CA)"
openssl req -new -newkey rsa:4096 -days 365 -x509 -subj "/CN=Demo-Kafka-Host" -keyout ca.host.key -out ca.host.cert -nodes
@echo "Create Kafka Server Certificate and store in Keystore"
keytool -genkey -keystore ${ALIAS}.keystore.jks -validity 365 \
-alias kafka-local \
-storepass ${PASSWORD} -keypass ${PASSWORD} \
-dname "CN=localhost" -ext ${SAN} -storetype pkcs12
keytool -list -v -keystore ${ALIAS}.keystore.jks \
-storepass ${PASSWORD} -keypass ${PASSWORD} -noprompt
@echo "Create Certificate signed request (CSR)"
keytool -keystore ${ALIAS}.keystore.jks \
-alias kafka-local \
-ext ${SAN} \
-certreq -file cert-file1 \
-storepass ${PASSWORD} -keypass ${PASSWORD}
keytool -printcertreq -file cert-file1 -v
@echo "Get CSR Signed with the host CA"
openssl x509 -req -CA ca.host.cert -CAkey ca.host.key -in cert-file1 -out cert-file-signed1 -days 365 -CAcreateserial \
-extfile openssl.conf \
-passin pass:${PASSWORD}
@echo "Import CA certificate in Keystore"
keytool -keystore ${ALIAS}.keystore.jks -alias CA-Host -import -file ca.host.cert \
-storepass ${PASSWORD} -keypass ${PASSWORD} -noprompt
@echo "Import Signed CSR In Keystore"
keytool -keystore ${ALIAS}.keystore.jks \
-alias kafka-local \
-import -file cert-file-signed1 \
-storepass ${PASSWORD} -keypass ${PASSWORD} -noprompt
@echo "List keystore"
keytool -list -v -keystore ${ALIAS}.keystore.jks \
-storepass ${PASSWORD} -keypass ${PASSWORD} -noprompt
openssl.conf
subjectAltName = DNS:kafka,DNS:localhost,IP:127.0.0.1
And the output
❯ make ssl
Create host Certificate Authority (CA)
openssl req -new -newkey rsa:4096 -days 365 -x509 -subj "/CN=Demo-Kafka-Host" -keyout ca.host.key -out ca.host.cert -nodes
Generating a 4096 bit RSA private key
................................++
...................................++
writing new private key to 'ca.host.key'
-----
Create Kafka Server Certificate and store in KeyStore
keytool -genkey -keystore kafka.server.keystore.jks -validity 365 \
-alias kafka-local \
-storepass 123456 -keypass 123456 \
-dname "CN=localhost" -ext "SAN=DNS:kafka,DNS:localhost,IP:127.0.0.1" -storetype pkcs12
keytool -list -v -keystore kafka.server.keystore.jks \
-storepass 123456 -keypass 123456 -noprompt
Keystore type: PKCS12
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: kafka-local
Creation date: Aug 29, 2022
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=localhost
Issuer: CN=localhost
Serial number: 5da063f4
Valid from: Mon Aug 29 13:33:28 PDT 2022 until: Tue Aug 29 13:33:28 PDT 2023
Certificate fingerprints:
SHA1: 4D:76:13:D9:63:F8:53:10:E2:9E:0F:B6:9B:08:55:EB:52:EB:21:24
SHA256: A6:54:9E:ED:89:FA:51:FC:36:ED:37:49:62:BF:59:6D:42:AE:0E:92:53:5D:D7:5A:B5:2C:25:EC:59:FE:01:C9
Signature algorithm name: SHA256withDSA
Subject Public Key Algorithm: 2048-bit DSA key
Version: 3
Extensions:
#1: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
DNSName: kafka
DNSName: localhost
IPAddress: 127.0.0.1
]
#2: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: B4 19 A4 98 BD 46 AA 6E 6B 07 5B DC 2A A5 6A 4D .....F.nk.[.*.jM
0010: D2 FD 0E B7 ....
]
]
*******************************************
*******************************************
Create Certificate signed request (CSR)
keytool -keystore kafka.server.keystore.jks \
-alias kafka-local \
-ext "SAN=DNS:kafka,DNS:localhost,IP:127.0.0.1" \
-certreq -file cert-file1 \
-storepass 123456 -keypass 123456
keytool -printcertreq -file cert-file1 -v
PKCS #10 Certificate Request (Version 1.0)
Subject: CN=localhost
Format: X.509
Public Key: 2048-bit DSA key
Signature algorithm: SHA256withDSA
Extension Request:
#1: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
DNSName: kafka
DNSName: localhost
IPAddress: 127.0.0.1
]
#2: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: B4 19 A4 98 BD 46 AA 6E 6B 07 5B DC 2A A5 6A 4D .....F.nk.[.*.jM
0010: D2 FD 0E B7 ....
]
]
Get CSR Signed with the host CA
openssl x509 -req -CA ca.host.cert -CAkey ca.host.key -in cert-file1 -out cert-file-signed1 -days 365 -CAcreateserial \
-extfile openssl.conf \
-passin pass:123456
Signature ok
subject=/CN=localhost
Getting CA Private Key
Import CA certificate in KeyStore
keytool -keystore kafka.server.keystore.jks -alias CA-Host -import -file ca.host.cert \
-storepass 123456 -keypass 123456 -noprompt
Certificate was added to keystore
keytool -keystore kafka.server.keystore.external.jks -alias CA-Host -import -file ca.host.cert \
-storepass 123456 -keypass 123456 -noprompt
Certificate was added to keystore
Import Signed CSR In KeyStore
keytool -keystore kafka.server.keystore.jks \
-alias kafka-local \
-import -file cert-file-signed1 \
-storepass 123456 -keypass 123456 -noprompt
Certificate reply was installed in keystore
Warning:
The input uses the SHA1withRSA signature algorithm which is considered a security risk. This algorithm will be disabled in a future update.
Import host CA certificate In TrustStore
keytool -keystore kafka.server.truststore.jks -alias CA-Host -import -file ca.host.cert \
-storepass 123456 -keypass 123456 -noprompt
Certificate was added to keystore
List
keytool -list -v -keystore kafka.server.keystore.jks \
-storepass 123456 -keypass 123456 -noprompt
Keystore type: PKCS12
Keystore provider: SUN
Your keystore contains 2 entries
Alias name: ca-host
Creation date: Aug 29, 2022
Entry type: trustedCertEntry
Owner: CN=Demo-Kafka-Host
Issuer: CN=Demo-Kafka-Host
Serial number: 94ce4848798ef697
Valid from: Mon Aug 29 13:33:28 PDT 2022 until: Tue Aug 29 13:33:28 PDT 2023
Certificate fingerprints:
SHA1: C2:F4:55:06:A7:92:20:93:FC:42:00:56:53:E2:77:B5:2F:ED:E2:DF
SHA256: 93:45:A9:EC:08:1A:2E:EC:08:01:E1:48:44:67:93:64:AB:CD:C5:B2:F7:8C:C4:F3:7F:30:6D:DC:F1:3A:B4:22
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 1
*******************************************
*******************************************
Alias name: kafka-local
Creation date: Aug 29, 2022
Entry type: PrivateKeyEntry
Certificate chain length: 2
Certificate[1]:
Owner: CN=localhost
Issuer: CN=Demo-Kafka-Host
Serial number: 98e6c99ef5f443f6
Valid from: Mon Aug 29 13:33:29 PDT 2022 until: Tue Aug 29 13:33:29 PDT 2023
Certificate fingerprints:
SHA1: 42:11:13:0C:78:36:2B:09:1D:7A:46:A3:DC:5E:6B:98:07:7F:26:7E
SHA256: 30:7F:1F:64:23:16:00:35:C0:4C:66:2D:D3:E7:D1:87:4B:2A:06:C4:31:3C:1D:F8:C5:C1:E3:D6:B0:CE:16:C4
Signature algorithm name: SHA1withRSA (weak)
Subject Public Key Algorithm: 2048-bit DSA key
Version: 3
Extensions:
#1: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
DNSName: kafka
DNSName: localhost
IPAddress: 127.0.0.1
]
Certificate[2]:
Owner: CN=Demo-Kafka-Host
Issuer: CN=Demo-Kafka-Host
Serial number: 94ce4848798ef697
Valid from: Mon Aug 29 13:33:28 PDT 2022 until: Tue Aug 29 13:33:28 PDT 2023
Certificate fingerprints:
SHA1: C2:F4:55:06:A7:92:20:93:FC:42:00:56:53:E2:77:B5:2F:ED:E2:DF
SHA256: 93:45:A9:EC:08:1A:2E:EC:08:01:E1:48:44:67:93:64:AB:CD:C5:B2:F7:8C:C4:F3:7F:30:6D:DC:F1:3A:B4:22
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 1
*******************************************
*******************************************
Can see the SubjectAlternativeName
block flow through all the requests
SubjectAlternativeName [
DNSName: kafka
DNSName: localhost
IPAddress: 127.0.0.1
]