#!/bin/bash # # requires CA.pl from OpenSSL: https://github.com/openssl/openssl/blob/master/apps/CA.pl.in # # generating CA.pl from OpenSSL source: # /usr/bin/perl "-I." -Mconfigdata "util/dofile.pl" \ # "-oMakefile" apps/CA.pl.in > "apps/CA.pl" # sudo cp apps/CA.pl /usr/local/bin # # This script requires that a CA certificate has already been created and # that the CA private key passphrase can be found in $CA_ROOT/cacert.pass # # NB: OpenSSL doesn't handle concurrent access to the CA database. # Wrap this script with flock command or use some other method to serialize access. # CAPL_ORIG=/usr/lib/ssl/misc/CA.pl OPENSSL=/usr/bin/openssl function display_help() { echo "${0} Usage :" echo -e "\t--country\tSpecify the Country of the certificate" echo -e "\t--cadir\t\tSpecify the CA directory" echo -e "\t--cn\t\tSpecify the CN of the certificate" echo -e "\t--locality\tSpecify the Locality of the certificate" echo -e "\t--mail\t\tSpecify the Mail of the certificate" echo -e "\t--organization\tSpecify the Organization of the certificate" echo -e "\t--st\t\tSpecify the State or Province of the certificate" echo -e "\t--days\t\tSpecify the validty of the certificate in days (default 1095)" echo -e "\t--newca\t\tGenerate a new Certificate Authority. Can't use with --newcert" echo -e "\t--newcert\tGenerate a new Certificate. Can't use with --newca" echo -e "\t--updateca\tAdd certificate or CA to update-ca-certificates" echo -e "\t--genpub\t\tGenerate Public key of the certificate" echo -e "\t-h or --help\tThis help" echo "" echo "Examples :" echo "./issue_certificate.sh --newca --cadir /tmp/cademo --country FR --cn \"BLORAND Test CA\" --locality DINAN --mail webmaster@blorand.org --organization BLORAND --st BRETAGNE --days \$((365 * 30)) --updatca" echo "./issue_certificate.sh --newcert --cadir /tmp/cademo --country FR --cn benoit.blorand.local --locality DINAN --mail webmaster@blorand.org --organization BLORAND --st BRETAGNE --days \$((365 * 30)) --genpub" } GET_OPT=`getopt -o h --long help,country:,cadir:,cn:,locality:,mail:,organization:,st:,days:,newca,newcert,updateca,genpub -n "$0 parameters" -- "$@"` if [ ! "${?}" == "0" ] ; then display_help exit 1 fi eval set -- "$GET_OPT" while true ; do case ${1} in --country) CERT_COUNTRY="${2}" shift 2 ;; --cadir) CADIR="${2}" shift 2 ;; --cn) CERT_CN="${2}" shift 2 ;; --locality) CERT_LOCALITY="${2}" shift 2 ;; --mail) CERT_MAIL="${2}" shift 2 ;; --organization) CERT_ORGANIZATION="${2}" shift 2 ;; --st) CERT_ST="${2}" shift 2 ;; --days) CERT_DAYS="-days ${2}" shift 2 ;; --newca) NEWCA=1 shift ;; --newcert) NEWCERT=1 shift ;; --updateca) UPDATECA=1 shift ;; --genpub) GENPUB=1 shift ;; -h|--help) display_help exit 0 ;; --) shift break ;; *) display_help >&2 exit 1 ;; esac done if [ ! -z "${NEWCA}" -a ! -z "${NEWCERT}" ] ; then echo "Only one of --newca or --newcert is possible" >&2 display_help >&2 exit 1 fi if [ -z "${CERT_COUNTRY}" -o -z "${CERT_CN}" -o -z "${CERT_LOCALITY}" -o -z "${CERT_MAIL}" -o -z "${CERT_ORGANIZATION}" -o -z "${CERT_ST}" ] ; then echo "Almost one of --country --cadir --cn --locality --mail --organization --st is missing..." >&2 display_help >&2 exit 1 fi CERT_BASE=${CADIR}/certs if [ ! -z "${NEWCA}" ] ; then if [ ! -d "${CADIR}" -o ! -f "${CADIR}/serial" ]; then echo "No Certificate Authority Root found in current directory." if [ -d "$CADIR" ]; then rm -r ${CADIR}-backup > /dev/null 2>&1 mv $CADIR ${CADIR}-backup fi mkdir -p "${CADIR}" sed "s@\./demoCA@${CADIR}@g" /etc/ssl/openssl.cnf > "${CADIR}/openssl.cnf" CAPL="${CADIR}/CA.pl" sed "s@\./demoCA@${CADIR}@g" ${CAPL_ORIG} > ${CAPL} chmod +x ${CAPL} ORIG_UMASK=`umask` umask 0077 pass=`openssl rand -base64 18 | tee "${CADIR}/cacert.pass"` umask ${ORIG_UMASK} SUBJECT="/C=${CERT_COUNTRY}/L=${CERT_LOCALITY}/ST=${CERT_ST}/O=${CERT_ORGANIZATION}/CN=${CERT_CN}/emailAddress=${CERT_MAIL}" echo "" | OPENSSL_CONFIG="-config '${CADIR}/openssl.cnf'" OPENSSL=${OPENSSL} ${CAPL} -newca -extra-req "-passout file:'${CADIR}/cacert.pass' -subj '${SUBJECT}' ${CERT_DAYS} -batch" -extra-ca "-passin file:'${CADIR}/cacert.pass' ${CERT_DAYS} -batch" if [ ! -z "${UPDATECA}" ] ; then mkdir -p /usr/local/share/ca-certificates/extra ln -s ${CADIR}/cacert.pem "/usr/local/share/ca-certificates/extra/${CERT_CN}.crt" /usr/sbin/update-ca-certificates fi else echo "There is already a $CADIR folder !" exit 1 fi exit 0 fi if [ ! -z "${NEWCERT}" ]; then CAPL="${CADIR}/CA.pl" if [ ! -e "${CADIR}/certs/${CERT_CN}.pem" ] ; then pass=`openssl rand -base64 18 | tee "${CADIR}/certs/${CERT_CN}.pass"` echo "issuing certificate for ${CERT_CN}" # create certificate request SUBJECT="/C=${CERT_COUNTRY}/L=${CERT_LOCALITY}/ST=${CERT_ST}/O=${CERT_ORGANIZATION}/CN=${CERT_CN}/emailAddress=${CERT_MAIL}" OPENSSL_CONFIG="-config '${CADIR}/openssl.cnf'" OPENSSL=${OPENSSL} ${CAPL} -newreq -extra-req "-passout file:'${CADIR}/certs/${CERT_CN}.pass' -subj '${SUBJECT}' ${CERT_DAYS} -batch" # sign certificate request OPENSSL_CONFIG="-config '${CADIR}/openssl.cnf'" OPENSSL=${OPENSSL} ${CAPL} -sign -extra-ca "-passin file:'${CADIR}/cacert.pass' ${CERT_DAYS} -batch" if [ "$?" -ne 0 ]; then echo "FATAL: failed to sign, aborting" exit 1 fi cat newkey.pem newcert.pem > "${CADIR}/certs/${CERT_CN}.pem" chmod 600 "${CADIR}/certs/${CERT_CN}.pem" rm newkey.pem newcert.pem newreq.pem if [ ! -z "${GENPUB}" ] ; then OPENSSL_CONFIG="-config '${CADIR}/openssl.cnf'" ${OPENSSL} rsa -in "${CADIR}/certs/${CERT_CN}.pem" -out "${CADIR}/certs/${CERT_CN}-public.pem" -outform PEM -pubout -passin file:"${CADIR}/certs/${CERT_CN}.pass" fi else echo "Certificate '${CADIR}/${CERT_CN}.pem' already exist" echo "Can't continue" exit 1 fi exit 0 fi exit 0