Provide subjectAltName to openssl directly on the command line

Based on link from DarkLighting, here's the command I came up with using nested subshells.

openssl req -new -sha256 \
    -key domain.key \
    -subj "/C=US/ST=CA/O=Acme, Inc./CN=example.com" \
    -reqexts SAN \
    -config <(cat /etc/ssl/openssl.cnf \
        <(printf "\n[SAN]\nsubjectAltName=DNS:example.com,DNS:www.example.com")) \
    -out domain.csr

All one line:

openssl req -new -sha256 -key domain.key -subj "/C=US/ST=CA/O=Acme, Inc./CN=example.com" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:example.com,DNS:www.example.com")) -out domain.csr

Example use:

user@hostname:~$ openssl req -new -sha256 -key domain.key -subj "/C=US/ST=CA/O=Acme, Inc./CN=example.com" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:example.com,DNS:www.example.com\n")) -out domain.csr
user@hostname:~$ openssl req -in domain.csr -text -noout
Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=US, ST=CA, O=Acme, Inc., CN=example.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:a8:05:50:86:49:98:c8:05:01:e9:50:18:7f:2f:
                    b4:89:09:29:d1:c1:58:d8:14:bb:58:1d:25:50:11:
                    bb:43:d8:28:03:a5:de:59:49:bb:d2:f7:d3:79:5c:
                    c6:99:2c:98:ff:99:23:8c:df:96:7c:ea:4b:62:2a:
                    a4:c2:84:f5:5d:62:7f:7d:c4:7c:e2:c3:db:e6:58:
                    03:c2:26:9d:02:da:bb:84:d9:11:82:fe:38:12:9b:
                    c7:b6:ff:b2:40:30:38:b1:44:d8:47:1d:43:4a:29:
                    58:6b:49:ec:33:d7:dc:a7:1b:90:05:3a:f5:e6:16:
                    98:08:5d:2d:7e:b4:ea:a2:a4:b1:84:89:f7:f1:c4:
                    67:a6:a1:06:70:dd:4e:6b:0c:f8:b5:9b:bc:3f:06:
                    ee:90:d6:86:29:52:d3:af:f6:d4:2f:c6:cf:4b:5a:
                    b8:cd:01:74:6d:5c:25:a8:02:1c:7c:e8:66:3d:46:
                    07:b1:9d:ef:cc:eb:90:b6:bf:7b:33:e0:5f:b2:9b:
                    e8:b4:12:67:2f:8d:0d:9b:54:9d:95:6e:09:83:cb:
                    f3:5b:1f:31:8e:3b:ca:4e:08:e0:40:c0:60:40:72:
                    dd:0d:3e:99:ec:7c:ac:c4:3c:ba:85:9d:d9:d9:6b:
                    02:2e:bf:a8:a3:02:1d:eb:c8:58:e3:04:b3:a5:f1:
                    67:37
                Exponent: 65537 (0x10001)
        Attributes:
        Requested Extensions:
            X509v3 Subject Alternative Name: 
                DNS:example.com, DNS:www.example.com
    Signature Algorithm: sha256WithRSAEncryption
         a2:1d:1a:e8:56:43:e7:e5:c7:c1:04:c1:6a:eb:d5:70:92:78:
         06:c1:96:fa:60:e2:5f:3c:95:ee:75:ed:70:52:c1:f0:a7:54:
         d2:9f:4a:2f:52:0f:d4:27:d8:13:73:1f:21:be:34:3f:0a:9c:
         f1:2a:5c:98:d4:28:b8:9c:78:44:e8:ea:70:f3:11:6b:26:c3:
         d6:29:b3:25:a0:81:ea:a2:55:31:f2:63:c8:60:6d:68:e3:ab:
         24:c9:46:33:92:8f:f2:a7:72:43:c6:aa:bd:8d:e9:6f:64:64:
         9e:fe:30:48:3f:06:2e:58:7c:b5:ef:b1:4d:c3:84:cc:02:a5:
         58:c3:3f:d8:ed:98:c7:54:b9:5e:50:44:5e:be:99:c2:e4:03:
         81:4b:1f:47:9a:b0:4d:74:7b:10:29:2f:84:fd:d1:70:88:2e:
         ea:f3:42:b7:06:94:4a:06:f6:92:10:4c:ce:de:65:89:2d:0a:
         f1:0f:79:90:02:a4:b9:6d:b8:39:db:de:6e:34:61:4f:21:36:
         a0:b5:73:2b:2b:c6:7e:2f:f2:e5:1e:51:9f:85:c8:17:9c:1a:
         b6:59:b0:41:a7:06:c8:5b:f4:88:92:c9:34:71:9d:73:f0:2e:
         31:ae:ed:ab:35:0e:b4:8a:9a:72:7c:6f:7a:3e:5d:66:49:26:
         26:99:e1:69

As of OpenSSL 1.1.1, providing subjectAltName directly on command line becomes much easier, with the introduction of the -addext flag to openssl req (via this commit).

The commit adds an example to the openssl req man page:

Example of giving the most common attributes (subject and extensions)
on the command line:

 openssl req -new -subj "/C=GB/CN=foo" \
                  -addext "subjectAltName = DNS:foo.co.uk" \
                  -addext "certificatePolicies = 1.2.3.4" \
                  -newkey rsa:2048 -keyout key.pem -out req.pem

This has been merged into the master branch of the openssl command on Github, and as of April 18 2018 can be installed via a git pull + compile (or via Homebrew if on OS X: brew install --devel [email protected]).

Note that if you have set the config attribute "req_extensions" at section "[req]" in openssl.cfg, it will ignore the command-line parameter


My solution was to pass subjectAltName via an environment variable.

First have this added to openssl.conf:

[ san_env ]
subjectAltName=${ENV::SAN}

Then set the environment variable before invoking openssl:

export SAN=DNS:value1,DNS:value2
openssl req -extensions san_env -subj '/CN=value1' ...

Note: the -extensions san_env parameter needs to be present when signing the CSR as well as when generating it. Therefore, for CA-signed CSRs add -extensions san_env to the openssl ca command as well.