Skip to content

Commit

Permalink
Merge pull request #22 from octarinesec/revert-v1233
Browse files Browse the repository at this point in the history
Revert "overhaul of return values"
  • Loading branch information
rosti authored Jun 21, 2024
2 parents 8ccbf60 + fa3de65 commit 892f127
Show file tree
Hide file tree
Showing 26 changed files with 342 additions and 1,328 deletions.
151 changes: 58 additions & 93 deletions MAPL_engine/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ var DecisionNames = [...]string{
NONE: "none",
}

func Check(message *MessageAttributes, rules *Rules) (decision int, descisionString string, relevantRuleIndex int, results []int, appliedRulesIndices []int, ruleDescription string, checkExtraData []*map[string][]interface{}) {
func Check(message *MessageAttributes, rules *Rules) (decision int, descisionString string, relevantRuleIndex int, results []int, appliedRulesIndices []int, ruleDescription string, checkExtraData [][]map[string]interface{}) {
//
// for each message we check its attributes against all of the rules and return a decision
//
Expand All @@ -40,18 +40,14 @@ func Check(message *MessageAttributes, rules *Rules) (decision int, descisionStr

results = make([]int, N)
ruleDescriptions := make([]string, N)
// checkExtraData = make([][]map[string]interface{}, N)
checkExtraData = make([]*map[string][]interface{}, N)
checkExtraData = make([][]map[string]interface{}, N)

sem := make(chan int, N) // semaphore pattern
if false { // check in parallel

for i, rule := range rules.Rules { // check all the rules in parallel
go func(in_i int, in_rule Rule) {
returnedValues := make(map[string][]interface{})
returnedValuesPointer := &returnedValues
results[in_i], returnedValuesPointer = CheckOneRule(message, &in_rule)
checkExtraData[in_i] = returnedValuesPointer
results[in_i], checkExtraData[in_i] = CheckOneRule(message, &in_rule)
if desc, ok := in_rule.Metadata["description"]; ok {
ruleDescriptions[in_i] = desc
} else {
Expand All @@ -70,9 +66,7 @@ func Check(message *MessageAttributes, rules *Rules) (decision int, descisionStr
} else { // used only for debugging

for in_i, in_rule := range rules.Rules {
result, returnedValuesPointer := CheckOneRule(message, &in_rule)
results[in_i] = result
checkExtraData[in_i] = returnedValuesPointer
results[in_i], checkExtraData[in_i] = CheckOneRule(message, &in_rule)
if desc, ok := in_rule.Metadata["description"]; ok {
ruleDescriptions[in_i] = desc
} else {
Expand Down Expand Up @@ -104,7 +98,7 @@ func Check(message *MessageAttributes, rules *Rules) (decision int, descisionStr
}

// CheckOneRules gives the result of testing the message attributes with of one rule
func CheckOneRule(message *MessageAttributes, ruleOriginal *Rule) (int, *map[string][]interface{}) {
func CheckOneRule(message *MessageAttributes, ruleOriginal *Rule) (int, []map[string]interface{}) {

if !ruleOriginal.ruleAlreadyPrepared {
ruleOriginal.SetPredefinedStringsAndLists(GlobalPredefinedStringsAndLists) // use the global if not set already
Expand All @@ -115,78 +109,69 @@ func CheckOneRule(message *MessageAttributes, ruleOriginal *Rule) (int, *map[str

match := TestSender(rule, message)
if !match {
return DEFAULT, nil
return DEFAULT, []map[string]interface{}{}
}

match = TestReceiver(rule, message)
if !match {
return DEFAULT, nil
return DEFAULT, []map[string]interface{}{}
}

match = rule.OperationRegex.Match([]byte(message.RequestMethod)) // supports wildcards
if !match {
return DEFAULT, nil
return DEFAULT, []map[string]interface{}{}
}

// ----------------------
// compare resource:
if rule.Protocol == "tcp" {
match = rule.Resource.ResourceNameRegex.Match([]byte(message.DestinationPort))
if !match {
return DEFAULT, nil
return DEFAULT, []map[string]interface{}{}
}
} else {
if rule.Protocol != "*" {
if !strings.EqualFold(message.ContextProtocol, rule.Protocol) { // regardless of case // need to support wildcards!
return DEFAULT, nil
return DEFAULT, []map[string]interface{}{}
}

if rule.Resource.ResourceType != "*" {
if message.ContextType != rule.Resource.ResourceType { // need to support wildcards?
return DEFAULT, nil
return DEFAULT, []map[string]interface{}{}
}
}
match = rule.Resource.ResourceNameRegex.Match([]byte(message.RequestPath)) // supports wildcards
if !match {
return DEFAULT, nil
return DEFAULT, []map[string]interface{}{}
}
}
}

// ----------------------
// test conditions:
conditionsResult := true // if there are no conditions then we skip the test and return the rule.Decision
returnedValues := make(map[string][]interface{})
extraData := []map[string]interface{}{}
if rule.Conditions.ConditionsTree != nil {
conditionsResult = TestConditions(ruleOriginal, message, &returnedValues) // using original rule here. using prepared rule inside.
conditionsResult, extraData = TestConditions(ruleOriginal, message) // using original rule here. using prepared rule inside.
}
if conditionsResult == false {
return DEFAULT, nil
return DEFAULT, []map[string]interface{}{}
}

// ----------------------
// if we got here then the rule applies and we use the rule's decision
switch rule.Decision {
case "allow", "ALLOW", "Allow":
if len(returnedValues) == 0 {
return ALLOW, nil
}
return ALLOW, &returnedValues
return ALLOW, extraData
case "alert", "ALERT", "Alert":
if len(returnedValues) == 0 {
return ALERT, nil
}
return ALERT, &returnedValues
return ALERT, extraData
case "block", "BLOCK", "Block":
if len(returnedValues) == 0 {
return BLOCK, nil
}
return BLOCK, &returnedValues
return BLOCK, extraData
}
return DEFAULT, nil
return DEFAULT, []map[string]interface{}{}
}

func (rule *Rule) Check(message *MessageAttributes) (int, *map[string][]interface{}) {
func (rule *Rule) Check(message *MessageAttributes) (int, []map[string]interface{}) {
return CheckOneRule(message, rule)
}

Expand Down Expand Up @@ -260,32 +245,25 @@ func TestReceiver(rule *Rule, message *MessageAttributes) bool {
}

// testConditions tests the conditions of the rule with the message attributes
func TestConditions(rule *Rule, message *MessageAttributes, returnValues *map[string][]interface{}) bool { // to-do return error

if returnValues == nil {
returnValuesTemp := make(map[string][]interface{}, 0)
returnValues = &returnValuesTemp
}
func TestConditions(rule *Rule, message *MessageAttributes) (bool, []map[string]interface{}) { // to-do return error

if !rule.ruleAlreadyPrepared {
rule.SetPredefinedStringsAndLists(GlobalPredefinedStringsAndLists)
}

if rule.preparedRule.Conditions.ConditionsTree != nil {
return rule.preparedRule.Conditions.ConditionsTree.Eval(message, returnValues)
return rule.preparedRule.Conditions.ConditionsTree.Eval(message)
}
return false
return false, []map[string]interface{}{}

}

func (rule *Rule) TestConditions(message *MessageAttributes) (bool, *map[string][]interface{}) {
returnValuesTemp := make(map[string][]interface{}, 0)
returnValues := &returnValuesTemp
return TestConditions(rule, message, returnValues), returnValues
func (rule *Rule) TestConditions(message *MessageAttributes) (bool, []map[string]interface{}) {
return TestConditions(rule, message)
}

// testOneCondition tests one condition of the rule with the message attributes
func testOneCondition(c *Condition, message *MessageAttributes, returnValues *map[string][]interface{}) bool {
func testOneCondition(c *Condition, message *MessageAttributes) (bool, []map[string]interface{}) {

var valueToCompareInt int64
var valueToCompareFloat float64
Expand Down Expand Up @@ -337,16 +315,16 @@ func testOneCondition(c *Condition, message *MessageAttributes, returnValues *ma
}

case ("$sender"):
return testSenderAttributeCondition(c, message)
return testSenderAttributeCondition(c, message), []map[string]interface{}{}

case ("$receiver"):
return testReceiverAttributeCondition(c, message)
return testReceiverAttributeCondition(c, message), []map[string]interface{}{}

case ("senderLabel"):
return testSenderLabelCondition(c, message)
return testSenderLabelCondition(c, message), []map[string]interface{}{}

case ("receiverLabel"):
return testReceiverLabelCondition(c, message)
return testReceiverLabelCondition(c, message), []map[string]interface{}{}

case ("jsonpath"):
var flag bool
Expand All @@ -356,89 +334,76 @@ func testOneCondition(c *Condition, message *MessageAttributes, returnValues *ma
flag = testJsonPathCondition(c, message)
}
if flag && c.ReturnValueJsonpath != nil {
getExtraData(c, message, returnValues)
return flag
extraDataTemp := getExtraData(c, message)
return flag, []map[string]interface{}{extraDataTemp}
}
return flag
return flag, []map[string]interface{}{}

default:
log.Printf("condition keyword not supported: %+v\n", c) // was log.Fatalf
return false
return false, []map[string]interface{}{}
}
return result
return result, []map[string]interface{}{}
}
func getExtraData(c *Condition, message *MessageAttributes, returnValue *map[string][]interface{}) {
func getExtraData(c *Condition, message *MessageAttributes) map[string]interface{} {
if message.RequestRawInterface != nil {
getExtraDataFromInterface(c.PreparedReturnValueJsonpathQuery, c.PreparedReturnValueJsonpathQueryRelativeFlag, c.ReturnValueJsonpath, message, returnValue)
} else {
getExtraDataFromByteArray(c.ReturnValueJsonpath, c.PreparedReturnValueJsonpathQueryRelativeFlag, message, returnValue)
return getExtraDataFromInterface(c.PreparedReturnValueJsonpathQuery, c.PreparedReturnValueJsonpathQueryRelativeFlag, c.ReturnValueJsonpath, message)
}
return getExtraDataFromByteArray(c.ReturnValueJsonpath, c.PreparedReturnValueJsonpathQueryRelativeFlag, message)
}

func getExtraDataFromInterface(preparedReturnValueJsonpathQueryMap map[string]jsonpath.FilterFunc, preparedReturnValueJsonpathQueryRelativeFlag map[string]bool, returnValueJsonpathMap map[string]string, message *MessageAttributes, returnValue *map[string][]interface{}) {
func getExtraDataFromInterface(preparedReturnValueJsonpathQueryMap map[string]jsonpath.FilterFunc, preparedReturnValueJsonpathQueryRelativeFlag map[string]bool, returnValueJsonpathMap map[string]string, message *MessageAttributes) map[string]interface{} {
extraDataTemp := make(map[string]interface{})

for queryName, preparedQuery := range preparedReturnValueJsonpathQueryMap {
if returnValueJsonpathMap[queryName] == "$*" {
if preparedReturnValueJsonpathQueryRelativeFlag[queryName] {
appendReturnValue(queryName, returnValue, *message.RequestRawInterfaceRelative)
//extraDataTemp[queryName] = *message.RequestRawInterfaceRelative
extraDataTemp[queryName] = *message.RequestRawInterfaceRelative
} else {
appendReturnValue(queryName, returnValue, *message.RequestRawInterface)
//extraDataTemp[queryName] = *message.RequestRawInterface
extraDataTemp[queryName] = *message.RequestRawInterface
}
} else {
if preparedQuery != nil {
var err error
var returnValueEntry interface{}
var extraDataTempTemp interface{}
if preparedReturnValueJsonpathQueryRelativeFlag[queryName] {
returnValueEntry, err = queryInterface(preparedQuery, *message.RequestRawInterfaceRelative)
extraDataTempTemp, err = queryInterface(preparedQuery, *message.RequestRawInterfaceRelative)
} else {
returnValueEntry, err = queryInterface(preparedQuery, *message.RequestRawInterface)
extraDataTempTemp, err = queryInterface(preparedQuery, *message.RequestRawInterface)
}
if err == nil {
//extraDataTemp[queryName] = extraDataTempTemp
appendReturnValue(queryName, returnValue, returnValueEntry)
extraDataTemp[queryName] = extraDataTempTemp
}

} else {
// var x interface{}
// extraDataTemp[queryName] = x
var x interface{}
extraDataTemp[queryName] = x
}
}
}
return //extraDataTemp
}

func appendReturnValue(queryName string, returnValue *map[string][]interface{}, value interface{}) {
if array, ok := (*returnValue)[queryName]; !ok {
(*returnValue)[queryName] = []interface{}{value}
} else {
array = append(array, value)
(*returnValue)[queryName] = array
}
return extraDataTemp
}

func getExtraDataFromByteArray(returnValueJsonpathMap map[string]string, returnValueJsonpathQueryRelativeFlag map[string]bool, message *MessageAttributes, returnValue *map[string][]interface{}) {
//extraDataTemp := make(map[string]interface{})
func getExtraDataFromByteArray(returnValueJsonpathMap map[string]string, returnValueJsonpathQueryRelativeFlag map[string]bool, message *MessageAttributes) map[string]interface{} {
extraDataTemp := make(map[string]interface{})

for queryName, queryString := range returnValueJsonpathMap {
var returnValueEntryBytes []byte
var extraDataBytes []byte

if returnValueJsonpathQueryRelativeFlag[queryName] {
returnValueEntryBytes, _ = jsonslice.Get(*message.RequestJsonRawRelative, queryString)
extraDataBytes, _ = jsonslice.Get(*message.RequestJsonRawRelative, queryString)
} else {
returnValueEntryBytes, _ = jsonslice.Get(*message.RequestJsonRaw, queryString)
extraDataBytes, _ = jsonslice.Get(*message.RequestJsonRaw, queryString)
}

var returnValueEntry interface{}
err := json.Unmarshal(returnValueEntryBytes, &returnValueEntry)
var tempInterface interface{}
err := json.Unmarshal(extraDataBytes, &tempInterface)
if err == nil {
appendReturnValue(queryName, returnValue, returnValueEntry)
//extraDataTemp[queryName] = tempInterface
extraDataTemp[queryName] = tempInterface
}
}

//return extraDataTemp
return extraDataTemp
}

func testSenderAttributeCondition(c *Condition, message *MessageAttributes) bool {
Expand Down
Loading

0 comments on commit 892f127

Please sign in to comment.