slice 8C Phase A: agent disk endpoints + data-bearing classifier gate + mkfs (v0.12.0)
internal/storage: mkfs executor (Format, device-pinned, narrow FELHOM_FORMAT sudoers) + data-bearing device inspection (InspectDevice/DeviceProbe via blkid+lsblk; conservative — ambiguous=data-bearing). internal/localapi: /disks (+ data-bearing flag), /disks/assign (EnsureMount), /disks/eject (Unmount + dependent guests), /disks/format. SECURITY CENTERPIECE: the agent inspects the device itself; data-bearing format -> ClassStorageWipe gate -> pending_signature refused; the caller's claim is never trusted. Additive (no controller change yet). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -25,6 +25,16 @@ var (
|
||||
// smartctl is run against. Anything else is refused.
|
||||
reSMARTDevice = regexp.MustCompile(`^/dev/(sd[a-z]+|nvme[0-9]+n[0-9]+|hd[a-z]+|vd[a-z]+)$`)
|
||||
|
||||
// Block device for inspection / mkfs: a raw disk OR a partition under /dev. Like the SMART
|
||||
// whitelist but also allows the trailing partition number (sda1, nvme0n1p2, vdb3). No
|
||||
// by-* symlinks, no device-mapper, no traversal. This is the mkfs/inspect target — it is
|
||||
// validated AND the agent device-inspects it before any destructive decision (8C).
|
||||
reBlockDevice = regexp.MustCompile(`^/dev/(sd[a-z]+[0-9]*|nvme[0-9]+n[0-9]+(p[0-9]+)?|hd[a-z]+[0-9]*|vd[a-z]+[0-9]*)$`)
|
||||
|
||||
// Filesystem types the agent will mkfs. Deliberately tiny — the sudoers mkfs entries are
|
||||
// per-fstype binaries (mkfs.ext4 / mkfs.xfs), so this set MUST match those entries.
|
||||
reFSType = regexp.MustCompile(`^(ext4|xfs)$`)
|
||||
|
||||
// LVM VG / pool names: LVM permits [A-Za-z0-9._+-]; we forbid leading '-' (would look
|
||||
// like a flag) and cap the length.
|
||||
reLVMName = regexp.MustCompile(`^[A-Za-z0-9_+.][A-Za-z0-9_+.-]*$`)
|
||||
@@ -106,6 +116,25 @@ func ValidateSMARTDevice(device string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateBlockDevice accepts only a raw disk or partition path under /dev (the mkfs / inspect
|
||||
// target). The same strict-whitelist discipline as ValidateSMARTDevice: no symlinks, no
|
||||
// device-mapper, no traversal — refused before any command is built.
|
||||
func ValidateBlockDevice(device string) error {
|
||||
if !reBlockDevice.MatchString(device) {
|
||||
return fmt.Errorf("storage: refusing to operate on non-whitelisted block device %q", device)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateFSType accepts only a filesystem type the agent is configured to mkfs (ext4|xfs). The
|
||||
// set MUST match the per-fstype sudoers entries.
|
||||
func ValidateFSType(fstype string) error {
|
||||
if !reFSType.MatchString(fstype) {
|
||||
return fmt.Errorf("storage: unsupported filesystem type %q (want ext4|xfs)", fstype)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateLVMName accepts an LVM VG or LV (pool) name.
|
||||
func ValidateLVMName(name string) error {
|
||||
if name == "" {
|
||||
|
||||
Reference in New Issue
Block a user