#!/usr/bin/bash # Usage: request_cert.sh # Sample JSON: # { # "common_name": "", # "alt_names": "", # "ip_sans": "212.12.255.3,212.12.255.4,213.12.255.3,213.12.255.4", # "ttl": "180d" # } # # Simple Usage: request_cert.sh -s # set -eu AUTH_VAULT_URL=${AUTH_VAULT_URL-https://vault.dings:8199} CERT_VAULT_URL=${CERT_VAULT_URL-https://vault.dings:8200} # Unless a vault token is already provided by the user, fetch a token using LDAP credentials if [ -z "${VAULT_TOKEN-}" ]; then read -p USER: LDAPUSER read -s -p PASSWORD: LDAPPASSWD login_request_data=$(jq -c -n --arg password "$LDAPPASSWD" '{$password}') login_response_data=$(curl -Ssf -H "Content-Type: application/json" -d "$login_request_data" "$AUTH_VAULT_URL/v1/auth/ldap/login/$LDAPUSER") VAULT_TOKEN=$(echo "$login_response_data" | jq -r ".auth.client_token") echo $VAULT_TOKEN fi # These two extended regular expression are matching # RFC952, B. Lexical grammar, and , respectively readonly RFC952_name_ERE='[0-9A-Za-z]([0-9A-Za-z-]*[0-9A-Za-z])?' readonly RFC952_hname_ERE="$name_ERE(\\.$name_ERE)*" # usage: is_hostname STRING # Check if STRING is a valid host name per RFC952 is_hostname() { echo "$1" | grep -Eq "^$RFC952_hname_ERE\$" } # Following block will set the two variables CN and cert_request_data # depending on the provided arguments. # # CN is the common name to be used for the certificate. CN is also used to # specify the output directory and the file names of the generated key and # certificates. The common name should be a domainname as described by # [RFC952], section A. # [RFC952]: https://www.rfc-editor.org/rfc/rfc952.txt # # cert_response_data specifies the parameters to for generating a certificate # and key. The parameters should be specified as JSON object as described by # https://developer.hashicorp.com/vault/api-docs/secret/pki#generate-certificate-and-key # if [ $# = 2 ] && [ "$1" = -s ]; then # Simple usage: user has provided only a fully qualified domain name which should be used as common name for the certificate CN=$2 if ! is_hostname "$CN"; then echo "error: specified FQDN is not a valid hostname: $CN" >&2 exit 1 fi cert_request_data=$(jq -c -n --arg common_name "$CN" --arg ttl 90d '{$common_name,$ttl}' elif [ $# = 1 ]; then CN=$( cat $1 | jq -r ".common_name" ) if ! is_hostname "$CN"; then echo "error: common_name in $1 is not a valid hostname: $CN" >&2 exit 1 fi cert_request_data=$(cat "$1") else echo "USAGE: $0 -s |" exit 1 fi # Note that $CN does not have to be quoted after this point because we've # asserted it's a domain name above and thus cannot cause word splitting. # This comment can be deleted if $CN gets quoted below. if [ -d $CN ]; then rm -r $CN fi mkdir $CN # TODO rz_q-ca_2021aa and rz-drv look like they correspond to :issuer_ref and :name # in https://developer.hashicorp.com/vault/api-docs/secret/pki#generate-certificate-and-key # If that's the case, then both should probably be made configurable the same way CERT_VAULT_URL is cert_response_data=$(echo "$cert_request_data" | curl -Ssf -H "X-Vault-Token: $VAULT_TOKEN" -d @- "$CERT_VAULT_URL/v1/pki_rz_q-ca_2021aa/issue/rz-drv") echo "$cert_response_data" > $CN/$CN.json echo "$cert_response_data" | jq -r '.data.certificate' > $CN/$CN.cer echo "$cert_response_data" | jq -r '.data.private_key' > $CN/$CN.key echo "$cert_response_data" | jq -r '.data.ca_chain|join("\n")' > $CN/$CN.ca_chain cat $CN/$CN.cer $CN/$CN.ca_chain > $CN/$CN.cer_with_ca_chain