Skip to main content

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 -> pywrapper runs setuid_dsarch as the common user.
  • Mode 2 (pgstart specialist): a copy pgstart_<loginname> (e.g. pgstart_zji) runs any command as <loginname> via pgstart.py. <loginname> can be any user that belongs to the same group as PGLOG['COMMONUSER']. Execution is restricted to authorized callers (see pgstart.py below).

Two Python entry points are packaged alongside the C wrapper:

  • pywrapper.py — the default fallback target executed when pywrapper.c cannot resolve a matching setuid_<program> entry point. Acquires the effective UID via PgLOG.set_suid(), prints the caller's real and effective user names, and shows the pyproject.toml snippet plus the pywrapper-install -l <program> command needed to wrap a new script. Diagnostic flags -env, -inc, and -plg dump the environment variables, sys.path, and PGLOG dictionary respectively — handy for verifying the setuid environment before wiring up a real program.

  • pgstart.py — the Mode 2 launcher invoked through a pgstart_<loginname> copy of pywrapper. Reads the real/effective UIDs from PGLOG, then permits execution only if the real user is in [PGLOG['ADMINUSER'], euser, PGLOG['COMMONUSER']] (i.e. the admin specialist PGLOG['ADMINUSER'] — default zji — 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 via subprocess.Popen), -fg (explicit foreground, default), -cwd <dir> (chdir before exec), and the same -env/-inc/-plg diagnostics as pywrapper.py — and then runs the remaining arguments as a command (subprocess.run/Popen) under the effective UID, logging a host/program/timestamp/user line to pgstart.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

https://github.com/NCAR/rda-python-setuid

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rda_python_setuid-3.0.0.tar.gz (17.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rda_python_setuid-3.0.0-py3-none-any.whl (19.0 kB view details)

Uploaded Python 3

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

Hashes for rda_python_setuid-3.0.0.tar.gz
Algorithm Hash digest
SHA256 4aa72b44be98b99b50fed836aaaaba8a19c15ff55f4f913496037e96bd1bfc40
MD5 4429d69498bd1f7cc52e851267301982
BLAKE2b-256 a5fc697019806a38c47ade885f721bcd939e7c73b42dc4b1c9025cbf04fc5f85

See more details on using hashes here.

Provenance

The following attestation bundles were made for rda_python_setuid-3.0.0.tar.gz:

Publisher: publish.yml on NCAR/rda-python-setuid

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rda_python_setuid-3.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for rda_python_setuid-3.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d5f71b58ad47168c10ea46935c337e05db60b89d245d977cd63c06afe6ba13e9
MD5 ee6c985d0db632519dd071ea440192c5
BLAKE2b-256 1ba95b9012fe088a492f786713ec497ab995d58c7dde162ad805fc65bbd2bd3a

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page