Skip to content

Instantly share code, notes, and snippets.

@rjruss
Last active February 5, 2018 23:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rjruss/273e3a82611310d6b35c6b1ddb48bee1 to your computer and use it in GitHub Desktop.
Save rjruss/273e3a82611310d6b35c6b1ddb48bee1 to your computer and use it in GitHub Desktop.
#!/bin/bash
# Created by Robert Russell in 2017 to setup demo CA based on CA.pl
# Most likely wont do what you want it to do :) but I am using this
# Example of my use is here
# It can create certicates for SQL Anywhere, NODE, SAP NetWeaver Etc
# See the above blog link for examples
# https://blogs.sap.com/?p=613537
# I use the script as follows
# I use option 1 to create certificates/ID file for SQL Anywhere
# I use option 2 to create certificates file and unenctpyed key for NODE
# I use option 3 to sign CSRs from SAP NetWeaver PSEs
export CDIR=.
export TDIR=./tmpssl
rm -rf $TDIR
mkdir $TDIR
export CACLOC=/usr/share/ssl/misc:/usr/lib/ssl/misc
export CAC=CA.pl
export OPENSSL_CONF=$TDIR/ssl.cnf
export CAdir=$CDIR/demoCA
export CN=""
export SAN=""
#Server Certs
export EXTKEY="serverAuth"
export KEYUSA="digitalSignature,keyEncipherment,dataEncipherment,keyAgreement"
#CLIENT Certs
#export EXTKEY="clientAuth"
#export KEYUSA="digitalSignature,nonRepudiation,keyEncipherment"
#If creating Client certs remove the comments from the two lines above and
#convert to p12 with openssl command below
# openssl pkcs12 -export -clcerts -in newcert.pem -inkey newkey.pem -out client.p12
#The supported names are: digitalSignature, nonRepudiation, keyEncipherment,
#dataEncipherment, keyAgreement, keyCertSign, cRLSign,
#encipherOnly and decipherOnly
#SUSE client
#Key Usage: digitalSignature
# nonRepudiation
# keyEncipherment
#SUSE Server
#Key Usage: (critical)
# digitalSignature
# keyEncipherment
# keyAgreement
#CreateCert adds dataEncipherment
export PATH=$PATH:$CACLOC
if ! type -P $CAC ; then
echo "CA.pl script not found!"
echo "This script expects CA.pl to be in PATH $CACLOC"
exit
fi
echo "Creating openssl config file ssl.cnf "
#BUILD CONFIG FILE
cat <<EOF > $OPENSSL_CONF
[ ca ]
default_ca = CA_default # The default ca section
[ CA_default ]
dir = ./demoCA # Where everything is kept
certs = \$dir/certs # Where the issued certs are kept
crl_dir = \$dir/crl # Where the issued crl are kept
database = \$dir/index.txt # database index file.
new_certs_dir = \$dir/newcerts # default place for new certs.
certificate = \$dir/cacert.pem # The CA certificate
serial = \$dir/serial # The current serial number
crlnumber = \$dir/crlnumber # the current crl number
crl = \$dir/crl.pem # The current CRL
private_key = \$dir/private/cakey.pem# The private key
RANDFILE = \$dir/private/.rand # private random number file
x509_extensions = usr_cert # The extentions to add to the cert
name_opt = ca_default # Subject Name options
cert_opt = ca_default # Certificate field options
default_days = 3650 # how long to certify for
default_crl_days= 30 # how long before next CRL
default_md = sha256 # use public key default MD
preserve = no # keep passed DN ordering
policy = policy_match
[ policy_match ]
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_anything ]
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
default_bits = 2048
default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
#attributes = req_attributes
x509_extensions = v3_ca # The extentions to add to the self signed cert
string_mask = utf8only
req_extensions = v3_req # The extensions to add to a certificate request
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = GB
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = West Midlands
localityName = Locality Name (eg, city)
localityName_default = Solihull
0.organizationName = Organization Name (eg, company)
0.organizationName_default = Mine
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = Haw
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = \${ENV::CN}
commonName_max = 125
emailAddress = Email Address
emailAddress_default = rob.roosky@yahoo.com
emailAddress_max = 64
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
unstructuredName = An optional company name
[ usr_cert ]
basicConstraints=CA:FALSE
keyUsage = \${ENV::KEYUSA}
extendedKeyUsage = \${ENV::EXTKEY}
nsComment = "OpenSSL Generated Certificate"
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
subjectAltName=\${ENV::SAN}
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = \${ENV::KEYUSA}
extendedKeyUsage = \${ENV::EXTKEY}
subjectAltName=\${ENV::SAN}
[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = CA:true
keyUsage = cRLSign, keyCertSign
EOF
function ck_cn_name(){
if [[ -d "$CN" ]];then
echo "PROBLEM - Common Name already exists"
echo "Check that certificate already exists in directory $CN"
echo "To recreate - remove directory and entry from ./demoCA/index.txt"
grep $CN ./demoCA/index.txt
exit 1
fi
}
function common_name() {
printf "\n Enter Common Name e.g. vhcalnpl1.dummy.domain"
EX=N
CN=""
echo
while [[ $EX = "N" ]] ; do
read -p 'Enter Common Name : ' CNL
echo $CNL
read -p 'Continue (Y/N) answer N to enter Common Name again :' YN
echo $YN
echo ""
if [[ $YN = [Yy] ]] ;then
CN=$CNL
EX=Y
fi
done
ck_cn_name
}
function auto_cn_name(){
CN=`openssl req -text -noout -in newreq.pem|grep Subject:|sed '
s#$#,#
s#\(.*\)/email.*$#\1,#
s#.*CN=\(.*\)[\/,].*$#\1#'`
ck_cn_name
}
function san_name() {
if [[ $SAN = "" ]];then
SAN="DNS:$CN,"
fi
printf "\n Enter Subject Alternate Names "
printf "\n By default $CN will be used as a SAN"
printf "\n hostname -a for this host = `hostname -a`"
printf "\n Enter one SAN at a time and use N at the continue prompt to exit"
EX=N
printf "\n current SAN = $SAN \n"
while [[ $EX = "N" ]] ; do
read -p 'Enter new SAN Names one at a time (or leave blank & press enter): ' SANL
if [[ ! -z $SANL ]]; then
SANL="DNS:$SANL"
SAN="$SAN$SANL,"
fi
echo $SAN
read -p 'Press enter to input another SAN| N to exit| R reset entry (Y/N/R):' YN
echo $YN
if [[ $YN = [Rr] ]] ;then
SAN=""
fi
if [[ $YN = [Nn] ]] ;then
EX="Y"
fi
done
}
function sign_cert() {
printf "\npress ENTER TO SIGN NEW REQUEST"
read IDC
$CAC -sign
mkdir "$CN"
printf "\nCopying all files to new directory $CN\n"
cp newreq.pem newkey.pem newcert.pem "$CN"
}
echo $CAdir
if [ ! -d $CAdir ]; then
echo -e "\033[4mCA.pl default directory demoCA not found\033[0m"
echo "Using the CA.pl script to create new certificate authority in current dir"
printf "\nEnter a NAME for this Certificate Authority"
common_name
echo -e "\033[1mREMEMBER the password at the Enter PEM phrase prompt\033[0m"`
echo -e "\033[1m-password NEEDS to be between 4 to 20 chars long\033[0m"`
echo -e "\033[4mPress Enter to create new root CA at next prompt\033[0m"
SAN="DNS:dummy"
${CAC} -newca
echo $?
fi
title="Root Certificate Authority based on CA.pl "
prompt="Pick an option:"
options=("newreq (with encrypted key)" "newreq-nodes (without encrpted key)" "sign (already existing CSR in newreq.pem)")
echo "$title"
PS3="$prompt "
select opt in "${options[@]}" "Quit"; do
case "$REPLY" in
1 ) echo "You picked $opt "
common_name
SAN="DNS:$CN,"
san_name
SAN=`echo $SAN|sed "s/,$//"`
echo $SAN
$CAC -newreq
sign_cert
exit 0
;;
2 ) echo "You picked $opt "
common_name
SAN="DNS:$CN,"
san_name
SAN=`echo $SAN|sed "s/,$//"`
echo $SAN
$CAC -newreq-nodes
sign_cert
exit 0
;;
3 ) echo "You picked $opt which is option $REPLY"
if [[ -f newreq.pem ]]; then
SAN="DNS:dummy"
auto_cn_name
SAN=`openssl req -text -noout -in newreq.pem|grep DNS:`
printf "***Use [[$CN]] from request as SAN name"
san_name
if [[ ! -z $SAN ]];then
SAN=`echo $SAN|sed "s/,$//"`
sign_cert
else
printf "\nNo SAN entered please try again"
fi
else
printf "\nMissing newreq.pem file to sign"
fi
break
;;
$(( ${#options[@]}+1 )) ) echo "Goodbye!"; break;;
*) echo "Invalid option. Try another one.";continue;;
esac
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment