From 7e5a76e7996ebcba36536c8fecd31a95280f3417 Mon Sep 17 00:00:00 2001 From: B Stack Date: Wed, 6 Dec 2017 06:51:36 -0500 Subject: Initial commit --- files/certreq.sh | 336 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100755 files/certreq.sh (limited to 'files/certreq.sh') diff --git a/files/certreq.sh b/files/certreq.sh new file mode 100755 index 0000000..dea652f --- /dev/null +++ b/files/certreq.sh @@ -0,0 +1,336 @@ +#!/bin/sh +# Filename: certreq.sh +# Location: atower201:/etc/ansible/roles/certreq/files/certreq.sh +# Author: bgstack15@gmail.com +# Startdate: 2017-11-17 09:13:53 +# Title: Script that Requests a Certificate from a Microsoft Sub-CA +# Purpose: Automate host certificate generation in a domain environment +# Package: ansible role certreq +# History: +# 2017-11-22 Added ca cert chain +# Usage: in ansible role certreq +# Microsoft CA cert templates have permissions on them. A user must be able to "enroll" on the template. +# Reference: ftemplate.sh 2017-10-10x; framework.sh 2017-10-09a +# fundamental curl statements https://stackoverflow.com/questions/31283476/submitting-base64-csr-to-a-microsoft-ca-via-curl/39722983#39722983 +# Improve: +fiversion="2017-10-10x" +certreqversion="2017-11-29a" + +usage() { + less -F >&2 <] +version ${certreqversion} + -d debug Show debugging info, including parsed variables. + -h usage Show this usage block. + -V version Show script version number. + -u username User to connect via ntlm to CA. Can be "username" or "domain\\username" + -p password + -w workdir Temp directory to work in. Default is a (mktemp -d). + -t template Template to request from CA. Default is "ConfigMgrLinuxClientCertificate" + --cn CN to request. Default is the \$( hostname -f ) + --ca CA hostname or base URL. Example: ca2.example.com +Return values under 1000: A non-zero value is the sum of the items listed here: + 0 Everything worked + 1 Cert file is still a CSR + 2 Cert file is html, probably due to permissions/credentials issue + 4 Return code of curl statement that saves cert file is non-zero + 8 Cert file does not contain whole certificate +16 Cert does not contain an issuer +Return values above 1000: +1001 Help or version info displayed +1002 Count or type of flaglessvals is incorrect +1003 Incorrect OS type +1004 Unable to find dependency +1005 Not run as root or sudo +ENDUSAGE +} + +# DEFINE FUNCTIONS + +# DEFINE TRAPS + +clean_certreq() { + # use at end of entire script if you need to clean up tmpfiles + #rm -f ${tmpfile} 1>/dev/null 2>&1 + if test -z "${CR_NC}"; + then + nohup /bin/bash </dev/null 2>&1 & +sleep "${CERTREQ_CLEANUP_SEC:-300}" ; /bin/rm -r "${CERTREQ_WORKDIR}" 2>/dev/null ; +EOF +#sleep "${CERTREQ_CLEANUP_SEC:-300}" ; /bin/rm -r "${CERTREQ_WORKDIR}" 2>/dev/null ; echo "slash-dollar-0=\"\$0\" slash-slash-dollar-0=\"\\$0\"" > /dev/pts/2 ; + fi + +} + +CTRLC() { + # use with: trap "CTRLC" 2 + # useful for controlling the ctrl+c keystroke + : +} + +CTRLZ() { + # use with: trap "CTRLZ" 18 + # useful for controlling the ctrl+z keystroke + : +} + +parseFlag() { + flag="$1" + hasval=0 + case ${flag} in + # INSERT FLAGS HERE + "d" | "debug" | "DEBUG" | "dd" ) setdebug; ferror "debug level ${debug}";; + "usage" | "help" | "h" ) usage; exit 1001;; + "V" | "fcheck" | "version" ) ferror "${scriptfile} version ${certreqversion}"; exit 1001;; + "u" | "user" | "username" ) getval; CERTREQ_USER="${tempval}";; + "p" | "pass" | "password" ) getval; CERTREQ_PASS="${tempval}";; + "w" | "work" | "workdir" ) getval; CERTREQ_WORKDIR="${tempval}";; + "t" | "temp" | "template" ) getval; CERTREQ_TEMPLATE="${tempval}";; + "cn" | "common-name" | "commonname" ) getval; CERTREQ_CNPARAM="${tempval}";; + "ca" | "certauthority" | "cauthority" ) getval; CERTREQ_CAPARAM="${tempval}";; + "c" | "conf" | "conffile" | "config" ) getval; conffile="${tempval}";; + "nc" | "nocleanup" ) CR_NC=1;; + esac + + debuglev 10 && { test ${hasval} -eq 1 && ferror "flag: ${flag} = ${tempval}" || ferror "flag: ${flag}"; } +} + +# DETERMINE LOCATION OF FRAMEWORK +while read flocation; do if test -f ${flocation} && test "$( sh ${flocation} --fcheck )" -ge 20170608; then frameworkscript="${flocation}"; break; fi; done <&2 && exit 1004 + +# INITIALIZE VARIABLES +# variables set in framework: +# today server thistty scriptdir scriptfile scripttrim +# is_cronjob stdin_piped stdout_piped stderr_piped sendsh sendopts +. ${frameworkscript} || echo "$0: framework did not run properly. Continuing..." 1>&2 +infile1= +outfile1= +#logfile=${scriptdir}/${scripttrim}.${today}.out # defined farther down +define_if_new interestedparties "bgstack15@gmail.com" +# SIMPLECONF +define_if_new default_conffile "/tmp/certreq.conf" +define_if_new defuser_conffile ~/.config/certreq/certreq.conf + +# REACT TO OPERATING SYSTEM TYPE +case $( uname -s ) in + Linux) [ ];; + *) echo "${scriptfile}: 3. Indeterminate OS: $( uname -s )" 1>&2 && exit 1003;; +esac + +## REACT TO ROOT STATUS +#case ${is_root} in +# 1) # proper root +# [ ] ;; +# sudo) # sudo to root +# [ ] ;; +# "") # not root at all +# #ferror "${scriptfile}: 5. Please run as root or sudo. Aborted." +# #exit 1005 +# [ ] +# ;; +#esac + +# SET CUSTOM SCRIPT AND VALUES +#setval 1 sendsh sendopts<&2 +} + +# MAIN LOOP +{ + # GENERATE PRIVATE KEY + openssl req -new -nodes \ + -out "${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.crt" \ + -keyout "${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.key" \ + -subj "${CERTREQ_SUBJECT}" + CERT="$( cat "${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.crt" | tr -d '\n\r' )" + DATA="Mode=newreq&CertRequest=${CERT}&C&TargetStoreFlags=0&SaveCert=yes" + CERT="$( echo ${CERT} | sed -e 's/+/%2B/g' | tr -s ' ' '+' )" + CERTATTRIB="CertificateTemplate:${CERTREQ_TEMPLATE}" + + # SUBMIT CERTIFICATE SIGNING REQUEST + OUTPUTLINK="$( curl -k -u "${CERTREQ_USER}:${CERTREQ_PASS}" --ntlm \ + "${CERTREQ_CA}/certsrv/certfnsh.asp" \ + -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' \ + -H 'Accept-Encoding: gzip, deflate' \ + -H 'Accept-Language: en-US,en;q=0.5' \ + -H 'Connection: keep-alive' \ + -H "Host: ${CERTREQ_CAHOST}" \ + -H "Referer: ${CERTREQ_CA}/certsrv/certrqxt.asp" \ + -H 'User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko' \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + --data "Mode=newreq&CertRequest=${CERT}&CertAttrib=${CERTATTRIB}&TargetStoreFlags=0&SaveCert=yes&ThumbPrint=" | grep -A 1 'function handleGetCert() {' | tail -n 1 | cut -d '"' -f 2 )" + CERTLINK="${CERTREQ_CA}/certsrv/${OUTPUTLINK}" + + # FETCH SIGNED CERTIFICATE + curl -k -u "${CERTREQ_USER}:${CERTREQ_PASS}" --ntlm $CERTLINK \ + -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' \ + -H 'Accept-Encoding: gzip, deflate' \ + -H 'Accept-Language: en-US,en;q=0.5' \ + -H 'Connection: keep-alive' \ + -H "Host: ${CERTREQ_CAHOST}" \ + -H "Referer: ${CERTREQ_CA}/certsrv/certrqxt.asp" \ + -H 'User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko' \ + -H 'Content-Type: application/x-www-form-urlencoded' > "${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.crt" + finaloutput=$? + + # GET NUMBER OF CURRENT CA CERT + RESPONSE="$( curl -s -k -u "${CERTREQ_USER}:${CERTREQ_PASS}" --ntlm \ + "${CERTREQ_CA}/certsrv/certcarc.asp" \ + -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' \ + -H 'Accept-Encoding: gzip, deflate' \ + -H 'Accept-Language: en-US,en;q=0.5' \ + -H 'Connection: keep-alive' \ + -H "Host: ${CERTREQ_CAHOST}" \ + -H "Referer: ${CERTREQ_CA}/certsrv/certrqxt.asp" \ + -H 'User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko' \ + -H 'Content-Type: application/x-www-form-urlencoded' )" + CURRENTNUM="$( echo "${RESPONSE}" | grep -cE 'Option' )" + + # GET LATEST CA CERT CHAIN + CURRENT_P7B="$( curl -s -k -u "${CERTREQ_USER}:${CERTREQ_PASS}" --ntlm \ + "${CERTREQ_CA}/certsrv/certnew.p7b?ReqID=CACert&Renewal=${CURRENTNUM}" \ + -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' \ + -H 'Accept-Encoding: gzip, deflate' \ + -H 'Accept-Language: en-US,en;q=0.5' \ + -H 'Connection: keep-alive' \ + -H "Host: ${CERTREQ_CAHOST}" \ + -H "Referer: ${CERTREQ_CA}/certsrv/certrqxt.asp" \ + -H 'User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko' \ + -H 'Content-Type: application/x-www-form-urlencoded' )" + + # CONVERT TO PEM + echo "${CURRENT_P7B}" | openssl pkcs7 -print_certs -out "${CERTREQ_TEMPFILE}" + + # RENAME TO PROPER FILENAME + # will read only the first cert, so get domain of issuer of it. + CA_DOMAIN="$( openssl x509 -in "${CERTREQ_TEMPFILE}" -noout -issuer 2>&1 | sed -r -e 's/^.*CN=[A-Za-z0-9]+\.//;' )" + CHAIN_FILE="chain-${CA_DOMAIN}.crt" + mv -f "${CERTREQ_TEMPFILE}" "${CERTREQ_WORKDIR}/${CHAIN_FILE}" 1>/dev/null 2>&1 + +} 1> ${logfile} 2>&1 + +# CHECK EVERYTHING +failed=0 +openssloutput="$( openssl x509 -in "${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.crt" -noout -subject -issuer -startdate -enddate 2>/dev/null )" +grep -qE -- 'REQUEST--' "${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.crt" && failed=$(( failed + 1 )) +grep -qiE '\<\/?body\>' "${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.crt" && failed=$(( failed + 2 )) +test ${finaloutput} -ne 0 && failed=$(( failed + 4 )) +grep -qE -- '--END CERTIFICATE--' "${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.crt" || failed=$(( failed + 8 )) +#echo "${openssloutput}" | grep -qE "subject.*${CERTREQ_SUBJECT}" || failed=$(( failed + 16 )) +echo "${openssloutput}" | grep -qE "issuer.*" || failed=$(( failed + 16 )) + +# if everything was successful, display information below +#if test ${failed} -eq 0; +#then + echo "workdir: ${CERTREQ_WORKDIR}" + echo "logfile: ${logfile}" + echo "certificate: ${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.crt" + echo "key: ${CERTREQ_WORKDIR}/${CERTREQ_CNPARAM}.key" + echo "chain: ${CERTREQ_WORKDIR}/${CHAIN_FILE}" +#fi +clean_certreq +exit "${failed}" + +# EMAIL LOGFILE +#${sendsh} ${sendopts} "${server} ${scriptfile} out" ${logfile} ${interestedparties} -- cgit