refactor: modularize audit and harden build validation
This commit is contained in:
@@ -1,14 +1,82 @@
|
||||
package platform
|
||||
|
||||
import "context"
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// tpmDeviceGlob is a seam for tests. It reports the sysfs TPM device nodes
|
||||
// the kernel has registered; an empty result means the platform exposes no
|
||||
// TPM at all (no discrete chip, or firmware/BIOS has it disabled).
|
||||
var tpmDeviceGlob = func() []string {
|
||||
matches, _ := filepath.Glob("/sys/class/tpm/tpm*")
|
||||
return matches
|
||||
}
|
||||
|
||||
var tpmReadFile = os.ReadFile
|
||||
|
||||
// TPMPresent reports whether sysfs identifies a registered device as TPM 2.x.
|
||||
// The validation pack uses tpm2-tools, so a TPM 1.2 device is not sufficient.
|
||||
func (s *System) TPMPresent() bool {
|
||||
for _, device := range tpmDeviceGlob() {
|
||||
version, err := tpmReadFile(filepath.Join(device, "tpm_version_major"))
|
||||
if err == nil && strings.TrimSpace(string(version)) == "2" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// RunTPMValidationPack verifies TPM 2.0 communication using read-only
|
||||
// commands. It deliberately excludes SelfTest, provisioning, NV writes, PCR
|
||||
// changes, key creation, and ownership operations.
|
||||
//
|
||||
// When the platform exposes no TPM device at all, the pack does not run the
|
||||
// tpm2_* tools: without a TCTI device they only ever emit a wall of
|
||||
// "Failed to open ... /dev/tpmrm0" errors that read as a hard failure when
|
||||
// the real situation is "this machine has no TPM". Instead it writes an
|
||||
// UNSUPPORTED summary and returns, the same way the storage pack handles a
|
||||
// host with no drives.
|
||||
func (s *System) RunTPMValidationPack(ctx context.Context, baseDir string, logFunc func(string)) (string, error) {
|
||||
if !s.TPMPresent() {
|
||||
return writeTPMUnsupportedRun(baseDir, logFunc)
|
||||
}
|
||||
return runAcceptancePackCtx(ctx, baseDir, "tpm", tpmValidationJobs(), logFunc)
|
||||
}
|
||||
|
||||
func writeTPMUnsupportedRun(baseDir string, logFunc func(string)) (string, error) {
|
||||
if strings.TrimSpace(baseDir) == "" {
|
||||
baseDir = "/var/log/bee-sat"
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
runDir := filepath.Join(baseDir, "tpm-"+now.Format("20060102-150405"))
|
||||
if err := os.MkdirAll(runDir, 0755); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if logFunc != nil {
|
||||
logFunc("no TPM 2.x device reported by sysfs; skipping read-only TPM checks")
|
||||
}
|
||||
|
||||
var summary strings.Builder
|
||||
fmt.Fprintf(&summary, "run_at_utc=%s\n", now.Format(time.RFC3339))
|
||||
summary.WriteString("tpm_present=false\n")
|
||||
summary.WriteString("skip_reason=no TPM 2.x device reported by sysfs; tpm2-tools are not applicable\n")
|
||||
summary.WriteString("tpm_check_status=UNSUPPORTED\n")
|
||||
summary.WriteString("overall_status=UNSUPPORTED\n")
|
||||
summary.WriteString("job_ok=0\n")
|
||||
summary.WriteString("job_failed=0\n")
|
||||
summary.WriteString("job_unsupported=1\n")
|
||||
summary.WriteString("job_informational_failed=0\n")
|
||||
if err := os.WriteFile(filepath.Join(runDir, "summary.txt"), []byte(summary.String()), 0644); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return runDir, nil
|
||||
}
|
||||
|
||||
func tpmValidationJobs() []satJob {
|
||||
return []satJob{
|
||||
{name: "01-properties-fixed.log", cmd: []string{"tpm2_getcap", "properties-fixed"}},
|
||||
|
||||
Reference in New Issue
Block a user