Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/70198.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Isolate salt daemon writable state under per-daemon `/var/lib/salt/<daemon>/` directories so the `/opt/saltstack/salt` onedir tree stays `root:root 0755`. `SALT_ONEDIR_HARDEN=1` is now the default on 3009.0+; `SALT_ONEDIR_HARDEN=0` restores the legacy `chown -R salt /opt/saltstack/salt` behavior for one release and emits a deprecation warning. `salt-pip` and `_salt_onedir_extras.py` honor `SALT_EXTRAS_DIR` at runtime so the relocated extras tree stays importable by the daemon.
30 changes: 30 additions & 0 deletions doc/topics/releases/templates/3009.0.md.template
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,36 @@
Add release specific details below
-->

## Hardened onedir layout (`SALT_ONEDIR_HARDEN=1` by default)

Starting with 3009.0, the Linux packaging isolates each salt daemon's
writable state under per-daemon directories:

- `/var/lib/salt/minion/{home,extras-<py>}` for `salt-minion`
- `/var/lib/salt/master/{home,extras-<py>}` for `salt-master`
- `/var/lib/salt/syndic/{home,extras-<py>}` for `salt-syndic`
- `/var/lib/salt/api/{home,extras-<py>}` for `salt-api`
- `/var/lib/salt/cloud/{home,extras-<py>}` for `salt-cloud`

The `/opt/saltstack/salt` onedir tree now stays owned by
`root:root` at `0755` — the packaging postinst / posttrans scriptlets
no longer chown the tree to the salt user. On upgrade from a legacy
install, the existing `/opt/saltstack/salt/extras-<py>` contents are
migrated into the per-daemon `/var/lib/salt/<daemon>/extras-<py>`
directory automatically.

`salt-pip install` and the runtime `_salt_onedir_extras` import hook
honor the `SALT_EXTRAS_DIR` environment variable so packages installed
via `salt-pip` continue to be importable by the daemon at runtime.

### Opting out for one release

Set `SALT_ONEDIR_HARDEN=0` in `/etc/default/salt-setup` (DEB) or
`/etc/sysconfig/salt-minion-setup` (RPM) to keep the legacy
`chown -R salt /opt/saltstack/salt` behavior. This opt-out is available
for the 3009 release cycle only; the legacy layout will be removed in a
future release. See {issue}`70198`.

<!--
Do not edit the changelog below.
This is auto generated.
Expand Down
18 changes: 13 additions & 5 deletions pkg/common/onedir/_salt_onedir_extras.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import os
import pathlib
import sys


def setup(pth_file_path):
# Discover the extras-<py-major>.<py-minor> directory
extras_parent_path = pathlib.Path(pth_file_path).resolve().parent.parent
if not sys.platform.startswith("win"):
extras_parent_path = extras_parent_path.parent
# Honor SALT_EXTRAS_DIR when set (packaging with SALT_ONEDIR_HARDEN
# relocates the extras tree outside /opt/saltstack/salt so the onedir
# can stay read-only). See issue #70198. Fall back to the historical
# <relenv_root>/extras-<py-major>.<py-minor> location otherwise.
extras_override = os.environ.get("SALT_EXTRAS_DIR")
if extras_override:
extras_path = extras_override
else:
extras_parent_path = pathlib.Path(pth_file_path).resolve().parent.parent
if not sys.platform.startswith("win"):
extras_parent_path = extras_parent_path.parent

extras_path = str(extras_parent_path / "extras-{}.{}".format(*sys.version_info))
extras_path = str(extras_parent_path / "extras-{}.{}".format(*sys.version_info))

