mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-19 19:01:42 +00:00
68eeff069e
AssociateAccessPolicy recorded a policy association but never granted it in the cluster. Bake static ClusterRoleBindings for the mulga: groups into the eks-node image, project a principal's cluster-scoped associated policies onto those groups in the TokenReview webhook, and reject namespace scope at association time since there is no namespace-scoped RBAC writer.
116 lines
6.1 KiB
Bash
116 lines
6.1 KiB
Bash
#!/bin/sh
|
|
set -eu
|
|
|
|
# k3s-prestart — reproduces the start_pre logic from scripts/images/eks-node/
|
|
# k3s.initd so the same steps can later be wrapped by a systemd unit's
|
|
# ExecStartPre=: refuses to start on a restore-block marker, derives
|
|
# config.yaml from its skeleton, stages the konnectivity-agent + CoreDNS
|
|
# manifests, and waits (bounded) for the token-webhook kubeconfig. This
|
|
# start_pre performs no OpenRC state mutation (no command_args to set), so it
|
|
# needs no /run env file for the caller to source afterwards.
|
|
#
|
|
# Run as ExecStartPre=/start_pre; a nonzero exit here must stop the caller
|
|
# from ever invoking k3s, same as the OpenRC start_pre returning 1.
|
|
|
|
LOGTAG="k3s-prestart"
|
|
|
|
BLOCK_MARKER=${BLOCK_MARKER:-/run/spinifex-eks/k3s-restore-block}
|
|
K3S_CONFIG=${K3S_CONFIG:-/etc/rancher/k3s/config.yaml}
|
|
K3S_CONFIG_SKEL=${K3S_CONFIG_SKEL:-/etc/rancher/k3s/config.yaml.skel}
|
|
FIRST_BOOT_ENVFILE=${FIRST_BOOT_ENVFILE:-/etc/spinifex-eks/first-boot.env}
|
|
KONN_AGENT_MANIFEST_SRC=${KONN_AGENT_MANIFEST_SRC:-/usr/share/spinifex-eks/konnectivity/konnectivity-agent.yaml}
|
|
KONN_AGENT_MANIFEST_DST=${KONN_AGENT_MANIFEST_DST:-/var/lib/rancher/k3s/server/manifests/konnectivity-agent.yaml}
|
|
COREDNS_SRC=${COREDNS_SRC:-/usr/share/spinifex-eks/coredns/coredns-mulga.yaml}
|
|
COREDNS_SKIP=${COREDNS_SKIP:-/var/lib/rancher/k3s/server/manifests/coredns.yaml.skip}
|
|
COREDNS_DST=${COREDNS_DST:-/var/lib/rancher/k3s/server/manifests/coredns-mulga.yaml}
|
|
ACCESS_POLICY_BINDINGS_SRC=${ACCESS_POLICY_BINDINGS_SRC:-/usr/share/spinifex-eks/rbac/eks-access-policy-bindings.yaml}
|
|
ACCESS_POLICY_BINDINGS_DST=${ACCESS_POLICY_BINDINGS_DST:-/var/lib/rancher/k3s/server/manifests/eks-access-policy-bindings.yaml}
|
|
TOKEN_WEBHOOK_KUBECONFIG=${TOKEN_WEBHOOK_KUBECONFIG:-/etc/spinifex-eks/token-webhook.kubeconfig}
|
|
WAIT_SECS=${WAIT_SECS:-30}
|
|
|
|
# Konnectivity agent image (apiserver-network-proxy). Pinned alongside the
|
|
# konnectivity-server version baked by setup.sh; staged into the worker
|
|
# DaemonSet below.
|
|
KONN_AGENT_IMAGE="registry.k8s.io/kas-network-proxy/proxy-agent:v0.30.3"
|
|
|
|
# mulga-eks-k3s-recovery drops this marker when a required-snapshot restore
|
|
# could not fetch its etcd snapshot. Refuse to start: a fresh DR seed with no
|
|
# snapshot would cluster-init an EMPTY datastore (silent total data loss). The
|
|
# marker is in /run tmpfs, cleared on reboot, so recovery retries the fetch
|
|
# next boot and k3s starts once the snapshot restores.
|
|
if [ -f "${BLOCK_MARKER}" ]; then
|
|
echo "[${LOGTAG}] restore-snapshot could not fetch the required etcd snapshot; refusing to start k3s on an empty datastore (see mulga-eks-k3s-recovery log)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# config.yaml is written by k3s-first-boot from the skeleton + cloud-init
|
|
# data. Refuse to start if neither exists.
|
|
if [ ! -f "${K3S_CONFIG}" ]; then
|
|
if [ -f "${K3S_CONFIG_SKEL}" ]; then
|
|
cp "${K3S_CONFIG_SKEL}" "${K3S_CONFIG}"
|
|
else
|
|
echo "[${LOGTAG}] no ${K3S_CONFIG} and no ${K3S_CONFIG_SKEL} to derive from" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Konnectivity agent: stage the worker-side DaemonSet into the auto-deploy dir
|
|
# (the apiserver `cluster` egress selector tunnels through konnectivity-server,
|
|
# which the agents dial out to). __KONN_HOST__ is the NLB endpoint agents reach,
|
|
# seeded by the launcher in first-boot.env; __KONN_AGENT_IMAGE__ is pinned here.
|
|
# The agent learns the apiserver replica count from the server handshake
|
|
# (--sync-forever), so no server-count token is substituted here. Guarded on
|
|
# the baked manifest so an older image without it simply skips the agent.
|
|
if [ -f "${KONN_AGENT_MANIFEST_SRC}" ]; then
|
|
# The guard above is on the manifest, not the env file, so awk may be handed
|
|
# a path that does not exist and exit nonzero. Swallow that under `set -e`:
|
|
# an absent env file must fall through to the empty-host warning below and
|
|
# still let k3s start, not abort the control plane before it boots.
|
|
konn_host=$(awk -F= '/^EKS_KONNECTIVITY_HOST=/{print $2}' \
|
|
"${FIRST_BOOT_ENVFILE}" 2>/dev/null || true)
|
|
if [ -n "${konn_host}" ]; then
|
|
mkdir -p "$(dirname "${KONN_AGENT_MANIFEST_DST}")"
|
|
sed -e "s|__KONN_HOST__|${konn_host}|g" \
|
|
-e "s|__KONN_AGENT_IMAGE__|${KONN_AGENT_IMAGE}|g" \
|
|
"${KONN_AGENT_MANIFEST_SRC}" \
|
|
> "${KONN_AGENT_MANIFEST_DST}"
|
|
echo "[${LOGTAG}] konnectivity-agent staged (host ${konn_host})"
|
|
else
|
|
echo "[${LOGTAG}] EKS_KONNECTIVITY_HOST empty; konnectivity-agent not staged, apiserver->pod egress will fail" >&2
|
|
fi
|
|
fi
|
|
|
|
# Node-local CoreDNS: suppress k3s's bundled CoreDNS (a single Deployment that
|
|
# tolerates the CP taint and strands itself on the control-plane node) and
|
|
# deploy the Mulga DaemonSet variant so every node resolves via its own
|
|
# CoreDNS. Worker pods cannot reach a CP-resident CoreDNS — the worker<->CP
|
|
# overlay does not cross the VPC boundary. Staged pre-start so the deploy
|
|
# controller never applies the bundled manifest. Guarded on the baked bundle:
|
|
# an older image without it keeps k3s's CoreDNS rather than losing DNS.
|
|
if [ -f "${COREDNS_SRC}" ]; then
|
|
mkdir -p "$(dirname "${COREDNS_DST}")"
|
|
: > "${COREDNS_SKIP}"
|
|
cp "${COREDNS_SRC}" "${COREDNS_DST}"
|
|
fi
|
|
|
|
# Static ClusterRoleBindings for the EKS access-policy groups (mulga:eks-admin/
|
|
# edit/view). No templating, so a plain idempotent copy; guarded on the baked
|
|
# manifest so an older image without it just leaves the associations unbound.
|
|
if [ -f "${ACCESS_POLICY_BINDINGS_SRC}" ]; then
|
|
mkdir -p "$(dirname "${ACCESS_POLICY_BINDINGS_DST}")"
|
|
cp "${ACCESS_POLICY_BINDINGS_SRC}" "${ACCESS_POLICY_BINDINGS_DST}"
|
|
fi
|
|
|
|
# The apiserver is configured with --authentication-token-webhook-config-file
|
|
# pointing at the kubeconfig eks-token-webhook writes at startup. `before k3s`
|
|
# orders the webhook's start but it backgrounds, so wait (bounded) for the
|
|
# kubeconfig to land before letting the apiserver load a missing file.
|
|
i=0
|
|
while [ ! -f "${TOKEN_WEBHOOK_KUBECONFIG}" ] && [ "${i}" -lt "${WAIT_SECS}" ]; do
|
|
sleep 1
|
|
i=$((i + 1))
|
|
done
|
|
if [ ! -f "${TOKEN_WEBHOOK_KUBECONFIG}" ]; then
|
|
echo "[${LOGTAG}] eks-token-webhook kubeconfig absent after ${i}s; IAM token auth will be unavailable until the webhook starts" >&2
|
|
fi
|