Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for lists of tactics #4

Merged
merged 2 commits into from
Oct 18, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 63 additions & 10 deletions raidengine/raidengine.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,28 @@ import (
"time"

"github.com/hashicorp/go-hclog"
"github.com/spf13/viper"

"github.com/privateerproj/privateer-sdk/utils"
)

// StrikeResult is a struct that contains the results of a test
// MovementResult is a struct that contains the results of a single step within a strike
type MovementResult struct {
Passed bool // Passed is true if the test passed
Description string // Description is a human-readable description of the test
Message string // Message is a human-readable description of the test result
Function string // Function is the name of the code that was executed
Value interface{} // Value is the object that was returned during the movement
}

// StrikeResult is a struct that contains the results of a check for a single control
type StrikeResult struct {
Passed bool // Passed is true if the test passed
Description string // Description is a human-readable description of the test
Message string // Message is a human-readable description of the test result
DocsURL string // DocsURL is a link to the documentation for the test
ControlID string // ControlID is the ID of the control that the test is validating
Passed bool // Passed is true if the test passed
Description string // Description is a human-readable description of the test
Message string // Message is a human-readable description of the test result
DocsURL string // DocsURL is a link to the documentation for the test
ControlID string // ControlID is the ID of the control that the test is validating
Movements map[string]MovementResult // Movements is a list of functions that were executed during the test
}

// RaidResults is a struct that contains the results of all strikes, orgainzed by name
Expand All @@ -33,7 +44,13 @@ type RaidResults struct {
EndTime string // EndTime is the time the raid ended
StrikeResults map[string]StrikeResult // StrikeResults is a map of strike names to their results
}

type Strikes interface {
SetLogger(loggerName string)
}

type Strike func() (strikeName string, result StrikeResult)

type cleanupFunc func() error

var logger hclog.Logger
Expand All @@ -45,16 +62,52 @@ var cleanup = func() error {
return nil
}

// Run is used to execute a list of strikes provided by a Raid and customize by user config
func Run(raidName string, strikes []Strike) error {
logger = GetLogger(raidName, false)
func Run(raidName string, availableStrikes map[string][]Strike, strikes Strikes) (err error) {
tacticsMultiple := fmt.Sprintf("raids.%s.tactics", raidName)
tacticSingular := fmt.Sprintf("raids.%s.tactic", raidName)
if viper.IsSet(tacticsMultiple) {
tactics := viper.GetStringSlice(tacticsMultiple)
for _, tactic := range tactics {
viper.Set(tacticSingular, tactic)
loggerName := fmt.Sprintf("%s-%s", raidName, tactic)
strikes.SetLogger(loggerName)
newErr := RunRaid(loggerName, getStrikes(raidName, availableStrikes))
if newErr != nil {
if err != nil {
err = fmt.Errorf("%s\n%s", err.Error(), newErr.Error())
} else {
err = newErr
}
}
}
return err
}
loggerName := fmt.Sprintf("%s-%s", raidName, viper.GetString(tacticSingular))
strikes.SetLogger(loggerName)
return RunRaid(loggerName, getStrikes(raidName, availableStrikes)) // Return errors from strike executions
}

// GetStrikes returns a list of probe objects
func getStrikes(raidName string, availableStrikes map[string][]Strike) []Strike {
tactic := viper.GetString(fmt.Sprintf("raids.%s.tactic", raidName))
strikes := availableStrikes[tactic]
if len(strikes) == 0 {
message := fmt.Sprintf("No strikes were found for the provided strike set: %s", tactic)
logger.Error(message)
}
return strikes
}

// RunRaid is used to execute a list of strikes provided by a Raid and customize by user config
func RunRaid(name string, strikes []Strike) error {
logger = GetLogger(name, false)
closeHandler()

var attempts int
var failures int

raidResults := &RaidResults{
RaidName: raidName,
RaidName: name,
StartTime: time.Now().String(),
}

Expand Down