if extras_path in sys.path and sys.path[0] != extras_path:
# The extras directory must come first
Expand Down
40 changes: 39 additions & 1 deletion pkg/debian/salt-api.postinst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@ set -e
case "$1" in
configure)
. /usr/share/debconf/confmodule
# Source setup configuration so SALT_ONEDIR_HARDEN / SALT_HOME /
# SALT_EXTRAS_DIR are visible. See issue #70198.
if [ -f /etc/default/salt-setup ]; then
. /etc/default/salt-setup
fi
if [ -f /etc/sysconfig/salt-minion-setup ]; then
. /etc/sysconfig/salt-minion-setup
fi
[ -n "$SALT_ONEDIR_HARDEN" ] || SALT_ONEDIR_HARDEN=1
if [ "$SALT_ONEDIR_HARDEN" = "1" ]; then
[ -n "$SALT_HOME" ] || SALT_HOME=/var/lib/salt/api/home
if [ -z "$SALT_EXTRAS_DIR" ]; then
PY_VER=$(/opt/saltstack/salt/bin/python3 -c "import sys; sys.stdout.write('{}.{}'.format(*sys.version_info)); sys.stdout.flush()" 2>/dev/null || echo "")
[ -n "$PY_VER" ] && SALT_EXTRAS_DIR=/var/lib/salt/api/extras-${PY_VER}
fi
fi
if db_get salt-api/user; then
if [ "$RET" != "root" ]; then
if [ ! -e "/var/log/salt/api" ]; then
Expand All @@ -29,7 +45,29 @@ case "$1" in
# Only set ownership on fresh install, preserve on upgrade
if [ -z "$2" ]; then
chown $RET:$RET /var/log/salt/api
chown -R $RET:$RET /opt/saltstack/salt || true
if [ "$SALT_ONEDIR_HARDEN" = "1" ]; then
install -d -m 0755 -o "$RET" -g "$RET" /var/lib/salt/api
[ -n "$SALT_HOME" ] && install -d -m 0755 -o "$RET" -g "$RET" "$SALT_HOME"
[ -n "$SALT_EXTRAS_DIR" ] && install -d -m 0755 -o "$RET" -g "$RET" "$SALT_EXTRAS_DIR"
else
logger -t salt-api "SALT_ONEDIR_HARDEN=0: legacy /opt/saltstack/salt chown layout is deprecated and will be removed in a future release; unset the variable or set it to 1 to opt into the hardened per-daemon /var/lib/salt/api/ layout." 2>/dev/null || true
chown -R $RET:$RET /opt/saltstack/salt || true
if [ -n "$SALT_EXTRAS_DIR" ] && [ -d "$SALT_EXTRAS_DIR" ]; then
chown -R $RET:$RET "$SALT_EXTRAS_DIR" || true
fi
fi
fi
# Upgrade migration: hardened only. Move populated legacy extras
# into per-daemon location, idempotent otherwise.
if [ "$SALT_ONEDIR_HARDEN" = "1" ] && [ -n "$PY_VER" ] \
&& [ -d "/opt/saltstack/salt/extras-${PY_VER}" ] \
&& [ -n "$(ls -A /opt/saltstack/salt/extras-${PY_VER} 2>/dev/null)" ] \
&& [ -d "$SALT_EXTRAS_DIR" ] \
&& [ -z "$(ls -A ${SALT_EXTRAS_DIR} 2>/dev/null)" ]; then
mv /opt/saltstack/salt/extras-${PY_VER}/* "$SALT_EXTRAS_DIR"/ 2>/dev/null || true
mv /opt/saltstack/salt/extras-${PY_VER}/.[!.]* "$SALT_EXTRAS_DIR"/ 2>/dev/null || true
rmdir /opt/saltstack/salt/extras-${PY_VER} 2>/dev/null || true
chown -R $RET:$RET "$SALT_EXTRAS_DIR" || true
fi
fi
fi
Expand Down
22 changes: 17 additions & 5 deletions pkg/debian/salt-api.preinst
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,34 @@ set -e
# Source setup configuration if present. The DEB-conventional location is
# /etc/default/salt-setup; /etc/sysconfig/salt-minion-setup is honored as
# well for cross-distro parity with the RPM packaging. Either file may
# pre-set SALT_HOME, SALT_USER, SALT_GROUP, SALT_NAME, or SALT_EXTRAS_DIR.
# Values in the sourced files win over inherited env vars; the [ -n ... ]
# || guards below preserve whatever was set, falling back to the hardcoded
# defaults only when nothing was supplied.
# pre-set SALT_HOME, SALT_USER, SALT_GROUP, SALT_NAME, SALT_EXTRAS_DIR,
# or SALT_ONEDIR_HARDEN. Values in the sourced files win over inherited
# env vars; the [ -n ... ] || guards below preserve whatever was set,
# falling back to the hardcoded defaults only when nothing was supplied.
if [ -f /etc/default/salt-setup ]; then
. /etc/default/salt-setup
fi
if [ -f /etc/sysconfig/salt-minion-setup ]; then
. /etc/sysconfig/salt-minion-setup
fi

[ -n "$SALT_HOME" ] || SALT_HOME=/opt/saltstack/salt
# SALT_ONEDIR_HARDEN=1 (default on 3009.0+) relocates the salt-api
# writable state out of /opt/saltstack/salt into /var/lib/salt/api/ so
# the onedir tree can stay root-owned and 0755. See issue #70198.
[ -n "$SALT_ONEDIR_HARDEN" ] || SALT_ONEDIR_HARDEN=1

[ -n "$SALT_USER" ] || SALT_USER=salt
[ -n "$SALT_NAME" ] || SALT_NAME="Salt"
[ -n "$SALT_GROUP" ] || SALT_GROUP=salt

# SALT_HOME default in hardened mode points at the per-daemon dir under
# /var/lib/salt/api. Explicit SALT_HOME still wins.
if [ "$SALT_ONEDIR_HARDEN" = "1" ]; then
[ -n "$SALT_HOME" ] || SALT_HOME=/var/lib/salt/api/home
else
[ -n "$SALT_HOME" ] || SALT_HOME=/opt/saltstack/salt
fi

case "$1" in
install)
# Propagate the resolved SALT_USER (from /etc/default/salt-setup,
Expand Down
40 changes: 38 additions & 2 deletions pkg/debian/salt-cloud.postinst
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,50 @@ set -e
case "$1" in
configure)
. /usr/share/debconf/confmodule
# Source setup configuration so SALT_ONEDIR_HARDEN / SALT_HOME /
# SALT_EXTRAS_DIR are visible. See issue #70198.
if [ -f /etc/default/salt-setup ]; then
. /etc/default/salt-setup
fi
if [ -f /etc/sysconfig/salt-minion-setup ]; then
. /etc/sysconfig/salt-minion-setup
fi
[ -n "$SALT_ONEDIR_HARDEN" ] || SALT_ONEDIR_HARDEN=1
PY_VER=$(/opt/saltstack/salt/bin/python3 -c "import sys; sys.stdout.write('{}.{}'.format(*sys.version_info)); sys.stdout.flush()" 2>/dev/null || echo "")
if [ "$SALT_ONEDIR_HARDEN" = "1" ]; then
[ -n "$SALT_HOME" ] || SALT_HOME=/var/lib/salt/cloud/home
if [ -z "$SALT_EXTRAS_DIR" ] && [ -n "$PY_VER" ]; then
SALT_EXTRAS_DIR=/var/lib/salt/cloud/extras-${PY_VER}
fi
fi
if db_get salt-master/user
then
if [ "$RET" != "root" ]; then
PY_VER=$(/opt/saltstack/salt/bin/python3 -c "import sys; sys.stdout.write('{}.{}'.format(*sys.version_info)); sys.stdout.flush;")
# Only set ownership on fresh install, preserve on upgrade
if [ -z "$2" ]; then
chown -R $RET:$RET /etc/salt/cloud.deploy.d /opt/saltstack/salt/lib/python${PY_VER}/site-packages/salt/cloud/deploy
chown -R $RET:$RET /opt/saltstack/salt || true
if [ "$SALT_ONEDIR_HARDEN" = "1" ]; then
install -d -m 0755 -o "$RET" -g "$RET" /var/lib/salt/cloud
[ -n "$SALT_HOME" ] && install -d -m 0755 -o "$RET" -g "$RET" "$SALT_HOME"
[ -n "$SALT_EXTRAS_DIR" ] && install -d -m 0755 -o "$RET" -g "$RET" "$SALT_EXTRAS_DIR"
else
logger -t salt-cloud "SALT_ONEDIR_HARDEN=0: legacy /opt/saltstack/salt chown layout is deprecated and will be removed in a future release; unset the variable or set it to 1 to opt into the hardened per-daemon /var/lib/salt/cloud/ layout." 2>/dev/null || true
chown -R $RET:$RET /opt/saltstack/salt || true
if [ -n "$SALT_EXTRAS_DIR" ] && [ -d "$SALT_EXTRAS_DIR" ]; then
chown -R $RET:$RET "$SALT_EXTRAS_DIR" || true
fi
fi
fi
# Upgrade migration: hardened only, one-shot.
if [ "$SALT_ONEDIR_HARDEN" = "1" ] && [ -n "$PY_VER" ] \
&& [ -d "/opt/saltstack/salt/extras-${PY_VER}" ] \
&& [ -n "$(ls -A /opt/saltstack/salt/extras-${PY_VER} 2>/dev/null)" ] \
&& [ -d "$SALT_EXTRAS_DIR" ] \
&& [ -z "$(ls -A ${SALT_EXTRAS_DIR} 2>/dev/null)" ]; then
mv /opt/saltstack/salt/extras-${PY_VER}/* "$SALT_EXTRAS_DIR"/ 2>/dev/null || true
mv /opt/saltstack/salt/extras-${PY_VER}/.[!.]* "$SALT_EXTRAS_DIR"/ 2>/dev/null || true
rmdir /opt/saltstack/salt/extras-${PY_VER} 2>/dev/null || true
chown -R $RET:$RET "$SALT_EXTRAS_DIR" || true
fi
fi
fi
Expand Down
52 changes: 52 additions & 0 deletions pkg/debian/salt-cloud.preinst
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/bin/sh
# preinst script for salt-cloud.
#
# See: dh_installdeb(1).

set -e

# Summary of how this script can be called:
# * <new-preinst> 'install'
# * <new-preinst> 'install' <old-version>
# * <new-preinst> 'upgrade' <old-version>
# * <old-preinst> 'abort-upgrade' <new-version>
# for details, see https://www.debian.org/doc/debian-policy/ or
# the debian-policy package.

# Source setup configuration if present. The DEB-conventional location is
# /etc/default/salt-setup; /etc/sysconfig/salt-minion-setup is honored as
# well for cross-distro parity with the RPM packaging. Either file may
# pre-set SALT_HOME, SALT_USER, SALT_GROUP, SALT_NAME, SALT_EXTRAS_DIR,
# or SALT_ONEDIR_HARDEN. Values in the sourced files win over inherited
# env vars; the [ -n ... ] || guards below preserve whatever was set,
# falling back to the hardcoded defaults only when nothing was supplied.
if [ -f /etc/default/salt-setup ]; then
. /etc/default/salt-setup
fi
if [ -f /etc/sysconfig/salt-minion-setup ]; then
. /etc/sysconfig/salt-minion-setup
fi

# SALT_ONEDIR_HARDEN=1 (default on 3009.0+) relocates the salt-cloud
# writable state out of /opt/saltstack/salt into /var/lib/salt/cloud/
# so the onedir tree can stay root-owned and 0755. See issue #70198.
[ -n "$SALT_ONEDIR_HARDEN" ] || SALT_ONEDIR_HARDEN=1

[ -n "$SALT_USER" ] || SALT_USER=salt
[ -n "$SALT_NAME" ] || SALT_NAME="Salt"
[ -n "$SALT_GROUP" ] || SALT_GROUP=salt

# SALT_HOME default in hardened mode points at the per-daemon dir under
# /var/lib/salt/cloud. Explicit SALT_HOME still wins.
if [ "$SALT_ONEDIR_HARDEN" = "1" ]; then
[ -n "$SALT_HOME" ] || SALT_HOME=/var/lib/salt/cloud/home
else
[ -n "$SALT_HOME" ] || SALT_HOME=/opt/saltstack/salt
fi

# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.

#DEBHELPER#

exit 0
1 change: 1 addition & 0 deletions pkg/debian/salt-common.dirs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/var/cache/salt
/var/log/salt
/var/run/salt
/var/lib/salt
/usr/share/fish/vendor_completions.d
/opt/saltstack/salt
/etc/salt
Expand Down
21 changes: 20 additions & 1 deletion pkg/debian/salt-common.preinst
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,31 @@ if [ -f /etc/sysconfig/salt-minion-setup ]; then
. /etc/sysconfig/salt-minion-setup
fi

[ -n "$SALT_HOME" ] || SALT_HOME=/opt/saltstack/salt
# SALT_ONEDIR_HARDEN=1 (default on 3009.0+) relocates the salt user's
# writable state out of /opt/saltstack/salt into per-daemon
# /var/lib/salt/<daemon>/. Setting SALT_ONEDIR_HARDEN=0 preserves the
# legacy layout for one release. See issue #70198.
[ -n "$SALT_ONEDIR_HARDEN" ] || SALT_ONEDIR_HARDEN=1

[ -n "$SALT_USER" ] || SALT_USER=salt
[ -n "$SALT_NAME" ] || SALT_NAME="Salt"
[ -n "$SALT_GROUP" ] || SALT_GROUP=salt
[ -n "$SALT_SHELL" ] || SALT_SHELL=/usr/sbin/nologin

# SALT_HOME default depends on SALT_ONEDIR_HARDEN. In hardened mode the
# salt user's account home moves under /var/lib/salt so
# /opt/saltstack/salt can stay root-owned and 0755. The per-daemon
# preinst scripts may reassign SALT_HOME to /var/lib/salt/<daemon>/home
# so whichever daemon's preinst runs last owns the passwd home entry;
# this is intentional -- see issue #70198.
if [ -z "$SALT_HOME" ]; then
if [ "$SALT_ONEDIR_HARDEN" = "1" ]; then
SALT_HOME=/var/lib/salt/home
else
SALT_HOME=/opt/saltstack/salt
fi
fi

case "$1" in
install|upgrade)
# create user to avoid running server as root
Expand Down
53 changes: 48 additions & 5 deletions pkg/debian/salt-master.postinst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,22 @@ set -e
case "$1" in
configure)
. /usr/share/debconf/confmodule
# Source setup configuration so SALT_ONEDIR_HARDEN / SALT_HOME /
# SALT_EXTRAS_DIR are visible. See issue #70198.
if [ -f /etc/default/salt-setup ]; then
. /etc/default/salt-setup
fi
if [ -f /etc/sysconfig/salt-minion-setup ]; then
. /etc/sysconfig/salt-minion-setup
fi
[ -n "$SALT_ONEDIR_HARDEN" ] || SALT_ONEDIR_HARDEN=1
if [ "$SALT_ONEDIR_HARDEN" = "1" ]; then
[ -n "$SALT_HOME" ] || SALT_HOME=/var/lib/salt/master/home
if [ -z "$SALT_EXTRAS_DIR" ]; then
PY_VER=$(/opt/saltstack/salt/bin/python3 -c "import sys; sys.stdout.write('{}.{}'.format(*sys.version_info)); sys.stdout.flush()" 2>/dev/null || echo "")
[ -n "$PY_VER" ] && SALT_EXTRAS_DIR=/var/lib/salt/master/extras-${PY_VER}
fi
fi
if db_get salt-master/user; then
if [ "$RET" != "root" ]; then
if [ ! -e "/var/log/salt/master" ]; then
Expand All @@ -33,11 +49,38 @@ case "$1" in
fi
# Only set ownership on fresh install, preserve on upgrade
if [ -z "$2" ]; then
chown -R $RET:$RET /etc/salt/pki/master /etc/salt/master.d \
/var/log/salt/master /var/log/salt/key \
/var/cache/salt/master /var/run/salt/master \
/opt/saltstack/salt \
|| true
if [ "$SALT_ONEDIR_HARDEN" = "1" ]; then
install -d -m 0755 -o "$RET" -g "$RET" /var/lib/salt/master
[ -n "$SALT_HOME" ] && install -d -m 0755 -o "$RET" -g "$RET" "$SALT_HOME"
[ -n "$SALT_EXTRAS_DIR" ] && install -d -m 0755 -o "$RET" -g "$RET" "$SALT_EXTRAS_DIR"
chown -R $RET:$RET /etc/salt/pki/master /etc/salt/master.d \
/var/log/salt/master /var/log/salt/key \
/var/cache/salt/master /var/run/salt/master \
|| true
else
logger -t salt-master "SALT_ONEDIR_HARDEN=0: legacy /opt/saltstack/salt chown layout is deprecated and will be removed in a future release; unset the variable or set it to 1 to opt into the hardened per-daemon /var/lib/salt/master/ layout." 2>/dev/null || true
chown -R $RET:$RET /etc/salt/pki/master /etc/salt/master.d \
/var/log/salt/master /var/log/salt/key \
/var/cache/salt/master /var/run/salt/master \
/opt/saltstack/salt \
|| true
if [ -n "$SALT_EXTRAS_DIR" ] && [ -d "$SALT_EXTRAS_DIR" ]; then
chown -R $RET:$RET "$SALT_EXTRAS_DIR" || true
fi
fi
fi
# Upgrade migration: hardened only, one-shot. If legacy extras
# populated and new empty, move contents. Runs on both fresh
# install (no-op) and upgrade (migrates once).
if [ "$SALT_ONEDIR_HARDEN" = "1" ] && [ -n "$PY_VER" ] \
&& [ -d "/opt/saltstack/salt/extras-${PY_VER}" ] \
&& [ -n "$(ls -A /opt/saltstack/salt/extras-${PY_VER} 2>/dev/null)" ] \
&& [ -d "$SALT_EXTRAS_DIR" ] \
&& [ -z "$(ls -A ${SALT_EXTRAS_DIR} 2>/dev/null)" ]; then
mv /opt/saltstack/salt/extras-${PY_VER}/* "$SALT_EXTRAS_DIR"/ 2>/dev/null || true
mv /opt/saltstack/salt/extras-${PY_VER}/.[!.]* "$SALT_EXTRAS_DIR"/ 2>/dev/null || true
rmdir /opt/saltstack/salt/extras-${PY_VER} 2>/dev/null || true
chown -R $RET:$RET "$SALT_EXTRAS_DIR" || true
fi
fi
fi
Expand Down
Loading
Loading