#!/bin/bash
#
# idea... only.
# I've to create ~2100 ssl certificates from database
#
export SCRIPT_PATH=$( cd "$(dirname "${BASH_SOURCE}")" ; pwd -P )
DEFAULT_DOMAIN='reverse.com'
DEFAULT_IP='123.123.123.123'
declare -A DIR_NAME
DIR_NAME[cnf]='etc'
DIR_NAME[db]='db'
DIR_NAME[private]='private'
DIR_NAME[public]='public'
DIR_NAME[intermediateDir]='intermediate'
DIR_NAME[lookup]='lookup'
DIR_NAME[caRoot]='ca'
DIR_NAME[caEmail]='ca-email'
DIR_NAME[caSoftware]='ca-software'
DIR_NAME[caTls]='ca-tls'
DIR_NAME[crtEmail]='crt-email'
DIR_NAME[crtSoftware]='crt-software'
DIR_NAME[crtTls]='crt-tls'
DIR_NAME[email]='email'
DIR_NAME[software]='software'
DIR_NAME[tls]='tls'
declare -r DIR_NAME
declare -A FILE_NAME
FILE_NAME[cnf]='%s.%s.cnf'
FILE_NAME[csr]='%s.%s.csr'
FILE_NAME[p12]='%s.%s.p12'
FILE_NAME[crt]='%s.%s.crt'
FILE_NAME[crtPem]='%s.%s.crt.pem'
FILE_NAME[cer]='%s.%s.cer'
FILE_NAME[chainPem]='%s.%s.chain.pem'
FILE_NAME[chainP7c]='%s.%s.chain.p7c'
FILE_NAME[crtDb]='%s.%s.crt.db'
FILE_NAME[crtSrl]='%s.%s.crt.srl'
FILE_NAME[crl]='%s.%s.crl'
FILE_NAME[crlPem]='%s.%s.crl.pem'
FILE_NAME[crlSrl]='%s.%s.crl.srl'
FILE_NAME[key]='%s.%s.key'
FILE_NAME[keyPem]='%s.%s.key.pem'
FILE_NAME[password]='%s.%s.pwd'
declare -r FILE_NAME
declare -A DIRECTORIES_CA_ROOT
DIRECTORIES_CA_ROOT[caPath]="${DIR_NAME[caRoot]}"
DIRECTORIES_CA_ROOT[dbPath]="${DIR_NAME[caRoot]}/${DIR_NAME[db]}"
DIRECTORIES_CA_ROOT[cnfPath]="${DIR_NAME[caRoot]}/${DIR_NAME[cnf]}"
DIRECTORIES_CA_ROOT[privatePath]="${DIR_NAME[caRoot]}/${DIR_NAME[private]}"
declare -r DIRECTORIES_CA_ROOT
declare -A DIRECTORIES_CA_EMAIL
DIRECTORIES_CA_EMAIL[caPath]="${DIR_NAME[caEmail]}"
DIRECTORIES_CA_EMAIL[dbPath]="${DIR_NAME[caEmail]}/${DIR_NAME[db]}"
DIRECTORIES_CA_EMAIL[cnfPath]="${DIR_NAME[caEmail]}/${DIR_NAME[cnf]}"
DIRECTORIES_CA_EMAIL[privatePath]="${DIR_NAME[caEmail]}/${DIR_NAME[private]}"
declare -r DIRECTORIES_CA_EMAIL
declare -A DIRECTORIES_CRT_EMAIL
DIRECTORIES_CRT_EMAIL[crtPath]="${DIR_NAME[crtEmail]}"
DIRECTORIES_CRT_EMAIL[cnfPath]="${DIR_NAME[crtEmail]}/${DIR_NAME[cnf]}"
DIRECTORIES_CRT_EMAIL[privatePath]="${DIR_NAME[crtEmail]}/${DIR_NAME[private]}"
declare -r DIRECTORIES_CRT_EMAIL
declare -A DIRECTORIES_CA_SOFTWARE
DIRECTORIES_CA_SOFTWARE[caPath]="${DIR_NAME[caSoftware]}"
DIRECTORIES_CA_SOFTWARE[dbPath]="${DIR_NAME[caSoftware]}/${DIR_NAME[db]}"
DIRECTORIES_CA_SOFTWARE[cnfPath]="${DIR_NAME[caSoftware]}/${DIR_NAME[cnf]}"
DIRECTORIES_CA_SOFTWARE[privatePath]="${DIR_NAME[caSoftware]}/${DIR_NAME[private]}"
declare -r DIRECTORIES_CA_SOFTWARE
declare -A DIRECTORIES_CRT_SOFTWARE
DIRECTORIES_CRT_SOFTWARE[crtPath]="${DIR_NAME[crtSoftware]}"
DIRECTORIES_CRT_SOFTWARE[cnfPath]="${DIR_NAME[crtSoftware]}/${DIR_NAME[cnf]}"
DIRECTORIES_CRT_SOFTWARE[privatePath]="${DIR_NAME[crtSoftware]}/${DIR_NAME[private]}"
declare -r DIRECTORIES_CRT_SOFTWARE
declare -A DIRECTORIES_CA_TLS
DIRECTORIES_CA_TLS[caPath]="${DIR_NAME[caTls]}"
DIRECTORIES_CA_TLS[dbPath]="${DIR_NAME[caTls]}/${DIR_NAME[db]}"
DIRECTORIES_CA_TLS[cnfPath]="${DIR_NAME[caTls]}/${DIR_NAME[cnf]}"
DIRECTORIES_CA_TLS[privatePath]="${DIR_NAME[caTls]}/${DIR_NAME[private]}"
declare -r DIRECTORIES_CA_TLS
declare -A DIRECTORIES_CRT_TLS
DIRECTORIES_CRT_TLS[crtPath]="${DIR_NAME[crtTls]}"
DIRECTORIES_CRT_TLS[cnfPath]="${DIR_NAME[crtTls]}/${DIR_NAME[cnf]}"
DIRECTORIES_CRT_TLS[privatePath]="${DIR_NAME[crtTls]}/${DIR_NAME[private]}"
declare -r DIRECTORIES_CRT_TLS
declare -A DIRECTORIES_PUB
DIRECTORIES_PUB[email]="${DIR_NAME[public]}/${DIR_NAME[email]}"
DIRECTORIES_PUB[software]="${DIR_NAME[public]}/${DIR_NAME[software]}"
DIRECTORIES_PUB[tls]="${DIR_NAME[public]}/${DIR_NAME[tls]}"
declare -r DIRECTORIES_PUB
check_result()
{
if [ $1 -ne 0 ]; then
echo -e "\e[91m Error\e[39m $2"
exit $1
fi
echo -e "\e[92m Ok\e[39m"
}
warn_result()
{
if [ $1 -ne 0 ]; then
echo -e "\e[93m Warning\e[39m $2"
fi
}
check_prompt()
{
if [ $1 -ne 0 ]; then
warn_result "$@"
read -p 'Would you like to continue [y/n]: ' answer
if [ "$answer" != 'y' ] && [ "$answer" != 'Y' ]; then
echo 'Goodbye'
exit 1
fi
fi
}
writeNewCert()
{
local domain=$1
local x=$(printf '%-64s' "create certificates for")
local y=$(printf '%-64s' "$domain")
local z=$(printf '%-64s' '')
echo -e "\e[90m$z\e[39m"
echo -e "\e[92m$x\e[39m"
echo -e "\e[96m$y\e[39m"
echo -e "\e[90m$z\e[39m"
}
writeDelCert()
{
local domain=$1
local x=$(printf '%-64s' "delete certificates for")
local y=$(printf '%-64s' "$domain")
local z=$(printf '%-64s' '')
echo -e "\e[90m$z\e[39m"
echo -e "\e[91m$x\e[39m"
echo -e "\e[96m$y\e[39m"
echo -e "\e[90m$z\e[39m"
}
writeRevCert()
{
local domain=$1
local x=$(printf '%-64s' "revoke certificates for")
local y=$(printf '%-64s' "$domain")
local z=$(printf '%-64s' '')
echo -e "\e[90m$z\e[39m"
echo -e "\e[93m$x\e[39m"
echo -e "\e[96m$y\e[39m"
echo -e "\e[90m$z\e[39m"
}
writeNewType()
{
local type=$1
echo -e "\e[97m• \e[92mcreate\e[97m $type\e[39m"
}
writeDelType()
{
local type=$1
echo -e "\e[97m• \e[91mdelete\e[97m $type\e[39m"
}
writeNewItem()
{
local item=$1
echo -e "\e[90m \e[92m+\e[90m $item\e[39m"
}
writeDelItem()
{
local item=$1
echo -e "\e[90m \e[91m-\e[90m $item\e[39m"
}
writeDelItem2()
{
local item=$1
echo -e "\e[90m \e[91m-\e[90m $item\e[39m"
}
writeNewItem2()
{
local item=$1
echo -e "\e[90m \e[92m+\e[90m $item\e[39m"
}
#
# certificate reverse.com domain.com create tls-server ssl
#
certificate()
{
local reverseDomain=$1
local domain=$2
local action=$3
local configType=$4
local fileNameInfix=$5
local subject=$6
##############################################################
#
# bootstrap
#
##############################################################
local fileName="$fileNameInfix;;$domain"
getDomainPath()
{
local reverseDomain=$1
local domain=$2
local lookup="$reverseDomain/lookup/$domain"
if [ -f $lookup ]; then
echo $(head -n 1 "$lookup")
fi
}
getBaseType()
{
local type=$1
case "$type" in
email)
echo 'email'
;;
tls-server|tls-server-external|tls-client|tls-client-external)
echo 'tls'
;;
code-signing)
echo 'software'
;;
*)
check_result 1 "invalid request type $type; {email|tls-client|tls-client-external|tls-server|tls-server-external|code-signing}"
esac
}
declare -A FILES
declare -A DIRS
getFiles()
{
local domain=$1
local domainPath=$2
local baseType=$3
local configType=$4
local fileName=$5
local caType
local crtType
DIRS[ca]=$domainPath
DIRS[pub]=$domainPath/${DIR_NAME[public]}
case "$baseType" in
email)
local caType=${DIR_NAME[caEmail]}
local crtType=${DIR_NAME[crtEmail]}
DIRS[caDb]=$domainPath/${DIRECTORIES_CA_EMAIL[dbPath]}
DIRS[caCnf]=$domainPath/${DIRECTORIES_CA_EMAIL[cnfPath]}
DIRS[caPrivate]=$domainPath/${DIRECTORIES_CA_EMAIL[privatePath]}
DIRS[crt]=$domainPath/${DIRECTORIES_CRT_EMAIL[crtPath]}
DIRS[crtCnf]=$domainPath/${DIRECTORIES_CRT_EMAIL[cnfPath]}
DIRS[crtPrivate]=$domainPath/${DIRECTORIES_CRT_EMAIL[privatePath]}
DIRS[pubCrt]=$domainPath/${DIRECTORIES_PUB[email]}
;;
tls)
local caType=${DIR_NAME[caTls]}
local crtType=${DIR_NAME[crtTls]}
DIRS[caDb]=$domainPath/${DIRECTORIES_CA_TLS[dbPath]}
DIRS[caCnf]=$domainPath/${DIRECTORIES_CA_TLS[cnfPath]}
DIRS[caPrivate]=$domainPath/${DIRECTORIES_CA_TLS[privatePath]}
DIRS[crt]=$domainPath/${DIRECTORIES_CRT_TLS[crtPath]}
DIRS[crtCnf]=$domainPath/${DIRECTORIES_CRT_TLS[cnfPath]}
DIRS[crtPrivate]=$domainPath/${DIRECTORIES_CRT_TLS[privatePath]}
DIRS[pubCrt]=$domainPath/${DIRECTORIES_PUB[tls]}
;;
software)
local caType=${DIR_NAME[caSoftware]}
local crtType=${DIR_NAME[crtSoftware]}
DIRS[caDb]=$domainPath/${DIRECTORIES_CA_SOFTWARE[dbPath]}
DIRS[caCnf]=$domainPath/${DIRECTORIES_CA_SOFTWARE[cnfPath]}
DIRS[caPrivate]=$domainPath/${DIRECTORIES_CA_SOFTWARE[privatePath]}
DIRS[crt]=$domainPath/${DIRECTORIES_CRT_SOFTWARE[crtPath]}
DIRS[crtCnf]=$domainPath/${DIRECTORIES_CRT_SOFTWARE[cnfPath]}
DIRS[crtPrivate]=$domainPath/${DIRECTORIES_CRT_SOFTWARE[privatePath]}
DIRS[pubCrt]=$domainPath/${DIRECTORIES_PUB[software]}
;;
*)
check_result 1 "invalid request baseType $baseType; {email|tls|software}"
esac
FILES[caChainPem]=${DIRS[ca]}/$(printf ${FILE_NAME[chainPem]} $domain $caType)
FILES[caCrl]=${DIRS[caDb]}/$(printf ${FILE_NAME[crl]} $domain $caType)
FILES[caCnf]=${DIRS[caCnf]}/$(printf ${FILE_NAME[cnf]} $domain $caType)
FILES[caPwd]=${DIRS[caPrivate]}/$(printf ${FILE_NAME[password]} $domain $caType)
FILES[crt]=${DIRS[crt]}/$(printf ${FILE_NAME[crt]} $fileName $configType)
FILES[crtCsr]=${DIRS[crt]}/$(printf ${FILE_NAME[csr]} $fileName $configType)
FILES[crtP12]=${DIRS[crt]}/$(printf ${FILE_NAME[p12]} $fileName $configType)
FILES[crtChainPem]=${DIRS[crt]}/$(printf ${FILE_NAME[chainPem]} $fileName $configType)
FILES[crtCnf]=${DIRS[crtCnf]}/$(printf ${FILE_NAME[cnf]} $domain $configType)
FILES[crtKey]=${DIRS[crtPrivate]}/$(printf ${FILE_NAME[key]} $fileName $configType)
FILES[pubCaCrl]=${DIRS[pub]}/$(printf ${FILE_NAME[crl]} $domain $caType)
FILES[pubCer]=${DIRS[pubCrt]}/$(printf ${FILE_NAME[cer]} $fileName $configType)
FILES[pubChainP7c]=${DIRS[pubCrt]}/$(printf ${FILE_NAME[chainP7c]} $fileName $configType)
FILES[pubKeyPem]=${DIRS[pubCrt]}/$(printf ${FILE_NAME[keyPem]} $fileName $configType)
FILES[pubCrtPem]=${DIRS[pubCrt]}/$(printf ${FILE_NAME[crtPem]} $fileName $configType)
}
local domainPath=$(getDomainPath $reverseDomain $domain)
local baseType=$(getBaseType $configType)
getFiles $domain $domainPath $baseType $configType $fileName
local lvl=$(grep -o '/intermediate/' <<< "$domainPath" | wc -l)
case "$lvl" in
0)
export CA_0_SCRIPT_PATH="$domainPath"
;;
1)
export CA_1_SCRIPT_PATH="$domainPath"
;;
2)
export CA_2_SCRIPT_PATH="$domainPath"
;;
esac
##############################################################
#
# actions
#
##############################################################
case "$action" in
create)
writeNewCert "$4: $5"
if [ -e ${FILES[crt]} ]; then
writeDelType "old $4: $5"
certificate "$1" "$2" revoke "$4" "$5"
fi
case "$configType" in
tls-server)
writeNewType "$4: $5"
writeNewItem 'csr + key'
export SAN="DNS:$domain,DNS:*.$domain"
openssl req -new \
-config ${FILES[crtCnf]} \
-out ${FILES[crtCsr]} \
-keyout ${FILES[crtKey]} \
-subj "/C=BE/ST=Antwerp/O=### Network $domain/CN=$domain"
check_result $? 'unable to create csr + key'
openssl ca \
-batch \
-config ${FILES[caCnf]} \
-in ${FILES[crtCsr]} \
-out ${FILES[crt]} \
-passin file:${FILES[caPwd]} \
-extensions server_ext \
> /dev/null 2>&1
check_result $? 'unable to create crt'
writeNewItem 'dump'
head -3 ${FILES[crtKey]}
head -3 ${FILES[crtCsr]}
head -3 ${FILES[crt]}
writeNewItem "verify"
openssl verify -CAfile ${FILES[caChainPem]} ${FILES[crt]}
writeNewItem 'p12'
openssl pkcs12 -export \
-name "$domain: $fileNameInfix (TLS Network Component)" \
-inkey ${FILES[crtKey]} \
-passout pass:\
-in ${FILES[crt]} \
-certfile ${FILES[caChainPem]} \
-out ${FILES[crtP12]} \
> /dev/null 2>&1
check_result $? 'unable to create p12'
writeNewItem 'pem key from p12'
openssl pkcs12 -nocerts -nodes \
-in ${FILES[crtP12]} \
-passin pass:\
-out ${FILES[pubKeyPem]} \
> /dev/null 2>&1
check_result $? 'unable to create pem key'
writeNewItem 'passfree pem key'
openssl rsa \
-in ${FILES[pubKeyPem]} \
-out ${FILES[pubKeyPem]} \
> /dev/null 2>&1
check_result $? 'unable to create passfree pem key'
writeNewItem 'pem crt from p12'
openssl pkcs12 -clcerts -nokeys \
-in ${FILES[crtP12]} \
-passin pass:\
-out ${FILES[pubCrtPem]} \
> /dev/null 2>&1
check_result $? 'unable to create p12'
;;
esac
;;
delete)
writeDelCert "$4: $5"
if [ -e ${FILES[crt]} ]; then
certificate "$1" "$2" revoke "$4" "$5"
fi
writeDelType 'files'
writeDelItem ${FILES[crt]}
rm ${FILES[crt]} > /dev/null 2>&1
writeDelItem ${FILES[crtCsr]}
rm ${FILES[crtCsr]} > /dev/null 2>&1
writeDelItem ${FILES[crtP12]}
rm ${FILES[crtP12]} > /dev/null 2>&1
writeDelItem ${FILES[crtKey]}
rm ${FILES[crtKey]} > /dev/null 2>&1
writeDelItem ${FILES[pubCrtPem]}
rm ${FILES[pubCrtPem]} > /dev/null 2>&1
writeDelItem ${FILES[pubKeyPem]}
rm ${FILES[pubKeyPem]} > /dev/null 2>&1
;;
revoke)
writeRevCert "$4: $5"
if [ -e ${FILES[crt]} ]; then
local lastSrl=$(openssl x509 -in ${FILES[crt]} -serial -noout)
local lastFnr=$(openssl x509 -in ${FILES[crt]} -fingerprint -noout)
local revokationReason
case "$configType" in
email)
revokationReason=affiliationChanged
;;
tls-server|tls-server-external|tls-client|tls-client-external)
revokationReason=affiliationChanged
;;
code-signing)
revokationReason=affiliationChanged
;;
esac
check_prompt 1 "certificate $fileName.$configType.crt exists as \n\t$lastSrl\n\t$lastFnr\n"
echo "Please set the revokation reason, default CRL reason for type $configType is $revokationReason."
echo '[1] unspecified'
echo '[2] keyCompromise'
echo '[3] CACompromise'
echo '[4] affiliationChanged'
echo '[5] superseded'
echo '[6] cessationOfOperation'
echo '[7] certificateHold'
echo '[8] removeFromCRL'
echo '[n] set no reason'
read -p 'Please set the revokation reason [1-8]: ' answer
case "$answer" in
1)
revokationReason=unspecified
;;
2)
revokationReason=keyCompromise
;;
3)
revokationReason=CACompromise
;;
4)
revokationReason=affiliationChanged
;;
5)
revokationReason=superseded
;;
6)
revokationReason=cessationOfOperation
;;
7)
revokationReason=certificateHold
;;
8)
revokationReason=removeFromCRL
;;
'n'|'N')
revokationReason=no
;;
*)
warn_result 1 "Nothing selected. Continue with default and set $revokationReason"
esac
if [ $revokationReason == 'no' ]; then
openssl ca \
-config ${FILES[caCnf]} \
-revoke ${FILES[crt]} \
-passin file:${FILES[caPwd]} \
> /dev/null 2>&1
else
openssl ca \
-config ${FILES[caCnf]} \
-revoke ${FILES[crt]} \
-passin file:${FILES[caPwd]} \
-crl_reason $revokationReason \
> /dev/null 2>&1
fi
openssl ca -gencrl \
-config ${FILES[caCnf]} \
-out ${FILES[caCrl]} \
-passin file:${FILES[caPwd]} \
> /dev/null 2>&1
openssl crl \
-in ${FILES[caCrl]} \
-out ${FILES[pubCaCrl]} \
-outform der \
> /dev/null 2>&1
fi
;;
esac
}
Comments