Skip to content

Commit

Permalink
Update to use SDK v0.0.15 (#34)
Browse files Browse the repository at this point in the history
* updated config handling for list

Signed-off-by: Eddie Knight <[email protected]>

* Added RaidPkg handler, commented out the Run() logic for this commit

Signed-off-by: Eddie Knight <[email protected]>

* fixed the busted list command

Signed-off-by: Eddie Knight <[email protected]>

fixed the busted list command for real this time

Signed-off-by: Eddie Knight <[email protected]>

* lets go update the raid handlers to use the new config structure, see what happens

Signed-off-by: Eddie Knight <[email protected]>

* Finalize new config handler logic

Signed-off-by: Eddie Knight <[email protected]>

* added loglevel flag to plugin args

Signed-off-by: Eddie Knight <[email protected]>

* cleanup

Signed-off-by: Eddie Knight <[email protected]>

Update cmd/list.go

cleanup

Signed-off-by: Eddie Knight <[email protected]>

cleanup

Signed-off-by: Eddie Knight <[email protected]>

fixed bad import

Signed-off-by: Eddie Knight <[email protected]>

finished debugging SDK

Signed-off-by: Eddie Knight <[email protected]>

* Updated to import from SDK v0.0.15

Signed-off-by: Eddie Knight <[email protected]>

---------

Signed-off-by: Eddie Knight <[email protected]>
  • Loading branch information
eddie-knight authored Nov 30, 2024
1 parent d0c14b2 commit 4833e6a
Show file tree
Hide file tree
Showing 12 changed files with 228 additions and 255 deletions.
1 change: 1 addition & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- [ ] Logger seems to be putting everything from plugins out as DEBUG from the core logger
8 changes: 2 additions & 6 deletions cmd/approved-raids.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ var (
// StartApprovedRaid will run a single raid after ensuring it is installed
// Approved raids are listed in run/approved-raids.go
func StartApprovedRaid(raidName string) (err error) {
configVar := make(map[string]interface{}, 1)
configVar[raidName] = make(map[string]interface{}, 1)
viper.Set("Raids", configVar)

err = installIfNotPresent(raidName)
if err != nil {
logger.Error(fmt.Sprintf(
Expand All @@ -51,9 +47,9 @@ func StartApprovedRaid(raidName string) (err error) {

func installIfNotPresent(raidName string) (err error) {
installed := false
raids := GetAvailableRaids()
raids := GetRaids()
for _, raid := range raids {
if raid == raidName {
if raid.Name == raidName {
installed = true
logger.Trace("Raid already installed.")
}
Expand Down
19 changes: 0 additions & 19 deletions cmd/errors.go

This file was deleted.

56 changes: 28 additions & 28 deletions cmd/generate-raid.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ import (
"strings"

"github.com/go-git/go-git/v5"
"github.com/labstack/gommon/log"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"gopkg.in/yaml.v2"
)

type ControlCatalog struct {
CategoryIDFriendly string
ServiceName string
Tactics map[string][]string

Metadata Metadata `yaml:"metadata"`
Metadata Metadata `yaml:"metadata"`

Controls []Control `yaml:"controls"`
Features []Feature `yaml:"features"`
Expand All @@ -30,10 +30,10 @@ type ControlCatalog struct {

// Metadata is a struct that represents the metadata.yaml file
type Metadata struct {
Title string `yaml:"title"`
ID string `yaml:"id"`
Description string `yaml:"description"`
ReleaseDetails []ReleaseDetails `yaml:"release_details"`
Title string `yaml:"title"`
ID string `yaml:"id"`
Description string `yaml:"description"`
ReleaseDetails []ReleaseDetails `yaml:"release_details"`
}

type ReleaseDetails struct {
Expand All @@ -48,10 +48,10 @@ type ReleaseDetails struct {
}

type ReleaseManager struct {
Name string `yaml:"name"`
GithubId string `yaml:"github_id"`
Company string `yaml:"company"`
Summary string `yaml:"summary"`
Name string `yaml:"name"`
GithubId string `yaml:"github_id"`
Company string `yaml:"company"`
Summary string `yaml:"summary"`
}

type Feature struct {
Expand All @@ -70,22 +70,22 @@ type Threat struct {

type Control struct {
IDFriendly string
ID string `yaml:"id"`
Title string `yaml:"title"`
Objective string `yaml:"objective"`
ControlFamily string `yaml:"control_family"`
Threats []string `yaml:"threats"`
NISTCSF string `yaml:"nist_csf"`
MITREATTACK string `yaml:"mitre_attack"`
ControlMappings map[string]interface{} `yaml:"control_mappings"`
TestRequirements []TestRequirement `yaml:"test_requirements"`
ID string `yaml:"id"`
Title string `yaml:"title"`
Objective string `yaml:"objective"`
ControlFamily string `yaml:"control_family"`
Threats []string `yaml:"threats"`
NISTCSF string `yaml:"nist_csf"`
MITREATTACK string `yaml:"mitre_attack"`
ControlMappings map[string]interface{} `yaml:"control_mappings"`
TestRequirements []TestRequirement `yaml:"test_requirements"`
}

type TestRequirement struct {
IDFriendly string
ID string `yaml:"id"`
Text string `yaml:"text"`
TLPLevels []string `yaml:"tlp_levels"`
IDFriendly string
ID string `yaml:"id"`
Text string `yaml:"text"`
TLPLevels []string `yaml:"tlp_levels"`
}

var TemplatesDir string
Expand Down Expand Up @@ -123,12 +123,12 @@ func generateRaid() {
}
data, err := readData()
if err != nil {
log.Error(err.Error())
logger.Error(err.Error())
return
}
data.ServiceName = viper.GetString("service-name")
if data.ServiceName == "" {
log.Error(fmt.Errorf("--service-name is required to generate a raid."))
logger.Error("--service-name is required to generate a raid.")
return
}

Expand Down Expand Up @@ -156,7 +156,7 @@ func generateRaid() {
func setupTemplatingEnvironment() error {
SourcePath = viper.GetString("source-path")
if SourcePath == "" {
return fmt.Errorf("--source-path is required to generate a raid from a control set from local file or URL.")
return fmt.Errorf("--source-path is required to generate a raid from a control set from local file or URL")
}

if viper.GetString("local-templates") != "" {
Expand Down Expand Up @@ -245,8 +245,8 @@ func readData() (data ControlCatalog, err error) {
// Add the test ID to the tactics map for each TLP level
for _, tlpLevel := range testReq.TLPLevels {
if data.Tactics[tlpLevel] == nil {
data.Tactics[tlpLevel] = []string{}
}
data.Tactics[tlpLevel] = []string{}
}
data.Tactics[tlpLevel] = append(data.Tactics[tlpLevel], strings.ReplaceAll(testReq.ID, ".", "_"))
}
}
Expand Down
100 changes: 49 additions & 51 deletions cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,29 +16,19 @@ var (
// listCmd represents the list command
var listCmd = &cobra.Command{
Use: cmdName,
Short: "Consult the Charts! List all raids that have been requested",
Short: "Consult the Charts! List all raids that have been installed.",
Run: func(cmd *cobra.Command, args []string) {
raids := SortAvailableAndRequested()
if len(raids) < 1 {
if viper.GetBool("available") {
fmt.Fprintln(writer, "No raids present in the binaries path:", viper.GetString("binaries-path"))
} else {
fmt.Fprintln(writer, "No raids requested in the current configuration.")
if viper.GetBool("all") {
fmt.Fprintln(writer, "| Raid \t | Available \t| Requested \t|")
for _, raidPkg := range GetRaids() {
fmt.Fprintf(writer, "| %s \t | %t \t| %t \t|\n", raidPkg.Name, raidPkg.Available, raidPkg.Requested)
}
} else {
if viper.GetBool("available") {
// list only the available raids
fmt.Fprintln(writer, "| Raid \t | Available \t|")
for raidName, raidStatus := range raids {
if raidStatus.Available {
fmt.Fprintf(writer, "| %s \t | %t \t|\n", raidName, raidStatus.Available)
}
}
} else {
// print all raids requested and available
fmt.Fprintln(writer, "| Raid \t | Available \t| Requested \t|")
for raidName, raidStatus := range raids {
fmt.Fprintf(writer, "| %s \t | %t \t| %t \t|\n", raidName, raidStatus.Available, raidStatus.Requested)
// list only the available raids
fmt.Fprintln(writer, "| Raid \t | Requested \t|")
for _, raidPkg := range GetRaids() {
if raidPkg.Available {
fmt.Fprintf(writer, "| %s \t | %t \t|\n", raidPkg.Name, raidPkg.Requested)
}
}
}
Expand All @@ -49,53 +39,61 @@ var listCmd = &cobra.Command{
func init() {
rootCmd.AddCommand(listCmd)

listCmd.PersistentFlags().BoolP("available", "a", false, "Review the fleet! List all raids that have been installed.")
viper.BindPFlag("available", listCmd.PersistentFlags().Lookup("available"))
listCmd.PersistentFlags().BoolP("all", "a", false, "Review the Fleet! List all raids that have been installed or requested in the current config.")
viper.BindPFlag("all", listCmd.PersistentFlags().Lookup("all"))
}

// GetRequestedRaids returns a list of raid names requested in the config
func GetRequestedRaids() (raids []string) {
if viper.Get("Raids") != nil {
raidsVars := viper.Get("Raids").(map[string]interface{})
for raidName := range raidsVars {
raids = append(raids, raidName)
func getRequestedRaids() (requestedRaidPackages []*RaidPkg) {
services := viper.GetStringMap("services")
for serviceName := range services {
raidName := viper.GetString("services." + serviceName + ".raid")
if raidName != "" && !Contains(requestedRaidPackages, raidName) {
raidPkg := NewRaidPkg(raidName, serviceName)
raidPkg.Requested = true
requestedRaidPackages = append(requestedRaidPackages, raidPkg)
}
}
return
return requestedRaidPackages
}

// GetAvailableRaids returns a list of raids found in the binaries path
func GetAvailableRaids() (raids []string) {
func getAvailableRaids() (availableRaidPackages []*RaidPkg) {
raidPaths, _ := hcplugin.Discover("*", viper.GetString("binaries-path"))
for _, raidPath := range raidPaths {
raids = append(raids, path.Base(raidPath))
raidPkg := NewRaidPkg(path.Base(raidPath), "")
raidPkg.Available = true
availableRaidPackages = append(availableRaidPackages, raidPkg)
}
return
return availableRaidPackages
}

type RaidStatus struct {
Available bool
Requested bool
}
var allRaids []*RaidPkg

func SortAvailableAndRequested() map[string]RaidStatus {
raids := make(map[string]RaidStatus)
requestedRaids := GetRequestedRaids()
availableRaids := GetAvailableRaids()
// loop through available raids, then requested raids to make sure available raids have requested status
for _, availableRaid := range availableRaids {
raids[availableRaid] = RaidStatus{Available: true, Requested: false}
for _, requestedRaid := range requestedRaids {
if requestedRaid == availableRaid {
raids[availableRaid] = RaidStatus{Available: true, Requested: true}
}
func GetRaids() []*RaidPkg {
if allRaids != nil {
return allRaids
}
output := make([]*RaidPkg, 0)
for _, raid := range getRequestedRaids() {
if Contains(getAvailableRaids(), raid.Name) {
raid.Available = true
}
output = append(output, raid)
}
// loop through requested raids to make sure all requested raids are represented
for _, requestedRaid := range requestedRaids {
if _, ok := raids[requestedRaid]; !ok {
raids[requestedRaid] = RaidStatus{Available: false, Requested: true}
for _, raid := range getAvailableRaids() {
if !Contains(output, raid.Name) {
output = append(output, raid)
}
}
return output
}

func Contains(slice []*RaidPkg, search string) bool {
for _, raid := range slice {
if raid.Name == search {
return true
}
}
return raids
return false
}
82 changes: 82 additions & 0 deletions cmd/objects.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package cmd

import (
"fmt"
"os/exec"
"path/filepath"
"runtime"
"strings"

hcplugin "github.com/hashicorp/go-plugin"
"github.com/spf13/viper"
)

// RaidError retains an error object and the name of the pack that generated it
type RaidError struct {
Raid string
Err error
}

// RaidErrors holds a list of errors and an Error() method
// so it adheres to the standard Error interface
type RaidErrors struct {
Errors []RaidError
}

func (e *RaidErrors) Error() string {
return fmt.Sprintf("Service Pack Errors: %v", e.Errors)
}

type RaidPkg struct {
Name string
Path string
ServiceTarget string
Command *exec.Cmd
Result string

Available bool
Requested bool
Error error
}

func (p *RaidPkg) getBinary() (binaryName string, err error) {
p.Name = filepath.Base(strings.ToLower(p.Name)) // in some cases a filepath may arrive here instead of the base name; overwrite if so
if runtime.GOOS == "windows" && !strings.HasSuffix(p.Name, ".exe") {
p.Name = fmt.Sprintf("%s.exe", p.Name)
}
plugins, _ := hcplugin.Discover(p.Name, viper.GetString("binaries-path"))
if len(plugins) != 1 {
err = fmt.Errorf("failed to locate requested plugin '%s' at path '%s'", p.Name, viper.GetString("binaries-path"))
return
}
binaryName = plugins[0]

return
}

func (p *RaidPkg) queueCmd() {
cmd := exec.Command(p.Path)
flags := []string{
fmt.Sprintf("--config=%s", viper.GetString("config")),
fmt.Sprintf("--loglevel=%s", viper.GetString("loglevel")),
fmt.Sprintf("--service=%s", p.ServiceTarget),
}
for _, flag := range flags {
cmd.Args = append(cmd.Args, flag)
p.Command = cmd
}
}

func NewRaidPkg(raidName string, serviceName string) *RaidPkg {
raid := &RaidPkg{
Name: raidName,
}
path, err := raid.getBinary()
if err != nil {
raid.Error = err
}
raid.Path = path
raid.ServiceTarget = serviceName
raid.queueCmd()
return raid
}
Loading

0 comments on commit 4833e6a

Please sign in to comment.