forked from linuxboot/contest
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(plugins/teststeps): add new hsi teststep
Signed-off-by: llogen <[email protected]>
- Loading branch information
Showing
4 changed files
with
203 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") | ||
// } | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |