fix: grant Control scoped access to mesh state #57
4 changed files with 97 additions and 10 deletions
|
|
@ -574,6 +574,7 @@ prepare_control_state() {
|
|||
chown -R "$CONTROL_USER:$CONTROL_USER" "$STATE_DIR/control"
|
||||
find "$STATE_DIR/control" -type d -exec chmod 0700 {} +
|
||||
find "$STATE_DIR/control" -type f -exec chmod 0600 {} +
|
||||
repair_mesh_state_permissions
|
||||
}
|
||||
|
||||
reverse_control_state_migration() {
|
||||
|
|
@ -682,6 +683,22 @@ read_mesh_value() {
|
|||
awk -F '=' -v key="$key" '$1 == key { print substr($0, index($0, "=") + 1); exit }' "$ETC_DIR/mesh.env"
|
||||
}
|
||||
|
||||
ensure_mesh_state() {
|
||||
install -d -m 0770 -o root -g "$CONTROL_USER" "$MESH_DIR"
|
||||
touch "$MESH_DIR/nodes.tsv"
|
||||
chown root:"$CONTROL_USER" "$MESH_DIR/nodes.tsv"
|
||||
chmod 0660 "$MESH_DIR/nodes.tsv"
|
||||
}
|
||||
|
||||
repair_mesh_state_permissions() {
|
||||
[[ -d "$MESH_DIR" ]] || return 0
|
||||
install -d -m 0770 -o root -g "$CONTROL_USER" "$MESH_DIR"
|
||||
if [[ -e "$MESH_DIR/nodes.tsv" ]]; then
|
||||
chown root:"$CONTROL_USER" "$MESH_DIR/nodes.tsv"
|
||||
chmod 0660 "$MESH_DIR/nodes.tsv"
|
||||
fi
|
||||
}
|
||||
|
||||
render_hub_wireguard_config() {
|
||||
local private_key endpoint port node_id address public_key status
|
||||
private_key="$(cat "$WG_DIR/hub.key")"
|
||||
|
|
@ -719,8 +736,10 @@ mesh_init() {
|
|||
fi
|
||||
[[ "$public_endpoint" =~ ^[A-Za-z0-9]([A-Za-z0-9.-]{0,251}[A-Za-z0-9])?$ ]] \
|
||||
|| fail "Invalid WireGuard public endpoint."
|
||||
ensure_system_user "$CONTROL_USER"
|
||||
ensure_mesh_packages
|
||||
install -d -m 0700 "$WG_DIR" "$MESH_DIR" /etc/wireguard
|
||||
install -d -m 0700 -o root -g root "$WG_DIR" /etc/wireguard
|
||||
ensure_mesh_state
|
||||
if [[ ! -f "$WG_DIR/hub.key" ]]; then
|
||||
umask 077
|
||||
wg genkey >"$WG_DIR/hub.key"
|
||||
|
|
@ -736,8 +755,6 @@ HUB_PUBLIC_KEY=$hub_public
|
|||
MESH_NETWORK=$MESH_NETWORK
|
||||
EOF
|
||||
chmod 0644 "$ETC_DIR/mesh.env"
|
||||
touch "$MESH_DIR/nodes.tsv"
|
||||
chmod 0600 "$MESH_DIR/nodes.tsv"
|
||||
printf '%s\n' 'net.ipv4.ip_forward=1' >"/etc/sysctl.d/90-ochenstarik-smm-mesh.conf"
|
||||
sysctl --system >/dev/null
|
||||
write_mesh_firewall
|
||||
|
|
@ -761,9 +778,7 @@ EOF
|
|||
|
||||
reserve_node_address() {
|
||||
local node_id="$1" existing host address
|
||||
install -d -m 0700 "$MESH_DIR"
|
||||
touch "$MESH_DIR/nodes.tsv"
|
||||
chmod 0600 "$MESH_DIR/nodes.tsv"
|
||||
ensure_mesh_state
|
||||
existing="$(awk -F '\t' -v node="$node_id" '$1 == node { print $2; exit }' "$MESH_DIR/nodes.tsv")"
|
||||
if [[ -n "$existing" ]]; then
|
||||
printf '%s\n' "$existing"
|
||||
|
|
@ -1359,7 +1374,8 @@ add_mesh_peer() {
|
|||
awk -F '\t' -v OFS='\t' -v node="$node_id" -v address="$address" -v key="$public_key" \
|
||||
'$1 == node { print node, address, key, "active"; found=1; next } { print } END { if (!found) exit 1 }' \
|
||||
"$MESH_DIR/nodes.tsv" >"$tmp" || { rm -f -- "$tmp"; fail "Peer reservation is missing."; }
|
||||
chmod 0600 "$tmp"
|
||||
chown root:"$CONTROL_USER" "$tmp"
|
||||
chmod 0660 "$tmp"
|
||||
mv -- "$tmp" "$MESH_DIR/nodes.tsv"
|
||||
render_hub_wireguard_config
|
||||
systemctl restart wg-quick@smm0.service
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ LockPersonality=true
|
|||
RestrictSUIDSGID=true
|
||||
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
|
||||
UMask=0077
|
||||
ReadWritePaths=/var/lib/ochenstarik-server-monitor-manager/control
|
||||
ReadWritePaths=/var/lib/ochenstarik-server-monitor-manager/control /var/lib/ochenstarik-server-monitor-manager/mesh
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
|
|
|||
|
|
@ -527,7 +527,18 @@ rm -rf "$role_fixture/lib/agent"
|
|||
rm -rf -- "$role_fixture"
|
||||
|
||||
grep -Fq 'UMask=0077' "$root/deploy/ochenstarik-smm-control.service"
|
||||
grep -Fq 'ReadWritePaths=/var/lib/ochenstarik-server-monitor-manager/control' "$root/deploy/ochenstarik-smm-control.service"
|
||||
grep -Fq 'ReadWritePaths=/var/lib/ochenstarik-server-monitor-manager/control /var/lib/ochenstarik-server-monitor-manager/mesh' "$root/deploy/ochenstarik-smm-control.service"
|
||||
grep -Fq 'install -d -m 0770 -o root -g "$CONTROL_USER" "$MESH_DIR"' "$bootstrap"
|
||||
grep -Fq 'chown root:"$CONTROL_USER" "$MESH_DIR/nodes.tsv"' "$bootstrap"
|
||||
grep -Fq 'chmod 0660 "$MESH_DIR/nodes.tsv"' "$bootstrap"
|
||||
grep -Fq 'install -d -m 0700 -o root -g root "$WG_DIR" /etc/wireguard' "$bootstrap"
|
||||
mesh_init_definition="$(extract_bootstrap_function mesh_init)"
|
||||
grep -Fq ' ensure_system_user "$CONTROL_USER"' <<<"$mesh_init_definition"
|
||||
[[ "$(grep -Fc ' ensure_mesh_state' "$bootstrap")" -eq 2 ]]
|
||||
grep -Fq ' repair_mesh_state_permissions' <<<"$prepare_control_state_definition"
|
||||
if [[ "$(uname -s)" != MINGW* ]] && command -v sudo >/dev/null 2>&1; then
|
||||
bash "$root/tests/bootstrap/test-mesh-state-permissions.sh"
|
||||
fi
|
||||
native_smoke="$root/tests/bootstrap/run-native-systemd-smoke.sh"
|
||||
grep -Fq 'node_code="$(sudo "$system_bootstrap" node-code smoke-node)"' "$native_smoke"
|
||||
grep -Fq 'export SMM_ENROLL_CODE="$node_code"' "$native_smoke"
|
||||
|
|
@ -870,4 +881,3 @@ grep -Fq 'record_installed_version agent' "$bootstrap" || {
|
|||
}
|
||||
|
||||
printf '%s\n' "BOOTSTRAP_CONTRACT=PASS"
|
||||
|
||||
|
|
|
|||
61
tests/bootstrap/test-mesh-state-permissions.sh
Normal file
61
tests/bootstrap/test-mesh-state-permissions.sh
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
root="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
bootstrap="$root/deploy/ochenstarik-server-monitor-manager.sh"
|
||||
fixture="$(mktemp -d -t smm-mesh-permissions.XXXXXXXX)"
|
||||
test_user="$(id -un)"
|
||||
test_group="$(id -gn)"
|
||||
mesh_dir="$fixture/state/mesh"
|
||||
wg_dir="$fixture/etc/wireguard"
|
||||
|
||||
cleanup() {
|
||||
sudo rm -rf -- "$fixture"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
extract_function() {
|
||||
local name="$1"
|
||||
awk -v name="$name" '
|
||||
$0 == name "() {" { capture=1 }
|
||||
capture { print }
|
||||
capture && $0 == "}" { exit }
|
||||
' "$bootstrap"
|
||||
}
|
||||
|
||||
ensure_definition="$(extract_function ensure_mesh_state)"
|
||||
repair_definition="$(extract_function repair_mesh_state_permissions)"
|
||||
runner="$fixture/apply-permissions.sh"
|
||||
{
|
||||
printf '%s\n%s\n' "$ensure_definition" "$repair_definition"
|
||||
printf '%s\n' 'ensure_mesh_state'
|
||||
} >"$runner"
|
||||
|
||||
sudo env MESH_DIR="$mesh_dir" CONTROL_USER="$test_group" bash "$runner"
|
||||
[[ "$(sudo stat -c '%a:%U:%G' "$mesh_dir")" == "770:root:$test_group" ]]
|
||||
[[ "$(sudo stat -c '%a:%U:%G' "$mesh_dir/nodes.tsv")" == "660:root:$test_group" ]]
|
||||
|
||||
printf '%s\n' $'fixture-node\t10.77.0.2\t-\treserved' >>"$mesh_dir/nodes.tsv"
|
||||
grep -Fq 'fixture-node' "$mesh_dir/nodes.tsv"
|
||||
|
||||
sudo install -d -m 0700 -o root -g root "$wg_dir"
|
||||
printf '%s\n' 'private-hub-key' | sudo tee "$wg_dir/hub.key" >/dev/null
|
||||
sudo chown root:root "$wg_dir/hub.key"
|
||||
sudo chmod 0600 "$wg_dir/hub.key"
|
||||
if sudo -u "$test_user" test -r "$wg_dir/hub.key"; then
|
||||
printf '%s\n' 'Control-equivalent user can read the Hub private key' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sudo chmod 0700 "$mesh_dir"
|
||||
sudo chmod 0600 "$mesh_dir/nodes.tsv"
|
||||
{
|
||||
printf '%s\n%s\n' "$ensure_definition" "$repair_definition"
|
||||
printf '%s\n' 'repair_mesh_state_permissions'
|
||||
} >"$runner"
|
||||
sudo env MESH_DIR="$mesh_dir" CONTROL_USER="$test_group" bash "$runner"
|
||||
[[ "$(sudo stat -c '%a:%U:%G' "$mesh_dir")" == "770:root:$test_group" ]]
|
||||
[[ "$(sudo stat -c '%a:%U:%G' "$mesh_dir/nodes.tsv")" == "660:root:$test_group" ]]
|
||||
|
||||
printf '%s\n' 'MESH_STATE_PERMISSIONS=PASS'
|
||||
Loading…
Reference in a new issue