Documentation
¶
Overview ¶
Package hostctx describes observed facts about a system, so that findings can be upgraded from possible to confirmed.
The interface exists from the start even though the live implementation lands later, because rules must be written against it and must behave sensibly when nothing is known. Unknown is the zero implementation: every question returns "not known", so a rule needs no nil checks and the no-context path is the one exercised by default.
Live implementations read files only, never subprocesses: `/sys/fs/selinux/ enforce`, `/proc/self/mountinfo`, `/etc/subuid`, `/etc/subgid`. That is the spec's guidance, and it is also what makes a captured context replayable, since a directory of files can be serialised but a subprocess cannot.
Index ¶
- func Capture(dir string) error
- func Describe(c Context) []string
- type Context
- type IDRange
- type Live
- func (l *Live) ExistingUnitNames() ([]string, bool)
- func (l *Live) MountFor(path string) (Mount, bool)
- func (l *Live) Mounts() []Mount
- func (l *Live) Rootless() (bool, bool)
- func (l *Live) SELinux() SELinuxMode
- func (l *Live) SubGIDRanges() ([]IDRange, bool)
- func (l *Live) SubUIDRanges() ([]IDRange, bool)
- func (l *Live) UnprivilegedPortStart() (int, bool)
- type Mount
- type SELinuxMode
- type Static
- func (s Static) ExistingUnitNames() ([]string, bool)
- func (s Static) MountFor(path string) (Mount, bool)
- func (s Static) Rootless() (bool, bool)
- func (s Static) SELinux() SELinuxMode
- func (s Static) SubGIDRanges() ([]IDRange, bool)
- func (s Static) SubUIDRanges() ([]IDRange, bool)
- func (s Static) UnprivilegedPortStart() (int, bool)
- type Unknown
- func (Unknown) ExistingUnitNames() ([]string, bool)
- func (Unknown) MountFor(string) (Mount, bool)
- func (Unknown) Rootless() (bool, bool)
- func (Unknown) SELinux() SELinuxMode
- func (Unknown) SubGIDRanges() ([]IDRange, bool)
- func (Unknown) SubUIDRanges() ([]IDRange, bool)
- func (Unknown) UnprivilegedPortStart() (int, bool)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Capture ¶
Capture writes the live context to a directory, so it can be replayed elsewhere. Capture on the machine where something is wrong, lint on your own.
The files keep their original paths under the directory, so replay is the same code reading the same layout, which is what keeps live and replay from diverging.
Types ¶
type Context ¶
type Context interface {
// SELinux reports the SELinux mode, or SELinuxUnknown.
SELinux() SELinuxMode
// MountFor returns the mount entry whose mount point is the longest
// prefix of the given path: the filesystem that path actually lives on.
MountFor(path string) (Mount, bool)
// SubUIDRanges and SubGIDRanges return the calling user's subordinate ID
// allocations.
SubUIDRanges() ([]IDRange, bool)
SubGIDRanges() ([]IDRange, bool)
// UnprivilegedPortStart returns net.ipv4.ip_unprivileged_port_start.
// QD031 must read this rather than assume 1024: administrators commonly
// lower it to 80.
UnprivilegedPortStart() (int, bool)
// ExistingUnitNames returns the names of units already installed in the
// Quadlet search path, for collision detection.
ExistingUnitNames() ([]string, bool)
// Rootless reports whether Podman is running rootless.
Rootless() (bool, bool)
}
Context is what rules may consult about the host.
Every method reports whether the fact is known, so that a rule can distinguish "the host says no" from "we did not look". Conflating the two is how a linter starts asserting things it has not checked.
type Live ¶
type Live struct {
// Root is prefixed to every path read, which is what lets the same code
// serve both the live system (Root = "") and a captured directory.
Root string
// contains filtered or unexported fields
}
Live reads facts from the running system.
Everything here comes from files, never subprocesses. That is the spec's guidance, and it is also what makes a captured context replayable: a directory of files can be serialised and read back, whereas a subprocess cannot. It also means quaddoc works with no podman binary present.
func NewReplay ¶
NewReplay returns a context reading a previously captured directory. The findings it produces are identical to those from the machine it was captured on, which is the whole point: capture on the broken machine, lint anywhere.
func (*Live) ExistingUnitNames ¶
ExistingUnitNames lists units already installed in the Quadlet search path.
func (*Live) MountFor ¶
MountFor returns the filesystem a path is on: the mount whose mount point is the longest prefix of the path.
func (*Live) Rootless ¶
Rootless reports whether Podman would run rootless, which is simply whether the effective user is root.
func (*Live) SELinux ¶
func (l *Live) SELinux() SELinuxMode
SELinux reads the enforcement mode.
The file is absent on a kernel without SELinux, which is how "disabled" is distinguished from "permissive": permissive has policy loaded and the file present containing 0.
func (*Live) SubGIDRanges ¶
SubGIDRanges returns the calling user's subordinate GID allocations.
func (*Live) SubUIDRanges ¶
SubUIDRanges returns the calling user's subordinate UID allocations.
func (*Live) UnprivilegedPortStart ¶
UnprivilegedPortStart reads net.ipv4.ip_unprivileged_port_start from procfs rather than invoking sysctl, so there is no subprocess and the value can be captured.
type Mount ¶
type Mount struct {
// MountPoint is where the filesystem is mounted.
MountPoint string
// FSType is the filesystem type, e.g. `ext4`, `nfs4`, `fuse.sshfs`.
// QD003 decides from this, not from a path pattern.
FSType string
// Options are the mount options, which may include a `context=` setting
// that makes relabelling unnecessary or wrong.
Options string
}
Mount is one entry from the mount table.
type SELinuxMode ¶
type SELinuxMode int
SELinuxMode is the state of SELinux on a system.
const ( // SELinuxUnknown means no host context was gathered. SELinuxUnknown SELinuxMode = iota // SELinuxDisabled means SELinux is absent from the kernel. SELinuxDisabled // SELinuxPermissive means policy is loaded but violations are logged // rather than denied. SELinuxPermissive // SELinuxEnforcing means policy is loaded and enforced. SELinuxEnforcing )
func (SELinuxMode) String ¶
func (m SELinuxMode) String() string
type Static ¶
type Static struct {
SELinuxMode SELinuxMode
Mounts []Mount
SubUID []IDRange
SubGID []IDRange
PortStart int
PortStartKnown bool
UnitNames []string
UnitNamesKnown bool
IsRootless bool
RootlessKnown bool
}
Static is a Context with fixed answers, for tests and for replaying a captured context.
func (Static) ExistingUnitNames ¶
func (Static) MountFor ¶
MountFor returns the longest mount point that prefixes path, which is the filesystem the path is actually on. A shorter match like `/` would otherwise shadow the specific mount the caller cares about.
func (Static) SELinux ¶
func (s Static) SELinux() SELinuxMode
func (Static) SubGIDRanges ¶
func (Static) SubUIDRanges ¶
func (Static) UnprivilegedPortStart ¶
type Unknown ¶
type Unknown struct{}
Unknown is a Context that knows nothing. It is the default, so that the no-host-context path is the one exercised unless the user opts in.
func (Unknown) ExistingUnitNames ¶
func (Unknown) SELinux ¶
func (Unknown) SELinux() SELinuxMode