2021-01-19 08:10:28 +00:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
args="$@"
|
|
|
|
|
|
|
|
set -o nounset
|
|
|
|
set -e errexit
|
|
|
|
|
|
|
|
certbot=/run/current-system/sw/bin/certbot
|
|
|
|
jq=/run/current-system/sw/bin/jq
|
|
|
|
curl=/run/current-system/sw/bin/curl
|
|
|
|
|
|
|
|
cert_name="$SERVICE-$ENVIRONMENT"
|
|
|
|
domains="-d $DOMAIN_NAME"
|
|
|
|
for san in $ALTERNATIVE_NAMES; do
|
|
|
|
domains="$domains -d $san"
|
|
|
|
done
|
|
|
|
|
|
|
|
case "$args" in
|
|
|
|
"--renew")
|
|
|
|
printf "Running Certbot (for renewal) before deploying certificate..\n\n"
|
2021-01-19 12:40:04 +00:00
|
|
|
$certbot certonly --non-interactive --agree-tos -m webmaster@"$DOMAIN_NAME" --work-dir "$LETSENCRYPT_DIR"/lib --logs-dir "$LETSENCRYPT_DIR"/log --config-dir "$LETSENCRYPT_DIR"/etc --dns-route53 --preferred-challenges dns $domains
|
2021-01-19 08:10:28 +00:00
|
|
|
;;
|
|
|
|
*)
|
|
|
|
printf "Deploying existing certificate without running Certbot..\n\n"
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
2021-01-19 12:08:44 +00:00
|
|
|
key="$(sed 's/$/\\n/' $LETSENCRYPT_DIR/etc/live/$DOMAIN_NAME/privkey.pem | tr -d '\n')"
|
|
|
|
fullchain="$(sed 's/$/\\n/' $LETSENCRYPT_DIR/etc/live/$DOMAIN_NAME/fullchain.pem | tr -d '\n')"
|
|
|
|
service_ports="$(printf "%s" "$SERVICE_PORTS" | tr ',' ' ' | xargs)"
|
2021-01-19 08:10:28 +00:00
|
|
|
|
|
|
|
lb_id=$($curl -s -H "Authorization: Bearer $API_TOKEN" "https://api.hetzner.cloud/v1/load_balancers?label_selector=service==$SERVICE%2Cenvironment==$ENVIRONMENT" | $jq '.load_balancers[0].id')
|
|
|
|
|
|
|
|
case "$lb_id" in
|
|
|
|
""|*[!0-9]*)
|
|
|
|
printf "Load balancer for %s in environment \"%s\" could not be found\n" "$SERVICE" "$ENVIRONMENT"
|
|
|
|
exit 1
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
update_load_balancer() {
|
|
|
|
case "$1" in
|
|
|
|
*[0-9]*)
|
|
|
|
_proto=https
|
|
|
|
_certs="[$1]"
|
|
|
|
;;
|
|
|
|
"")
|
|
|
|
printf "Temporarily disabling https for renewal\n"
|
|
|
|
_proto=http
|
|
|
|
_redirect_http="false"
|
|
|
|
_certs="[]"
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
printf "Something went wrong, tried to process certificate with ID \"%s\"\n" "$cert_id"
|
|
|
|
exit 1
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
for sp in $service_ports; do
|
2021-01-22 15:50:04 +00:00
|
|
|
case "$sp" in
|
|
|
|
"443")
|
|
|
|
_redirect_http="true"
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
_redirect_http="false"
|
|
|
|
;;
|
|
|
|
esac
|
2021-01-19 08:10:28 +00:00
|
|
|
error=$($curl -s -XPOST -H "Authorization: Bearer $API_TOKEN" -H "Content-Type: application/json" -d "{\"listen_port\": $sp, \"protocol\": \"$_proto\", \"http\":{\"redirect_http\": $_redirect_http, \"certificates\": $_certs}}" "https://api.hetzner.cloud/v1/load_balancers/$lb_id/actions/update_service" | $jq -r '.error')
|
|
|
|
case "$(printf "%s" "$error" | $jq -r '.code')" in
|
|
|
|
"null")
|
|
|
|
printf "Certificate with ID \"%s\" has been successfully assigned to service port %s on the load balancer with ID \"%s\"\n" "$1" "$sp" "$lb_id"
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
printf "There has been an unexpected error: %s\n" "$error"
|
|
|
|
exit 1
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
done
|
|
|
|
}
|
|
|
|
|
|
|
|
cert_id=$($curl -s -H "Authorization: Bearer $API_TOKEN" "https://api.hetzner.cloud/v1/certificates?label_selector=service=$SERVICE%2Cenvironment=$ENVIRONMENT" | $jq '.certificates[0].id')
|
|
|
|
|
|
|
|
#
|
|
|
|
# Determine whether a certificate for the same service and environment already exists
|
|
|
|
#
|
|
|
|
case "$cert_id" in
|
|
|
|
""|*[0-9]*)
|
|
|
|
update_load_balancer ""
|
|
|
|
printf "Deleting existing certificate with id %s so that it can be replaced by a new one\n" "$cert_id"
|
|
|
|
$curl -s -X DELETE -H "Authorization: Bearer $API_TOKEN" "https://api.hetzner.cloud/v1/certificates/$cert_id"
|
|
|
|
;;
|
|
|
|
"null")
|
|
|
|
printf "Currently there is no certificate deployed for %s in environment \"%s\", setting up a new one\n" "$SERVICE" "$ENVIRONMENT"
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
printf "Something went wrong: %s\n" "$cert_id"
|
|
|
|
exit 1
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
#
|
|
|
|
# Deploy key and certificate to Hetzner security service
|
|
|
|
#
|
|
|
|
error=$($curl -s -XPOST -H "Authorization: Bearer $API_TOKEN" -H "Content-Type: application/json" -d "{\"name\":\"$cert_name\",\"labels\":{\"service\": \"$SERVICE\", \"environment\": \"$ENVIRONMENT\"},\"certificate\":\"$fullchain\",\"private_key\":\"$key\"}" 'https://api.hetzner.cloud/v1/certificates' | $jq '.error')
|
|
|
|
|
|
|
|
case "$(printf "%s" "$error" | $jq -r '.code')" in
|
|
|
|
"null")
|
|
|
|
cert_id=$($curl -s -H "Authorization: Bearer $API_TOKEN" "https://api.hetzner.cloud/v1/certificates?label_selector=service=$SERVICE%2Cenvironment=$ENVIRONMENT" | $jq '.certificates[0].id')
|
|
|
|
printf "The certificate %s has been successfully added to the Hetzner security service with ID \"%s\"\n" "$cert_name" "$cert_id"
|
|
|
|
update_load_balancer "$cert_id"
|
|
|
|
;;
|
|
|
|
"uniqueness_error")
|
|
|
|
printf "A certificate with the same fingerprint already exists! Exiting\n"
|
|
|
|
exit 1
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
printf "There has been an unexpected error: %s\n" "$error"
|
|
|
|
exit 1
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|