RDA Python Package to setuid for program executions as an effective or common user
Project description
RDA Python package, including a C code wrapper, to execute commandline applications via setuid for effective and common user names.
Overview
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_<loginname>(e.g.pgstart_zji) runs any command as<loginname>viapgstart.py.<loginname>can be any user that belongs to the same group asPGLOG['COMMONUSER']. Execution is restricted to authorized callers (seepgstart.pybelow).
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_<loginname>copy ofpywrapper. Reads the real/effective UIDs fromPGLOG, then permits execution only if the real user is in[PGLOG['ADMINUSER'], euser, PGLOG['COMMONUSER']](i.e. the admin specialistPGLOG['ADMINUSER']— defaultzji— the effective user themselves, or the shared common user); 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.
Dependency requirement
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 creates the symlink
dsarch -> pywrapper; running dsarch goes through the setuid wrapper, which
execs setuid_dsarch as CommonUser.
The main() of each wrapped program (e.g. rda_python_dsarch/dsarch.py) must
also call show_setup_guide() at the top of main(), passing an instance of
the program's class along with the package name and list of setuid program
names:
def main():
from rda_python_setuid.setup_guide import show_setup_guide
object = DsArch()
show_setup_guide(object, 'rda_python_dsarch', ['dsarch'])
...
When setuid_dsarch is invoked directly (before pywrapper symlinks are set
up, so euid ≠ CommonUser), show_setup_guide() prints the shared setuid setup
guide and exits. When invoked via the dsarch -> pywrapper symlink (euid =
CommonUser), get_command() strips the setuid_ prefix, the check inside
show_setup_guide() fails, and the program runs normally.
Environment setup
Create a Python environment first; package installs in the next section run inside whichever environment you activate here.
Option A — Python venv (DECS machines)
python3 -m venv $ENVHOME # e.g. /glade/u/home/gdexdata/gdexmsenv
source $ENVHOME/bin/activate
Option B — Conda (DAV/Casper)
conda create --prefix $ENVHOME python=3.12 # e.g. /glade/work/gdexdata/conda-envs/pg-gdex
conda activate $ENVHOME
Installing rda-python-setuid
Pick whichever install mode fits your workflow. All four pull in the
transitive dependency (rda_python_common) automatically. Once installed,
the pywrapper-install CLI is available for the setuid wiring steps below.
For local development, clone this repo alongside your project and install it in editable mode so that changes are picked up without re-installing:
git clone https://github.com/NCAR/rda-python-setuid.git
cd rda-python-setuid
pip install -e .
To test a specific branch (e.g. an in-progress feature or fix branch), pass
-b/--branch to git clone:
git clone -b <branch-name> https://github.com/NCAR/rda-python-setuid.git
cd rda-python-setuid
pip install -e .
For a regular (non-editable) install from a checkout:
pip install /path/to/rda-python-setuid
For a production install on a system that uses the published distribution:
pip install rda_python_setuid
Setuid wrapper setup
With rda_python_setuid installed in the active environment, run
pywrapper-install with no arguments to display the full user guide:
pywrapper-install
Full setuid setup (requires sudo access to CommonUser)
# 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 -c|--compile
# 3. Wire up each program as a setuid entry (specify name or use 'all'):
pywrapper-install -l|--link dsarch
pywrapper-install -l|--link all # auto-link every setuid_* entry not yet linked
# 4. Optionally, install a pgstart_<loginname> binary so <loginname> (any user
# in the same group as PGLOG['COMMONUSER']) can run commands as themselves
# via the setuid wrapper. Same command in both cases — only the invoker
# differs:
#
# 4a. If PGLOG['ADMINUSER'] (default zji) can `sudo -u <loginname>`, the
# admin sets it up on the user's behalf:
pywrapper-install -p|--pgstart -n|--username <loginname>
#
# 4b. Otherwise <loginname> runs the same command themselves (no sudo
# from ADMINUSER required, since they already are <loginname>):
pywrapper-install -p|--pgstart -n|--username <loginname>
Update an existing installation (no sudo required)
When the package is upgraded and a new pywrapper.c is bundled, use -u/--update
to recompile and reinstall all setuid binaries without needing sudo. The existing
pgstart_* binaries in bin/ are used to perform the privileged operations:
pywrapper-install -u|--update [-n|--username gdexdata] [-e|--envhome $ENVHOME]
Simple install (no sudo required, runs as current user)
Users 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|--link dsarch -s|--simple
pywrapper-install -l|--link all -s|--simple # or link all setuid_* entries at once
Runtime flow
user runs: dsarch [args]
| (symlink -> pywrapper, setuid bit -> EUID=gdexdata)
pywrapper.c: execv(bin/setuid_dsarch, args)
setuid_dsarch: calls dsarch:main() as gdexdata
Github
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rda_python_setuid-3.0.0.tar.gz.
File metadata
- Download URL: rda_python_setuid-3.0.0.tar.gz
- Upload date:
- Size: 17.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4aa72b44be98b99b50fed836aaaaba8a19c15ff55f4f913496037e96bd1bfc40
|
|
| MD5 |
4429d69498bd1f7cc52e851267301982
|
|
| BLAKE2b-256 |
a5fc697019806a38c47ade885f721bcd939e7c73b42dc4b1c9025cbf04fc5f85
|
Provenance
The following attestation bundles were made for rda_python_setuid-3.0.0.tar.gz:
Publisher:
publish.yml on NCAR/rda-python-setuid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rda_python_setuid-3.0.0.tar.gz -
Subject digest:
4aa72b44be98b99b50fed836aaaaba8a19c15ff55f4f913496037e96bd1bfc40 - Sigstore transparency entry: 1756374400
- Sigstore integration time:
-
Permalink:
NCAR/rda-python-setuid@ea2f0a7ac42f87352bb2a85c783ea72a8ad12bb3 -
Branch / Tag:
refs/tags/v3.0.0 - Owner: https://github.com/NCAR
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ea2f0a7ac42f87352bb2a85c783ea72a8ad12bb3 -
Trigger Event:
release
-
Statement type:
File details
Details for the file rda_python_setuid-3.0.0-py3-none-any.whl.
File metadata
- Download URL: rda_python_setuid-3.0.0-py3-none-any.whl
- Upload date:
- Size: 19.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d5f71b58ad47168c10ea46935c337e05db60b89d245d977cd63c06afe6ba13e9
|
|
| MD5 |
ee6c985d0db632519dd071ea440192c5
|
|
| BLAKE2b-256 |
1ba95b9012fe088a492f786713ec497ab995d58c7dde162ad805fc65bbd2bd3a
|
Provenance
The following attestation bundles were made for rda_python_setuid-3.0.0-py3-none-any.whl:
Publisher:
publish.yml on NCAR/rda-python-setuid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rda_python_setuid-3.0.0-py3-none-any.whl -
Subject digest:
d5f71b58ad47168c10ea46935c337e05db60b89d245d977cd63c06afe6ba13e9 - Sigstore transparency entry: 1756374408
- Sigstore integration time:
-
Permalink:
NCAR/rda-python-setuid@ea2f0a7ac42f87352bb2a85c783ea72a8ad12bb3 -
Branch / Tag:
refs/tags/v3.0.0 - Owner: https://github.com/NCAR
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ea2f0a7ac42f87352bb2a85c783ea72a8ad12bb3 -
Trigger Event:
release
-
Statement type: