commit 36f81c3f5f03b6d54ee442179627e009e6ae1b1a Author: Clemens Schwaighofer Date: Tue Nov 5 10:16:34 2024 +0900 Initial checking diff --git a/ReadMe.md b/ReadMe.md new file mode 100644 index 0000000..2b7e884 --- /dev/null +++ b/ReadMe.md @@ -0,0 +1,42 @@ +# SSL Create script + +Create new SSL certificates for signing + +## Options + +```sh +Usage: bin/create_ssl.sh -f [-o ] [-s] [-v [-v] ...] + +-f: mandatory input file. CSV format with | separations +Format: +Country|State|Location|Organization|Organizational Unit|domain name|password +-s: switch output path from / to / +-o: optional output folder. If not given, then output will be written to current folder +-v: verbose output (CSR/KEY) as echo to terminal +``` + +## Template file layout + +The base file (CSV) for creating new certicates has the following format. + +The separator is the `|` and not ; + +```txt +Country|State|Location|Organization|Organizational Unit|domain name|password|confirm email +``` + +### Sample + +```txt +jp|Toyko|Minato-ku|Foo Bar|IT Department|foobar.org|1234567|hostmaster@foobar.org +``` + +```sh +bin/create_ssl.sh -f path/to/file.csv -o output/path +``` + +This will creaet a new folder with + +`YYYYMMDD/foobar.org/` and in ther are the SSL data stored + +If the `-s` flag is used the folder is reveres `foobar.org/YYYYMMDD/` diff --git a/bin/create_ssl.sh b/bin/create_ssl.sh new file mode 100755 index 0000000..ac68fb1 --- /dev/null +++ b/bin/create_ssl.sh @@ -0,0 +1,205 @@ +#!/bin/bash +# creates SSL key requests from a input file +# needs country|state|locality|organization|organization unit|domain|password|confirm email + +function usage () +{ + cat <<- EOT + Usage: ${0##/*/} -f [-o ] [-s] [-v [-v] ...] + + -f: mandatory input file. CSV format with | separations + Format: + Country|State|Location|Organization|Organizational Unit|domain name|password + -s: switch output path from / to / + -o: optional output folder. If not given, then output will be written to current folder + -v: verbose output (CSR/KEY) as echo to terminal + EOT +} + +# input sample +# Country|State|Location|Organization|Organizational Unit|domain name|password|confirm email + +country=''; +state=''; +locality=''; +organization=''; +organizationalunit=''; +commonname=''; # that is the domain +verbose=0; # verbose level +# for get opt +OPTARG_REGEX="^-"; +# log file +logfile="ssl_create.$(date +%Y%m%d_%H%M%S).log"; +# opt args +FILE=''; # file to read in +OUTPUT=''; # optional target path +SWITCH_FOLDER=0; + +while getopts ":f:o:sv" opt; do + # pre test for unfilled + if [ "${opt}" = ":" ] || [[ "${OPTARG-}" =~ ${OPTARG_REGEX} ]]; then + if [ "${opt}" = ":" ]; then + CHECK_OPT=${OPTARG}; + else + CHECK_OPT=${opt}; + fi; + case ${CHECK_OPT} in + f) + # file + echo "-f needs file name"; + ERROR=1; + ;; + o) + echo "-o needs a folder name"; + ERROR=1; + ;; + esac + fi; + + case ${opt} in + # the file from where we read in, must be set + f) + # file + if [ -z "${FILE}" ]; then + FILE="${OPTARG}"; + fi; + ;; + # output target, if not set current path is used + o) + # output + if [ -z "${OUTPUT}" ]; then + OUTPUT="${OPTARG}"; + fi; + ;; + # switch folder output path + s) + # switch + SWITCH_FOLDER=1; + ;; + # verbose output + v) + # verbose + verbose=$(( verbose+1 )); + ;; + \?) + echo -e "\n Option does not exist: $OPTARG\n"; + usage; + exit 1; + ;; + esac; +done + +if [ -n "$ERROR" ]; then + exit 0; +fi; + +# $FILE is a file with all the data in | separated form +if [ ! -f "${FILE}" ]; then + echo "The input file '${FILE}' is not set or could not be read"; + exit 0; +fi; + +if [ -n "${OUTPUT}" ]; then + if [ ! -d "${OUTPUT}" ]; then + echo "The output folder '${OUTPUT}' does not exist"; + exit 0; + fi; + # check if we can write into that folder + touch "${OUTPUT}/tmpfile" || echo "[!] touch failed"; + if [ ! -f "${OUTPUT}/tmpfile" ]; then + echo "Cannot write to '${OUTPUT}'"; + exit 0; + else + rm -f "${OUTPUT}/tmpfile"; + fi; + # just in case add / + OUTPUT=${OUTPUT}'/'; +fi; + +# start log file +LOGFILE="tee -a ${OUTPUT}${logfile}"; +# print overview info +echo "PWD : $(pwd)" | $LOGFILE; +echo "INPUT : ${FILE}" | $LOGFILE; +echo -n "OUTPUT: " | $LOGFILE; +if [ -z "${OUTPUT}" ]; then + pwd | $LOGFILE; +else + echo "${OUTPUT}" | $LOGFILE; +fi; + +# loop through file and create all the data in the current folder +while read -r i; do + country=$(echo "${i}" | cut -d "|" -f 1); + state=$(echo "${i}" | cut -d "|" -f 2); + locality=$(echo "${i}" | cut -d "|" -f 3); + organization=$(echo "${i}" | cut -d "|" -f 4); + organizationalunit=$(echo "${i}" | cut -d "|" -f 5); + commonname=$(echo "${i}" | cut -d "|" -f 6); + password=$(echo "${i}" | cut -d "|" -f 7); + orderemail=$(echo "${i}" | cut -d "|" -f 8); + echo "--------------------- [START: ${commonname}]" | $LOGFILE; + # error flag + error=0; + # one is missing, we abort + for check in country state locality organization organizationalunit commonname password; + do + if [ -z "${!check}" ]; + then + echo "${check} is missing" | $LOGFILE; + error=1; + fi; + done; + if [ ${error} = 1 ]; + then + echo "--------------------- [ERROR]" | $LOGFILE; + exit 0; + fi; + # copy for file handling (gets folder prefixed with date + domain name) + # if we have *. we strip the *. and replace it with WILDCARD + # shellcheck disable=SC2001 + domain=$(echo "${commonname}" | sed -e 's/\*\./WILDCARD\./'); + if [ ${SWITCH_FOLDER} == 1 ]; then + path=${OUTPUT}${domain}'/'$(date +%F); + else + path=${OUTPUT}$(date +%F)'/'${domain}; + fi; + mkdir -p "${path}" + domain=${path}'/'${domain}; + # start generating + echo "Creating base pem for ${commonname}" | $LOGFILE; + openssl genrsa -des3 -passout pass:"${password}" -out "${domain}.pem" 2048 | $LOGFILE; + # generate csr + echo "Creating CSR for ${commonname} with '/C=${country}/ST=${state}/L=${locality}/O=${organization}/OU=${organizationalunit}/CN=${commonname}'" | $LOGFILE; + openssl req -new -key "${domain}.pem" -out "${domain}.csr" -passin pass:"${password}" -subj "/C=${country}/ST=${state}/L=${locality}/O=${organization}/OU=${organizationalunit}/CN=${commonname}" | $LOGFILE; + # convert pem to key + echo "Converting ${commonname} pem to key" | $LOGFILE; + openssl rsa -in "${domain}.pem" -passin pass:"${password}" -out "${domain}.key" | $LOGFILE; + + # helper/viewers + echo "VIEW CSR: openssl req -text -noout -verify -in ${domain}.csr" | $LOGFILE; + echo "VIEW CRT: openssl x509 -in ${domain}.crt -text -noout" | $LOGFILE; + echo "VIEW PEM/KEY: openssl rsa -noout -text -in ${domain}.pem" | $LOGFILE; + + echo "ORDER EMAIL: ${orderemail}" | $LOGFILE; + + # print out the CSR and KEY [the ones we need] + if [ "${verbose}" = 1 ]; then + echo ""; + echo "====================="; + echo "= CSR ="; + echo "====================="; + cat "${domain}.csr"; + echo "====================="; + + echo ""; + echo "====================="; + echo "= KEY ="; + echo "====================="; + cat "${domain}.key"; + echo "====================="; + echo ""; + fi; + + echo "--------------------- [OK]" | $LOGFILE; +done <<< "$(cat "${FILE}")"; diff --git a/bin/modern_ssl_create.sh b/bin/modern_ssl_create.sh new file mode 100755 index 0000000..45c760c --- /dev/null +++ b/bin/modern_ssl_create.sh @@ -0,0 +1,37 @@ +#!/bin/bash +# Generate "modern" self-signed TLS certificate + +echo 'Hostnames (space-separated, 1st will be CN, issuer, and filename prefix): ' +read -r -e -i "${hostname:-host.example.com}" hostnames +echo 'IP addresses (space-separated): ' +read -r -e -i "${ip:-192.168.2.1}" ips + +umask 0077 + +san_dns='' +for h in ${hostnames} +do + [[ -z ${cn} ]] && dn="CN=${h}" && cn="${h}" + san_dns="DNS:${h},${san_dns}" +done + +for i in ${ips} +do + san_ip="IP:${i},${san_ip}" +done + +subjectAltName="${san_dns}" +[[ -n ${san_ip} ]] && subjectAltName="${subjectAltName}${san_ip}" +subjectAltName="${subjectAltName%,*}" + +set -u +set -e +openssl ecparam -genkey -name secp384r1 -noout -out "${cn}.key.pem" +openssl req -reqexts san_details -new -key "${cn}.key.pem" -sha256 -days "${days:-10000}" -x509 -extensions san_details -out "${cn}.cert.pem" -config <(printf '[req] \n prompt=no \n utf8=yes \n distinguished_name=dn_details \n req_extensions=san_details \n [dn_details] \n %s \n [san_details] \n subjectAltName=%s\n' "${dn}" "${subjectAltName}") + +echo "All done, cert data follows:" +openssl x509 -in "${cn}.cert.pem" -noout +openssl x509 -in "${cn}.cert.pem" -noout -text +ls -l "./${cn}.key.pem" "./${cn}.cert.pem" + +# __END__ diff --git a/template/ssl_test.csv b/template/ssl_test.csv new file mode 100644 index 0000000..97e491b --- /dev/null +++ b/template/ssl_test.csv @@ -0,0 +1 @@ +Country|State|Location|Organization|Organizational Unit|domain name|password|confirm email