Release catalyst

This commit is contained in:
Jonas Plum
2021-12-13 00:39:15 +01:00
commit 15cf0ebd49
339 changed files with 111677 additions and 0 deletions

182
database/playbookutils.go Normal file
View File

@@ -0,0 +1,182 @@
package database
import (
"errors"
"fmt"
"log"
"sort"
"github.com/SecurityBrewery/catalyst/caql"
"github.com/SecurityBrewery/catalyst/dag"
"github.com/SecurityBrewery/catalyst/generated/models"
)
func playbookGraph(playbook *models.Playbook) (*dag.Graph, error) {
d := dag.NewGraph()
var taskIDs []string
for taskID := range playbook.Tasks {
taskIDs = append(taskIDs, taskID)
}
sort.Strings(taskIDs)
for _, taskID := range taskIDs {
if err := d.AddNode(taskID); err != nil {
return nil, errors.New("could not add node")
}
}
for _, taskID := range taskIDs {
task := playbook.Tasks[taskID]
for next := range task.Next {
if err := d.AddEdge(taskID, next); err != nil {
return nil, errors.New("could not add edge")
}
}
}
return d, nil
}
func toTaskResponse(playbook *models.Playbook, taskID string, order int, graph *dag.Graph) (*models.TaskResponse, error) {
task, ok := playbook.Tasks[taskID]
if !ok {
return nil, fmt.Errorf("task %s not found", taskID)
}
tr := &models.TaskResponse{
Automation: task.Automation,
Closed: task.Closed,
Created: task.Created,
Data: task.Data,
Done: task.Done,
Join: task.Join,
Payload: task.Payload,
Name: task.Name,
Next: task.Next,
Owner: task.Owner,
Schema: task.Schema,
Type: task.Type,
// Active: active,
// Order: v.Order,
}
tr.Order = int64(order)
taskActive, _ := active(playbook, taskID, graph, task)
tr.Active = taskActive
return tr, nil
}
func activePlaybook(playbook *models.Playbook, taskID string) (bool, error) {
task, ok := playbook.Tasks[taskID]
if !ok {
return false, fmt.Errorf("playbook does not contain tasks %s", taskID)
}
d, err := playbookGraph(playbook)
if err != nil {
return false, err
}
return active(playbook, taskID, d, task)
}
func active(playbook *models.Playbook, taskID string, d *dag.Graph, task *models.Task) (bool, error) {
if task.Done {
return false, nil
}
parents := d.GetParents(taskID)
if len(parents) == 0 {
return true, nil // valid(&task)
}
if task.Join != nil && *task.Join {
for _, parent := range parents {
parentTask := playbook.Tasks[parent]
if !parentTask.Done {
return false, nil
}
requirement := parentTask.Next[taskID]
b, err := evalRequirement(requirement, parentTask.Data)
if err != nil {
return false, err
}
if !b {
return false, nil
}
}
return true, nil
}
for _, parent := range parents {
parentTask := playbook.Tasks[parent]
if !parentTask.Done {
// return false, nil
continue
}
requirement := parentTask.Next[taskID]
b, err := evalRequirement(requirement, parentTask.Data)
if err != nil {
continue
}
if b {
return true, nil
}
}
return false, nil
}
func evalRequirement(aql string, data interface{}) (bool, error) {
if aql == "" {
return true, nil
}
parser := caql.Parser{}
tree, err := parser.Parse(aql)
if err != nil {
return false, err
}
var dataMap map[string]interface{}
if data != nil {
if dataMapX, ok := data.(map[string]interface{}); ok {
dataMap = dataMapX
} else {
log.Println("wrong data type for task data")
}
}
v, err := tree.Eval(dataMap)
if err != nil {
return false, err
}
if b, ok := v.(bool); ok {
return b, nil
}
return false, err
}
/*
// "github.com/qri-io/jsonschema"
func valid(task *models.Task) (bool, error) {
schema, err := json.Marshal(task.Schema)
if err != nil {
return false, err
}
rs := &jsonschema.Schema{}
if err := json.Unmarshal(schema, rs); err != nil {
return false, err
}
state := rs.Validate(context.Background(), task.Data)
return len(*state.Errs) > 0, nil
}
*/