Generating and Organizing SSL CSR

At work, even though I support Windows Servers by profession, I choose to use a Linux OS on my desktop/laptop. I have to admit that when I started at RackSpace SSL certs were not my strong suite. By now after almost a year and a half, I have had to generate a ton of SSL CSR’s for our customers so they can order certificates. Right away I found the below shell script which generates the CSR. The script was originally wrote in 2005 and required some minor updates to get it to work with newer versions of openSSL. I updated the script, and also customized it to allow for organizing the certificates based on the ticket number.

Most support jobs I have worked at use a ticketing system of some sort, so you should be able to adapt the script to your needs. My general setup is to place the shell script in a folder called SSL, when you call the script it will ask first for the ticket number you are working on, then the account number of the customer. It then asks you for the information regarding the SSL CSR (State, City, Common Name, Org, Org Unit and so on). Once done it generates the CSR, displays the output of “openssl req -in SSLCSR.csr -noout -text”, then displays the CSR and KEY for easy copy and past. It stores the files a folder named by the ticket number which it first asked. It also creates a separate sub directory called “private” which is where the private key is stored. I recommend you make the private folder read only by root, and set a low permission mask of 0644. Another addition to the script is that I had it set extended attributes on the csr and key files. This makes it easy to search for later on when a customer lost the key, or if something went wrong in when sending the customer the CSR/KEY (extra spaces’s, line breaks and such).

#!/bin/sh
# csr.sh: Certificate Signing Request Generator
# Copyright(c) 2005 Evaldo Gardenali <evaldo@gardenali.biz>
# Modified 2012 Dustin Coates <dcoates@systemoverload.net>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. Neither the name of the author nor the names of its contributors may
# be used to endorse or promote products derived from this software
# without specific prior written permission.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# ChangeLog:
# Tue Jan 10 16:09:00 DBC 2012 - dcoates - Changes to support newer openssl and to support other attributes.
# Mon May 23 00:14:37 BRT 2005 - evaldo - Initial Release</dcoates@systemoverload.net></evaldo@gardenali.biz>

# be safe about permissions
LASTUMASK=`umask`
umask 077

# OpenSSL for HPUX needs a random file
RANDOMFILE=$HOME/.rnd

# create a config file for openssl
CONFIG=`mktemp -q /tmp/openssl-conf.XXXXXXXX`
if [ ! $? -eq 0 ]; then
echo “Could not create temporary config file. exiting”
exit 1
fi

echo “Private Key and Certificate Signing Request Generator”
echo “This script was designed to suit the request format needed by”
echo “the CAcert Certificate Authority. www.CAcert.org”
echo

printf “Ticket Number: ”
read TICKET
printf “Account Number: ”
read ACCOUNT
printf “Country Code [XX]: ”
read COUNTRY
printf “State [some-state]: ”
read STATE
printf “City [some-city]: ”
read CITY
printf “Company Name [some-company]: ”
read COMPANY
printf “Department [some-department]: ”
read DEPT
printf “FQDN/CommonName (ie. www.example.com) : ”
read COMMONNAME

echo “Type SubjectAltNames for the certificate, one per line. Enter a
blank line to finish”
SAN=1 # bogus value to begin the loop
SANAMES=”” # sanitize
while [ ! “$SAN” = “” ]; do
printf “SubjectAltName: DNS:”
read SAN
if [ “$SAN” = “” ]; then break; fi # end of input
if [ “$SANAMES” = “” ]; then
SANAMES=”DNS:$SAN”
else
SANAMES=”$SANAMES,DNS:$SAN”
fi
done

# Config File Generation

cat < $CONFIG
# ————– BEGIN custom openssl.cnf —–
HOME = $HOME
EOF

if [ “`uname -s`” = “HP-UX” ]; then
echo ” RANDFILE = $RANDOMFILE” >> $CONFIG
fi

cat <> $CONFIG
oid_section = new_oids
[ new_oids ]
[ req ]
default_days = 730 # how long to certify for
default_keyfile = $HOME/${HOST}_privatekey.pem
distinguished_name = req_distinguished_name
encrypt_key = no
string_mask = nombstr
EOF

if [ ! “$SANAMES” = “” ]; then
echo “req_extensions = v3_req # Extensions to add to certificate
request” >> $CONFIG
fi

cat <> $CONFIG
[ req_distinguished_name ]
countryName = AU
countryName_default = $COUNTRY
countryName_min = 2
countryName_max = 2
stateOrProvinceName = Some-State
stateOrProvinceName_default = $STATE
localityName = Some City
localityName_default = $CITY
0.organizationName = Internet Widgits Pty Ltd
0.organizationName_default = $COMPANY
organizationalUnitName = Some-Dept
organizationalUnitName_default = $DEPT
commonName = Common Name (eg, YOUR name)
commonName_default = $COMMONNAME
commonName_max = 64
[ v3_req ]
EOF

if [ ! “$SANAMES” = “” ]; then
echo “subjectAltName=$SANAMES” >> $CONFIG
fi

echo “# ————– END custom openssl.cnf —–” >> $CONFIG
mkdir $TICKET
mkdir $TICKET/private
echo “Running OpenSSL…”
#openssl req -batch -config $CONFIG -newkey rsa:2048 -out $HOME/ssl/$TICKET/${COMMONNAME}_csr.pem
openssl req -batch -config $CONFIG -new -newkey rsa:2048 -nodes -out $HOME/ssl/$TICKET/${COMMONNAME}.csr -keyout $HOME/ssl/$TICKET/private/${COMMONNAME}.key
echo “Copy the following Certificate Request and paste into CAcert
website to obtain a Certificate.”
echo “When you receive your certificate, you ‘should’ name it something
like ${COMMONNAME}.pem”
echo
openssl req -in $HOME/ssl/$TICKET/${COMMONNAME}.csr -noout -text
cat $HOME/ssl/$TICKET/${COMMONNAME}.csr $HOME/ssl/$TICKET/private/${COMMONNAME}.key
echo
echo The Certificate request is also available in $HOME/ssl/$TICKET/${COMMONNAME}.csr
echo The Private Key is stored in $HOME/ssl/$TICKET/private/${COMMONNAME}.key
echo

setfattr -n user.ticket -v $TICKET $HOME/ssl/$TICKET/
setfattr -n user.ticket -v $TICKET $HOME/ssl/$TICKET/${COMMONNAME}.csr
setfattr -n user.ticket -v $TICKET $HOME/ssl/$TICKET/private/${COMMONNAME}.key

setfattr -n user.account -v $ACCOUNT $HOME/ssl/$TICKET/
setfattr -n user.account -v $ACCOUNT $HOME/ssl/$TICKET/${COMMONNAME}.csr
setfattr -n user.account -v $ACCOUNT $HOME/ssl/$TICKET/private/${COMMONNAME}.key

rm $CONFIG


#restore umask
umask $LASTUMASK

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.