Skip to content

Commit

Permalink
feat(plugins/teststeps): add new hsi teststep
Browse files Browse the repository at this point in the history
Signed-off-by: llogen <[email protected]>
  • Loading branch information
llogen committed Oct 16, 2024
1 parent d11dde7 commit fb930ba
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 0 deletions.
2 changes: 2 additions & 0 deletions cmds/contest/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import (
firmware_version "github.com/linuxboot/contest/plugins/teststeps/fw_version"
fwhunt "github.com/linuxboot/contest/plugins/teststeps/fwhunt"
fwts "github.com/linuxboot/contest/plugins/teststeps/fwts"
hsi "github.com/linuxboot/contest/plugins/teststeps/hsi"
hwaas "github.com/linuxboot/contest/plugins/teststeps/hwaas"
ping "github.com/linuxboot/contest/plugins/teststeps/ping"
qemu "github.com/linuxboot/contest/plugins/teststeps/qemu"
Expand Down Expand Up @@ -142,6 +143,7 @@ func GetPluginConfig() *PluginConfig {
pc.TestStepLoaders = append(pc.TestStepLoaders, fwhunt.Load)
pc.TestStepLoaders = append(pc.TestStepLoaders, fwts.Load)
pc.TestStepLoaders = append(pc.TestStepLoaders, firmware_version.Load)
pc.TestStepLoaders = append(pc.TestStepLoaders, hsi.Load)
pc.TestStepLoaders = append(pc.TestStepLoaders, hwaas.Load)
pc.ReporterLoaders = append(pc.ReporterLoaders, noop.Load)
pc.TestStepLoaders = append(pc.TestStepLoaders, ping.Load)
Expand Down
74 changes: 74 additions & 0 deletions plugins/teststeps/hsi/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package hsi

import (
"encoding/json"
"fmt"
"time"

"github.com/linuxboot/contest/pkg/event"
"github.com/linuxboot/contest/pkg/event/testevent"
"github.com/linuxboot/contest/pkg/events"
"github.com/linuxboot/contest/pkg/test"
"github.com/linuxboot/contest/pkg/xcontext"
"github.com/linuxboot/contest/plugins/teststeps"
)

// Name is the name used to look this plugin up.
var Name = "HSI"

const (
parametersKeyword = "parameters"
)

const (
defaultTimeout time.Duration = time.Minute
)

type parameters struct {
Level int `json:"security_level"`
}

// TestStep implementation for this teststep plugin
type TestStep struct {
parameters
}

// Run executes the step.
func (ts *TestStep) Run(ctx xcontext.Context, ch test.TestStepChannels, params test.TestStepParameters, ev testevent.Emitter, resumeState json.RawMessage) (json.RawMessage, error) {
tr := NewTargetRunner(ts, ev)
return teststeps.ForEachTarget(Name, ctx, ch, tr.Run)
}

func (ts *TestStep) populateParams(stepParams test.TestStepParameters) error {
var parameters *test.Param

if parameters = stepParams.GetOne(parametersKeyword); parameters.IsEmpty() {
return fmt.Errorf("parameters cannot be empty")
}

if err := json.Unmarshal(parameters.JSON(), &ts.parameters); err != nil {
return fmt.Errorf("failed to deserialize parameters: %v", err)
}

return nil
}

// ValidateParameters validates the parameters associated to the TestStep
func (ts *TestStep) ValidateParameters(ctx xcontext.Context, params test.TestStepParameters) error {
return ts.populateParams(params)
}

// New initializes and returns a new SSHCmd test step.
func New() test.TestStep {
return &TestStep{}
}

// Load returns the name, factory and events which are needed to register the step.
func Load() (string, test.TestStepFactory, []event.Name) {
return Name, New, events.Events
}

// Name returns the name of the Step
func (ts TestStep) Name() string {
return Name
}
25 changes: 25 additions & 0 deletions plugins/teststeps/hsi/output.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package hsi

import (
"fmt"
"strings"
)

// Function to format teststep information and append it to a string builder.
func (ts TestStep) writeTestStep(builders ...*strings.Builder) {
for _, builder := range builders {
builder.WriteString("Input Parameter:\n")
builder.WriteString(" Parameter:\n")
builder.WriteString(fmt.Sprintf(" HSI Security Level: %d\n", ts.Level))
builder.WriteString("\n")
builder.WriteString("\n")
}
}

// // Function to format command information and append it to a string builder.
// func writeCommand(addr string, builders ...*strings.Builder) {
// for _, builder := range builders {
// builder.WriteString(fmt.Sprintf("Running Ping on %s\n", addr))
// builder.WriteString("\n")
// }
// }
102 changes: 102 additions & 0 deletions plugins/teststeps/hsi/runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package hsi

import (
"encoding/json"
"fmt"
"log"
"os/exec"
"strings"
"time"

"github.com/insomniacslk/xjson"
"github.com/linuxboot/contest/pkg/event/testevent"
"github.com/linuxboot/contest/pkg/events"
"github.com/linuxboot/contest/pkg/target"
"github.com/linuxboot/contest/pkg/xcontext"
)

type TargetRunner struct {
ts *TestStep
ev testevent.Emitter
}

type Error struct {
Msg string `json:"error"`
}

func NewTargetRunner(ts *TestStep, ev testevent.Emitter) *TargetRunner {
return &TargetRunner{
ts: ts,
ev: ev,
}
}

func (r *TargetRunner) Run(ctx xcontext.Context, target *target.Target) error {
var outputBuf strings.Builder

ctx, cancel := xcontext.WithTimeout(ctx, time.Duration(xjson.Duration(defaultTimeout)))
defer cancel()

r.ts.writeTestStep(&outputBuf)

// for any ambiguity, outcome is an error interface, but it encodes whether the process
// was launched sucessfully and it resulted in a failure; err means the launch failed
if err := r.runHSI(&outputBuf); err != nil {
return events.EmitError(ctx, outputBuf.String(), target, r.ev, err)
}

return events.EmitLog(ctx, outputBuf.String(), target, r.ev)
}

type FwupdSecurity struct {
SecurityAttributes []SecurityInfo `json:"SecurityAttributes"`
SecurityEvents []SecurityInfo `json:"SecurityEvents"`
}

type SecurityInfo struct {
AppstreamId string `json:"AppstreamId"`
Created int64 `json:"Created"`
HsiLevel int `json:"HsiLevel"`
HsiResult string `json:"HsiResult"`
HsiResultSuccess string `json:"HsiResultSuccess"`
Name string `json:"Name"`
Summary string `json:"Summary"`
Description string `json:"Description"`
Plugin string `json:"Plugin"`
Uri string `json:"Uri"`
Flags []string `json:"Flags"`
Guid []string `json:"Guid,omitempty"`
BiosSettingId string `json:"BiosSettingId,omitempty"`
BiosSettingCurrent string `json:"BiosSettingCurrentValue,omitempty"`
BiosSettingTarget string `json:"BiosSettingTargetValue,omitempty"`
}

func (r *TargetRunner) runHSI(_ *strings.Builder) error {
// writeCommand(fmt.Sprintf("'%s:%d'", r.ts.Host, r.ts.Port), outputBuf)

cmd := exec.Command("fwupdmgr", "security", "--json")
output, err := cmd.CombinedOutput()
if err != nil {
fmt.Printf("Error running command: %v\n", err)

return err
}

var hsiData FwupdSecurity

if err := json.Unmarshal(output, &hsiData); err != nil {
log.Fatalf("Error unmarshalling JSON: %v", err)
}

for _, attr := range hsiData.SecurityAttributes {
fmt.Printf("Name: %s\nSummary: %s\nResult: %s\nFlags: %v\n\n",
attr.Name, attr.Summary, attr.HsiResult, attr.Flags)
}

for _, event := range hsiData.SecurityEvents {
fmt.Printf("Name: %s\nSummary: %s\nResult: %s\nFlags: %v\n\n",
event.Name, event.Summary, event.HsiResult, event.Flags)
}

return nil
}

0 comments on commit fb930ba

Please sign in to comment.