19. Access control by user and group
Note
This is a plan. It describes the access model PMIx is moving to, and the order in which the pieces are being implemented. The Status section at the end says which parts are in place today. Anything not yet implemented behaves as it did before this work began.
This page is for two audiences:
Users and administrators, who need to know who can see a job’s data and act on a job, and how to widen that.
Developers of PMIx and of host environments, who need to know where each check is made and what a host has to do.
19.1. Summary
Access to a job - reading its data, pulling its output, monitoring or signalling its processes - is decided by who is asking (their user ID and groups), not by which job the requester belongs to.
By default, only the job’s owner can access it. The owner can widen that when the job is started, by naming other users and/or groups with
PMIX_ACCESS_PERMISSIONS.Crossing jobs is normal and supported. A debugger or tool that asks about another job succeeds whenever its user is allowed.
These rules govern requests that clients and tools make of a PMIx server. They do not restrict the host environment itself - see below.
19.2. Who is governed: the host versus clients and tools
A PMIx server lives inside a host environment: a resource manager,
launcher, or other system daemon that calls PMIx_server_init and
supplies the pmix_server_module_t up-calls. Many hosts run as a
privileged service account that is not root.
The host is not restricted. The library does not limit what the host can do through the server APIs (registering jobs, delivering output, answering data requests, and so on), and does not second-guess what the host does with a request passed up to it. The host is the authority for its own operations.
Clients and tools are governed. A request a client or tool sends to a server is checked against the target job’s permissions:
by the server library, for data and operations it handles itself;
by the host, for operations the library passes up to it. For these the library tells the host exactly who is asking - the requester’s process ID,
PMIX_USERIDandPMIX_GRPID(see pmix_server_module_t(5)) - and the host applies the same rule.
The requester’s identity is the one established when it connected to the server (the connection handshake verifies it against the host’s registration). It is not something the request itself can claim.
A request can pass through more than one server: a host relays what one
of its clients or tools asked for to another server - a workflow
manager to the resource manager, a launcher to a scheduler. The identity
is fixed where the request entered, and a relaying host passes it on
with its PMIX_USERID and PMIX_GRPID marked PMIX_INFO_RELAYED
(PMIx_Info_relayed(3)). The next server
keeps them, so the operation is judged by who asked for it rather than
by the relaying process. Only a PMIx server’s library sends the mark -
any other process’s library clears it - so a process that is not a
server speaks only for itself. A server trusts the account a relaying
server gives.
19.3. Terms
- Owner
The user (and primary group) a job belongs to - normally the user who started it.
- Requester
The client or tool making a request, identified by the user ID and group ID recorded when it connected.
- Access list
Additional users and groups the owner has allowed, given with
PMIX_ACCESS_PERMISSIONS.
19.4. The rule
A requester may access a job if any of the following holds:
the requester’s user ID is 0 (root);
the requester’s user ID is the server’s own effective user ID - the account the host runs as, which can already inspect the server process itself;
the requester’s user ID is the job owner’s;
the requester’s user ID is in the job’s access list;
the requester belongs to a group in the job’s access list - its primary group or any supplementary group.
Otherwise the request fails with PMIX_ERR_NO_PERMISSIONS.
19.5. Establishing a job’s permissions
The owner. The host gives the job’s owner when it registers the
job, as PMIX_USERID and PMIX_GRPID in the info passed to
PMIx_server_register_nspace. Either may be a number or a user or
group name; names are resolved when the job is registered. If the host
does not give them:
the owner is the user and group the job’s clients were registered with (
PMIx_server_register_client);failing that, the owner is the server’s own user.
A tool’s owner is the user and group it presented when it connected.
The access list. A user widens access when starting a job, by
passing PMIX_ACCESS_PERMISSIONS in the job-level directives of
PMIx_Spawn. Its value is a data array of pmix_info_t holding
either or both of:
PMIX_ACCESS_USERIDS- a data array of user IDs (numbers or names);PMIX_ACCESS_GRPIDS- a data array of group IDs (numbers or names).
The host passes the list on when it registers the job, on every node
that hosts a part of it. The same attributes already govern access to
published data (PMIx_Publish), so users meet one vocabulary.
Group membership is the groups a user belongs to by its account -
its primary group and its supplementary groups - and not the group a
process happens to be running as. The server keeps a record of each user
it knows, keyed by user ID. The host registers each user
(PMIx_server_register_resources with PMIX_USERID), and may give
the groups it belongs to with it (PMIX_GRPID, as an array), in which
case the server looks nothing up. Otherwise the server looks the groups
up once, when the user becomes known: the host registers it or a job it
owns, or it connects as a tool.
Root and the server’s own user are never recorded - they need no groups.
A requester the server was never told about - one on another node (see
Data held on another node) - is recorded at its first check. A check
that finds the user in none of the job’s groups looks them up again
before refusing, so a user added to a group is admitted from its next
request. A record is dropped when the host deregisters that user
(PMIx_server_deregister_resources with PMIX_USERID), and at
finalize.
19.6. What is covered
Area |
Examples |
Checked by |
|---|---|---|
Job-level data |
|
server library |
Process data on this node |
|
server library |
Process data on another node |
|
the server that holds the data (see below) |
Query and resolve |
process tables, namespace information, |
server library for what it answers; host for the rest |
Output forwarding |
|
host approves each pull; library for inheritance |
Output files |
|
file ownership and mode (see below) |
Monitoring |
|
server library for processes on its node; host for others |
Job control |
signal, kill, terminate, abort, stdin |
host; server library for cleanup directives it handles |
Sessions and allocations |
extending, releasing, spawning into an allocation |
host (by user, not by namespace) |
19.7. What the server library checks
Beyond the rule itself, a few things hold for every check the server library makes:
A job’s own processes always access their own job.
The server’s own namespace describes the server, not anyone’s job, and anyone may read it.
A job the host has not registered with this server - one known here only because data for it arrived from elsewhere - has no permissions here to judge by. Requests for its data are checked by the server that holds it (see Data held on another node). Acting on such a job - cleanup, monitoring, following its output - is allowed only for root and the server’s own user.
Where the checks are made:
Request |
Check |
|---|---|
|
The requester must be allowed the target job. A request waiting for a job to be registered is checked again once it is. |
|
The requester must be allowed that job. |
|
Naming a job, the requester must be allowed it. Naming none, the answer includes only the jobs the requester may access. |
|
Processes named by |
Cleanup directives ( |
The requester must be allowed every job it names, and the cleanup runs as the requester - each entry records who asked - never as the job’s user or the server. A job the server does not know is refused. |
Output forwarding inherited by a spawned job |
A subscription to a job’s output follows into the jobs it spawns only if its requester may access each of them. |
19.8. Data held on another node
When a requester asks for data the local server does not have, the server asks its host, which fetches it from the server that holds it (direct modex). The check is made by the server that holds the data, because that server has the job’s permissions:
The requesting server names the requester in its
direct_modexup-call -PMIX_REQUESTOR,PMIX_USERIDandPMIX_GRPID, the user and group being those established when the requester connected. Requesters of different identities are sent up separately; requesters of one identity share a fetch.The host passes that identity to the holding server through
PMIx_server_dmodex_request2, a new form ofPMIx_server_dmodex_requestthat takes an info array (every PMIx API carries one).The holding server applies the rule and answers, or refuses with
PMIX_ERR_NO_PERMISSIONS.The requesting server keeps a copy of what it receives, and remembers which identities the holding server approved. From that copy it answers only those, the job’s own processes, root, and its own user; any other requester is asked about as though the copy were not there, and gets its own fetch. This applies to
PMIx_Get, to a refresh of a client’s cache, and to query and resolve answered from the copy.
A host that still uses PMIx_server_dmodex_request passes no
requester identity, and the holding server answers as it does today.
The capability flag PMIX_CAP_DMODEX_REQUEST2 tells a host that the
library provides PMIx_server_dmodex_request2.
19.10. Not covered
Event notification. The process raising an event chooses who receives it through the event’s range. The one exception is
PMIX_DEBUGGER_RELEASE, which lets a process held for a debugger continue: a server accepts it from a client or tool only if the rule above permits that requester for the job of every process the event can reach. A job the server has not had registered is left to the host, which relays the event.Published data (
PMIx_Publish/PMIx_Lookup). The host’s data server already governs it per published item withPMIX_ACCESS_PERMISSIONS.
19.11. Compatibility
A host that registers no owner gets the fallback above: the user its clients were registered with, then the server’s own user. On a node that hosts none of a job’s processes there are no clients, so there only root and the server’s own user can access that job. A host running as the same user as its jobs sees no change; a host running as a service account should register each job’s owner.
A host that does not pass ``PMIX_ACCESS_PERMISSIONS`` at registration gets owner-only access for every job, which is the default.
Clients and tools of any version are identified by their connection, so nothing changes for them.
Hosts can detect the library’s support through capability flags in
pmix_version.h:PMIX_CAP_REQUESTER_ID(the requester’s identity on up-calls),PMIX_CAP_DMODEX_REQUEST2(PMIx_server_dmodex_request2) andPMIX_CAP_ACCESS_CHECK(pmix_server_access_check()).
19.12. What a host needs to do
Register each job’s owner (
PMIX_USERID,PMIX_GRPID) and access list (PMIX_ACCESS_PERMISSIONS) withPMIx_server_register_nspaceon every node that hosts part of the job.Accept
PMIX_ACCESS_PERMISSIONSin spawn requests and carry it with the job.Apply the rule to the operations it performs for clients and tools - job control, abort, stdin, IOF pull approval, queries it answers, monitoring of other nodes, sessions and allocations - using the requester identity the library passes in each up-call. A host linked with the library applies exactly the library’s rule by keeping its own copies and calling
pmix_server_access_check()(declared in the installedsrc/server/pmix_server_ops.h) from its own thread: apmix_access_tfor each job, loaded withpmix_server_access_load()from the info it registers the job with, and apmix_user_tfor each requester. None of these touch the library’s state. When the host drops a user it deregisters it from the library too, so the two stay in step. ThePMIX_GRPIDin an up-call is the group the requester chose to charge the work to and is not verified: it is not an input to the rule.Carry the requester’s identity when it relays a request to another of its daemons.
Answer direct-modex requests with
PMIx_server_dmodex_request2, passing the requester’s identity.
PRRTE is the reference host, and implements these alongside the library changes.
19.13. Status
Phase |
Work |
State |
|---|---|---|
0 |
The requester’s process ID, |
Done |
1 |
Each job’s owner and access list stored by the server library, from the host’s registration; one check implementing the rule; group membership cached per user. |
Done |
2 |
The server library applies the rule to what it answers itself: job and process data, query and resolve, monitoring of local processes, cleanup directives, and IOF inheritance. |
Done |
3 |
|
Done |
4 |
Output file ownership and modes; server-mediated job data for requesters the shared-memory file mode does not admit, with shared-memory segments read-only to their readers. |
Done |
5 |
|
Done |