From 777f72d1bae76e2f2a6a33152dcd806cb7b034fc Mon Sep 17 00:00:00 2001 From: Doctor Vince Date: Fri, 22 Dec 2023 09:20:19 -0500 Subject: [PATCH] add Nahum's UEFI variable code --- actions/interface.go | 2 +- actions/inventory.go | 21 +++++++++----- utils/uefi_vars.go | 66 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 80 insertions(+), 9 deletions(-) diff --git a/actions/interface.go b/actions/interface.go index 31702831..0f373698 100644 --- a/actions/interface.go +++ b/actions/interface.go @@ -143,7 +143,7 @@ type FirmwareChecksumCollector interface { // UEFIVarsCollector defines an interface to collect EFI variables type UEFIVarsCollector interface { UtilAttributeGetter - UEFIVariables(ctx context.Context) (keyValues map[string]string, err error) + GetUEFIVars(ctx context.Context) (utils.UEFIVars, error) } // Updaters diff --git a/actions/inventory.go b/actions/inventory.go index 535a9777..fd72c7d7 100644 --- a/actions/inventory.go +++ b/actions/inventory.go @@ -3,6 +3,7 @@ package actions import ( "context" + "encoding/json" "runtime/debug" "strings" @@ -150,8 +151,7 @@ func NewInventoryCollectorAction(options ...Option) *InventoryCollectorAction { firmware.MakeOutputPath(), firmware.TraceExecution(a.trace), ), - // implement uefi vars collector and plug in here - // UEFIVarsCollector: , + UEFIVarsCollector: &utils.UEFIVariableCollector{}, } } @@ -738,20 +738,27 @@ func (a *InventoryCollectorAction) CollectUEFIVariables(ctx context.Context) err return nil } - keyValues, err := a.collectors.UEFIVariables(ctx) + keyValues, err := a.collectors.UEFIVarsCollector.GetUEFIVars(ctx) if err != nil { return err } - if len(keyValues) == 0 || a.device.BIOS == nil { + if len(keyValues) == 0 { + // seems unlikely return nil } - for k, v := range keyValues { - // do we want a prefix? - a.device.Metadata["EFI_VAR-"+k] = v + if a.device.BIOS == nil { + a.device.BIOS.Metadata = map[string]string{} + } + + jsonBytes, err := json.Marshal(keyValues) + if err != nil { + return errors.Wrap(err, "marshaling uefi variables") } + a.device.BIOS.Metadata["uefi-variables"] = string(jsonBytes) + return nil } diff --git a/utils/uefi_vars.go b/utils/uefi_vars.go index 6317166d..6d75e8b8 100644 --- a/utils/uefi_vars.go +++ b/utils/uefi_vars.go @@ -1,3 +1,67 @@ +//nolint:wsl // god it's useless package utils -// UEFIVarsCollector implementation goes here +import ( + "context" + "crypto/sha256" + "fmt" + "io/fs" + + //nolint:staticcheck // this is deprecated but I can't rewrite now + "io/ioutil" + "path/filepath" + + "github.com/metal-toolbox/ironlib/model" +) + +type UEFIVariableCollector struct{} + +func (UEFIVariableCollector) Attributes() (model.CollectorUtility, string, error) { + return "uefi-variable-collector", "", nil +} + +type UEFIVarEntry struct { + Path string `json:"path"` + Size int64 `json:"size"` + Sha256sum string `json:"sha256sum"` + Error bool `json:"error"` +} + +type UEFIVars map[string]UEFIVarEntry + +func (UEFIVariableCollector) GetUEFIVars(ctx context.Context) (UEFIVars, error) { + uefivars := make(map[string]UEFIVarEntry) + walkme := "/sys/firmware/efi/efivars" + err := filepath.Walk(walkme, func(path string, info fs.FileInfo, err error) error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + + entry := UEFIVarEntry{Path: path} + if err != nil { + // Capture all errors, even directories + entry.Error = true + uefivars[info.Name()] = entry + return nil // Keep walking + } + // No need to capture anything for directory entries without errors + if info.IsDir() { + return nil + } + entry.Size = info.Size() + b, err := ioutil.ReadFile(path) + if err != nil { + entry.Error = true + } else { + entry.Sha256sum = fmt.Sprintf("%x", sha256.Sum256(b)) + } + uefivars[info.Name()] = entry + return nil // Keep walking + }) + if err != nil { + return nil, err + } + return uefivars, nil +}