core.group
Manage local OS groups: group creation and removal.
core.group brings the set of local groups to the required composition via groupadd / groupdel. present has present-or-create semantics: an existing group is not reconciled (gid is not checked or changed) and yields changed=false. The module does not manage membership — core.user adds members to a group. Requires root.
Requirements
- Rootrequired
- Side
soul-side - Collection
soulstack.system - Category
system
run_as_rootexec_subprocessStates
core.group.present — The group exists (created via groupadd if it is missing).
The group did not exist and was created.
The group already exists — the existing group's gid is not checked.
Parameters
| Param | Type | Required / default | Description |
|---|---|---|---|
name | string | required | Group name. |
gid | int | optional | Explicit gid (groupadd -g). Applies only on creation. |
system | bool | optional | System group (groupadd -r), gid from the system range. Only on creation. |
Example — System group for a service account
- name: Ensure the app system group exists module: core.group.present params: name: appsvc system: trueOutput
| Field | Type | Description |
|---|---|---|
name | string | |
exists | true | |
created | bool |
core.group.absent — The group is removed.
The group existed and was removed (groupdel).
The group does not exist.
Parameters
| Param | Type | Required / default | Description |
|---|---|---|---|
name | string | required | Group name. |
Output
| Field | Type | Description |
|---|---|---|
name | string | |
exists | false |
Notes
- present — present-or-create: for an already existing group the gid is not checked or changed (the module trusts the first creator). If a group with the same name already exists with a "foreign" gid, a repeated present will not align it; changed=true only when the group did not exist and was created.
- The module does not manage membership: core.group only creates/removes the group, while core.user adds members to it via -G / -g. groupdel does not clean up active memberships in /etc/passwd — that is groupdel's own behavior.
- gid goes to groupadd -g literally, without a range check; system: true takes the gid from the system range and is compatible with an explicit gid (you can set both). The existence check is in-process (user.LookupGroup), without a subprocess.
Security & defaults
- The main risk is recreating a privileged group. name is not validated for meaning: core.group.present with name: sudo / wheel / docker will create a privileged group if it does not exist (on a fresh VM, for example), and a subsequent core.user with that group gives its holder an effective path to root. The risk is not in groupadd itself but in the group becoming a ready "privilege carrier" for later membership.
- A group name from input.* / register.* / soulprint.* must be trusted (the Destiny/scenario author), not external input. For a service account, pin an explicit unprivileged system group.
- gid is not validated and is not reconciled for an existing group: if the name is taken by a group with a "foreign" gid, a repeated present will not align it — the module trusts the first creator. Removal is via absent (groupdel).
- required_capabilities [run_as_root, exec_subprocess] is a declaration for soul-lint's static check against the host's allowed_capabilities, not a runtime privilege escalation: groupadd/groupdel run with the soul agent process's privileges (as root).