Skip to content

Commit

Permalink
implemented risk and ratings explanation generation
Browse files Browse the repository at this point in the history
  • Loading branch information
joreiche committed Jun 17, 2024
1 parent 6ad6635 commit c9dd546
Show file tree
Hide file tree
Showing 71 changed files with 2,724 additions and 888 deletions.
46 changes: 31 additions & 15 deletions cmd/script/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package main
import (
"flag"
"fmt"
"os"
"path/filepath"

"github.com/threagile/threagile/pkg/risks/script"
"github.com/threagile/threagile/pkg/types"
"gopkg.in/yaml.v3"
"os"
"path/filepath"
"strings"
)

func main() {
Expand Down Expand Up @@ -53,28 +53,44 @@ func main() {
return
}

printedRisks, printError := yaml.Marshal(generatedRisks)
if printError != nil {
fmt.Printf("error printing risks for %q: %v\n", newRule.Category().ID, printError)
return
}
for n, risk := range generatedRisks {
riskExplanation := risk.RiskExplanation
ratingExplanation := risk.RatingExplanation
risk.RiskExplanation = nil
risk.RatingExplanation = nil

fmt.Printf("generated risks for %q: \n%v\n", newRule.Category().ID, string(printedRisks))
for _, riskLine := range riskExplanation {
fmt.Println(riskLine)
}
fmt.Println("")

for _, ratingLine := range ratingExplanation {
fmt.Println(ratingLine)
}
fmt.Println("")

for _, risk := range generatedRisks {
assets, assetsError := newRule.GetTechnicalAssetsByRiskID(parsedModel, risk.SyntheticId)
if assetsError != nil {
fmt.Printf("failed to get assets for risk %q: %v\n", risk.SyntheticId, assetsError)
printedRisks, printError := yaml.Marshal(risk)
if printError != nil {
fmt.Printf("error printing risk #%d for %q: %v\n", n+1, newRule.Category().ID, printError)
return
}

fmt.Printf("generated risk #%d for %q: \n%v\n", n+1, newRule.Category().ID, string(printedRisks))

assets := make([]*types.TechnicalAsset, 0)
for _, techAsset := range parsedModel.TechnicalAssets {
if strings.EqualFold(techAsset.Id, risk.MostRelevantTechnicalAssetId) {
assets = append(assets, techAsset)
}
}

if len(assets) > 0 {
fmt.Printf("found %d asset(s) for risk %q\n", len(assets), risk.SyntheticId)
fmt.Printf("found %d asset(s) for risk #%d %q\n", len(assets), n+1, risk.SyntheticId)
for _, asset := range assets {
fmt.Printf(" - %v\n", asset.Title)
}
} else {
fmt.Printf("no assets found for risk %q\n", risk.SyntheticId)
fmt.Printf("no assets found for risk #%d %q\n", n+1, risk.SyntheticId)
}
}
}
140 changes: 140 additions & 0 deletions pkg/risks/script/common/any-value.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package common

import (
"fmt"
"github.com/shopspring/decimal"
)

type AnyValue struct {
value any
name Path
event *Event
}

func (what AnyValue) Value() any {
return what.value
}

func (what AnyValue) Name() Path {
return what.name
}

func (what AnyValue) SetName(name ...string) {
what.name.SetPath(name...)
}

func (what AnyValue) Event() *Event {
return what.event
}

func (what AnyValue) PlainValue() any {
switch castValue := what.value.(type) {
case Value:
return castValue.PlainValue()
}

return what.value
}

func (what AnyValue) Text() []string {
switch castValue := what.value.(type) {
case []any:
text := make([]string, 0)
for _, item := range castValue {
text = append(text, fmt.Sprintf(" - %v", item))
}

return text

case map[string]any:
text := make([]string, 0)
for name, item := range castValue {
text = append(text, fmt.Sprintf(" %v: %v", name, item))
}

return text
}

return []string{fmt.Sprintf("%v", what.PlainValue())}
}

func NilValue() Value {
return &AnyValue{}
}

func SomeValue(anyValue any, event *Event) Value {
switch castValue := anyValue.(type) {
case string:
return SomeStringValue(castValue, event)

case bool:
return SomeBoolValue(castValue, event)

case decimal.Decimal:
return SomeDecimalValue(castValue, event)

case int:
return SomeDecimalValue(decimal.NewFromInt(int64(castValue)), event)

case int8:
return SomeDecimalValue(decimal.NewFromInt(int64(castValue)), event)

case int16:
return SomeDecimalValue(decimal.NewFromInt(int64(castValue)), event)

case int32:
return SomeDecimalValue(decimal.NewFromInt(int64(castValue)), event)

case int64:
return SomeDecimalValue(decimal.NewFromInt(castValue), event)

case float32:
return SomeDecimalValue(decimal.NewFromFloat32(castValue), event)

case float64:
return SomeDecimalValue(decimal.NewFromFloat(castValue), event)

case []Value:
return SomeArrayValue(castValue, event)

case []any:
array := make([]Value, 0)
for _, item := range castValue {
switch castItem := item.(type) {
case Value:
array = append(array, castItem)

default:
array = append(array, SomeValue(castItem, nil))
}
}

return SomeArrayValue(array, event)

case Value:
return castValue
}

return &AnyValue{
value: anyValue,
event: event,
}
}

func AddValueHistory(anyValue Value, history []*Event) Value {
if anyValue == nil {
if len(history) == 0 {
return nil
}

return SomeValue(nil, NewEvent(NewValueProperty(nil), EmptyPath()).AddHistory(history))
}

event := anyValue.Event()
if event == nil {
path := anyValue.Name()
event = NewEvent(NewValueProperty(anyValue), &path).AddHistory(history)
}

return SomeValue(anyValue.PlainValue(), event)
}
4 changes: 2 additions & 2 deletions pkg/risks/script/common/array-expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package common
type ArrayExpression interface {
ParseArray(script any) (ArrayExpression, any, error)
ParseAny(script any) (Expression, any, error)
EvalArray(scope *Scope) ([]any, string, error)
EvalAny(scope *Scope) (any, string, error)
EvalArray(scope *Scope) (*ArrayValue, string, error)
EvalAny(scope *Scope) (Value, string, error)
Literal() string
}
96 changes: 96 additions & 0 deletions pkg/risks/script/common/array-value.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package common

import (
"fmt"
)

type ArrayValue struct {
value []Value
name Path
event *Event
}

func (what ArrayValue) Value() any {
return what.value
}

func (what ArrayValue) Name() Path {
return what.name
}

func (what ArrayValue) SetName(name ...string) {
what.name.SetPath(name...)
}

func (what ArrayValue) Event() *Event {
return what.event
}

func (what ArrayValue) ArrayValue() []Value {
return what.value
}

func (what ArrayValue) PlainValue() any {
values := make([]any, 0)
for _, value := range what.value {
values = append(values, value.PlainValue())
}

return values
}

func (what ArrayValue) Text() []string {
text := make([]string, 0)
for _, item := range what.value {
itemText := item.Text()
switch len(itemText) {
case 0:

case 1:
text = append(text, " - "+itemText[0])

default:
text = append(text, " - ")

for _, line := range itemText {
text = append(text, " "+line)
}
}
}

return text
}

func EmptyArrayValue() *ArrayValue {
return &ArrayValue{}
}

func SomeArrayValue(value []Value, event *Event) *ArrayValue {
return &ArrayValue{
value: value,
event: event,
}
}

func ToArrayValue(value Value) (*ArrayValue, error) {
var arrayValue []Value
switch castValue := value.Value().(type) {
case []Value:
arrayValue = castValue

case []any:
arrayValue = make([]Value, 0)
for _, item := range castValue {
arrayValue = append(arrayValue, SomeValue(item, nil))
}

default:
return nil, fmt.Errorf("expected value-expression to eval to an array instead of %T", value.Value)
}

return &ArrayValue{
value: arrayValue,
name: value.Name(),
event: value.Event(),
}, nil
}
4 changes: 2 additions & 2 deletions pkg/risks/script/common/bool-expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package common
type BoolExpression interface {
ParseBool(script any) (BoolExpression, any, error)
ParseAny(script any) (Expression, any, error)
EvalBool(scope *Scope) (bool, string, error)
EvalAny(scope *Scope) (any, string, error)
EvalBool(scope *Scope) (*BoolValue, string, error)
EvalAny(scope *Scope) (Value, string, error)
Literal() string
}
65 changes: 65 additions & 0 deletions pkg/risks/script/common/bool-value.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package common

import (
"fmt"
)

type BoolValue struct {
value bool
name Path
event *Event
}

func (what BoolValue) Value() any {
return what.value
}

func (what BoolValue) Name() Path {
return what.name
}

func (what BoolValue) SetName(name ...string) {
what.name.SetPath(name...)
}

func (what BoolValue) Event() *Event {
return what.event
}

func (what BoolValue) PlainValue() any {
return what.value
}

func (what BoolValue) Text() []string {
return []string{fmt.Sprintf("%v", what.value)}
}

func (what BoolValue) BoolValue() bool {
return what.value
}

func EmptyBoolValue() *BoolValue {
return &BoolValue{}
}

func SomeBoolValue(value bool, event *Event) *BoolValue {
return &BoolValue{
value: value,
event: event,
}
}

func ToBoolValue(value Value) (*BoolValue, error) {
castValue, ok := value.Value().(bool)

var conversionError error
if !ok {
conversionError = fmt.Errorf("expected value-expression to eval to a bool instead of %T", value.Value)
}

return &BoolValue{
value: castValue,
name: value.Name(),
event: value.Event(),
}, conversionError
}
Loading

0 comments on commit c9dd546

Please sign in to comment.