#!/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" $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 ;; *) printf "Deploying existing certificate without running Certbot..\n\n" ;; esac 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)" 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 case "$sp" in "443") _redirect_http="true" ;; *) _redirect_http="false" ;; esac 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