summaryrefslogtreecommitdiffstats
path: root/request_cert.sh
blob: 2e7b636b93a5c5ba545aed35150431b81da640b8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#!/usr/bin/bash
# Usage: request_cert.sh <filename.json>
# 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 <fqdn>
#

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, <name> and <hname>, 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 <fqdn>|<filename>"
   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