RDA Python package, including a C code wrapper, to execute commandline applications via setuid for effective and common user names.
rda_python_setuid provides a C binary (pywrapper) that acquires a setuid effective
user, then execvs a Python entry point script. This allows Python programs to run
as a designated common user (e.g. gdexdata) without requiring sudo access.
Two modes are supported:
- Mode 1 (CommonUser program): a symlink
dsarch -> pywrapperrunssetuid_dsarchas the common user. - Mode 2 (pgstart specialist): a copy
pgstart_zjiruns any command as specialistzjiviapgstart.py, restricted to authorized users.
Two Python entry points are packaged alongside the C wrapper:
-
pywrapper.py— the default fallback target executed whenpywrapper.ccannot resolve a matchingsetuid_<program>entry point. Acquires the effective UID viaPgLOG.set_suid(), prints the caller's real and effective user names, and shows thepyproject.tomlsnippet plus thepywrapper-install -l <program>command needed to wrap a new script. Diagnostic flags-env,-inc, and-plgdump the environment variables,sys.path, andPGLOGdictionary respectively — handy for verifying the setuid environment before wiring up a real program. -
pgstart.py— the Mode 2 launcher invoked through apgstart_<USER>copy ofpywrapper. Reads the real/effective UIDs fromPGLOG, then permits execution only if the real user matches the effective user or the shared GDEX common user (PGLOG['GDEXUSER']); unauthorized callers receive an informational message and exit. After authorization it parses leading flag tokens —-bg(background viasubprocess.Popen),-fg(explicit foreground, default),-cwd <dir>(chdir before exec), and the same-env/-inc/-plgdiagnostics aspywrapper.py— and then runs the remaining arguments as a command (subprocess.run/Popen) under the effective UID, logging a host/program/timestamp/user line topgstart.log.
Any Python package whose programs are to be run via the setuid mechanism must declare
rda_python_setuid as a dependency in its pyproject.toml:
[project]
dependencies = [
"rda_python_setuid",
...
]It must also register each wrapped program's connector entry point with a setuid_
prefix:
[project.scripts]
"setuid_dsarch" = "rda_python_dsarch.dsarch:main"pip install then places setuid_dsarch in the environment's bin/ directory
automatically. pywrapper-install -l/--link locks it down to chmod 700 so users
cannot bypass the setuid wrapper by running it directly.
python3 -m venv $ENVHOME # e.g. /glade/u/home/gdexdata/gdexmsenv
source $ENVHOME/bin/activate
pip install rda_python_setuid rda_python_dsarch ...conda create -n pg-gdex python=3.10
conda activate pg-gdex
pip install rda_python_setuid rda_python_dsarch ...The conda environment is typically at /glade/work/gdexdata/conda-envs/pg-gdex.
After setting up the environment and installing packages, run pywrapper-install
with no arguments to display the full user guide:
pywrapper-install# 1. Install the target package (pulls in rda_python_setuid automatically):
pip install rda_python_dsarch
# 2. Compile pywrapper C binary (once per environment):
pywrapper-install
# 3. Wire up each program as a setuid entry:
pywrapper-install -l dsarch
# 4. Optionally, allow a specialist to run commands as themselves:
pywrapper-install -p -u zjiUsers who do not need the setuid mechanism can skip steps 2–4 and create a
direct symlink from dsarch to setuid_dsarch:
pip install rda_python_dsarch
pywrapper-install -l dsarch -suser runs: dsarch [args]
| (symlink -> pywrapper, setuid bit -> EUID=gdexdata)
pywrapper.c: execv(bin/setuid_dsarch, args)
| (chmod 700, only gdexdata can exec directly)
setuid_dsarch: calls dsarch:main() as gdexdata