ALL

Solo para leer y verificar. No puedes copiar, usar, modificar ni redistribuir este código. Aviso completo en la página principal.

tunnel/deploy/all-tunnel-cert-hook

SHA-256: cb7c4603c06c393075eb42be31018d0c3a9fa1be5ef5fcc62de49924f9bdf554
64 líneas · 3896 bytes · Ver en GitHub

1#!/bin/sh
2# certbot --deploy-hook for the ALL tunnel node's OWN certificate. certbot runs it after every successful renewal with RENEWED_LINEAGE set to the
3# directory of the new certificate. It never trusts that the files are good and never reports success it did not see:
4# 1. the new pair is checked: it is a certificate for THIS node's name, not about to expire, and its key is the key of the certificate;
5# 2. it is installed atomically (key first, then chain; the node reads files it can use and refuses a pair that does not match, so a reader never takes half);
6# 3. the node is told to reload (systemctl reload sends SIGHUP: no restart, no dropped handshake, the streams that are open keep their certificate);
7# 4. when the node's /metrics can be read, it must now report THIS certificate's end. A node that kept the old one is a failure, not a log line.
8# Any failure exits non-zero, so certbot fails, all-tunnel-certbot.service fails and all-tunnel-certbot-failed.service shouts (see that unit).
9set -eu
10umask 077
11here=$(dirname "$0")
12. "${ALL_TUNNEL_LIB:-$here/all-tunnel-cert-lib.sh}"
13
14lineage="${RENEWED_LINEAGE:-}"
15[ -n "$lineage" ] || die "RENEWED_LINEAGE is not set: this script is certbot's deploy hook"
16src_cert="$lineage/fullchain.pem"
17src_key="$lineage/privkey.pem"
18[ -r "$src_cert" ] && [ -r "$src_key" ] || die "the renewed files are missing in $lineage"
19
20host=$(env_value TUNNEL_NODE_HOST)
21dst_cert=$(env_value TUNNEL_CERT_FILE)
22dst_key=$(env_value TUNNEL_KEY_FILE)
23[ -n "$host" ] && [ -n "$dst_cert" ] && [ -n "$dst_key" ] || die "$ALL_TUNNEL_ENV does not say TUNNEL_NODE_HOST, TUNNEL_CERT_FILE and TUNNEL_KEY_FILE"
24
25openssl x509 -in "$src_cert" -noout -checkend 86400 >/dev/null || die "the renewed certificate is already expired or expires within a day"
26openssl x509 -in "$src_cert" -noout -text | grep -Eq "DNS:$host(,|[[:space:]]|\$)" || die "the renewed certificate does not carry this node's name"
27cert_key=$(openssl x509 -in "$src_cert" -noout -pubkey | openssl sha256)
28file_key=$(openssl pkey -in "$src_key" -pubout | openssl sha256)
29[ "$cert_key" = "$file_key" ] || die "the renewed key does not belong to the renewed certificate"
30
31install_atomic() { # install_atomic MODE SOURCE DESTINATION: copy beside the destination, then rename over it
32 mode=$1; from=$2; to=$3
33 dir=$(dirname "$to")
34 [ -d "$dir" ] || install -d -m 0755 "$dir"
35 tmp="$to.new.$$"
36 install -m "$mode" "$from" "$tmp"
37 owner=$(stat -c %u:%g "$dir" 2>/dev/null || true) # the node's dynamic user owns its state directory; the files must be readable by it
38 if [ -n "$owner" ] && [ "$(id -u)" -eq 0 ]; then chown "$owner" "$tmp"; fi
39 mv -f "$tmp" "$to"
40}
41install_atomic 0600 "$src_key" "$dst_key"
42install_atomic 0644 "$src_cert" "$dst_cert"
43
44if systemctl is-active --quiet "$ALL_TUNNEL_UNIT"; then
45 systemctl reload "$ALL_TUNNEL_UNIT" || die "the node did not accept the reload"
46 expected=$(not_after_epoch "$src_cert") || expected=""
47 if [ -n "$expected" ]; then
48 seen=""
49 tries=${ALL_TUNNEL_RELOAD_TRIES:-10}
50 i=0
51 while [ "$i" -lt "$tries" ]; do
52 i=$((i + 1))
53 seen=$(metric all_tunnel_node_cert_not_after_seconds)
54 [ -z "$seen" ] && break # /metrics cannot be read: the monitor and ct_watch.py still watch the certificate the node serves
55 [ "$seen" = "$expected" ] && break
56 sleep "${ALL_TUNNEL_RELOAD_PAUSE:-1}"
57 done
58 if [ -n "$seen" ] && [ "$seen" != "$expected" ]; then die "the node reloaded but still reports a certificate that ends at $seen, not $expected"; fi
59 [ -n "$seen" ] || say warning "the node's /metrics cannot be read: the new certificate was installed and the node told to reload, but not confirmed"
60 fi
61else
62 say warning "the node is not running: the new certificate is installed, and the node reads it when it starts"
63fi
64say info "node certificate renewed and in service for $host"