Skip to content

Commit

Permalink
actions/inventory: define interfaces for collecting firmware checksum…
Browse files Browse the repository at this point in the history
…s and efi vars

Wire in collectors
  • Loading branch information
joelrebel committed Dec 21, 2023
1 parent 5625ee8 commit f7f1f13
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 1 deletion.
14 changes: 14 additions & 0 deletions actions/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,20 @@ type TPMCollector interface {
TPMs(ctx context.Context) ([]*common.TPM, error)
}

// Checksum collectors

// FirmwareChecksumCollector defines an interface to collect firmware checksums
type FirmwareChecksumCollector interface {
UtilAttributeGetter
BIOSLogoChecksum(ctx context.Context) (sha256 [32]byte, err error)
}

// UEFIVarsCollector defines an interface to collect EFI variables
type UEFIVarsCollector interface {
UtilAttributeGetter
UEFIVariables(ctx context.Context) (keyValues map[string]string, err error)
}

// Updaters

// DriveUpdater defines an interface to update drive firmware
Expand Down
98 changes: 97 additions & 1 deletion actions/inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package actions

import (
"context"
"fmt"
"runtime/debug"
"strings"

Expand All @@ -11,6 +12,7 @@ import (
"github.com/r3labs/diff/v2"
"golang.org/x/exp/slices"

"github.com/metal-toolbox/ironlib/firmware"
"github.com/metal-toolbox/ironlib/model"
"github.com/metal-toolbox/ironlib/utils"
)
Expand Down Expand Up @@ -53,6 +55,8 @@ type Collectors struct {
CPLDCollector
BIOSCollector
TPMCollector
FirmwareChecksumCollector
UEFIVarsCollector
StorageControllerCollectors []StorageControllerCollector
DriveCollectors []DriveCollector
DriveCapabilitiesCollectors []DriveCapabilityCollector
Expand All @@ -68,7 +72,9 @@ func (c *Collectors) Empty() bool {
c.TPMCollector == nil &&
len(c.StorageControllerCollectors) == 0 &&
len(c.DriveCollectors) == 0 &&
len(c.DriveCapabilitiesCollectors) == 0 {
len(c.DriveCapabilitiesCollectors) == 0 &&
c.UEFIVarsCollector == nil &&
c.FirmwareChecksumCollector == nil {
return true
}

Expand Down Expand Up @@ -139,6 +145,9 @@ func NewInventoryCollectorAction(options ...Option) *InventoryCollectorAction {
utils.NewHdparmCmd(a.trace),
utils.NewNvmeCmd(a.trace),
},
FirmwareChecksumCollector: firmware.NewChecksumCollector(a.trace),
// implement uefi vars collector and plug in here
// UEFIVarsCollector: ,
}
}

Expand Down Expand Up @@ -226,6 +235,18 @@ func (a *InventoryCollectorAction) Collect(ctx context.Context, device *common.D
return errors.Wrap(err, "error retrieving TPM inventory")
}

// Collect Firmware checksums
err = a.CollectFirmwareChecksums(ctx)
if err != nil && a.failOnError {
return errors.Wrap(err, "error retrieving Firmware checksums")
}

// Collect UEFI variables
err = a.CollectUEFIVariables(ctx)
if err != nil && a.failOnError {
return errors.Wrap(err, "error retrieving UEFI variables")
}

// Update StorageControllerCollectors based on controller vendor attributes
if a.dynamicCollection {
for _, sc := range a.device.StorageControllers {
Expand Down Expand Up @@ -650,6 +671,81 @@ func (a *InventoryCollectorAction) CollectTPMs(ctx context.Context) error {
return nil
}

// CollectFirmwareChecksums executes the Firmware checksum collector and updates the component metadata.
func (a *InventoryCollectorAction) CollectFirmwareChecksums(ctx context.Context) error {
// nolint:errcheck // deferred method catches a panic, error check not required.
defer func() error {
if r := recover(); r != nil && a.failOnError {
return errors.Wrap(ErrPanic, string(debug.Stack()))
}

return nil
}()

if a.collectors.FirmwareChecksumCollector == nil {
return nil
}

// skip collector if its been disabled
collectorKind, _, _ := a.collectors.FirmwareChecksumCollector.Attributes()
if slices.Contains(a.disabledCollectorUtilities, collectorKind) {
return nil
}

sum, err := a.collectors.BIOSLogoChecksum(ctx)
if err != nil {
return err
}

if len(sum) == 0 || a.device.BIOS == nil {
return nil
}

// not sure if this is the ideal way to cover the byte array
// maybe the interface method should return a checksum string instead?
a.device.BIOS.Metadata["bios-checksum"] = fmt.Sprintf("%s", sum)

return nil
}

// CollectUEFIVariables executes the UEFI variable collector and stores them on the device object
func (a *InventoryCollectorAction) CollectUEFIVariables(ctx context.Context) error {
// nolint:errcheck // deferred method catches a panic, error check not required.
defer func() error {
if r := recover(); r != nil && a.failOnError {
return errors.Wrap(ErrPanic, string(debug.Stack()))
}

return nil
}()

if a.collectors.UEFIVarsCollector == nil {
return nil
}

// skip collector if its been disabled
collectorKind, _, _ := a.collectors.UEFIVarsCollector.Attributes()
if slices.Contains(a.disabledCollectorUtilities, collectorKind) {
return nil
}

keyValues, err := a.collectors.UEFIVariables(ctx)
if err != nil {
return err
}

if len(keyValues) == 0 || a.device.BIOS == nil {
return nil
}

for k, v := range keyValues {
// do we want a prefix?
a.device.Metadata["EFI_VAR-"+k] = v
}

return nil
}

// CollectStorageControllers executes the StorageControllers collectors and updates device storage controller data
//
// nolint:gocyclo // this is fine for now
Expand Down

0 comments on commit f7f1f13

Please sign in to comment.