mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-08-06 19:14:50 +00:00
TRA-4622 Remove rules feature UI (#1178)
* Removed policy rules (validation rules) feature * updated test pcap * Remove rules * fix replay in rules Co-authored-by: Roy Island <roy@up9.com> Co-authored-by: RoyUP9 <87927115+RoyUP9@users.noreply.github.com> Co-authored-by: Roee Gadot <roee.gadot@up9.com>
This commit is contained in:
parent
13ed8eb58a
commit
302333b4ae
@ -30,7 +30,6 @@ require (
|
|||||||
github.com/up9inc/mizu/tap/extensions/kafka v0.0.0
|
github.com/up9inc/mizu/tap/extensions/kafka v0.0.0
|
||||||
github.com/up9inc/mizu/tap/extensions/redis v0.0.0
|
github.com/up9inc/mizu/tap/extensions/redis v0.0.0
|
||||||
github.com/wI2L/jsondiff v0.1.1
|
github.com/wI2L/jsondiff v0.1.1
|
||||||
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0
|
|
||||||
k8s.io/api v0.23.3
|
k8s.io/api v0.23.3
|
||||||
k8s.io/apimachinery v0.23.3
|
k8s.io/apimachinery v0.23.3
|
||||||
k8s.io/client-go v0.23.3
|
k8s.io/client-go v0.23.3
|
||||||
|
@ -707,8 +707,6 @@ github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6Ut
|
|||||||
github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk=
|
github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk=
|
||||||
github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
|
github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 h1:6fRhSjgLCkTD3JnJxvaJ4Sj+TYblw757bqYgZaOq5ZY=
|
|
||||||
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
|
|
||||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
@ -12,7 +12,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/dependency"
|
"github.com/up9inc/mizu/agent/pkg/dependency"
|
||||||
"github.com/up9inc/mizu/agent/pkg/models"
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/oas"
|
"github.com/up9inc/mizu/agent/pkg/oas"
|
||||||
"github.com/up9inc/mizu/agent/pkg/servicemap"
|
"github.com/up9inc/mizu/agent/pkg/servicemap"
|
||||||
|
|
||||||
@ -101,20 +100,13 @@ func startReadingChannel(outputItems <-chan *tapApi.OutputChannelItem, extension
|
|||||||
|
|
||||||
for item := range outputItems {
|
for item := range outputItems {
|
||||||
extension := extensionsMap[item.Protocol.Name]
|
extension := extensionsMap[item.Protocol.Name]
|
||||||
resolvedSource, resolvedDestionation, namespace := resolveIP(item.ConnectionInfo)
|
resolvedSource, resolvedDestination, namespace := resolveIP(item.ConnectionInfo)
|
||||||
|
|
||||||
if namespace == "" && item.Namespace != tapApi.UnknownNamespace {
|
if namespace == "" && item.Namespace != tapApi.UnknownNamespace {
|
||||||
namespace = item.Namespace
|
namespace = item.Namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
mizuEntry := extension.Dissector.Analyze(item, resolvedSource, resolvedDestionation, namespace)
|
mizuEntry := extension.Dissector.Analyze(item, resolvedSource, resolvedDestination, namespace)
|
||||||
if extension.Protocol.Name == "http" {
|
|
||||||
harEntry, err := har.NewEntry(mizuEntry.Request, mizuEntry.Response, mizuEntry.StartTime, mizuEntry.ElapsedTime)
|
|
||||||
if err == nil {
|
|
||||||
rules, _, _ := models.RunValidationRulesState(*harEntry, mizuEntry.Destination.Name)
|
|
||||||
mizuEntry.Rules = rules
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := json.Marshal(mizuEntry)
|
data, err := json.Marshal(mizuEntry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
basenine "github.com/up9inc/basenine/client/go"
|
basenine "github.com/up9inc/basenine/client/go"
|
||||||
"github.com/up9inc/mizu/agent/pkg/app"
|
"github.com/up9inc/mizu/agent/pkg/app"
|
||||||
"github.com/up9inc/mizu/agent/pkg/har"
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/models"
|
"github.com/up9inc/mizu/agent/pkg/models"
|
||||||
"github.com/up9inc/mizu/logger"
|
"github.com/up9inc/mizu/logger"
|
||||||
"github.com/up9inc/mizu/shared"
|
"github.com/up9inc/mizu/shared"
|
||||||
@ -95,24 +94,10 @@ func (e *BasenineEntriesProvider) GetEntry(singleEntryRequest *models.SingleEntr
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var rules []map[string]interface{}
|
|
||||||
var isRulesEnabled bool
|
|
||||||
if protocol.Name == "http" {
|
|
||||||
harEntry, _ := har.NewEntry(entry.Request, entry.Response, entry.StartTime, entry.ElapsedTime)
|
|
||||||
_, rulesMatched, _isRulesEnabled := models.RunValidationRulesState(*harEntry, entry.Destination.Name)
|
|
||||||
isRulesEnabled = _isRulesEnabled
|
|
||||||
inrec, _ := json.Marshal(rulesMatched)
|
|
||||||
if err := json.Unmarshal(inrec, &rules); err != nil {
|
|
||||||
logger.Log.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &tapApi.EntryWrapper{
|
return &tapApi.EntryWrapper{
|
||||||
Protocol: *protocol,
|
Protocol: *protocol,
|
||||||
Representation: string(representation),
|
Representation: string(representation),
|
||||||
Data: entry,
|
Data: entry,
|
||||||
Base: base,
|
Base: base,
|
||||||
Rules: rules,
|
|
||||||
IsRulesEnabled: isRulesEnabled,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/up9inc/mizu/agent/pkg/har"
|
"github.com/up9inc/mizu/agent/pkg/har"
|
||||||
"github.com/up9inc/mizu/agent/pkg/rules"
|
|
||||||
tapApi "github.com/up9inc/mizu/tap/api"
|
tapApi "github.com/up9inc/mizu/tap/api"
|
||||||
|
|
||||||
basenine "github.com/up9inc/basenine/client/go"
|
basenine "github.com/up9inc/basenine/client/go"
|
||||||
@ -143,9 +142,3 @@ type ExtendedCreator struct {
|
|||||||
*har.Creator
|
*har.Creator
|
||||||
Source *string `json:"_source"`
|
Source *string `json:"_source"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunValidationRulesState(harEntry har.Entry, service string) (tapApi.ApplicableRules, []rules.RulesMatched, bool) {
|
|
||||||
resultPolicyToSend, isEnabled := rules.MatchRequestPolicy(harEntry, service)
|
|
||||||
statusPolicyToSend, latency, numberOfRules := rules.PassedValidationRules(resultPolicyToSend)
|
|
||||||
return tapApi.ApplicableRules{Status: statusPolicyToSend, Latency: latency, NumberOfRules: numberOfRules}, resultPolicyToSend, isEnabled
|
|
||||||
}
|
|
||||||
|
@ -171,8 +171,6 @@ func ExecuteRequest(replayData *Details, timeout time.Duration) *Response {
|
|||||||
Representation: string(representation),
|
Representation: string(representation),
|
||||||
Data: entryUnmarshalled,
|
Data: entryUnmarshalled,
|
||||||
Base: base,
|
Base: base,
|
||||||
Rules: nil,
|
|
||||||
IsRulesEnabled: false,
|
|
||||||
},
|
},
|
||||||
ErrorMessage: "",
|
ErrorMessage: "",
|
||||||
}
|
}
|
||||||
|
@ -97,8 +97,6 @@ func TestValid(t *testing.T) {
|
|||||||
Representation: string(representation),
|
Representation: string(representation),
|
||||||
Data: entry,
|
Data: entry,
|
||||||
Base: base,
|
Base: base,
|
||||||
Rules: nil,
|
|
||||||
IsRulesEnabled: false,
|
|
||||||
}
|
}
|
||||||
t.Logf("%+v", result)
|
t.Logf("%+v", result)
|
||||||
//data, _ := json.MarshalIndent(result, "", " ")
|
//data, _ := json.MarshalIndent(result, "", " ")
|
||||||
|
@ -1,124 +0,0 @@
|
|||||||
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(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
|
|
||||||
}
|
|
@ -53,7 +53,6 @@ func init() {
|
|||||||
tapCmd.Flags().String(configStructs.HumanMaxEntriesDBSizeTapName, defaultTapConfig.HumanMaxEntriesDBSize, "Override the default max entries db size")
|
tapCmd.Flags().String(configStructs.HumanMaxEntriesDBSizeTapName, defaultTapConfig.HumanMaxEntriesDBSize, "Override the default max entries db size")
|
||||||
tapCmd.Flags().String(configStructs.InsertionFilterName, defaultTapConfig.InsertionFilter, "Set the insertion filter. Accepts string or a file path.")
|
tapCmd.Flags().String(configStructs.InsertionFilterName, defaultTapConfig.InsertionFilter, "Set the insertion filter. Accepts string or a file path.")
|
||||||
tapCmd.Flags().Bool(configStructs.DryRunTapName, defaultTapConfig.DryRun, "Preview of all pods matching the regex, without tapping them")
|
tapCmd.Flags().Bool(configStructs.DryRunTapName, defaultTapConfig.DryRun, "Preview of all pods matching the regex, without tapping them")
|
||||||
tapCmd.Flags().String(configStructs.EnforcePolicyFile, defaultTapConfig.EnforcePolicyFile, "Yaml file path with policy rules")
|
|
||||||
tapCmd.Flags().Bool(configStructs.ServiceMeshName, defaultTapConfig.ServiceMesh, "Record decrypted traffic if the cluster is configured with a service mesh and with mtls")
|
tapCmd.Flags().Bool(configStructs.ServiceMeshName, defaultTapConfig.ServiceMesh, "Record decrypted traffic if the cluster is configured with a service mesh and with mtls")
|
||||||
tapCmd.Flags().Bool(configStructs.TlsName, defaultTapConfig.Tls, "Record tls traffic")
|
tapCmd.Flags().Bool(configStructs.TlsName, defaultTapConfig.Tls, "Record tls traffic")
|
||||||
tapCmd.Flags().Bool(configStructs.ProfilerName, defaultTapConfig.Profiler, "Run pprof server")
|
tapCmd.Flags().Bool(configStructs.ProfilerName, defaultTapConfig.Profiler, "Run pprof server")
|
||||||
|
@ -12,7 +12,6 @@ import (
|
|||||||
"github.com/up9inc/mizu/cli/telemetry"
|
"github.com/up9inc/mizu/cli/telemetry"
|
||||||
"github.com/up9inc/mizu/cli/utils"
|
"github.com/up9inc/mizu/cli/utils"
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
core "k8s.io/api/core/v1"
|
core "k8s.io/api/core/v1"
|
||||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
@ -45,16 +44,6 @@ func RunMizuTap() {
|
|||||||
|
|
||||||
apiProvider = apiserver.NewProvider(GetApiServerUrl(config.Config.Tap.GuiPort), apiserver.DefaultRetries, apiserver.DefaultTimeout)
|
apiProvider = apiserver.NewProvider(GetApiServerUrl(config.Config.Tap.GuiPort), apiserver.DefaultRetries, apiserver.DefaultTimeout)
|
||||||
|
|
||||||
var err error
|
|
||||||
var serializedValidationRules string
|
|
||||||
if config.Config.Tap.EnforcePolicyFile != "" {
|
|
||||||
serializedValidationRules, err = readValidationRules(config.Config.Tap.EnforcePolicyFile)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Errorf(uiUtils.Error, fmt.Sprintf("Error reading policy file: %v", errormessage.FormatError(err)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kubernetesProvider, err := getKubernetesProviderForCli()
|
kubernetesProvider, err := getKubernetesProviderForCli()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -98,7 +87,7 @@ func RunMizuTap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.Log.Infof("Waiting for Mizu Agent to start...")
|
logger.Log.Infof("Waiting for Mizu Agent to start...")
|
||||||
if state.mizuServiceAccountExists, err = resources.CreateTapMizuResources(ctx, kubernetesProvider, serializedValidationRules, serializedMizuConfig, config.Config.IsNsRestrictedMode(), config.Config.MizuResourcesNamespace, config.Config.AgentImage, config.Config.Tap.MaxEntriesDBSizeBytes(), config.Config.Tap.ApiServerResources, config.Config.ImagePullPolicy(), config.Config.LogLevel(), config.Config.Tap.Profiler); err != nil {
|
if state.mizuServiceAccountExists, err = resources.CreateTapMizuResources(ctx, kubernetesProvider, serializedMizuConfig, config.Config.IsNsRestrictedMode(), config.Config.MizuResourcesNamespace, config.Config.AgentImage, config.Config.Tap.MaxEntriesDBSizeBytes(), config.Config.Tap.ApiServerResources, config.Config.ImagePullPolicy(), config.Config.LogLevel(), config.Config.Tap.Profiler); err != nil {
|
||||||
var statusError *k8serrors.StatusError
|
var statusError *k8serrors.StatusError
|
||||||
if errors.As(err, &statusError) && (statusError.ErrStatus.Reason == metav1.StatusReasonAlreadyExists) {
|
if errors.As(err, &statusError) && (statusError.ErrStatus.Reason == metav1.StatusReasonAlreadyExists) {
|
||||||
logger.Log.Info("Mizu is already running in this namespace, change the `mizu-resources-namespace` configuration or run `mizu clean` to remove the currently running Mizu instance")
|
logger.Log.Info("Mizu is already running in this namespace, change the `mizu-resources-namespace` configuration or run `mizu clean` to remove the currently running Mizu instance")
|
||||||
@ -240,15 +229,6 @@ func getErrorDisplayTextForK8sTapManagerError(err kubernetes.K8sTapManagerError)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func readValidationRules(file string) (string, error) {
|
|
||||||
rules, err := shared.DecodeEnforcePolicy(file)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
newContent, _ := yaml.Marshal(&rules)
|
|
||||||
return string(newContent), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getMizuApiFilteringOptions() (*api.TrafficFilteringOptions, error) {
|
func getMizuApiFilteringOptions() (*api.TrafficFilteringOptions, error) {
|
||||||
var compiledRegexSlice []*api.SerializableRegexp
|
var compiledRegexSlice []*api.SerializableRegexp
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ const (
|
|||||||
HumanMaxEntriesDBSizeTapName = "max-entries-db-size"
|
HumanMaxEntriesDBSizeTapName = "max-entries-db-size"
|
||||||
InsertionFilterName = "insertion-filter"
|
InsertionFilterName = "insertion-filter"
|
||||||
DryRunTapName = "dry-run"
|
DryRunTapName = "dry-run"
|
||||||
EnforcePolicyFile = "traffic-validation-file"
|
|
||||||
ServiceMeshName = "service-mesh"
|
ServiceMeshName = "service-mesh"
|
||||||
TlsName = "tls"
|
TlsName = "tls"
|
||||||
ProfilerName = "profiler"
|
ProfilerName = "profiler"
|
||||||
@ -42,7 +41,6 @@ type TapConfig struct {
|
|||||||
HumanMaxEntriesDBSize string `yaml:"max-entries-db-size" default:"200MB"`
|
HumanMaxEntriesDBSize string `yaml:"max-entries-db-size" default:"200MB"`
|
||||||
InsertionFilter string `yaml:"insertion-filter" default:""`
|
InsertionFilter string `yaml:"insertion-filter" default:""`
|
||||||
DryRun bool `yaml:"dry-run" default:"false"`
|
DryRun bool `yaml:"dry-run" default:"false"`
|
||||||
EnforcePolicyFile string `yaml:"traffic-validation-file"`
|
|
||||||
ApiServerResources shared.Resources `yaml:"api-server-resources"`
|
ApiServerResources shared.Resources `yaml:"api-server-resources"`
|
||||||
TapperResources shared.Resources `yaml:"tapper-resources"`
|
TapperResources shared.Resources `yaml:"tapper-resources"`
|
||||||
ServiceMesh bool `yaml:"service-mesh" default:"false"`
|
ServiceMesh bool `yaml:"service-mesh" default:"false"`
|
||||||
|
@ -14,14 +14,14 @@ import (
|
|||||||
core "k8s.io/api/core/v1"
|
core "k8s.io/api/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateTapMizuResources(ctx context.Context, kubernetesProvider *kubernetes.Provider, serializedValidationRules string, serializedMizuConfig string, isNsRestrictedMode bool, mizuResourcesNamespace string, agentImage string, maxEntriesDBSizeBytes int64, apiServerResources shared.Resources, imagePullPolicy core.PullPolicy, logLevel logging.Level, profiler bool) (bool, error) {
|
func CreateTapMizuResources(ctx context.Context, kubernetesProvider *kubernetes.Provider, serializedMizuConfig string, isNsRestrictedMode bool, mizuResourcesNamespace string, agentImage string, maxEntriesDBSizeBytes int64, apiServerResources shared.Resources, imagePullPolicy core.PullPolicy, logLevel logging.Level, profiler bool) (bool, error) {
|
||||||
if !isNsRestrictedMode {
|
if !isNsRestrictedMode {
|
||||||
if err := createMizuNamespace(ctx, kubernetesProvider, mizuResourcesNamespace); err != nil {
|
if err := createMizuNamespace(ctx, kubernetesProvider, mizuResourcesNamespace); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := createMizuConfigmap(ctx, kubernetesProvider, serializedValidationRules, serializedMizuConfig, mizuResourcesNamespace); err != nil {
|
if err := createMizuConfigmap(ctx, kubernetesProvider, serializedMizuConfig, mizuResourcesNamespace); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,8 +71,8 @@ func createMizuNamespace(ctx context.Context, kubernetesProvider *kubernetes.Pro
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func createMizuConfigmap(ctx context.Context, kubernetesProvider *kubernetes.Provider, serializedValidationRules string, serializedMizuConfig string, mizuResourcesNamespace string) error {
|
func createMizuConfigmap(ctx context.Context, kubernetesProvider *kubernetes.Provider, serializedMizuConfig string, mizuResourcesNamespace string) error {
|
||||||
err := kubernetesProvider.CreateConfigMap(ctx, mizuResourcesNamespace, kubernetes.ConfigMapName, serializedValidationRules, serializedMizuConfig)
|
err := kubernetesProvider.CreateConfigMap(ctx, mizuResourcesNamespace, kubernetes.ConfigMapName, serializedMizuConfig)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ const (
|
|||||||
NodeNameEnvVar = "NODE_NAME"
|
NodeNameEnvVar = "NODE_NAME"
|
||||||
ConfigDirPath = "/app/config/"
|
ConfigDirPath = "/app/config/"
|
||||||
DataDirPath = "/app/data/"
|
DataDirPath = "/app/data/"
|
||||||
ValidationRulesFileName = "validation-rules.yaml"
|
|
||||||
ConfigFileName = "mizu-config.json"
|
ConfigFileName = "mizu-config.json"
|
||||||
DefaultApiServerPort = 8899
|
DefaultApiServerPort = 8899
|
||||||
LogLevelEnvVar = "LOG_LEVEL"
|
LogLevelEnvVar = "LOG_LEVEL"
|
||||||
|
@ -4,11 +4,9 @@ go 1.17
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/docker/go-units v0.4.0
|
github.com/docker/go-units v0.4.0
|
||||||
github.com/golang-jwt/jwt/v4 v4.2.0
|
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||||
github.com/up9inc/mizu/logger v0.0.0
|
github.com/up9inc/mizu/logger v0.0.0
|
||||||
github.com/up9inc/mizu/tap/api v0.0.0
|
github.com/up9inc/mizu/tap/api v0.0.0
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
|
||||||
k8s.io/api v0.23.3
|
k8s.io/api v0.23.3
|
||||||
k8s.io/apimachinery v0.23.3
|
k8s.io/apimachinery v0.23.3
|
||||||
k8s.io/client-go v0.23.3
|
k8s.io/client-go v0.23.3
|
||||||
@ -38,11 +36,11 @@ require (
|
|||||||
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
||||||
github.com/go-openapi/swag v0.21.1 // indirect
|
github.com/go-openapi/swag v0.21.1 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
|
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
github.com/google/btree v1.0.1 // indirect
|
github.com/google/btree v1.0.1 // indirect
|
||||||
github.com/google/go-cmp v0.5.7 // indirect
|
github.com/google/go-cmp v0.5.7 // indirect
|
||||||
github.com/google/gofuzz v1.2.0 // indirect
|
github.com/google/gofuzz v1.2.0 // indirect
|
||||||
github.com/google/martian v2.1.0+incompatible // indirect
|
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||||
@ -81,6 +79,7 @@ require (
|
|||||||
google.golang.org/protobuf v1.27.1 // indirect
|
google.golang.org/protobuf v1.27.1 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||||
k8s.io/cli-runtime v0.23.3 // indirect
|
k8s.io/cli-runtime v0.23.3 // indirect
|
||||||
k8s.io/component-base v0.23.3 // indirect
|
k8s.io/component-base v0.23.3 // indirect
|
||||||
k8s.io/klog/v2 v2.40.1 // indirect
|
k8s.io/klog/v2 v2.40.1 // indirect
|
||||||
|
@ -282,7 +282,6 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
|||||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
|
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
|
@ -685,11 +685,8 @@ func (provider *Provider) handleRemovalError(err error) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *Provider) CreateConfigMap(ctx context.Context, namespace string, configMapName string, serializedValidationRules string, serializedMizuConfig string) error {
|
func (provider *Provider) CreateConfigMap(ctx context.Context, namespace string, configMapName string, serializedMizuConfig string) error {
|
||||||
configMapData := make(map[string]string)
|
configMapData := make(map[string]string)
|
||||||
if serializedValidationRules != "" {
|
|
||||||
configMapData[shared.ValidationRulesFileName] = serializedValidationRules
|
|
||||||
}
|
|
||||||
configMapData[shared.ConfigFileName] = serializedMizuConfig
|
configMapData[shared.ConfigFileName] = serializedMizuConfig
|
||||||
|
|
||||||
configMap := &core.ConfigMap{
|
configMap := &core.ConfigMap{
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
package shared
|
package shared
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/op/go-logging"
|
"github.com/op/go-logging"
|
||||||
"github.com/up9inc/mizu/logger"
|
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -135,83 +130,3 @@ type HealthResponse struct {
|
|||||||
type VersionResponse struct {
|
type VersionResponse struct {
|
||||||
Ver string `json:"ver"`
|
Ver string `json:"ver"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RulesPolicy struct {
|
|
||||||
Rules []RulePolicy `yaml:"rules"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RulePolicy struct {
|
|
||||||
Type string `yaml:"type"`
|
|
||||||
Service string `yaml:"service"`
|
|
||||||
Path string `yaml:"path"`
|
|
||||||
Method string `yaml:"method"`
|
|
||||||
Key string `yaml:"key"`
|
|
||||||
Value string `yaml:"value"`
|
|
||||||
ResponseTime int64 `yaml:"response-time"`
|
|
||||||
Name string `yaml:"name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type RulesMatched struct {
|
|
||||||
Matched bool `json:"matched"`
|
|
||||||
Rule RulePolicy `json:"rule"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *RulePolicy) validateType() bool {
|
|
||||||
permitedTypes := []string{"json", "header", "slo"}
|
|
||||||
_, found := Find(permitedTypes, r.Type)
|
|
||||||
if !found {
|
|
||||||
logger.Log.Errorf("Only json, header and slo types are supported on rule definition. This rule will be ignored. rule name: %s", r.Name)
|
|
||||||
found = false
|
|
||||||
}
|
|
||||||
if strings.ToLower(r.Type) == "slo" {
|
|
||||||
if r.ResponseTime <= 0 {
|
|
||||||
logger.Log.Errorf("When rule type is slo, the field response-time should be specified and have a value >= 1. rule name: %s", r.Name)
|
|
||||||
found = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return found
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rules *RulesPolicy) ValidateRulesPolicy() []int {
|
|
||||||
invalidIndex := make([]int, 0)
|
|
||||||
for i := range rules.Rules {
|
|
||||||
validated := rules.Rules[i].validateType()
|
|
||||||
if !validated {
|
|
||||||
invalidIndex = append(invalidIndex, i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return invalidIndex
|
|
||||||
}
|
|
||||||
|
|
||||||
func Find(slice []string, val string) (int, bool) {
|
|
||||||
for i, item := range slice {
|
|
||||||
if item == val {
|
|
||||||
return i, true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1, false
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecodeEnforcePolicy(path string) (RulesPolicy, error) {
|
|
||||||
content, err := ioutil.ReadFile(path)
|
|
||||||
enforcePolicy := RulesPolicy{}
|
|
||||||
if err != nil {
|
|
||||||
return enforcePolicy, err
|
|
||||||
}
|
|
||||||
err = yaml.Unmarshal(content, &enforcePolicy)
|
|
||||||
if err != nil {
|
|
||||||
return enforcePolicy, err
|
|
||||||
}
|
|
||||||
invalidIndex := enforcePolicy.ValidateRulesPolicy()
|
|
||||||
var k = 0
|
|
||||||
if len(invalidIndex) != 0 {
|
|
||||||
for i, rule := range enforcePolicy.Rules {
|
|
||||||
if !ContainsInt(invalidIndex, i) {
|
|
||||||
enforcePolicy.Rules[k] = rule
|
|
||||||
k++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
enforcePolicy.Rules = enforcePolicy.Rules[:k]
|
|
||||||
}
|
|
||||||
return enforcePolicy, nil
|
|
||||||
}
|
|
||||||
|
@ -10,15 +10,6 @@ func Contains(slice []string, containsValue string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func ContainsInt(slice []int, containsValue int) bool {
|
|
||||||
for _, sliceValue := range slice {
|
|
||||||
if sliceValue == containsValue {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func Unique(slice []string) []string {
|
func Unique(slice []string) []string {
|
||||||
keys := make(map[string]bool)
|
keys := make(map[string]bool)
|
||||||
var list []string
|
var list []string
|
||||||
|
@ -164,40 +164,30 @@ type Entry struct {
|
|||||||
RequestSize int `json:"requestSize"`
|
RequestSize int `json:"requestSize"`
|
||||||
ResponseSize int `json:"responseSize"`
|
ResponseSize int `json:"responseSize"`
|
||||||
ElapsedTime int64 `json:"elapsedTime"`
|
ElapsedTime int64 `json:"elapsedTime"`
|
||||||
Rules ApplicableRules `json:"rules,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type EntryWrapper struct {
|
type EntryWrapper struct {
|
||||||
Protocol Protocol `json:"protocol"`
|
Protocol Protocol `json:"protocol"`
|
||||||
Representation string `json:"representation"`
|
Representation string `json:"representation"`
|
||||||
Data *Entry `json:"data"`
|
Data *Entry `json:"data"`
|
||||||
Base *BaseEntry `json:"base"`
|
Base *BaseEntry `json:"base"`
|
||||||
Rules []map[string]interface{} `json:"rulesMatched,omitempty"`
|
|
||||||
IsRulesEnabled bool `json:"isRulesEnabled"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type BaseEntry struct {
|
type BaseEntry struct {
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
Protocol Protocol `json:"proto,omitempty"`
|
Protocol Protocol `json:"proto,omitempty"`
|
||||||
Capture Capture `json:"capture"`
|
Capture Capture `json:"capture"`
|
||||||
Summary string `json:"summary,omitempty"`
|
Summary string `json:"summary,omitempty"`
|
||||||
SummaryQuery string `json:"summaryQuery,omitempty"`
|
SummaryQuery string `json:"summaryQuery,omitempty"`
|
||||||
Status int `json:"status"`
|
Status int `json:"status"`
|
||||||
StatusQuery string `json:"statusQuery"`
|
StatusQuery string `json:"statusQuery"`
|
||||||
Method string `json:"method,omitempty"`
|
Method string `json:"method,omitempty"`
|
||||||
MethodQuery string `json:"methodQuery,omitempty"`
|
MethodQuery string `json:"methodQuery,omitempty"`
|
||||||
Timestamp int64 `json:"timestamp,omitempty"`
|
Timestamp int64 `json:"timestamp,omitempty"`
|
||||||
Source *TCP `json:"src"`
|
Source *TCP `json:"src"`
|
||||||
Destination *TCP `json:"dst"`
|
Destination *TCP `json:"dst"`
|
||||||
IsOutgoing bool `json:"isOutgoing,omitempty"`
|
IsOutgoing bool `json:"isOutgoing,omitempty"`
|
||||||
Latency int64 `json:"latency"`
|
Latency int64 `json:"latency"`
|
||||||
Rules ApplicableRules `json:"rules,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ApplicableRules struct {
|
|
||||||
Latency int64 `json:"latency,omitempty"`
|
|
||||||
Status bool `json:"status,omitempty"`
|
|
||||||
NumberOfRules int `json:"numberOfRules,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -13,4 +13,4 @@ test-pull-bin:
|
|||||||
|
|
||||||
test-pull-expect:
|
test-pull-expect:
|
||||||
@mkdir -p expect
|
@mkdir -p expect
|
||||||
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect13/amqp/\* expect
|
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect14/amqp/\* expect
|
||||||
|
@ -298,7 +298,6 @@ func (d dissecting) Summarize(entry *api.Entry) *api.BaseEntry {
|
|||||||
Destination: entry.Destination,
|
Destination: entry.Destination,
|
||||||
IsOutgoing: entry.Outgoing,
|
IsOutgoing: entry.Outgoing,
|
||||||
Latency: entry.ElapsedTime,
|
Latency: entry.ElapsedTime,
|
||||||
Rules: entry.Rules,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,4 +13,4 @@ test-pull-bin:
|
|||||||
|
|
||||||
test-pull-expect:
|
test-pull-expect:
|
||||||
@mkdir -p expect
|
@mkdir -p expect
|
||||||
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect13/http/\* expect
|
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect14/http/\* expect
|
||||||
|
@ -341,7 +341,6 @@ func (d dissecting) Summarize(entry *api.Entry) *api.BaseEntry {
|
|||||||
Destination: entry.Destination,
|
Destination: entry.Destination,
|
||||||
IsOutgoing: entry.Outgoing,
|
IsOutgoing: entry.Outgoing,
|
||||||
Latency: entry.ElapsedTime,
|
Latency: entry.ElapsedTime,
|
||||||
Rules: entry.Rules,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,4 +13,4 @@ test-pull-bin:
|
|||||||
|
|
||||||
test-pull-expect:
|
test-pull-expect:
|
||||||
@mkdir -p expect
|
@mkdir -p expect
|
||||||
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect13/kafka/\* expect
|
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect14/kafka/\* expect
|
||||||
|
@ -208,7 +208,6 @@ func (d dissecting) Summarize(entry *api.Entry) *api.BaseEntry {
|
|||||||
Destination: entry.Destination,
|
Destination: entry.Destination,
|
||||||
IsOutgoing: entry.Outgoing,
|
IsOutgoing: entry.Outgoing,
|
||||||
Latency: entry.ElapsedTime,
|
Latency: entry.ElapsedTime,
|
||||||
Rules: entry.Rules,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,4 +13,4 @@ test-pull-bin:
|
|||||||
|
|
||||||
test-pull-expect:
|
test-pull-expect:
|
||||||
@mkdir -p expect
|
@mkdir -p expect
|
||||||
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect13/redis/\* expect
|
@[ "${skipexpect}" ] && echo "Skipping downloading expected JSONs" || gsutil -o 'GSUtil:parallel_process_count=5' -o 'GSUtil:parallel_thread_count=5' -m cp -r gs://static.up9.io/mizu/test-pcap/expect14/redis/\* expect
|
||||||
|
@ -136,7 +136,6 @@ func (d dissecting) Summarize(entry *api.Entry) *api.BaseEntry {
|
|||||||
Destination: entry.Destination,
|
Destination: entry.Destination,
|
||||||
IsOutgoing: entry.Outgoing,
|
IsOutgoing: entry.Outgoing,
|
||||||
Latency: entry.ElapsedTime,
|
Latency: entry.ElapsedTime,
|
||||||
Rules: entry.Rules,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,9 +146,6 @@ export const EntryDetailed = () => {
|
|||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{!isLoading && entryData && <EntryViewer
|
{!isLoading && entryData && <EntryViewer
|
||||||
representation={entryData.representation}
|
representation={entryData.representation}
|
||||||
isRulesEnabled={entryData.isRulesEnabled}
|
|
||||||
rulesMatched={entryData.rulesMatched}
|
|
||||||
elapsedTime={entryData.data.elapsedTime}
|
|
||||||
color={entryData.protocol.backgroundColor}
|
color={entryData.protocol.backgroundColor}
|
||||||
/>}
|
/>}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
@ -265,110 +265,3 @@ export const EntryTableSection: React.FC<EntrySectionProps> = ({ title, color, a
|
|||||||
}
|
}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EntryPolicySectionProps {
|
|
||||||
title: string,
|
|
||||||
color: string,
|
|
||||||
latency?: number,
|
|
||||||
arrayToIterate: any[],
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EntryPolicySectionCollapsibleTitleProps {
|
|
||||||
label: string;
|
|
||||||
matched: string;
|
|
||||||
expanded: boolean;
|
|
||||||
setExpanded: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
const EntryPolicySectionCollapsibleTitle: React.FC<EntryPolicySectionCollapsibleTitleProps> = ({ label, matched, expanded, setExpanded }) => {
|
|
||||||
return <div className={styles.title}>
|
|
||||||
<span
|
|
||||||
className={`${styles.button}
|
|
||||||
${expanded ? styles.expanded : ''}`}
|
|
||||||
onClick={() => {
|
|
||||||
setExpanded(!expanded)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{expanded ? '-' : '+'}
|
|
||||||
</span>
|
|
||||||
<span>
|
|
||||||
<tr className={styles.dataLine}>
|
|
||||||
<td className={`${styles.dataKey} ${styles.rulesTitleSuccess}`}>{label}</td>
|
|
||||||
<td className={`${styles.dataKey} ${matched === 'Success' ? styles.rulesMatchedSuccess : styles.rulesMatchedFailure}`}>{matched}</td>
|
|
||||||
</tr>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
interface EntryPolicySectionContainerProps {
|
|
||||||
label: string;
|
|
||||||
matched: string;
|
|
||||||
children?: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const EntryPolicySectionContainer: React.FC<EntryPolicySectionContainerProps> = ({ label, matched, children }) => {
|
|
||||||
const [expanded, setExpanded] = useState(false);
|
|
||||||
return <CollapsibleContainer
|
|
||||||
className={styles.collapsibleContainer}
|
|
||||||
expanded={expanded}
|
|
||||||
title={<EntryPolicySectionCollapsibleTitle label={label} matched={matched} expanded={expanded} setExpanded={setExpanded} />}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</CollapsibleContainer>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const EntryTablePolicySection: React.FC<EntryPolicySectionProps> = ({ title, color, latency, arrayToIterate }) => {
|
|
||||||
return <React.Fragment>
|
|
||||||
{
|
|
||||||
arrayToIterate && arrayToIterate.length > 0 ?
|
|
||||||
<React.Fragment>
|
|
||||||
<EntrySectionContainer title={title} color={color}>
|
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
{arrayToIterate.map(({ rule, matched }, index) => {
|
|
||||||
return (
|
|
||||||
<EntryPolicySectionContainer key={index} label={rule.Name} matched={matched && (rule.Type === 'slo' ? rule.ResponseTime >= latency : true) ? "Success" : "Failure"}>
|
|
||||||
{
|
|
||||||
<React.Fragment>
|
|
||||||
{
|
|
||||||
rule.Key &&
|
|
||||||
<tr className={styles.dataValue}><td><b>Key:</b></td> <td>{rule.Key}</td></tr>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
rule.ResponseTime !== 0 &&
|
|
||||||
<tr className={styles.dataValue}><td><b>Response Time:</b></td> <td>{rule.ResponseTime}</td></tr>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
rule.Method &&
|
|
||||||
<tr className={styles.dataValue}><td><b>Method:</b></td> <td>{rule.Method}</td></tr>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
rule.Path &&
|
|
||||||
<tr className={styles.dataValue}><td><b>Path:</b></td> <td>{rule.Path}</td></tr>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
rule.Service &&
|
|
||||||
<tr className={styles.dataValue}><td><b>Service:</b></td> <td>{rule.Service}</td></tr>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
rule.Type &&
|
|
||||||
<tr className={styles.dataValue}><td><b>Type:</b></td> <td>{rule.Type}</td></tr>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
rule.Value &&
|
|
||||||
<tr className={styles.dataValue}><td><b>Value:</b></td> <td>{rule.Value}</td></tr>
|
|
||||||
}
|
|
||||||
</React.Fragment>
|
|
||||||
}
|
|
||||||
</EntryPolicySectionContainer>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</EntrySectionContainer>
|
|
||||||
</React.Fragment> : <span className={styles.noRules}>No rules could be applied to this request.</span>
|
|
||||||
}
|
|
||||||
</React.Fragment>
|
|
||||||
}
|
|
||||||
|
@ -2,7 +2,6 @@ import React, { useState, useCallback } from "react"
|
|||||||
import { useRecoilValue, useSetRecoilState } from "recoil"
|
import { useRecoilValue, useSetRecoilState } from "recoil"
|
||||||
import entryDataAtom from "../../../recoil/entryData"
|
import entryDataAtom from "../../../recoil/entryData"
|
||||||
import SectionsRepresentation from "./SectionsRepresentation";
|
import SectionsRepresentation from "./SectionsRepresentation";
|
||||||
import { EntryTablePolicySection } from "../EntrySections/EntrySections";
|
|
||||||
import { ReactComponent as ReplayIcon } from './replay.svg';
|
import { ReactComponent as ReplayIcon } from './replay.svg';
|
||||||
import styles from './EntryViewer.module.sass';
|
import styles from './EntryViewer.module.sass';
|
||||||
import { Tabs } from "../../UI";
|
import { Tabs } from "../../UI";
|
||||||
@ -10,7 +9,7 @@ import replayRequestModalOpenAtom from "../../../recoil/replayRequestModalOpen";
|
|||||||
|
|
||||||
const enabledProtocolsForReplay = ["http"]
|
const enabledProtocolsForReplay = ["http"]
|
||||||
|
|
||||||
export const AutoRepresentation: React.FC<any> = ({ representation, isRulesEnabled, rulesMatched, elapsedTime, color, isDisplayReplay = false }) => {
|
export const AutoRepresentation: React.FC<any> = ({ representation, color, isDisplayReplay = false }) => {
|
||||||
const entryData = useRecoilValue(entryDataAtom)
|
const entryData = useRecoilValue(entryDataAtom)
|
||||||
const setIsOpenRequestModal = useSetRecoilState(replayRequestModalOpenAtom)
|
const setIsOpenRequestModal = useSetRecoilState(replayRequestModalOpenAtom)
|
||||||
const isReplayDisplayed = useCallback(() => {
|
const isReplayDisplayed = useCallback(() => {
|
||||||
@ -33,7 +32,6 @@ export const AutoRepresentation: React.FC<any> = ({ representation, isRulesEnabl
|
|||||||
const { request, response } = JSON.parse(representation);
|
const { request, response } = JSON.parse(representation);
|
||||||
|
|
||||||
let responseTabIndex = 0;
|
let responseTabIndex = 0;
|
||||||
let rulesTabIndex = 0;
|
|
||||||
|
|
||||||
if (response) {
|
if (response) {
|
||||||
TABS.push(
|
TABS.push(
|
||||||
@ -45,16 +43,6 @@ export const AutoRepresentation: React.FC<any> = ({ representation, isRulesEnabl
|
|||||||
responseTabIndex = TABS.length - 1;
|
responseTabIndex = TABS.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRulesEnabled) {
|
|
||||||
TABS.push(
|
|
||||||
{
|
|
||||||
tab: 'Rules',
|
|
||||||
badge: null
|
|
||||||
}
|
|
||||||
);
|
|
||||||
rulesTabIndex = TABS.length - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div className={styles.Entry}>
|
return <div className={styles.Entry}>
|
||||||
{<div className={styles.body}>
|
{<div className={styles.body}>
|
||||||
<div className={styles.bodyHeader}>
|
<div className={styles.bodyHeader}>
|
||||||
@ -66,9 +54,6 @@ export const AutoRepresentation: React.FC<any> = ({ representation, isRulesEnabl
|
|||||||
{response && currentTab === TABS[responseTabIndex].tab && <React.Fragment>
|
{response && currentTab === TABS[responseTabIndex].tab && <React.Fragment>
|
||||||
<SectionsRepresentation data={response} color={color} />
|
<SectionsRepresentation data={response} color={color} />
|
||||||
</React.Fragment>}
|
</React.Fragment>}
|
||||||
{isRulesEnabled && currentTab === TABS[rulesTabIndex].tab && <React.Fragment>
|
|
||||||
<EntryTablePolicySection title={'Rule'} color={color} latency={elapsedTime} arrayToIterate={rulesMatched ? rulesMatched : []} />
|
|
||||||
</React.Fragment>}
|
|
||||||
</div>}
|
</div>}
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
@ -3,18 +3,12 @@ import { AutoRepresentation } from './AutoRepresentation';
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
representation: any;
|
representation: any;
|
||||||
isRulesEnabled: boolean;
|
|
||||||
rulesMatched: any;
|
|
||||||
color: string;
|
color: string;
|
||||||
elapsedTime: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const EntryViewer: React.FC<Props> = ({ representation, isRulesEnabled, rulesMatched, elapsedTime, color }) => {
|
const EntryViewer: React.FC<Props> = ({representation, color}) => {
|
||||||
return <AutoRepresentation
|
return <AutoRepresentation
|
||||||
representation={representation}
|
representation={representation}
|
||||||
isRulesEnabled={isRulesEnabled}
|
|
||||||
rulesMatched={rulesMatched}
|
|
||||||
elapsedTime={elapsedTime}
|
|
||||||
color={color}
|
color={color}
|
||||||
isDisplayReplay={true}
|
isDisplayReplay={true}
|
||||||
/>
|
/>
|
||||||
|
@ -20,31 +20,6 @@
|
|||||||
.rowSelected
|
.rowSelected
|
||||||
border: 1px $blue-color solid
|
border: 1px $blue-color solid
|
||||||
|
|
||||||
.ruleSuccessRow
|
|
||||||
background: #E8FFF1
|
|
||||||
|
|
||||||
.ruleSuccessRowSelected
|
|
||||||
border: 1px #6FCF97 solid
|
|
||||||
border-left: 5px #6FCF97 solid
|
|
||||||
|
|
||||||
.ruleFailureRow
|
|
||||||
background: #FFE9EF
|
|
||||||
|
|
||||||
.ruleFailureRowSelected
|
|
||||||
border: 1px $failure-color solid
|
|
||||||
border-left: 5px $failure-color solid
|
|
||||||
|
|
||||||
.ruleNumberText
|
|
||||||
font-size: 12px
|
|
||||||
font-weight: 600
|
|
||||||
white-space: nowrap
|
|
||||||
|
|
||||||
.ruleNumberTextFailure
|
|
||||||
color: #DB2156
|
|
||||||
|
|
||||||
.ruleNumberTextSuccess
|
|
||||||
color: #219653
|
|
||||||
|
|
||||||
.resolvedName
|
.resolvedName
|
||||||
text-overflow: ellipsis
|
text-overflow: ellipsis
|
||||||
white-space: nowrap
|
white-space: nowrap
|
||||||
|
@ -37,13 +37,6 @@ interface Entry {
|
|||||||
dst: TCPInterface,
|
dst: TCPInterface,
|
||||||
isOutgoing?: boolean;
|
isOutgoing?: boolean;
|
||||||
latency: number;
|
latency: number;
|
||||||
rules: Rules;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Rules {
|
|
||||||
status: boolean;
|
|
||||||
latency: number;
|
|
||||||
numberOfRules: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EntryProps {
|
interface EntryProps {
|
||||||
@ -67,7 +60,6 @@ export const EntryItem: React.FC<EntryProps> = ({entry, style, headingMode, name
|
|||||||
const isSelected = focusedEntryId === entry.id;
|
const isSelected = focusedEntryId === entry.id;
|
||||||
|
|
||||||
const classification = getClassification(entry.status)
|
const classification = getClassification(entry.status)
|
||||||
const numberOfRules = entry.rules.numberOfRules
|
|
||||||
let ingoingIcon;
|
let ingoingIcon;
|
||||||
let outgoingIcon;
|
let outgoingIcon;
|
||||||
switch(classification) {
|
switch(classification) {
|
||||||
@ -87,35 +79,6 @@ export const EntryItem: React.FC<EntryProps> = ({entry, style, headingMode, name
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let additionalRulesProperties = "";
|
|
||||||
let ruleSuccess = true;
|
|
||||||
let rule = 'latency' in entry.rules
|
|
||||||
if (rule) {
|
|
||||||
if (entry.rules.latency !== -1) {
|
|
||||||
if (entry.rules.latency >= entry.latency || !('latency' in entry)) {
|
|
||||||
additionalRulesProperties = styles.ruleSuccessRow
|
|
||||||
ruleSuccess = true
|
|
||||||
} else {
|
|
||||||
additionalRulesProperties = styles.ruleFailureRow
|
|
||||||
ruleSuccess = false
|
|
||||||
}
|
|
||||||
if (isSelected) {
|
|
||||||
additionalRulesProperties += ` ${entry.rules.latency >= entry.latency ? styles.ruleSuccessRowSelected : styles.ruleFailureRowSelected}`
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (entry.rules.status) {
|
|
||||||
additionalRulesProperties = styles.ruleSuccessRow
|
|
||||||
ruleSuccess = true
|
|
||||||
} else {
|
|
||||||
additionalRulesProperties = styles.ruleFailureRow
|
|
||||||
ruleSuccess = false
|
|
||||||
}
|
|
||||||
if (isSelected) {
|
|
||||||
additionalRulesProperties += ` ${entry.rules.status ? styles.ruleSuccessRowSelected : styles.ruleFailureRowSelected}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const isStatusCodeEnabled = ((entry.proto.name === "http" && "status" in entry) || entry.status !== 0);
|
const isStatusCodeEnabled = ((entry.proto.name === "http" && "status" in entry) || entry.status !== 0);
|
||||||
|
|
||||||
@ -123,7 +86,7 @@ export const EntryItem: React.FC<EntryProps> = ({entry, style, headingMode, name
|
|||||||
<div
|
<div
|
||||||
id={`entry-${entry.id}`}
|
id={`entry-${entry.id}`}
|
||||||
className={`${styles.row}
|
className={`${styles.row}
|
||||||
${isSelected && !rule ? styles.rowSelected : additionalRulesProperties}`}
|
${isSelected ? styles.rowSelected : ""}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!setFocusedEntryId) return;
|
if (!setFocusedEntryId) return;
|
||||||
setFocusedEntryId(entry.id);
|
setFocusedEntryId(entry.id);
|
||||||
@ -187,13 +150,7 @@ export const EntryItem: React.FC<EntryProps> = ({entry, style, headingMode, name
|
|||||||
</Queryable>
|
</Queryable>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{
|
|
||||||
rule ?
|
|
||||||
<div className={`${styles.ruleNumberText} ${ruleSuccess ? styles.ruleNumberTextSuccess : styles.ruleNumberTextFailure} ${rule ? styles.separatorRight : ""}`}>
|
|
||||||
{`Rules (${numberOfRules})`}
|
|
||||||
</div>
|
|
||||||
: ""
|
|
||||||
}
|
|
||||||
<div className={styles.separatorRight}>
|
<div className={styles.separatorRight}>
|
||||||
{headingMode ? <Queryable
|
{headingMode ? <Queryable
|
||||||
query={`namespace == "${namespace}"`}
|
query={`namespace == "${namespace}"`}
|
||||||
|
Loading…
Reference in New Issue
Block a user