I'm trying to get the certificates just right for our Jira/Confluence deployments in house. People access them differently, either from the hostname or the FQDN. I'm using Java 7's keytool so I have access to the server alternate name functionality:

-ext san=dns:jira

...and I hand it...

jira.example.com

...as the CN when generating the certificate. I then generate a signing request, hand the CSR off to our Win2k8r2 PKI for a certreq to get the key signed and import the key back into the keystore.

Now when I have it setup as I've said above my browsers (Chrome, Firefox, Safari) seem to think the jira is the only valid name even though when I inspect the certificate the CN shows the FQDN.

If I drop the ext it will use the CN which is the FQDN.

When I have multiple ext statements it just uses the last one and I've tried to string multiple DNS:foo under one ext entries together with various punctuation.

Another angle I've run across is to setup the web server to do a 301 to the FQDN. I'm fine with this as well but I'm stuck with Tomcat so "switch to Apache/nginx" won't work for me. This seems to be the only documentation I've come across to do something like that with Tomcat but its 3 years old and it's the end of the day for me. Have they added that functionality to Tomcat6?


I realize this question is pretty old but for anyone who may find it useful I'll mention what works for me:

  • use CN to enter some human friendly name like "our cool JIRA server" ;-)
  • enter san like this: -ext san=dns:jira,dns:jira.example.com

BTW, you can also add IP addresses if you like. I personaly use the following for my development computer:

keytool -certreq ... -file server.csr -keystore server.keystore ... -ext san=dns:localhost,dns:myComputerName,ip:127.0.0.1,ip:::1

NOTE: I use java8 keytool; I hope this works in java7 keytool as well but I haven't tested it


To verify the CSR has the SAN subject alternative names embedded, use the keytool to print the CSR:

keytool -printcertreq -file test.csr

If it worked, you will get something like:

#1: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
  DNSName: test.example.com
  DNSName: test
]

Note -- to get the two entries as above (test.example.com and test), you had to create the CSR as noted in "tomorrow's" answer as "-ext san=dns:test.example.com,dns:test".

Do not follow the misleading keytool documentation [{-ext ext}*] which indicates that zero or more "-ext" entries can be passed in on the command line:

-ext san=dns:test.example.com -ext san=dns:test

This will not work, you will only get the last extension DNS entry (san=dns:test).


Generate your multi-domain certificates with OpenSSL and not with keytool then convert key and certificate to a Java Keystore to use with Tomcat. The following example generates a self-signed certificate, it should be easy enough to adapt for a "real" certificate.

Generate an openssl.cnf following the guide in the link above then run these commands:

# Generates a self-signed certificate + key, omit if you already have one
openssl req -config openssl.cnf -x509 -days 3650 -newkey rsa:2048 \
   -out self-signed-certificate.pem -keyout pub-sec-key.pem
# Remove passphrase from key
openssl rsa -in pub-sec-key.pem -out new.key
# Generate PKCS12 keystore
openssl pkcs12 -export -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES \
   -export -in self-signed-certificate.pem -inkey new.key -name alias \
   -out keystore.p12
# Convert PKCS12 to JKS
keytool -importkeystore -destkeystore keystore.jks -deststoretype JKS \
   -srcstoretype PKCS12 -srckeystore keystore.p12

Pay attention to the alias value to -name in the above example. That's the name of the certificate you have to pass to tomcat.

For the sake of completion, I'll include how issuing a certificate with SANs may work with a Certificate Authority:

SAN                     = email:copy

...

[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName=${ENV::SAN}
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

Run this command to generate a Key + CSR containing SANs (untested):

SAN="DNS: domain1.example.com, DNS: domain2.example.com" openssl req \
   -config /path/to/openssl.conf \
   -subj "/C=XX/ST=XX/L=xxx/O=My Org/OU=My OU/CN=main.example.com" \
   -newkey rsa:2048 -out file.csr -keyout out.key \
   -infiles /path/to/csr/file.csr

Run this command to issue a certificate:

SAN="DNS: domain1.example.com, DNS: domain2.example.com" openssl ca \
   -config /path/to/openssl.conf -policy policy_anything \
   -subj "/C=XX/ST=XX/L=xxx/O=My Org/OU=My OU/CN=main.example.com" \
   -infiles /path/to/csr/file.csr