gencsr tooling
The snippet can be accessed without any authentication.
Authored by
Wolfspyre Automation
homegrown tool to make the creation and regeneration of ssl certificates a lil easier
gencsr.sh 9.39 KiB
#!/usr/bin/env bash
# v0.5 2023.09.01
# Retool to consume keyfile to gen CSR.
# v0.4
# put emailAddress back in the [dn] section.
# v0.3
# added SAN
export MIN_OPTS=3
export _STARTTIME=$(/bin/date +%s)
usage () {
cat <<EOF
Expects at least ${MIN_OPTS}
usage: $0 PARAMS_FILE #SANs #IPs OPTIONAL_KeyFile-to-reuse
PARAMS_FILE should contain:
C="US"
ST="Texas"
L="Austin"
O="Wolfspyre Labs"
OU="Public"
HOST='PRETTY_NAME'
BITS=2048
DAYS=1826
CN='CERT-CN-HERE'
CONTACT='domains@wolfspaw.com'
SAN1='san-one'
SAN2='SAN-two'
SAN3='you-get-the-drill'
IP1='1.2.3.4'
IP2='5.6.7.8'
IP3='127.0.0.1'
Debug statements will be output if the variable DEBUG exists; Example:
DEBUG=true; $0 params.txt 3 3 mykey.key
EOF
return -1
}
runningTime () {
_NOW=$(/bin/date +%s)
echo -e "$(( ${_NOW}-${_STARTTIME} ))"
}
error () {
MSG=$1
_time=$(runningTime)
echo -e "\033[31m[${_time}s] ERROR\033[0m: $MSG" >>/dev/stderr
}
warn () {
MSG=$1
_time=$(runningTime)
echo -e "\033[1;33m[${_time}s] WARN\033[0m: $MSG" >>/dev/stderr
}
info () {
MSG=$1
_time=$(runningTime)
echo -e "\033[32m[${_time}s] INFO\033[0m: $MSG"
}
debug () {
MSG=$1
_time=$(runningTime)
if [[ $2 && $2 == 'verbose' ]]; then
verbose_msg=true
else
verbose_msg=false
fi
if [ -n "$DEBUG" ]; then
if $verbose_msg; then
#only display verbose if DEBUG == verbose
if [ ${DEBUG} == 'verbose' ]; then
echo -e "\033[35mVERBOSE\033[0m: \033[32m[${_time}s] ${FUNCNAME[1]}()\033[0m: ${MSG}"
fi
else
echo -e "\033[34mDEBUG\033[0m: \033[32m[${_time}s] ${FUNCNAME[1]}()\033[0m: ${MSG}"
fi
fi
}
echodo() {
echo "${@}"
(${@})
}
infodo() {
info "${@}"
(${@})
}
containsElement () {
local e
for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
return 1
}
checkFile() {
_file=$1
if [[ -f ${_file} ]]; then
debug "$_file exists"
else
error "Specified file ${_file} doesn't exist. Cannot continue"
exit 1
fi
}
makeDirIfNeedful() {
_dir=$1
if [[ -d ${_dir} ]]; then
debug "$_dir exists"
else
warn "Specified dir ${_dir} doesn't exist. Doing the needful"
mkdir -p ${_dir}
fi
}
checkDir() {
_dir=$1
if [[ -d ${_dir} ]]; then
debug "$_dir exists"
else
error "Specified dir ${_dir} doesn't exist. Cannot continue"
exit 1
fi
}
checkMountpoint() {
_mountpoint=$1
_matches=$(/usr/bin/awk " \$2 ~ \"${_mountpoint}\" {print \$2}" /proc/mounts|/usr/bin/wc -l)
#if the second field of the output of /proc/mounts matches the mountpoint, print the output to wc to return the number of matches.
# this could be done differently.
if [[ "${_matches}" == 0 ]]; then
# we didn't get a match for some reason. Not a mountpoint we can trust. fail.
error "Got ${_matches} matches while inspecting /proc/mounts for ${_mountpoint}. Cannot proceed."
exit 1
elif [[ "${_matches}" == 1 ]]; then
debug "Success. matched ${_mountpoint} in /proc/mounts."
else
error "Got an unexpected count of ${_matches} when looking at /proc/mounts. Perhaps you could explicitly match versus regex?"
# Comment this out if you don't mind multiple matches for some reason.
exit 1
#
fi
}
echodo() {
echo "${@}"
(${@})
}
yearmon() {
date '+%Y%m%d'
}
fqdn() {
(nslookup ${1} 2>&1 || echo Name ${1}) \
| tail -3 | grep Name| sed -e 's,.*e:[ \t]*,,'
}
spinner()
{
#http://stackoverflow.com/questions/12498304/using-bash-to-display-a-progress-working-indicator
#http://stackoverflow.com/questions/1570262/shell-get-exit-code-of-background-process
local pid=$!
if [[ $1 ]]; then
local cmd=$1
debug "using ${cmd} as the command name for `ps -p ${pid} -o cmd h`"
else
local cmd=`ps -p ${pid} -o cmd h`
fi
local delay=0.5
local spinstr='|/-\'
echo -ne "\033[32m"
while [ "$(ps a | awk '{print $1}' | grep $pid)" ]; do
local temp=${spinstr#?}
printf "%c" "$spinstr"
local spinstr=$temp${spinstr%"$temp"}
sleep $delay
printf "\b\b\b"
done
wait $pid
local pidstatus=$?
debug "pid: ${pid} returned status: ${pidstatus}" verbose
printf "\b\b"
echo -ne "\033[0m"
case ${pidstatus} in
0 )
debug "${cmd} exited successfully"
;;
100 )
#apt-get returns this when it's installed a package
error "${cmd} could not install something? "
exit 1
;;
* )
#assume something went wrong
error "The execution of [ ${cmd} ] failed!"
exit 1
;;
esac
}
snifftest()
{
info "Checking that all necessary binaries exist"
for F in ${_SSLBIN}; do
checkFile ${F}
done
}
inspectCert(){
_CERT = $1
}
inspectCSR(){
_CSR=$1
checkFile ${_CSR}
infodo "${_SSLBIN} req -text -noout -in ${_CSR}"
}
inspectKey(){
_KEY=$1
_O='0'
_E='0'
checkFile ${_KEY}
info "Keyfile ${_KEY} found. Starting inspection"
if [[ `${_SSLBIN} rsa -in ${_KEY} -check -noout` ]]; then
info "Key ${_KEY} passes openssl inspection"
else
error "Key ${_KEY} no bueno! Openssl errored."
exit 1
fi
}
validateParams(){
for VAR in C ST L O OU HOST BITS DAYS CN CONTACT; do
if [[ $(echo ${!VAR}|wc -w) -gt 0 ]]; then
debug "Validating ${VAR}: ${!VAR}"
else
error "${VAR} seems wrong: ${!VAR}\n Please inspect yout params file: ${_PARAMSFILE}"
exit 1
fi
done
info "Params Validated"
return 0
}
validateSANs(){
_SANITER=0
_SCOUNT=$1
debug "Validating that we have ${_SCOUNT} SANs defined"
while [[ ${_SANITER} -lt ${_SANCOUNT} ]]; do
let _SANITER=(${_SANITER}+1)
_SN=SAN${_SANITER}
if [[ $(echo ${!_SN}|wc -w) -gt 0 ]]; then
debug "${_SANITER}/${_SANCOUNT}: SAN${_SANITER}: ${!_SN}"
else
error "SAN ${_SANITER} of ${_SANCOUNT} seems problematic. Check your paramsfile."
exit 1
fi
done
info "${_SANCOUNT} SAN vars present"
return 0
}
validateIPs(){
_IPITER=0
_ICOUNT=$1
debug "Validating that we have ${_ICOUNT} IPs defined"
while [[ ${_IPITER} -lt ${_IPCOUNT} ]]; do
let _IPITER=(${_IPITER}+1)
_IPN=IP${_IPITER}
if [[ $(echo ${!_IPN}|wc -w) -gt 0 ]]; then
debug "${_IPITER}/${_IPCOUNT}: IP${_IPITER}: ${!_IPN}"
else
error "IP ${_IPITER} of ${_IPCOUNT} of seems problematic. Check your paramsfile."
exit 1
fi
done
info "${_IPCOUNT} IP vars present"
return 0
}
fork() { (setsid "$@" &); }
validateME() {
debug "testing Params"
validateParams; _VP=$?
debug "testing SANs"
validateSANs ${_SANCOUNT}; _VS=$?
debug "testing IPs"
validateIPs ${_IPCOUNT}; _VI=$?
if [[ ${_VP} == 0 && ${_VS} == 0 && ${_VI} == 0 ]]; then
info "smells ok. Proceeding"
else
error "sorry. something went wrong. \n Fuck your day."
exit 1
fi;
}
genCSRDetails() {
export CSR="${HOST}-${DATE}-csr.pem"
export CSR_DETAILS="${HOST}-${DATE}-csr-details.txt"
export mydir="${PWD}"
export MYCSRPATH="${mydir}/${CSR}"
export MYKEYPATH="${mydir}/${_KEYFILE}"
export MYCSR_DETAILS="${mydir}/${CSR_DETAILS}"
debug "\n CSR: ${CSR}\n Details: ${MYCSR_DETAILS}\n CSR Path: ${MYCSRPATH}\n KeyPath: ${MYKEYPATH}"
info "Creating ${MYCSR_DETAILS}"
cat > ${MYCSR_DETAILS} <<-EOF
[req]
default_bits = ${BITS}
prompt = no
default_md = sha256
req_extensions = req_ext
x509_extensions = x509_ext
distinguished_name = dn
[ dn ]
emailAddress=${CONTACT}
C=${C}
ST=${ST}
L=${L}
O=${O}
OU=${OU}
CN = ${CN}
[ req_ext ]
subjectKeyIdentifier = hash
subjectAltName = @alt_names
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth, clientAuth, codeSigning, 1.3.6.1.5.5.8.2.2
[ x509_ext ]
subjectKeyIdentifier = hash
subjectAltName = @alt_names
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth, clientAuth, codeSigning, 1.3.6.1.5.5.8.2.2
[ alt_names ]
email = ${CONTACT}
EOF
_SANITER=0
_SCOUNT=${_SANCOUNT}
_IPITER=0
_ICOUNT=${_IPCOUNT}
debug "adding SANs\
$(while [[ ${_SANITER} -lt ${_SANCOUNT} ]]; do let _SANITER=(${_SANITER}+1) ; _SN=SAN${_SANITER}; echo "DNS.${_SANITER} = ${!_SN}">> ${MYCSR_DETAILS}; echo -n '.' ; done)"
debug "adding IPs\
$(while [[ ${_IPITER} -lt ${_IPCOUNT} ]]; do let _IPITER=(${_IPITER}+1); _IPN=IP${_IPITER}; echo "IP.${_IPITER} = ${!_IPN}" >> ${MYCSR_DETAILS}; echo -n '.'; done)"
info "CSR Details populated."
}
genCSR(){
if [[ -n ${_KEYFILE} ]]; then
info "Generating CSR from existing Keyfile: ${MYKEYPATH}"
infodo "${_SSLBIN} req -new -sha256 -nodes -extensions req_ext -out ${MYCSRPATH} -key ${MYKEYPATH} -config ${MYCSR_DETAILS} "
else
info "Generating CSR and key from details"
infodo "${_SSLBIN} req -new -sha256 -nodes -extensions req_ext -out ${MYCSRPATH} -newkey rsa:${BITS} -keyout ${MYKEYPATH} -config ${MYCSR_DETAILS} -days ${DAYS}"
echodo "${_SSLBIN} req -text -days ${DAYS} -noout -in ${MYCSRPATH}"
fi
}
if [ $# -lt ${MIN_OPTS} ]; then
usage
else
export _SSLBIN=`which openssl`
DATE=`yearmon`
info 'ensuring expected binaries are in place'
snifftest
_PARAMSFILE=$1
_SANCOUNT=$2||0
_IPCOUNT=$3||0
_KEYFILE=$4||false
info 'unsetting paramsfile keys'
for VAR in C ST L O OU HOST BITS DAYS CN CONTACT; do
unset ${!VAR}
done
. ${_PARAMSFILE}
validateME
if [[ -n $_KEYFILE ]]; then
info "Was Given KeyFile: ${_KEYFILE}"
inspectKey ${_KEYFILE};_KC=$?
else
info "No Keyfile Given"
fi
genCSRDetails; _CSRDRC=$?
if [[ ${_CSRDC} -eq 0 ]]; then
genCSR
else
warn "genCSRDetails return code was not 0: [ ${_CSRDC}]"
fi
fi
params 246 B
Please register or sign in to comment