| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- #!/bin/bash
- # Config
- CA_NAME="ca"
- DAYS=1825
- ROOT_POLICY="policy_root"
- ROOT_EXT="v3_ca"
- INTER_POLICY="policy_inter"
- INTER_EXT="v3_intermediate_ca"
- REQ_POLICY="policy_req"
- REQ_EXT="v3_req"
- PASS_DIR="${HOME}/.ansible/tls"
- ORG="Zi3"
- function makeDirExist {
- if [ -d "${1}" ] || [ "${1}" == "." ]; then
- return
- fi
- mkdir "${1}"
- if [ -n "${2}" ]; then
- chmod "${2}" "${1}"
- fi
- if [ -n "${3}" ]; then
- chown "${3}" "${1}"
- fi
- }
- # Decide what we're doing
- GEN_CA=1
- GEN_CERT=0
- if basename "${0}" | grep -q -i genCert; then
- GEN_CA=0
- GEN_CERT=1
- fi
- # Support intermediate CAs
- INTER="${1}"
- if [ -n "${INTER}" ] && [ "${INTER}" != "@" ]; then
- if [ ! -d "${INTER}" ]; then
- if [ ! -e $"${INTER}" ] && [ $GEN_CA -gt 0 ]; then
- echo "Creating intermediate CA directory: ${INTER}"
- makeDirExist "${INTER}" '0755'
- else
- echo "Intermediate CA directory does not exist: ${INTER}" 1>&2
- exit 1
- fi
- fi
- export CA_DIR="${INTER}"
- PRE_DASH="${INTER}-"
- PRE_DIR="${INTER}/"
- else
- export CA_DIR="@"
- INTER=""
- PRE_DASH=""
- PRE_DIR=""
- fi
- # Support alternate OUs
- if [ -z "${OU}" ]; then
- OU="${INTER}"
- fi
- # Calculate all our file paths
- CONF="openssl.conf"
- CA_CERT="${PRE_DIR}${CA_NAME}.pem"
- CERTS="${PRE_DIR}certs"
- KEYS="${PRE_DIR}keys"
- DB_DIR="${PRE_DIR}db"
- CRL="${DB_DIR}/crl/number"
- INDEX="${DB_DIR}/index.txt"
- SERIAL="${DB_DIR}/serial"
- # Ensure the passphrase file is available
- PASS_KEY="${PASS_DIR}/${PRE_DASH}key.pwd"
- PASS_CA="${PASS_DIR}/${PRE_DASH}ca-key.pwd"
- if [ $GEN_CA -gt 0 ]; then
- PASS_KEY="${PASS_DIR}/${PRE_DASH}ca-key.pwd"
- PASS_CA="${PASS_DIR}/ca-key.pwd"
- fi
- if [ ! -r "${PASS_KEY}" ]; then
- echo "Please create passphrase file: ${PASS_KEY}" 1>&2
- exit 3
- fi
- # If we're generating a normal certificate we need a name
- if [ $GEN_CERT -gt 0 ]; then
- CN="${2}"
- if [ -z "${CN}" ]; then
- echo "Certificate name not specified" 1>&2
- echo "Usage: ${0} INTERMEDIATE COMMON_NAME" 1>&2
- exit 1
- fi
- CERT="${CERTS}/${CN}.pem"
- KEY="${KEYS}/${CN}.key"
- fi
- # If we're generating a CA we know the name
- if [ $GEN_CA -gt 0 ]; then
- if [ -z "${INTER}" ]; then
- CN="Root_CA"
- else
- CN="Intermediate_CA"
- fi
- CERT="${CA_CERT}"
- KEY="${KEYS}/${CA_NAME}.key"
- # If we're signing with the root override the CA_CERT path
- CA_CERT="${CA_NAME}.pem"
- fi
- # Pick a subject
- if [ -n "${OU}" ]; then
- SUBJECT="/O=${ORG}/OU=${OU}/CN=${CN}"
- else
- SUBJECT="/O=${ORG}/CN=${CN}"
- fi
- # Remind admins what is happening
- if [ $GEN_CA -gt 0 ]; then
- echo
- echo "Generating new CA at ${PWD}/${PRE_DIR}"
- echo
- fi
- if [ $GEN_CERT -gt 0 ]; then
- echo
- echo "Generating certificate for ${CN} with ${INTER}"
- echo
- fi
- # Ensure this operation will be safe
- if [ ! -r "${CONF}" ]; then
- echo "Expected OpenSSL config: ${CONF}" 1>&2
- exit 1
- fi
- if [ -e "${CERT}" ]; then
- echo "Output certificate exists: ${CERT}" 1>&2
- exit 1
- fi
- if [ -e "${KEY}" ]; then
- echo "Output key exists: ${KEY}" 1>&2
- exit 1
- fi
- if [ $GEN_CA -gt 0 ]; then
- if [ -e "${SERIAL}" ] && [ "`cat "${SERIAL}"`" != "01" ]; then
- echo "Serial file exists and is not 0x01: ${SERIAL}" 1>&2
- exit 1
- fi
- if [ -e "${CRL}" ] && [ "`cat "${CRL}"`" != "01" ]; then
- echo "CRL number file exists and is not 0x01: ${CRL}" 1>&2
- exit 1
- fi
- if [ -e "${INDEX}" ] && [ -s "${INDEX}" ]; then
- echo "Index file exists and is not empty: ${INDEX}" 1>&2
- exit 1
- fi
- fi
- # Ensure the CA paths are available and valid
- if [ $GEN_CA -gt 0 ]; then
- makeDirExist "${CERTS}" '0755'
- makeDirExist "${KEYS}" '0700'
- # Setup the DB files
- makeDirExist "${DB_DIR}" '0755'
- echo "01" > "${SERIAL}"
- touch "${INDEX}"
- # And CRL for good measure
- makeDirExist "`dirname "${CRL}"`" '0755'
- echo "01" > "${CRL}"
- fi
- # Generate a new, encrypted key
- openssl ecparam -name secp521r1 -genkey | \
- openssl ec -aes256 -passout "file:${PASS_KEY}" -out "${KEY}"
- if [ ! -s "${KEY}" ]; then
- echo "Unable to generate private key" 1>&2
- exit 3
- fi
- # Generate and sign the certificate
- if [ -r "${CA_CERT}" ]; then
- CSR="${CERT}.csr"
- if [ -e "${CSR}" ]; then
- "CSR exists: ${CSR}" 1>&2
- exit 3
- fi
- # Generate a CSR
- openssl req -new \
- -config "${CONF}" \
- -subj "${SUBJECT}" \
- -key "${KEY}" \
- -passin "file:${PASS_KEY}" \
- -out "${CSR}"
- if [ ! -r "${CSR}" ]; then
- echo "Unable to generate CSR"
- exit 3
- fi
- # Remind admins what is happening
- echo
- echo "Signing ${CSR} with ${CA_CERT}"
- echo -en "Request:\n\t"
- openssl req -in "${CSR}" -text | grep 'Subject:'
- echo -en "CA:\n\t"
- openssl x509 -in "${CA_CERT}" -text | grep 'Subject:'
- echo
- # Sign with a CA
- DIR="${CA_DIR}"
- EXT="${REQ_EXT}"
- POLICY="${REQ_POLICY}"
- if [ "${DIR}" == "@" ] || [ $GEN_CA -gt 0 ]; then
- DIR="."
- EXT="${INTER_EXT}"
- POLICY="${INTER_POLICY}"
- fi
- CA_DIR="${DIR}" openssl ca -notext \
- -config "${CONF}" \
- -policy "${POLICY}" \
- -extensions "${EXT}" \
- -days "${DAYS}" \
- -passin "file:${PASS_CA}" \
- -in "${CERT}.csr" \
- -out "${CERT}"
- # Generate a chain certificate for validation
- if [ $GEN_CA -gt 0 ] && [ -r "${CERT}" ]; then
- cat "${CERT}" "${CA_CERT}" > "${PRE_DIR}ca-chain.pem"
- fi
- # Drop the CSR
- rm -f "${CERT}.csr"
- # Generate keys ansible can decrypt
- if [ -n "${INTER}" ] && [ $GEN_CA -le 0 ] && [ -s "${CERT}" ]; then
- echo
- echo "Encrypting ${KEY} for Ansible"
- echo
- ANSIBLE_KEY="`echo "${KEY}" | sed 's%.key$%.ansible%'`"
- openssl ec -in "${KEY}" -passin "file:${PASS_KEY}" -out "${ANSIBLE_KEY}"
- ansible-vault encrypt --encrypt-vault-id "${INTER}" "${ANSIBLE_KEY}"
- if ! head -n 1 "${ANSIBLE_KEY}" | grep -q "^\$ANSIBLE_VAULT"; then
- echo "Unable to generate ansible-encrypted key" 1>&2
- rm -f "${ANSIBLE_KEY}"
- fi
- fi
- else
- # Remind admins what is happening
- echo
- echo "Self-signing new root CA"
- echo
- # Root CA - self-sign
- openssl req -new -x509 \
- -config "${CONF}" \
- -subj "${SUBJECT}" \
- -extensions "${ROOT_EXT}" \
- -days "${DAYS}" \
- -key "${KEY}" \
- -passin "file:${PASS_KEY}" \
- -out "${CERT}"
- fi
- if [ ! -s "${CERT}" ]; then
- echo "Unable to generate certificate" 1>&2
- rm -f "${KEY}"
- exit 3
- fi
|