experimental json.sh support

This commit is contained in:
Lukas Schauer
2020-07-04 21:36:23 +02:00
parent dc552c602e
commit 7f970b527c
2 changed files with 215 additions and 55 deletions
+25 -55
View File
@@ -17,7 +17,9 @@ umask 077 # paranoid umask, we're creating private keys
exec 3>&-
exec 4>&-
VERSION="0.6.5"
. ./json.sh
VERSION="0.6.6"
# Find directory in which this script is stored by traversing all symbolic links
SOURCE="${0}"
@@ -298,7 +300,8 @@ init_system() {
fi
# Get CA URLs
CA_DIRECTORY="$(http_request get "${CA}")"
CA_DIRECTORY_RAW="$(http_request get "${CA}")"
CA_DIRECTORY="$(printf "%s" "${CA_DIRECTORY_RAW}" | jsonsh)"
# Automatic discovery of API version
if [[ "${API}" = "auto" ]]; then
@@ -407,11 +410,11 @@ init_system() {
# Read account information or request from CA if missing
if [[ -e "${ACCOUNT_KEY_JSON}" ]]; then
if [[ ${API} -eq 1 ]]; then
ACCOUNT_ID="$(cat "${ACCOUNT_KEY_JSON}" | get_json_int_value id)"
ACCOUNT_ID="$(cat "${ACCOUNT_KEY_JSON}" | jsonsh | get_json_int_value id)"
ACCOUNT_URL="${CA_REG}/${ACCOUNT_ID}"
else
if [[ -e "${ACCOUNT_ID_JSON}" ]]; then
ACCOUNT_URL="$(cat "${ACCOUNT_ID_JSON}" | get_json_string_value url)"
ACCOUNT_URL="$(cat "${ACCOUNT_ID_JSON}" | jsonsh | get_json_string_value url)"
fi
# if account URL is not storred, fetch it from the CA
if [[ -z "${ACCOUNT_URL:-}" ]]; then
@@ -468,41 +471,6 @@ hex2bin() {
printf -- "$(cat | _sed -e 's/[[:space:]]//g' -e 's/^(.(.{2})*)$/0\1/' -e 's/(.{2})/\\x\1/g')"
}
# Get string value from json dictionary
get_json_string_value() {
local filter
filter=$(printf 's/.*"%s": *"\([^"]*\)".*/\\1/p' "$1")
sed -n "${filter}"
}
# Get array value from json dictionary
get_json_array_value() {
local filter
filter=$(printf 's/.*"%s": *\\[\([^]]*\)\\].*/\\1/p' "$1")
sed -n "${filter}"
}
# Get sub-dictionary from json
get_json_dict_value() {
local filter
filter=$(printf 's/.*"%s": *{\([^}]*\)}.*/\\1/p' "$1")
sed -n "${filter}"
}
# Get integer value from json
get_json_int_value() {
local filter
filter=$(printf 's/.*"%s": *\([0-9]*\).*/\\1/p' "$1")
sed -n "${filter}"
}
rm_json_arrays() {
local filter
filter='s/\[[^][]*\]/null/g'
# remove three levels of nested arrays
sed -e "${filter}" -e "${filter}" -e "${filter}"
}
# OpenSSL writes to stderr/stdout even when there are no errors. So just
# display the output if the exit code was != 0 to simplify debugging.
_openssl() {
@@ -702,14 +670,14 @@ sign_csr() {
echo " + Requesting new certificate order from CA..."
order_location="$(signed_request "${CA_NEW_ORDER}" '{"identifiers": '"${challenge_identifiers}"'}' 4>&1 | grep -i ^Location: | awk '{print $2}' | tr -d '\r\n')"
result="$(signed_request "${order_location}" "" | clean_json)"
result="$(signed_request "${order_location}" "" | jsonsh)"
order_authorizations="$(echo ${result} | get_json_array_value authorizations)"
order_authorizations="$(echo "${result}" | get_json_array_values authorizations)"
finalize="$(echo "${result}" | get_json_string_value finalize)"
local idx=0
for uri in ${order_authorizations}; do
authorizations[${idx}]="$(echo "${uri}" | _sed -e 's/\"(.*)".*/\1/')"
authorizations[${idx}]="${uri}"
idx=$((idx+1))
done
echo " + Received ${idx} authorizations URLs from the CA"
@@ -727,14 +695,14 @@ sign_csr() {
for authorization in ${authorizations[*]}; do
if [[ "${API}" -eq 2 ]]; then
# Receive authorization ($authorization is authz uri)
response="$(signed_request "$(echo "${authorization}" | _sed -e 's/\"(.*)".*/\1/')" "" | clean_json)"
response="$(signed_request "$(echo "${authorization}" | _sed -e 's/\"(.*)".*/\1/')" "" | jsonsh)"
identifier="$(echo "${response}" | get_json_dict_value identifier | get_json_string_value value)"
echo " + Handling authorization for ${identifier}"
else
# Request new authorization ($authorization is altname)
identifier="${authorization}"
echo " + Requesting authorization for ${identifier}..."
response="$(signed_request "${CA_NEW_AUTHZ}" '{"resource": "new-authz", "identifier": {"type": "dns", "value": "'"${identifier}"'"}}' | clean_json)"
response="$(signed_request "${CA_NEW_AUTHZ}" '{"resource": "new-authz", "identifier": {"type": "dns", "value": "'"${identifier}"'"}}' | jsonsh)"
fi
# Check if authorization has already been validated
@@ -744,20 +712,22 @@ sign_csr() {
fi
# Find challenge in authorization
challenges="$(echo "${response}" | _sed 's/.*"challenges": \[(\{.*\})\].*/\1/')"
challenge="$(<<<"${challenges}" _sed -e 's/^[^\[]+\[(.+)\]$/\1/' -e 's/\}(, (\{)|(\]))/}\'$'\n''\2/g' | grep \""${CHALLENGETYPE}"\" || true)"
if [ -z "${challenge}" ]; then
allowed_validations="$(grep -Eo '"type": "[^"]+"' <<< "${challenges}" | grep -Eo ' "[^"]+"' | _sed -e 's/"//g' -e 's/^ //g')"
challengeindex="$(echo "${response}" | grep -E '^\["challenges",[0-9]+,"type"\]\s+"'"${CHALLENGETYPE}"'"' | cut -d',' -f2 || true)"
if [ -z "${challengeindex}" ]; then
allowed_validations="$(echo "${response}" | grep -E '^\["challenges",[0-9]+,"type"\]' | sed -e 's/\[[^\]*\]\s*//g' -e 's/^"//' -e 's/"$//' | tr '\n' ' ')"
_exiterr "Validating this certificate is not possible using ${CHALLENGETYPE}. Possible validation methods are: ${allowed_validations}"
fi
challenge="$(echo "${response}" | get_json_dict_value -p '"challenges",'"${challengeindex}")"
# Gather challenge information
challenge_names[${idx}]="${identifier}"
challenge_tokens[${idx}]="$(echo "${challenge}" | get_json_string_value token)"
if [[ ${API} -eq 2 ]]; then
challenge_uris[${idx}]="$(echo "${challenge}" | _sed 's/"validationRecord": ?\[[^]]+\]//g' | get_json_string_value url)"
challenge_uris[${idx}]="$(echo "${challenge}" | get_json_string_value url)"
else
challenge_uris[${idx}]="$(echo "${challenge}" | _sed 's/"validationRecord": ?\[[^]]+\]//g' | get_json_string_value uri)"
challenge_uris[${idx}]="$(echo "${challenge}" | get_json_dict_value validationRecord | get_json_string_value uri)"
fi
# Prepare challenge tokens and deployment parameters
@@ -810,12 +780,12 @@ sign_csr() {
# Ask the acme-server to verify our challenge and wait until it is no longer pending
if [[ ${API} -eq 1 ]]; then
result="$(signed_request "${challenge_uris[${idx}]}" '{"resource": "challenge", "keyAuthorization": "'"${keyauths[${idx}]}"'"}' | clean_json)"
result="$(signed_request "${challenge_uris[${idx}]}" '{"resource": "challenge", "keyAuthorization": "'"${keyauths[${idx}]}"'"}' | jsonsh)"
else
result="$(signed_request "${challenge_uris[${idx}]}" '{}' | clean_json)"
result="$(signed_request "${challenge_uris[${idx}]}" '{}' | jsonsh)"
fi
reqstatus="$(printf '%s\n' "${result}" | get_json_string_value status)"
reqstatus="$(echo "${result}" | get_json_string_value status)"
while [[ "${reqstatus}" = "pending" ]]; do
sleep 1
@@ -824,7 +794,7 @@ sign_csr() {
else
result="$(http_request get "${challenge_uris[${idx}]}")"
fi
reqstatus="$(printf '%s\n' "${result}" | get_json_string_value status)"
reqstatus="$(echo "${result}" | get_json_string_value status)"
done
[[ "${CHALLENGETYPE}" = "http-01" ]] && rm -f "${WELLKNOWN}/${challenge_tokens[${idx}]}"
@@ -870,7 +840,7 @@ sign_csr() {
crt64="$(signed_request "${CA_NEW_CERT}" '{"resource": "new-cert", "csr": "'"${csr64}"'"}' | "${OPENSSL}" base64 -e)"
crt="$( printf -- '-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----\n' "${crt64}" )"
else
result="$(signed_request "${finalize}" '{"csr": "'"${csr64}"'"}' | clean_json)"
result="$(signed_request "${finalize}" '{"csr": "'"${csr64}"'"}' | jsonsh)"
while :; do
status="$(echo "${result}" | get_json_string_value status)"
case "${status}"