-
Notifications
You must be signed in to change notification settings - Fork 0
/
export-ziti-ca.zsh
executable file
·96 lines (88 loc) · 3.36 KB
/
export-ziti-ca.zsh
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
94
95
96
#!/usr/bin/env zsh
#
# get the well-known CA certs of a Ziti controller as importable PEM and DER files
#
# EXAMPLE
#
# $ ./export-ziti-ca.zsh 13.36.15.32
# SUCCESS: certificates exported in /tmp/export-ziti-ca-13-36-15-32/:
# total 16K
# -rw-rw-r-- 1 kbingham kbingham 1.7K Sep 20 12:47 NetFoundry.der
# -rw-rw-r-- 1 kbingham kbingham 2.3K Sep 20 12:47 NetFoundry.pem
# -rw-rw-r-- 1 kbingham kbingham 1.5K Sep 20 12:47 Ziti-Controller-Intermediate-CA.der
# -rw-rw-r-- 1 kbingham kbingham 2.1K Sep 20 12:47 Ziti-Controller-Intermediate-CA.pem
# Ctrl-c to preserve files, <enter> to clean up
#
set -o pipefail
set -e
set -u
#
## make sure the controller's IPv4 is provided as $1, $ziti_ctrl_ip, or $ZITI_CTRL_IP
#
: ZITI_CTRL_IP="${ziti_ctrl_ip:-}" # adapt to common lowercase var name for compatibility
if [[ -z "${ZITI_CTRL_IP:-}" ]]; then # if null
if [[ ${#@} -eq 1 ]]; then # if param
ZITI_CTRL_IP="$1"
else
echo "ERROR: need Ziti controller IPv4 as \$ziti_ctrl_ip or \$1" >&2
exit 1
fi
fi
[[ "${ZITI_CTRL_IP}" =~ ([0-9]{1,3}\.?){4} ]] || {
echo "ERROR: \"${ZITI_CTRL_IP}\" is not an IPv4 address" >&2
exit 1
}
#
## run-lock with atomic mkdir to avoid race conditions on tmp file operations
#
BASENAME=$(basename $0)
LOCKDIR="/tmp/${BASENAME/.*sh/}-${ZITI_CTRL_IP//./-}/"
[[ -d "${LOCKDIR}" ]] && { # detect and preserve prior state
echo "ERROR: tmp dir exists, run 'rm -r \"${LOCKDIR}\"' and retry" >&2
exit 1
}
mkdir "${LOCKDIR}" || { # in case a colliding filename exists
echo "ERROR: failed to create a temporary lock directory in \"${LOCKDIR}\"" >&2
exit 1
}
cd "${LOCKDIR}"
# download the b64 encoding of the DER-form of the PKCS7 trust store,
# convert to ASCII as PEM-form,
# split into separate files with predictable prefix and serial number suffix,
# one per certificate
curl -sSfk "https://${ZITI_CTRL_IP}/.well-known/est/cacerts" \
| openssl base64 -d \
| openssl pkcs7 -inform DER -outform PEM -print_certs \
>| ./print_certs.pem
CERT_COUNT=$(grep -Ee '-----BEGIN CERTIFICATE-----' ./print_certs.pem|wc -l)
csplit -s -f 'cert-' ./print_certs.pem '/-----BEGIN CERTIFICATE-----/' "{$((CERT_COUNT - 1))}"
rm ./print_certs.pem
# de-duplicate certificates by sha256 fingerprint
for DUPLICATE in ./cert-*; do
grep -Eqe '-----BEGIN CERTIFICATE-----' "${DUPLICATE}" || {
rm "${DUPLICATE}" # clean detritus created by csplit
continue
}
openssl x509 -inform PEM -outform DER < "${DUPLICATE}" > "${DUPLICATE}.der"
SHA256SUM=$(openssl sha256 < "${DUPLICATE}.der"|cut -f2 -d' ')
mv "${DUPLICATE}.der" "sha256-${SHA256SUM}.der"
rm "${DUPLICATE}"
done
for UNIQUE in ./sha256-*.der; do
while IFS=',/' read -A SUBJECT_RDNS; do
for RDN in "${SUBJECT_RDNS[@]}"; do
#echo "RDN='$RDN'"
while IFS='= ' read RDN_KEY RDN_VALUE; do
[[ "${RDN_KEY}" == CN ]] && {
RDN_VALUE="${RDN_VALUE// /-}"
openssl x509 -inform DER -outform PEM < "${UNIQUE}" > "./${RDN_VALUE}.pem"
mv "${UNIQUE}" "./${RDN_VALUE}.der"
}
done <<< "${RDN}"
done
done < <(openssl x509 -inform DER -noout -subject -in "${UNIQUE}")
done
echo "SUCCESS: certificates exported in ${LOCKDIR}:"
ls -lAh "${LOCKDIR}"
read "?Ctrl-c to preserve files, <enter> to clean up"
rm -r "${LOCKDIR}"