rda-python-setuid 1.0.8__tar.gz → 3.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. rda_python_setuid-3.0.0/PKG-INFO +227 -0
  2. rda_python_setuid-3.0.0/README.md +211 -0
  3. {rda_python_setuid-1.0.8 → rda_python_setuid-3.0.0}/pyproject.toml +2 -2
  4. rda_python_setuid-3.0.0/src/rda_python_setuid/install.py +286 -0
  5. {rda_python_setuid-1.0.8 → rda_python_setuid-3.0.0}/src/rda_python_setuid/install.usg +54 -23
  6. {rda_python_setuid-1.0.8 → rda_python_setuid-3.0.0}/src/rda_python_setuid/pgstart.py +3 -3
  7. {rda_python_setuid-1.0.8 → rda_python_setuid-3.0.0}/src/rda_python_setuid/pywrapper.py +2 -0
  8. rda_python_setuid-3.0.0/src/rda_python_setuid/setuid_setup.usg +75 -0
  9. rda_python_setuid-3.0.0/src/rda_python_setuid/setup_guide.py +51 -0
  10. rda_python_setuid-3.0.0/src/rda_python_setuid.egg-info/PKG-INFO +227 -0
  11. {rda_python_setuid-1.0.8 → rda_python_setuid-3.0.0}/src/rda_python_setuid.egg-info/SOURCES.txt +2 -0
  12. rda_python_setuid-1.0.8/PKG-INFO +0 -147
  13. rda_python_setuid-1.0.8/README.md +0 -131
  14. rda_python_setuid-1.0.8/src/rda_python_setuid/install.py +0 -163
  15. rda_python_setuid-1.0.8/src/rda_python_setuid.egg-info/PKG-INFO +0 -147
  16. {rda_python_setuid-1.0.8 → rda_python_setuid-3.0.0}/LICENSE +0 -0
  17. {rda_python_setuid-1.0.8 → rda_python_setuid-3.0.0}/MANIFEST.in +0 -0
  18. {rda_python_setuid-1.0.8 → rda_python_setuid-3.0.0}/setup.cfg +0 -0
  19. {rda_python_setuid-1.0.8 → rda_python_setuid-3.0.0}/src/rda_python_setuid/__init__.py +0 -0
  20. {rda_python_setuid-1.0.8 → rda_python_setuid-3.0.0}/src/rda_python_setuid/pywrapper.c +0 -0
  21. {rda_python_setuid-1.0.8 → rda_python_setuid-3.0.0}/src/rda_python_setuid.egg-info/dependency_links.txt +0 -0
  22. {rda_python_setuid-1.0.8 → rda_python_setuid-3.0.0}/src/rda_python_setuid.egg-info/entry_points.txt +0 -0
  23. {rda_python_setuid-1.0.8 → rda_python_setuid-3.0.0}/src/rda_python_setuid.egg-info/requires.txt +0 -0
  24. {rda_python_setuid-1.0.8 → rda_python_setuid-3.0.0}/src/rda_python_setuid.egg-info/top_level.txt +0 -0
  25. {rda_python_setuid-1.0.8 → rda_python_setuid-3.0.0}/tests/test_setuid.py +0 -0
