Skip to content

Converge and enforce the declared subordinate-ID width#35

Merged
jcardozo-eth merged 6 commits into
mainfrom
feat/subid-minimum-width-enforcement
Jul 23, 2026
Merged

Converge and enforce the declared subordinate-ID width#35
jcardozo-eth merged 6 commits into
mainfrom
feat/subid-minimum-width-enforcement

Conversation

@jcardozo-eth

@jcardozo-eth jcardozo-eth commented Jul 23, 2026

Copy link
Copy Markdown
Member

Completes #15. The default-width bump was delivered in #20 (merged); this PR adds the enforcement part: a declared range is now converged, the preflight checks it, and divergences are surfaced.

What changes

rootless_docker.subid_count becomes a declared minimum width the module enforces per file, only ever widening a range and never shrinking one:

  • A new structured fact (lib/puppet_x/rootless_gitlab_runner/subids.rb, read through a thin lib/facter adapter) parses /etc/subuid and /etc/subgid into a per-owner map, so the catalog can reason about real host state that a compile and --noop cannot see.
  • When the runner's own range sits at the declared start but is narrower than subid_count, a single locked usermod (del-before-add) widens it in place, and a refreshonly restart of the rootless daemon fires so its user namespace picks up the new width. The old width comes from the fact, so the command is literal. A foreign-start or already-wider range is never rewritten.
  • The preflight now sums the runner's on-host ranges against the declared count and fails loud, with remedies, when a range the module does not own is too narrow.
  • Compile-time advisories cover every remaining divergence: an owned range wider than declared, a foreign range wide enough in sum, or a declared range overlapping another user's allocation (two users would share container UIDs). Only the exact-match state is silent.

Tests

Each row of the divergence case matrix is exercised at non-default values with the fact supplied directly (rspec cannot see host state), and the key assertions are mutation-checked.

Verification

just check green: validate + lint + 142 examples, 0 failures + docs-check PASS.

A structured fact parses /etc/subuid and /etc/subgid into per-file owner
maps, so the class can compare the declared range against real host state
that rspec and --noop cannot see. The parsing is a pure PuppetX module,
unit-tested without Facter or the filesystem; the fact is a thin adapter.
subid_count becomes a declared minimum width the module enforces per file.
When the runner user's range is the module-owned one but narrower than
declared, a single locked usermod rewrites it wider (del-before-add), and
the rootless daemon is restarted so the new user namespace takes effect.
The preflight now sums the runner's ranges against the declared count, so
a too-narrow foreign range fails loud instead of failing later in a job.
Every host/data divergence the module neither converges nor fails warns
each apply, including a declared range overlapping another user; only the
exact-match state is silent. Decisions read from the structured subid
fact, so the usermod commands are literal and guards test host state.
Correct the rootless_docker.manage option: subid_count is now a declared
minimum width enforced grow-only, not a create-only value left untouched
once set. Note the shadow auto-allocation collision at subid_start and the
compile-time overlap advisory. REFERENCE.md regenerated to match.
Replace the stale never-overwritten claim in the rootless_docker section
with the grow-only contract: a narrow module-owned range is widened in
place and the rootless daemon restarted, a foreign or wider range is left
alone, and the restart interrupts running jobs. The preflight now asserts
the declared subid_count, not a fixed 65,536.
@jcardozo-eth
jcardozo-eth merged commit 0a39be9 into main Jul 23, 2026
3 checks passed
@jcardozo-eth jcardozo-eth added this to the 2.0.0 milestone Jul 24, 2026
@jcardozo-eth jcardozo-eth added breaking Breaking change: lands only in a major release enhancement New feature or request labels Jul 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking Breaking change: lands only in a major release enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant