Ever tried generating CSR with SANs? It is tedious work. It involves populating an openssl config file with the additional domain names. Put it on a webapp, it does not eliminate the work, but only require minimal coding once.
SANs certificate is an extension to X.509, which allows additional domain names to be added to a certificate. As people starts to put more and more domains in a certificate, the work to generate a CSR becomes cumbersome. Maybe the future version of openssl will simplify the process. Until then, the domain names need to be put in a config file for openssl to read.
Building a webapp, or more like a couple of php pages make life easier. First, check that the openssl extension is enabled on php. Then here comes the php code.
Generate a RSA key, export the private key to a string variable
$keypair = openssl_pkey_new(array('private_key_bits' => 2048)); openssl_pkey_export($keypair, $privKey);
Create a form, get the usual inputs
$dn = array( "countryName" => $_POST["country"], "stateOrProvinceName" => $_POST["state"], "localityName" => $_POST["city"], "organizationName" => $_POST["orgname"], "commonName" => $_POST["cn"], "emailAddress" => $_POST["email"] );
Use a textarea to gather the SANs, then put it in an array
$sansRaw = $_POST["sans"]; $sansArr = explode("\n", $sansRaw); $sansArr = array_filter($sansArr, 'trim');
Write that to a temp openssl config file
$sslConfig = file_get_contents("/data/sites/x/csr/ssl-template.cnf"); $counter = 1; foreach ($sansArr as $line) { $fqdn = tidyFqdn($line); $sslConfig = $sslConfig . "\nDNS." . $counter . "=" . $fqdn; $counter++; } $sslConfigFile = "/data/sites/x/csr/tmp/ssl.cnf-" . rand(); file_put_contents($sslConfigFile, $sslConfig);
The template config looks like this
[ req ] distinguished_name = req_distinguished_name [ req_distinguished_name ] countryName = Country Name (2 letter code) stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = Some-State localityName = Locality Name (eg, city) 0.organizationName = Organization Name (eg, company) organizationalUnitName = Organizational Unit Name (eg, section) commonName = Common Name (e.g. server FQDN or YOUR name) emailAddress = Email Address [ v3_req ] subjectAltName = @req_sans [ req_sans ]
Create a config array and generate the CSR
$csrConfig = array( "digest_alg" => "sha256", "req_extensions" => "v3_req", "config" => $sslConfigFile ); $csrRes = openssl_csr_new($dn, $privKey, $csrConfig); openssl_csr_export($csrRes, $csr);
The CSR is now in the $csr variable. The private key that goes with it is in $privKey.