@@ -0,0 +1,227 @@
1
+ Metadata-Version: 2.4
2
+ Name: rda_python_setuid
3
+ Version: 3.0.0
4
+ Summary: RDA Python Package to setuid for program executions as an effective or common user
5
+ Author-email: Zaihua Ji <zji@ucar.edu>
6
+ Project-URL: Homepage, https://github.com/NCAR/rda-python-setuid
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Requires-Python: >=3.7
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: rda_python_common
15
+ Dynamic: license-file
16
+
17
+ RDA Python package, including a C code wrapper, to execute commandline applications
18
+ via setuid for effective and common user names.
19
+
20
+ ## Overview
21
+
22
+ `rda_python_setuid` provides a C binary (`pywrapper`) that acquires a setuid effective
23
+ user, then `execv`s a Python entry point script. This allows Python programs to run
24
+ as a designated common user (e.g. `gdexdata`) without requiring `sudo` access.
25
+
26
+ Two modes are supported:
27
+
28
+ - **Mode 1 (CommonUser program):** a symlink `dsarch -> pywrapper` runs `setuid_dsarch`
29
+ as the common user.
30
+ - **Mode 2 (pgstart specialist):** a copy `pgstart_<loginname>` (e.g. `pgstart_zji`)
31
+ runs any command as `<loginname>` via `pgstart.py`. `<loginname>` can be any
32
+ user that belongs to the same group as `PGLOG['COMMONUSER']`. Execution is
33
+ restricted to authorized callers (see `pgstart.py` below).
34
+
35
+ Two Python entry points are packaged alongside the C wrapper:
36
+
37
+ - **`pywrapper.py`** — the default fallback target executed when `pywrapper.c`
38
+ cannot resolve a matching `setuid_<program>` entry point. Acquires the
39
+ effective UID via `PgLOG.set_suid()`, prints the caller's real and effective
40
+ user names, and shows the `pyproject.toml` snippet plus the
41
+ `pywrapper-install -l <program>` command needed to wrap a new script.
42
+ Diagnostic flags `-env`, `-inc`, and `-plg` dump the environment variables,
43
+ `sys.path`, and `PGLOG` dictionary respectively — handy for verifying the
44
+ setuid environment before wiring up a real program.
45
+
46
+ - **`pgstart.py`** — the Mode 2 launcher invoked through a `pgstart_<loginname>`
47
+ copy of `pywrapper`. Reads the real/effective UIDs from `PGLOG`, then
48
+ permits execution only if the real user is in
49
+ `[PGLOG['ADMINUSER'], euser, PGLOG['COMMONUSER']]`
50
+ (i.e. the admin specialist `PGLOG['ADMINUSER']` — default `zji` — the
51
+ effective user themselves, or the shared common user); unauthorized callers receive
52
+ an informational message and exit. After authorization it parses leading
53
+ flag tokens — `-bg` (background via `subprocess.Popen`), `-fg` (explicit
54
+ foreground, default), `-cwd <dir>` (chdir before exec), and the same
55
+ `-env`/`-inc`/`-plg` diagnostics as `pywrapper.py` — and then runs the
56
+ remaining arguments as a command (`subprocess.run`/`Popen`) under the
57
+ effective UID, logging a host/program/timestamp/user line to `pgstart.log`.
58
+
59
+ ## Dependency requirement
60
+
61
+ Any Python package whose programs are to be run via the setuid mechanism must declare
62
+ `rda_python_setuid` as a dependency in its `pyproject.toml`:
63
+
64
+ ```toml
65
+ [project]
66
+ dependencies = [
67
+ "rda_python_setuid",
68
+ ...
69
+ ]
70
+ ```
71
+
72
+ It must also register each wrapped program's connector entry point with a `setuid_`
73
+ prefix:
74
+
75
+ ```toml
76
+ [project.scripts]
77
+ "setuid_dsarch" = "rda_python_dsarch.dsarch:main"
78
+ ```
79
+
80
+ `pip install` then places `setuid_dsarch` in the environment's `bin/` directory
81
+ automatically. `pywrapper-install -l/--link` creates the symlink
82
+ `dsarch -> pywrapper`; running `dsarch` goes through the setuid wrapper, which
83
+ execs `setuid_dsarch` as CommonUser.
84
+
85
+ The `main()` of each wrapped program (e.g. `rda_python_dsarch/dsarch.py`) must
86
+ also call `show_setup_guide()` at the top of `main()`, passing an instance of
87
+ the program's class along with the package name and list of setuid program
88
+ names:
89
+
90
+ ```python
91
+ def main():
92
+ from rda_python_setuid.setup_guide import show_setup_guide
93
+ object = DsArch()
94
+ show_setup_guide(object, 'rda_python_dsarch', ['dsarch'])
95
+ ...
96
+ ```
97
+
98
+ When `setuid_dsarch` is invoked directly (before pywrapper symlinks are set
99
+ up, so euid ≠ CommonUser), `show_setup_guide()` prints the shared setuid setup
100
+ guide and exits. When invoked via the `dsarch -> pywrapper` symlink (euid =
101
+ CommonUser), `get_command()` strips the `setuid_` prefix, the check inside
102
+ `show_setup_guide()` fails, and the program runs normally.
103
+
104
+ ## Environment setup
105
+
106
+ Create a Python environment first; package installs in the next section run
107
+ inside whichever environment you activate here.
108
+
109
+ ### Option A — Python venv (DECS machines)
110
+
111
+ ```bash
112
+ python3 -m venv $ENVHOME # e.g. /glade/u/home/gdexdata/gdexmsenv
113
+ source $ENVHOME/bin/activate
114
+ ```
115
+
116
+ ### Option B — Conda (DAV/Casper)
117
+
118
+ ```bash
119
+ conda create --prefix $ENVHOME python=3.12 # e.g. /glade/work/gdexdata/conda-envs/pg-gdex
120
+ conda activate $ENVHOME
121
+ ```
122
+
123
+ ## Installing rda-python-setuid
124
+
125
+ Pick whichever install mode fits your workflow. All four pull in the
126
+ transitive dependency (`rda_python_common`) automatically. Once installed,
127
+ the `pywrapper-install` CLI is available for the setuid wiring steps below.
128
+
129
+ For local development, clone this repo alongside your project and install it
130
+ in editable mode so that changes are picked up without re-installing:
131
+
132
+ ```bash
133
+ git clone https://github.com/NCAR/rda-python-setuid.git
134
+ cd rda-python-setuid
135
+ pip install -e .
136
+ ```
137
+
138
+ To test a specific branch (e.g. an in-progress feature or fix branch), pass
139
+ `-b/--branch` to `git clone`:
140
+
141
+ ```bash
142
+ git clone -b <branch-name> https://github.com/NCAR/rda-python-setuid.git
143
+ cd rda-python-setuid
144
+ pip install -e .
145
+ ```
146
+
147
+ For a regular (non-editable) install from a checkout:
148
+
149
+ ```bash
150
+ pip install /path/to/rda-python-setuid
151
+ ```
152
+
153
+ For a production install on a system that uses the published distribution:
154
+
155
+ ```bash
156
+ pip install rda_python_setuid
157
+ ```
158
+
159
+ ## Setuid wrapper setup
160
+
161
+ With `rda_python_setuid` installed in the active environment, run
162
+ `pywrapper-install` with no arguments to display the full user guide:
163
+
164
+ ```bash
165
+ pywrapper-install
166
+ ```
167
+
168
+ ### Full setuid setup (requires sudo access to CommonUser)
169
+
170
+ ```bash
171
+ # 1. Install the target package (pulls in rda_python_setuid automatically):
172
+ pip install rda_python_dsarch
173
+
174
+ # 2. Compile pywrapper C binary (once per environment):
175
+ pywrapper-install -c|--compile
176
+
177
+ # 3. Wire up each program as a setuid entry (specify name or use 'all'):
178
+ pywrapper-install -l|--link dsarch
179
+ pywrapper-install -l|--link all # auto-link every setuid_* entry not yet linked
180
+
181
+ # 4. Optionally, install a pgstart_<loginname> binary so <loginname> (any user
182
+ # in the same group as PGLOG['COMMONUSER']) can run commands as themselves
183
+ # via the setuid wrapper. Same command in both cases — only the invoker
184
+ # differs:
185
+ #
186
+ # 4a. If PGLOG['ADMINUSER'] (default zji) can `sudo -u <loginname>`, the
187
+ # admin sets it up on the user's behalf:
188
+ pywrapper-install -p|--pgstart -n|--username <loginname>
189
+ #
190
+ # 4b. Otherwise <loginname> runs the same command themselves (no sudo
191
+ # from ADMINUSER required, since they already are <loginname>):
192
+ pywrapper-install -p|--pgstart -n|--username <loginname>
193
+ ```
194
+
195
+ ### Update an existing installation (no sudo required)
196
+
197
+ When the package is upgraded and a new `pywrapper.c` is bundled, use `-u/--update`
198
+ to recompile and reinstall all setuid binaries without needing `sudo`. The existing
199
+ `pgstart_*` binaries in `bin/` are used to perform the privileged operations:
200
+
201
+ ```bash
202
+ pywrapper-install -u|--update [-n|--username gdexdata] [-e|--envhome $ENVHOME]
203
+ ```
204
+
205
+ ### Simple install (no sudo required, runs as current user)
206
+
207
+ Users who do not need the setuid mechanism can skip steps 2–4 and create a
208
+ direct symlink from `dsarch` to `setuid_dsarch`:
209
+
210
+ ```bash
211
+ pip install rda_python_dsarch
212
+ pywrapper-install -l|--link dsarch -s|--simple
213
+ pywrapper-install -l|--link all -s|--simple # or link all setuid_* entries at once
214
+ ```
215
+
216
+ ## Runtime flow
217
+
218
+ ```
219
+ user runs: dsarch [args]
220
+ | (symlink -> pywrapper, setuid bit -> EUID=gdexdata)
221
+ pywrapper.c: execv(bin/setuid_dsarch, args)
222
+ setuid_dsarch: calls dsarch:main() as gdexdata
223
+ ```
224
+
225
+ ## Github
226
+
227
+ <https://github.com/NCAR/rda-python-setuid>
@@ -0,0 +1,211 @@
1
+ RDA Python package, including a C code wrapper, to execute commandline applications
2
+ via setuid for effective and common user names.
3
+
4
+ ## Overview
5
+
6
+ `rda_python_setuid` provides a C binary (`pywrapper`) that acquires a setuid effective
7
+ user, then `execv`s a Python entry point script. This allows Python programs to run
8
+ as a designated common user (e.g. `gdexdata`) without requiring `sudo` access.
9
+
10
+ Two modes are supported:
11
+
12
+ - **Mode 1 (CommonUser program):** a symlink `dsarch -> pywrapper` runs `setuid_dsarch`
13
+ as the common user.
14
+ - **Mode 2 (pgstart specialist):** a copy `pgstart_<loginname>` (e.g. `pgstart_zji`)
15
+ runs any command as `<loginname>` via `pgstart.py`. `<loginname>` can be any
16
+ user that belongs to the same group as `PGLOG['COMMONUSER']`. Execution is
17
+ restricted to authorized callers (see `pgstart.py` below).
18
+
19
+ Two Python entry points are packaged alongside the C wrapper:
20
+
21
+ - **`pywrapper.py`** — the default fallback target executed when `pywrapper.c`
22
+ cannot resolve a matching `setuid_<program>` entry point. Acquires the
23
+ effective UID via `PgLOG.set_suid()`, prints the caller's real and effective
24
+ user names, and shows the `pyproject.toml` snippet plus the
25
+ `pywrapper-install -l <program>` command needed to wrap a new script.
26
+ Diagnostic flags `-env`, `-inc`, and `-plg` dump the environment variables,
27
+ `sys.path`, and `PGLOG` dictionary respectively — handy for verifying the
28
+ setuid environment before wiring up a real program.
29
+
30
+ - **`pgstart.py`** — the Mode 2 launcher invoked through a `pgstart_<loginname>`
31
+ copy of `pywrapper`. Reads the real/effective UIDs from `PGLOG`, then
32
+ permits execution only if the real user is in
33
+ `[PGLOG['ADMINUSER'], euser, PGLOG['COMMONUSER']]`
34
+ (i.e. the admin specialist `PGLOG['ADMINUSER']` — default `zji` — the
35
+ effective user themselves, or the shared common user); unauthorized callers receive
36
+ an informational message and exit. After authorization it parses leading
37
+ flag tokens — `-bg` (background via `subprocess.Popen`), `-fg` (explicit
38
+ foreground, default), `-cwd <dir>` (chdir before exec), and the same
39
+ `-env`/`-inc`/`-plg` diagnostics as `pywrapper.py` — and then runs the
40
+ remaining arguments as a command (`subprocess.run`/`Popen`) under the
41
+ effective UID, logging a host/program/timestamp/user line to `pgstart.log`.
42
+
43
+ ## Dependency requirement
44
+
45
+ Any Python package whose programs are to be run via the setuid mechanism must declare
46
+ `rda_python_setuid` as a dependency in its `pyproject.toml`:
47
+
48
+ ```toml
49
+ [project]
50
+ dependencies = [
51
+ "rda_python_setuid",
52
+ ...
53
+ ]
54
+ ```
55
+
56
+ It must also register each wrapped program's connector entry point with a `setuid_`
57
+ prefix:
58
+
59
+ ```toml
60
+ [project.scripts]
61
+ "setuid_dsarch" = "rda_python_dsarch.dsarch:main"
62
+ ```
63
+
64
+ `pip install` then places `setuid_dsarch` in the environment's `bin/` directory
65
+ automatically. `pywrapper-install -l/--link` creates the symlink
66
+ `dsarch -> pywrapper`; running `dsarch` goes through the setuid wrapper, which
67
+ execs `setuid_dsarch` as CommonUser.
68
+
69
+ The `main()` of each wrapped program (e.g. `rda_python_dsarch/dsarch.py`) must
70
+ also call `show_setup_guide()` at the top of `main()`, passing an instance of
71
+ the program's class along with the package name and list of setuid program
72
+ names:
73
+
74
+ ```python
75
+ def main():
76
+ from rda_python_setuid.setup_guide import show_setup_guide
77
+ object = DsArch()
78
+ show_setup_guide(object, 'rda_python_dsarch', ['dsarch'])
79
+ ...
80
+ ```
81
+
82
+ When `setuid_dsarch` is invoked directly (before pywrapper symlinks are set
83
+ up, so euid ≠ CommonUser), `show_setup_guide()` prints the shared setuid setup
84
+ guide and exits. When invoked via the `dsarch -> pywrapper` symlink (euid =
85
+ CommonUser), `get_command()` strips the `setuid_` prefix, the check inside
86
+ `show_setup_guide()` fails, and the program runs normally.
87
+
88
+ ## Environment setup
89
+
90
+ Create a Python environment first; package installs in the next section run
91
+ inside whichever environment you activate here.
92
+
93
+ ### Option A — Python venv (DECS machines)
94
+
95
+ ```bash
96
+ python3 -m venv $ENVHOME # e.g. /glade/u/home/gdexdata/gdexmsenv
97
+ source $ENVHOME/bin/activate
98
+ ```
99
+
100
+ ### Option B — Conda (DAV/Casper)
101
+
102
+ ```bash
103
+ conda create --prefix $ENVHOME python=3.12 # e.g. /glade/work/gdexdata/conda-envs/pg-gdex
104
+ conda activate $ENVHOME
105
+ ```
106
+
107
+ ## Installing rda-python-setuid
108
+
109
+ Pick whichever install mode fits your workflow. All four pull in the
110
+ transitive dependency (`rda_python_common`) automatically. Once installed,
111
+ the `pywrapper-install` CLI is available for the setuid wiring steps below.
112
+
113
+ For local development, clone this repo alongside your project and install it
114
+ in editable mode so that changes are picked up without re-installing:
115
+
116
+ ```bash
117
+ git clone https://github.com/NCAR/rda-python-setuid.git
118
+ cd rda-python-setuid
119
+ pip install -e .
120
+ ```
121
+
122
+ To test a specific branch (e.g. an in-progress feature or fix branch), pass
123
+ `-b/--branch` to `git clone`:
124
+
125
+ ```bash
126
+ git clone -b <branch-name> https://github.com/NCAR/rda-python-setuid.git
127
+ cd rda-python-setuid
128
+ pip install -e .
129
+ ```
130
+
131
+ For a regular (non-editable) install from a checkout:
132
+
133
+ ```bash
134
+ pip install /path/to/rda-python-setuid
135
+ ```
136
+
137
+ For a production install on a system that uses the published distribution:
138
+
139
+ ```bash
140
+ pip install rda_python_setuid
141
+ ```
142
+
143
+ ## Setuid wrapper setup
144
+
145
+ With `rda_python_setuid` installed in the active environment, run
146
+ `pywrapper-install` with no arguments to display the full user guide:
147
+
148
+ ```bash
149
+ pywrapper-install
150
+ ```
151
+
152
+ ### Full setuid setup (requires sudo access to CommonUser)
153
+
154
+ ```bash
155
+ # 1. Install the target package (pulls in rda_python_setuid automatically):
156
+ pip install rda_python_dsarch
157
+
158
+ # 2. Compile pywrapper C binary (once per environment):
159
+ pywrapper-install -c|--compile
160
+
161
+ # 3. Wire up each program as a setuid entry (specify name or use 'all'):
162
+ pywrapper-install -l|--link dsarch
163
+ pywrapper-install -l|--link all # auto-link every setuid_* entry not yet linked
164
+
165
+ # 4. Optionally, install a pgstart_<loginname> binary so <loginname> (any user
166
+ # in the same group as PGLOG['COMMONUSER']) can run commands as themselves
167
+ # via the setuid wrapper. Same command in both cases — only the invoker
168
+ # differs:
169
+ #
170
+ # 4a. If PGLOG['ADMINUSER'] (default zji) can `sudo -u <loginname>`, the
171
+ # admin sets it up on the user's behalf:
172
+ pywrapper-install -p|--pgstart -n|--username <loginname>
173
+ #
174
+ # 4b. Otherwise <loginname> runs the same command themselves (no sudo
175
+ # from ADMINUSER required, since they already are <loginname>):
176
+ pywrapper-install -p|--pgstart -n|--username <loginname>
177
+ ```
178
+
179
+ ### Update an existing installation (no sudo required)
180
+
181
+ When the package is upgraded and a new `pywrapper.c` is bundled, use `-u/--update`
182
+ to recompile and reinstall all setuid binaries without needing `sudo`. The existing
183
+ `pgstart_*` binaries in `bin/` are used to perform the privileged operations:
184
+
185
+ ```bash
186
+ pywrapper-install -u|--update [-n|--username gdexdata] [-e|--envhome $ENVHOME]
187
+ ```
188
+
189
+ ### Simple install (no sudo required, runs as current user)
190
+
191
+ Users who do not need the setuid mechanism can skip steps 2–4 and create a
192
+ direct symlink from `dsarch` to `setuid_dsarch`:
193
+
194
+ ```bash
195
+ pip install rda_python_dsarch
196
+ pywrapper-install -l|--link dsarch -s|--simple
197
+ pywrapper-install -l|--link all -s|--simple # or link all setuid_* entries at once
198
+ ```
199
+
200
+ ## Runtime flow
201
+
202
+ ```
203
+ user runs: dsarch [args]
204
+ | (symlink -> pywrapper, setuid bit -> EUID=gdexdata)
205
+ pywrapper.c: execv(bin/setuid_dsarch, args)
206
+ setuid_dsarch: calls dsarch:main() as gdexdata
207
+ ```
208
+
209
+ ## Github
210
+
211
+ <https://github.com/NCAR/rda-python-setuid>
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
 
7
7
  [project]
8
8
  name = "rda_python_setuid"
9
- version = "1.0.8"
9
+ version = "3.0.0"
10
10
  authors = [
11
11
  { name="Zaihua Ji", email="zji@ucar.edu" },
12
12
  ]
@@ -30,7 +30,7 @@ include-package-data = true
30
30
  where = ["src"]
31
31
 
32
32
  [tool.setuptools.package-data]
33
- "rda_python_setuid" = ["pywrapper.c", "install.usg"]
33
+ "rda_python_setuid" = ["pywrapper.c", "install.usg", "setuid_setup.usg"]
34
34
 
35
35
  [project.urls]
36
36
  "Homepage" = "https://github.com/NCAR/rda-python-setuid"