fetchcert: Add script to fetch certs from K8s

Since Fedora CoreOS machines are not managed by Ansible, we need another
way to keep the HTTPS certificate up-to-date.  To that end, I've added
the `fetchcert.sh` script, along with a corresponding systemd service
and timer unit, that will fetch the latest certificate from the Secret
resource managed by the Kubernetes API.  The script authenticates with
a long-lived bearer token associated with a particular Kubernetes
service account and downloads the current Secret to a local file.  If
the certificate in the Secret is different than the one already in
place, the certificate and key files are updated and nginx is reloaded.
master
Dustin 2023-09-21 22:23:22 -05:00
parent 222f40426a
commit d907b47db1
7 changed files with 130 additions and 0 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
*.ign
frigate.env
*.token

View File

@ -20,6 +20,9 @@ $(foreach t,$(wildcard *.yaml),$(eval $(call genrules,$(t))))
%.env: %.env.gpg
gpg2 --decrypt $< > $@
%.token: %.token.gpg
gpg2 --decrypt $< > $@
publish: \
nvr1.ign
rsync -rti $^ files.pyrocufflink.blue:public_html/

36
fetchcert.service Normal file
View File

@ -0,0 +1,36 @@
[Unit]
Description=Fetch HTTPS certificate from Kubernetes Secret API
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/bin/sh /etc/fetchcert/fetchcert.sh default pyrocufflink-cert
ProtectSystem=strict
ReadWritePaths=/etc/pki/nginx
CapabilityBoundingSet=CAP_CHOWN
DeviceAllow=
DevicePolicy=closed
LockPersonality=yes
MemoryDenyWriteExecute=yes
NoNewPrivileges=yes
PrivateDevices=yes
PrivateUsers=yes
PrivateTmp=yes
ProcSubset=pid
ProtectClock=yes
ProtectControlGroups=yes
ProtectHome=yes
ProtectHostname=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
ProtectProc=invisible
ProtectSystem=strict
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallFilter=~@privileged @resources

54
fetchcert.sh Normal file
View File

@ -0,0 +1,54 @@
#!/bin/sh
# vim: set sw=4 ts=4 sts=4 et :
namespace=$2
secret=$3
keyout=/etc/pki/nginx/private/server.key
crtout=/etc/pki/nginx/server.crt
tmpdir=$(mktemp -d)
trap 'rm -rf "${tmpdir}"' INT TERM QUIT EXIT
cat > "${tmpdir}"/ca.crt <<EOF
-----BEGIN CERTIFICATE-----
MIIC/jCCAeagAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl
cm5ldGVzMB4XDTIyMDgwMTAyNTUzM1oXDTMyMDcyOTAyNTUzM1owFTETMBEGA1UE
AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMs6
2PUOzIClsAgPv1Mn9CTwzSFMntAn7OppwK5BQ4E5Vd1yMjz3p0uA1ZINv1ORorG0
mLl95C7y+CWUGPx+stHKQr/40sLGyypbX+AfjoPzHiDbIcbZEff8X5RwKqzmT9V7
Yt29KewADod0z+fqNYa62MJDaUunfwaV8kKFU/WJM8IKv2eJxAtWzvK3iHAFhx0j
Xo4TlyINL9V9UMKLf12w6CA3G41uZIBCN3G7aJEm++eGoMdrPZUXlbCpbSztO85/
hbulVs+0hCIxWiI+mRmB5OoWlRYL4jA45oK/RtpEqSwZ95zlGNAChmH7rb0pTtNf
N0/C2wKAEL4POLx9kscCAwEAAaNZMFcwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB
/wQFMAMBAf8wHQYDVR0OBBYEFHYActCjEWdtsA+Ju25gxJh/vaLQMBUGA1UdEQQO
MAyCCmt1YmVybmV0ZXMwDQYJKoZIhvcNAQELBQADggEBAAfkYHecXUwyqvMSXmqr
ETqEzDCBini14s89VDhaDHOXBID9TKMVyeePdEYcPAJz3wo8fbx/+TL37K6hEuo+
7bUaamaumznsjg9L0Hth19GvuRKMXJlEpndRmE5K9hnaDLr94MLg9n1qGcEOt6tw
O6X5qqHf9AuuL39vt1+kSw6PeZZFZNMDZ8BdiTssw4btjQ2bsWu0wSiOSz/F8iRf
2vN5An5dheroDsFs4dZ9gnJ69TmqV1YqQxfRWqCxzfNJbgVm6AoBPwhL1JRuAU4N
3nCNoM9n2tLFDojT4un1778UVU91PtcBVdM9Nq+RC2jhXIyLBqsEK0ofOqFYqj3F
0EQ=
-----END CERTIFICATE-----
EOF
curl -fsSL \
-H 'Accept: application/json' \
-H "Authorization: Bearer $(cat /etc/fetchcert/token)" \
--cacert "${tmpdir}"/ca.crt \
https://kubernetes.pyrocufflink.blue:6443/api/v1/namespaces/${namespace}/secrets/${secret} \
-o "${tmpdir}"/secret.json \
|| exit
jq -r '.data["tls.key"]' "${tmpdir}"/secret.json \
| base64 -d > "${tmpdir}"/server.key
jq -r '.data["tls.crt"]' "${tmpdir}"/secret.json | \
base64 -d > "${tmpdir}"/server.crt
if [ "$(b2sum < "${tmpdir}"/server.crt)" != "$(b2sum < "${crtout}")" ]; then
install -m u=rw,go= -o 101 -g 101 "${tmpdir}"/server.key "${keyout}"
install -m u=rw,go=r -o root -g root "${tmpdir}"/server.crt "${crtout}"
chcon -t container_file_t "${keyout}" "${crtout}"
echo 'Certificate updated, reloading nginx ...' >&2
podman exec -it systemd-nginx nginx -s reload
fi

9
fetchcert.timer Normal file
View File

@ -0,0 +1,9 @@
[Unit]
Description=Periodically fetch certificate from Kubernetes
[Timer]
OnCalendar=*-*-* 0:0:0
RandomizedDelaySec=8h
[Install]
WantedBy=timers.target

22
fetchcert.yaml Normal file
View File

@ -0,0 +1,22 @@
variant: fcos
version: 1.4.0
storage:
files:
- path: /etc/fetchcert/fetchcert.sh
mode: 0755
contents:
local: fetchcert.sh
- path: /etc/systemd/system/fetchcert.service
mode: 0644
contents:
local: fetchcert.service
- path: /etc/systemd/system/fetchcert.timer
mode: 0644
contents:
local: fetchcert.timer
systemd:
units:
- name: fetchcert.timer
enabled: true

View File

@ -1,6 +1,11 @@
variant: fcos
version: 1.4.0
ignition:
config:
merge:
- local: fetchcert.ign
storage:
files:
- path: /etc/containers/systemd/nginx.container