mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-07-03 19:40:05 +00:00
* Make `logger` a separate module such that don't depend on `shared` module as a whole for logging * Update `Dockerfile`
125 lines
3.3 KiB
Go
125 lines
3.3 KiB
Go
package rules
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"fmt"
|
|
"reflect"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/up9inc/mizu/agent/pkg/har"
|
|
|
|
"github.com/up9inc/mizu/logger"
|
|
|
|
"github.com/up9inc/mizu/shared"
|
|
"github.com/yalp/jsonpath"
|
|
)
|
|
|
|
type RulesMatched struct {
|
|
Matched bool `json:"matched"`
|
|
Rule shared.RulePolicy `json:"rule"`
|
|
}
|
|
|
|
func appendRulesMatched(rulesMatched []RulesMatched, matched bool, rule shared.RulePolicy) []RulesMatched {
|
|
return append(rulesMatched, RulesMatched{Matched: matched, Rule: rule})
|
|
}
|
|
|
|
func ValidatePath(URLFromRule string, URL string) bool {
|
|
if URLFromRule != "" {
|
|
matchPath, err := regexp.MatchString(URLFromRule, URL)
|
|
if err != nil || !matchPath {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func ValidateService(serviceFromRule string, service string) bool {
|
|
if serviceFromRule != "" {
|
|
matchService, err := regexp.MatchString(serviceFromRule, service)
|
|
if err != nil || !matchService {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func MatchRequestPolicy(harEntry har.Entry, service string) (resultPolicyToSend []RulesMatched, isEnabled bool) {
|
|
enforcePolicy, err := shared.DecodeEnforcePolicy(fmt.Sprintf("%s%s", shared.ConfigDirPath, shared.ValidationRulesFileName))
|
|
if err == nil && len(enforcePolicy.Rules) > 0 {
|
|
isEnabled = true
|
|
}
|
|
for _, rule := range enforcePolicy.Rules {
|
|
if !ValidatePath(rule.Path, harEntry.Request.URL) || !ValidateService(rule.Service, service) {
|
|
continue
|
|
}
|
|
if rule.Type == "json" {
|
|
var bodyJsonMap interface{}
|
|
contentTextDecoded, _ := base64.StdEncoding.DecodeString(string(harEntry.Response.Content.Text))
|
|
if err := json.Unmarshal(contentTextDecoded, &bodyJsonMap); err != nil {
|
|
continue
|
|
}
|
|
out, err := jsonpath.Read(bodyJsonMap, rule.Key)
|
|
if err != nil || out == nil {
|
|
continue
|
|
}
|
|
var matchValue bool
|
|
if reflect.TypeOf(out).Kind() == reflect.String {
|
|
matchValue, err = regexp.MatchString(rule.Value, out.(string))
|
|
if err != nil {
|
|
continue
|
|
}
|
|
logger.Log.Info(matchValue, rule.Value)
|
|
} else {
|
|
val := fmt.Sprint(out)
|
|
matchValue, err = regexp.MatchString(rule.Value, val)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
}
|
|
resultPolicyToSend = appendRulesMatched(resultPolicyToSend, matchValue, rule)
|
|
} else if rule.Type == "header" {
|
|
for j := range harEntry.Response.Headers {
|
|
matchKey, err := regexp.MatchString(rule.Key, harEntry.Response.Headers[j].Name)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
if matchKey {
|
|
matchValue, err := regexp.MatchString(rule.Value, harEntry.Response.Headers[j].Value)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
resultPolicyToSend = appendRulesMatched(resultPolicyToSend, matchValue, rule)
|
|
}
|
|
}
|
|
} else {
|
|
resultPolicyToSend = appendRulesMatched(resultPolicyToSend, true, rule)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func PassedValidationRules(rulesMatched []RulesMatched) (bool, int64, int) {
|
|
var numberOfRulesMatched = len(rulesMatched)
|
|
var responseTime int64 = -1
|
|
|
|
if numberOfRulesMatched == 0 {
|
|
return false, 0, numberOfRulesMatched
|
|
}
|
|
|
|
for _, rule := range rulesMatched {
|
|
if !rule.Matched {
|
|
return false, responseTime, numberOfRulesMatched
|
|
} else {
|
|
if strings.ToLower(rule.Rule.Type) == "slo" {
|
|
if rule.Rule.ResponseTime < responseTime || responseTime == -1 {
|
|
responseTime = rule.Rule.ResponseTime
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return true, responseTime, numberOfRulesMatched
|
|
}
|