mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-06-24 07:14:15 +00:00
Remove OAS contract monitoring feature (#1163)
This commit is contained in:
parent
a96072623f
commit
1ebc51b45e
@ -6,7 +6,6 @@ require (
|
|||||||
github.com/antelman107/net-wait-go v0.0.0-20210623112055-cf684aebda7b
|
github.com/antelman107/net-wait-go v0.0.0-20210623112055-cf684aebda7b
|
||||||
github.com/chanced/openapi v0.0.8
|
github.com/chanced/openapi v0.0.8
|
||||||
github.com/djherbis/atime v1.1.0
|
github.com/djherbis/atime v1.1.0
|
||||||
github.com/getkin/kin-openapi v0.89.0
|
|
||||||
github.com/gin-contrib/pprof v1.3.0
|
github.com/gin-contrib/pprof v1.3.0
|
||||||
github.com/gin-contrib/static v0.0.1
|
github.com/gin-contrib/static v0.0.1
|
||||||
github.com/gin-gonic/gin v1.7.7
|
github.com/gin-gonic/gin v1.7.7
|
||||||
@ -59,7 +58,6 @@ require (
|
|||||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
||||||
github.com/fatih/camelcase v1.0.0 // indirect
|
github.com/fatih/camelcase v1.0.0 // indirect
|
||||||
github.com/fvbommel/sortorder v1.0.2 // indirect
|
github.com/fvbommel/sortorder v1.0.2 // indirect
|
||||||
github.com/ghodss/yaml v1.0.0 // indirect
|
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/go-errors/errors v1.4.2 // indirect
|
github.com/go-errors/errors v1.4.2 // indirect
|
||||||
github.com/go-logr/logr v1.2.2 // indirect
|
github.com/go-logr/logr v1.2.2 // indirect
|
||||||
|
@ -211,9 +211,6 @@ github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui72
|
|||||||
github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo=
|
github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo=
|
||||||
github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||||
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
||||||
github.com/getkin/kin-openapi v0.89.0 h1:p4nagHchUKGn85z/f+pse4aSh50nIBOYjOhMIku2hiA=
|
|
||||||
github.com/getkin/kin-openapi v0.89.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
|
||||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/gin-contrib/pprof v1.3.0 h1:G9eK6HnbkSqDZBYbzG4wrjCsA4e+cvYAHUZw6W+W9K0=
|
github.com/gin-contrib/pprof v1.3.0 h1:G9eK6HnbkSqDZBYbzG4wrjCsA4e+cvYAHUZw6W+W9K0=
|
||||||
github.com/gin-contrib/pprof v1.3.0/go.mod h1:waMjT1H9b179t3CxuG1cV3DHpga6ybizwfBaM5OXaB0=
|
github.com/gin-contrib/pprof v1.3.0/go.mod h1:waMjT1H9b179t3CxuG1cV3DHpga6ybizwfBaM5OXaB0=
|
||||||
@ -373,7 +370,6 @@ github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2c
|
|||||||
github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
|
github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
|
||||||
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||||
|
@ -1,107 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/getkin/kin-openapi/openapi3"
|
|
||||||
"github.com/getkin/kin-openapi/openapi3filter"
|
|
||||||
"github.com/getkin/kin-openapi/routers"
|
|
||||||
legacyrouter "github.com/getkin/kin-openapi/routers/legacy"
|
|
||||||
|
|
||||||
"github.com/up9inc/mizu/shared"
|
|
||||||
"github.com/up9inc/mizu/tap/api"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
ContractNotApplicable api.ContractStatus = 0
|
|
||||||
ContractPassed api.ContractStatus = 1
|
|
||||||
ContractFailed api.ContractStatus = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
func loadOAS(ctx context.Context) (doc *openapi3.T, contractContent string, router routers.Router, err error) {
|
|
||||||
path := fmt.Sprintf("%s%s", shared.ConfigDirPath, shared.ContractFileName)
|
|
||||||
bytesValue, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
contractContent = string(bytesValue)
|
|
||||||
loader := &openapi3.Loader{Context: ctx}
|
|
||||||
doc, _ = loader.LoadFromData(bytesValue)
|
|
||||||
err = doc.Validate(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
router, _ = legacyrouter.NewRouter(doc)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateOAS(ctx context.Context, doc *openapi3.T, router routers.Router, req *http.Request, res *http.Response) (isValid bool, reqErr error, resErr error) {
|
|
||||||
isValid = true
|
|
||||||
reqErr = nil
|
|
||||||
resErr = nil
|
|
||||||
|
|
||||||
// Find route
|
|
||||||
route, pathParams, err := router.FindRoute(req)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate request
|
|
||||||
requestValidationInput := &openapi3filter.RequestValidationInput{
|
|
||||||
Request: req,
|
|
||||||
PathParams: pathParams,
|
|
||||||
Route: route,
|
|
||||||
}
|
|
||||||
if reqErr = openapi3filter.ValidateRequest(ctx, requestValidationInput); reqErr != nil {
|
|
||||||
isValid = false
|
|
||||||
}
|
|
||||||
|
|
||||||
responseValidationInput := &openapi3filter.ResponseValidationInput{
|
|
||||||
RequestValidationInput: requestValidationInput,
|
|
||||||
Status: res.StatusCode,
|
|
||||||
Header: res.Header,
|
|
||||||
}
|
|
||||||
|
|
||||||
if res.Body != nil {
|
|
||||||
body, _ := ioutil.ReadAll(res.Body)
|
|
||||||
res.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
|
||||||
responseValidationInput.SetBodyBytes(body)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate response.
|
|
||||||
if resErr = openapi3filter.ValidateResponse(ctx, responseValidationInput); resErr != nil {
|
|
||||||
isValid = false
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleOAS(ctx context.Context, doc *openapi3.T, router routers.Router, req *http.Request, res *http.Response, contractContent string) (contract api.Contract) {
|
|
||||||
contract = api.Contract{
|
|
||||||
Content: contractContent,
|
|
||||||
Status: ContractNotApplicable,
|
|
||||||
}
|
|
||||||
|
|
||||||
isValid, reqErr, resErr := validateOAS(ctx, doc, router, req, res)
|
|
||||||
if isValid {
|
|
||||||
contract.Status = ContractPassed
|
|
||||||
} else {
|
|
||||||
contract.Status = ContractFailed
|
|
||||||
if reqErr != nil {
|
|
||||||
contract.RequestReason = reqErr.Error()
|
|
||||||
} else {
|
|
||||||
contract.RequestReason = ""
|
|
||||||
}
|
|
||||||
if resErr != nil {
|
|
||||||
contract.ResponseReason = resErr.Error()
|
|
||||||
} else {
|
|
||||||
contract.ResponseReason = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
@ -99,14 +99,6 @@ func startReadingChannel(outputItems <-chan *tapApi.OutputChannelItem, extension
|
|||||||
panic("Channel of captured messages is nil")
|
panic("Channel of captured messages is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
disableOASValidation := false
|
|
||||||
ctx := context.Background()
|
|
||||||
doc, contractContent, router, err := loadOAS(ctx)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Infof("Disabled OAS validation: %s", err.Error())
|
|
||||||
disableOASValidation = true
|
|
||||||
}
|
|
||||||
|
|
||||||
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, resolvedDestionation, namespace := resolveIP(item.ConnectionInfo)
|
||||||
@ -117,19 +109,6 @@ func startReadingChannel(outputItems <-chan *tapApi.OutputChannelItem, extension
|
|||||||
|
|
||||||
mizuEntry := extension.Dissector.Analyze(item, resolvedSource, resolvedDestionation, namespace)
|
mizuEntry := extension.Dissector.Analyze(item, resolvedSource, resolvedDestionation, namespace)
|
||||||
if extension.Protocol.Name == "http" {
|
if extension.Protocol.Name == "http" {
|
||||||
if !disableOASValidation {
|
|
||||||
var httpPair tapApi.HTTPRequestResponsePair
|
|
||||||
if err := json.Unmarshal([]byte(mizuEntry.HTTPPair), &httpPair); err != nil {
|
|
||||||
logger.Log.Error(err)
|
|
||||||
} else {
|
|
||||||
contract := handleOAS(ctx, doc, router, httpPair.Request.Payload.RawRequest, httpPair.Response.Payload.RawResponse, contractContent)
|
|
||||||
mizuEntry.ContractStatus = contract.Status
|
|
||||||
mizuEntry.ContractRequestReason = contract.RequestReason
|
|
||||||
mizuEntry.ContractResponseReason = contract.ResponseReason
|
|
||||||
mizuEntry.ContractContent = contract.Content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
harEntry, err := har.NewEntry(mizuEntry.Request, mizuEntry.Response, mizuEntry.StartTime, mizuEntry.ElapsedTime)
|
harEntry, err := har.NewEntry(mizuEntry.Request, mizuEntry.Response, mizuEntry.StartTime, mizuEntry.ElapsedTime)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
rules, _, _ := models.RunValidationRulesState(*harEntry, mizuEntry.Destination.Name)
|
rules, _, _ := models.RunValidationRulesState(*harEntry, mizuEntry.Destination.Name)
|
||||||
|
@ -54,7 +54,6 @@ func init() {
|
|||||||
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().String(configStructs.EnforcePolicyFile, defaultTapConfig.EnforcePolicyFile, "Yaml file path with policy rules")
|
||||||
tapCmd.Flags().String(configStructs.ContractFile, defaultTapConfig.ContractFile, "OAS/Swagger file to validate to monitor the contracts")
|
|
||||||
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")
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -13,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"
|
||||||
|
|
||||||
"github.com/getkin/kin-openapi/openapi3"
|
|
||||||
"gopkg.in/yaml.v3"
|
"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"
|
||||||
@ -57,30 +55,6 @@ func RunMizuTap() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read and validate the OAS file
|
|
||||||
var serializedContract string
|
|
||||||
if config.Config.Tap.ContractFile != "" {
|
|
||||||
bytes, err := ioutil.ReadFile(config.Config.Tap.ContractFile)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Errorf(uiUtils.Error, fmt.Sprintf("Error reading contract file: %v", errormessage.FormatError(err)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
serializedContract = string(bytes)
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
loader := &openapi3.Loader{Context: ctx}
|
|
||||||
doc, err := loader.LoadFromData(bytes)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Errorf(uiUtils.Error, fmt.Sprintf("Error loading contract file: %v", errormessage.FormatError(err)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = doc.Validate(ctx)
|
|
||||||
if err != nil {
|
|
||||||
logger.Log.Errorf(uiUtils.Error, fmt.Sprintf("Error validating contract file: %v", errormessage.FormatError(err)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
kubernetesProvider, err := getKubernetesProviderForCli()
|
kubernetesProvider, err := getKubernetesProviderForCli()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -124,7 +98,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, serializedContract, 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, 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 {
|
||||||
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")
|
||||||
|
@ -24,7 +24,6 @@ const (
|
|||||||
InsertionFilterName = "insertion-filter"
|
InsertionFilterName = "insertion-filter"
|
||||||
DryRunTapName = "dry-run"
|
DryRunTapName = "dry-run"
|
||||||
EnforcePolicyFile = "traffic-validation-file"
|
EnforcePolicyFile = "traffic-validation-file"
|
||||||
ContractFile = "contract"
|
|
||||||
ServiceMeshName = "service-mesh"
|
ServiceMeshName = "service-mesh"
|
||||||
TlsName = "tls"
|
TlsName = "tls"
|
||||||
ProfilerName = "profiler"
|
ProfilerName = "profiler"
|
||||||
@ -43,7 +42,6 @@ type TapConfig struct {
|
|||||||
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"`
|
EnforcePolicyFile string `yaml:"traffic-validation-file"`
|
||||||
ContractFile string `yaml:"contract"`
|
|
||||||
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"`
|
||||||
|
@ -5,16 +5,13 @@ go 1.17
|
|||||||
require (
|
require (
|
||||||
github.com/creasty/defaults v1.5.2
|
github.com/creasty/defaults v1.5.2
|
||||||
github.com/denisbrodbeck/machineid v1.0.1
|
github.com/denisbrodbeck/machineid v1.0.1
|
||||||
github.com/getkin/kin-openapi v0.89.0
|
|
||||||
github.com/google/go-github/v37 v37.0.0
|
github.com/google/go-github/v37 v37.0.0
|
||||||
github.com/google/uuid v1.3.0
|
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
|
||||||
github.com/spf13/cobra v1.3.0
|
github.com/spf13/cobra v1.3.0
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
github.com/up9inc/mizu/logger v0.0.0
|
github.com/up9inc/mizu/logger v0.0.0
|
||||||
github.com/up9inc/mizu/shared v0.0.0
|
github.com/up9inc/mizu/shared v0.0.0
|
||||||
github.com/up9inc/mizu/tap/api v0.0.0
|
github.com/up9inc/mizu/tap/api v0.0.0
|
||||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
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
|
||||||
@ -39,7 +36,6 @@ require (
|
|||||||
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
|
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
|
||||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
||||||
github.com/fvbommel/sortorder v1.0.2 // indirect
|
github.com/fvbommel/sortorder v1.0.2 // indirect
|
||||||
github.com/ghodss/yaml v1.0.0 // indirect
|
|
||||||
github.com/go-errors/errors v1.4.2 // indirect
|
github.com/go-errors/errors v1.4.2 // indirect
|
||||||
github.com/go-logr/logr v1.2.2 // indirect
|
github.com/go-logr/logr v1.2.2 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||||
@ -52,8 +48,8 @@ require (
|
|||||||
github.com/google/go-cmp v0.5.7 // indirect
|
github.com/google/go-cmp v0.5.7 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // 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/googleapis/gnostic v0.5.5 // indirect
|
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||||
github.com/imdario/mergo v0.3.12 // indirect
|
github.com/imdario/mergo v0.3.12 // indirect
|
||||||
@ -79,6 +75,7 @@ require (
|
|||||||
go.starlark.net v0.0.0-20220203230714-bb14e151c28f // indirect
|
go.starlark.net v0.0.0-20220203230714-bb14e151c28f // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab // indirect
|
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab // indirect
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
||||||
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220207234003-57398862261d // indirect
|
golang.org/x/sys v0.0.0-20220207234003-57398862261d // indirect
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
|
@ -190,9 +190,6 @@ github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui72
|
|||||||
github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo=
|
github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo=
|
||||||
github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||||
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
||||||
github.com/getkin/kin-openapi v0.89.0 h1:p4nagHchUKGn85z/f+pse4aSh50nIBOYjOhMIku2hiA=
|
|
||||||
github.com/getkin/kin-openapi v0.89.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
|
|
||||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||||
@ -294,7 +291,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=
|
||||||
|
@ -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, serializedContract 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, 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) {
|
||||||
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, serializedContract, serializedMizuConfig, mizuResourcesNamespace); err != nil {
|
if err := createMizuConfigmap(ctx, kubernetesProvider, serializedValidationRules, 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, serializedContract string, serializedMizuConfig string, mizuResourcesNamespace string) error {
|
func createMizuConfigmap(ctx context.Context, kubernetesProvider *kubernetes.Provider, serializedValidationRules string, serializedMizuConfig string, mizuResourcesNamespace string) error {
|
||||||
err := kubernetesProvider.CreateConfigMap(ctx, mizuResourcesNamespace, kubernetes.ConfigMapName, serializedValidationRules, serializedContract, serializedMizuConfig)
|
err := kubernetesProvider.CreateConfigMap(ctx, mizuResourcesNamespace, kubernetes.ConfigMapName, serializedValidationRules, serializedMizuConfig)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ const (
|
|||||||
ConfigDirPath = "/app/config/"
|
ConfigDirPath = "/app/config/"
|
||||||
DataDirPath = "/app/data/"
|
DataDirPath = "/app/data/"
|
||||||
ValidationRulesFileName = "validation-rules.yaml"
|
ValidationRulesFileName = "validation-rules.yaml"
|
||||||
ContractFileName = "contract-oas.yaml"
|
|
||||||
ConfigFileName = "mizu-config.json"
|
ConfigFileName = "mizu-config.json"
|
||||||
DefaultApiServerPort = 8899
|
DefaultApiServerPort = 8899
|
||||||
LogLevelEnvVar = "LOG_LEVEL"
|
LogLevelEnvVar = "LOG_LEVEL"
|
||||||
|
@ -684,14 +684,11 @@ func (provider *Provider) handleRemovalError(err error) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (provider *Provider) CreateConfigMap(ctx context.Context, namespace string, configMapName string, serializedValidationRules string, serializedContract string, serializedMizuConfig string) error {
|
func (provider *Provider) CreateConfigMap(ctx context.Context, namespace string, configMapName string, serializedValidationRules string, serializedMizuConfig string) error {
|
||||||
configMapData := make(map[string]string)
|
configMapData := make(map[string]string)
|
||||||
if serializedValidationRules != "" {
|
if serializedValidationRules != "" {
|
||||||
configMapData[shared.ValidationRulesFileName] = serializedValidationRules
|
configMapData[shared.ValidationRulesFileName] = serializedValidationRules
|
||||||
}
|
}
|
||||||
if serializedContract != "" {
|
|
||||||
configMapData[shared.ContractFileName] = serializedContract
|
|
||||||
}
|
|
||||||
configMapData[shared.ConfigFileName] = serializedMizuConfig
|
configMapData[shared.ConfigFileName] = serializedMizuConfig
|
||||||
|
|
||||||
configMap := &core.ConfigMap{
|
configMap := &core.ConfigMap{
|
||||||
|
250
tap/api/api.go
250
tap/api/api.go
@ -2,24 +2,13 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"sort"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/martian/har"
|
|
||||||
|
|
||||||
"github.com/up9inc/mizu/tap/dbgctl"
|
"github.com/up9inc/mizu/tap/dbgctl"
|
||||||
)
|
)
|
||||||
|
|
||||||
const mizuTestEnvVar = "MIZU_TEST"
|
|
||||||
const UnknownNamespace = ""
|
const UnknownNamespace = ""
|
||||||
|
|
||||||
var UnknownIp = net.IP{0, 0, 0, 0}
|
var UnknownIp = net.IP{0, 0, 0, 0}
|
||||||
@ -161,26 +150,21 @@ func (e *Emitting) Emit(item *OutputChannelItem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Entry struct {
|
type Entry struct {
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
Protocol Protocol `json:"proto"`
|
Protocol Protocol `json:"proto"`
|
||||||
Capture Capture `json:"capture"`
|
Capture Capture `json:"capture"`
|
||||||
Source *TCP `json:"src"`
|
Source *TCP `json:"src"`
|
||||||
Destination *TCP `json:"dst"`
|
Destination *TCP `json:"dst"`
|
||||||
Namespace string `json:"namespace"`
|
Namespace string `json:"namespace"`
|
||||||
Outgoing bool `json:"outgoing"`
|
Outgoing bool `json:"outgoing"`
|
||||||
Timestamp int64 `json:"timestamp"`
|
Timestamp int64 `json:"timestamp"`
|
||||||
StartTime time.Time `json:"startTime"`
|
StartTime time.Time `json:"startTime"`
|
||||||
Request map[string]interface{} `json:"request"`
|
Request map[string]interface{} `json:"request"`
|
||||||
Response map[string]interface{} `json:"response"`
|
Response map[string]interface{} `json:"response"`
|
||||||
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"`
|
Rules ApplicableRules `json:"rules,omitempty"`
|
||||||
ContractStatus ContractStatus `json:"contractStatus,omitempty"`
|
|
||||||
ContractRequestReason string `json:"contractRequestReason,omitempty"`
|
|
||||||
ContractResponseReason string `json:"contractResponseReason,omitempty"`
|
|
||||||
ContractContent string `json:"contractContent,omitempty"`
|
|
||||||
HTTPPair string `json:"httpPair,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type EntryWrapper struct {
|
type EntryWrapper struct {
|
||||||
@ -193,22 +177,21 @@ type EntryWrapper struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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"`
|
Rules ApplicableRules `json:"rules,omitempty"`
|
||||||
ContractStatus ContractStatus `json:"contractStatus"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApplicableRules struct {
|
type ApplicableRules struct {
|
||||||
@ -217,15 +200,6 @@ type ApplicableRules struct {
|
|||||||
NumberOfRules int `json:"numberOfRules,omitempty"`
|
NumberOfRules int `json:"numberOfRules,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ContractStatus int
|
|
||||||
|
|
||||||
type Contract struct {
|
|
||||||
Status ContractStatus `json:"status"`
|
|
||||||
RequestReason string `json:"requestReason"`
|
|
||||||
ResponseReason string `json:"responseReason"`
|
|
||||||
Content string `json:"content"`
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TABLE string = "table"
|
TABLE string = "table"
|
||||||
BODY string = "body"
|
BODY string = "body"
|
||||||
@ -246,170 +220,6 @@ type TableData struct {
|
|||||||
Selector string `json:"selector"`
|
Selector string `json:"selector"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
TypeHttpRequest = iota
|
|
||||||
TypeHttpResponse
|
|
||||||
)
|
|
||||||
|
|
||||||
type HTTPPayload struct {
|
|
||||||
Type uint8
|
|
||||||
Data interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPPayloader interface {
|
|
||||||
MarshalJSON() ([]byte, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPWrapper struct {
|
|
||||||
Method string `json:"method"`
|
|
||||||
Url string `json:"url"`
|
|
||||||
Details interface{} `json:"details"`
|
|
||||||
RawRequest *HTTPRequestWrapper `json:"rawRequest"`
|
|
||||||
RawResponse *HTTPResponseWrapper `json:"rawResponse"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h HTTPPayload) MarshalJSON() ([]byte, error) {
|
|
||||||
_, testEnvEnabled := os.LookupEnv(mizuTestEnvVar)
|
|
||||||
switch h.Type {
|
|
||||||
case TypeHttpRequest:
|
|
||||||
harRequest, err := har.NewRequest(h.Data.(*http.Request), true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("Failed converting request to HAR")
|
|
||||||
}
|
|
||||||
sort.Slice(harRequest.Headers, func(i, j int) bool {
|
|
||||||
if harRequest.Headers[i].Name < harRequest.Headers[j].Name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if harRequest.Headers[i].Name > harRequest.Headers[j].Name {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return harRequest.Headers[i].Value < harRequest.Headers[j].Value
|
|
||||||
})
|
|
||||||
sort.Slice(harRequest.QueryString, func(i, j int) bool {
|
|
||||||
if harRequest.QueryString[i].Name < harRequest.QueryString[j].Name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if harRequest.QueryString[i].Name > harRequest.QueryString[j].Name {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return harRequest.QueryString[i].Value < harRequest.QueryString[j].Value
|
|
||||||
})
|
|
||||||
if harRequest.PostData != nil {
|
|
||||||
sort.Slice(harRequest.PostData.Params, func(i, j int) bool {
|
|
||||||
if harRequest.PostData.Params[i].Name < harRequest.PostData.Params[j].Name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if harRequest.PostData.Params[i].Name > harRequest.PostData.Params[j].Name {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return harRequest.PostData.Params[i].Value < harRequest.PostData.Params[j].Value
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if testEnvEnabled {
|
|
||||||
harRequest.URL = ""
|
|
||||||
}
|
|
||||||
var reqWrapper *HTTPRequestWrapper
|
|
||||||
if !testEnvEnabled {
|
|
||||||
reqWrapper = &HTTPRequestWrapper{Request: h.Data.(*http.Request)}
|
|
||||||
}
|
|
||||||
return json.Marshal(&HTTPWrapper{
|
|
||||||
Method: harRequest.Method,
|
|
||||||
Details: harRequest,
|
|
||||||
RawRequest: reqWrapper,
|
|
||||||
})
|
|
||||||
case TypeHttpResponse:
|
|
||||||
harResponse, err := har.NewResponse(h.Data.(*http.Response), true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("Failed converting response to HAR")
|
|
||||||
}
|
|
||||||
sort.Slice(harResponse.Headers, func(i, j int) bool {
|
|
||||||
if harResponse.Headers[i].Name < harResponse.Headers[j].Name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if harResponse.Headers[i].Name > harResponse.Headers[j].Name {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return harResponse.Headers[i].Value < harResponse.Headers[j].Value
|
|
||||||
})
|
|
||||||
sort.Slice(harResponse.Cookies, func(i, j int) bool {
|
|
||||||
if harResponse.Cookies[i].Name < harResponse.Cookies[j].Name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if harResponse.Cookies[i].Name > harResponse.Cookies[j].Name {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return harResponse.Cookies[i].Value < harResponse.Cookies[j].Value
|
|
||||||
})
|
|
||||||
var resWrapper *HTTPResponseWrapper
|
|
||||||
if !testEnvEnabled {
|
|
||||||
resWrapper = &HTTPResponseWrapper{Response: h.Data.(*http.Response)}
|
|
||||||
}
|
|
||||||
return json.Marshal(&HTTPWrapper{
|
|
||||||
Method: "",
|
|
||||||
Url: "",
|
|
||||||
Details: harResponse,
|
|
||||||
RawResponse: resWrapper,
|
|
||||||
})
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("HTTP payload cannot be marshaled: %v", h.Type))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPWrapperTricky struct {
|
|
||||||
Method string `json:"method"`
|
|
||||||
Url string `json:"url"`
|
|
||||||
Details interface{} `json:"details"`
|
|
||||||
RawRequest *http.Request `json:"rawRequest"`
|
|
||||||
RawResponse *http.Response `json:"rawResponse"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPMessage struct {
|
|
||||||
IsRequest bool `json:"isRequest"`
|
|
||||||
CaptureTime time.Time `json:"captureTime"`
|
|
||||||
Payload HTTPWrapperTricky `json:"payload"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPRequestResponsePair struct {
|
|
||||||
Request HTTPMessage `json:"request"`
|
|
||||||
Response HTTPMessage `json:"response"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPRequestWrapper struct {
|
|
||||||
*http.Request
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *HTTPRequestWrapper) MarshalJSON() ([]byte, error) {
|
|
||||||
body, _ := ioutil.ReadAll(r.Request.Body)
|
|
||||||
r.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
|
||||||
return json.Marshal(&struct { //nolint
|
|
||||||
Body string `json:"Body,omitempty"`
|
|
||||||
GetBody string `json:"GetBody,omitempty"`
|
|
||||||
Cancel string `json:"Cancel,omitempty"`
|
|
||||||
*http.Request
|
|
||||||
}{
|
|
||||||
Body: string(body),
|
|
||||||
Request: r.Request,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type HTTPResponseWrapper struct {
|
|
||||||
*http.Response
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *HTTPResponseWrapper) MarshalJSON() ([]byte, error) {
|
|
||||||
body, _ := ioutil.ReadAll(r.Response.Body)
|
|
||||||
r.Response.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
|
||||||
return json.Marshal(&struct { //nolint
|
|
||||||
Body string `json:"Body,omitempty"`
|
|
||||||
GetBody string `json:"GetBody,omitempty"`
|
|
||||||
Cancel string `json:"Cancel,omitempty"`
|
|
||||||
*http.Response
|
|
||||||
}{
|
|
||||||
Body: string(body),
|
|
||||||
Response: r.Response,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type TcpReaderDataMsg interface {
|
type TcpReaderDataMsg interface {
|
||||||
GetBytes() []byte
|
GetBytes() []byte
|
||||||
GetTimestamp() time.Time
|
GetTimestamp() time.Time
|
||||||
|
@ -2,9 +2,6 @@ module github.com/up9inc/mizu/tap/api
|
|||||||
|
|
||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require (
|
require github.com/up9inc/mizu/tap/dbgctl v0.0.0
|
||||||
github.com/google/martian v2.1.0+incompatible
|
|
||||||
github.com/up9inc/mizu/tap/dbgctl v0.0.0
|
|
||||||
)
|
|
||||||
|
|
||||||
replace github.com/up9inc/mizu/tap/dbgctl v0.0.0 => ../dbgctl
|
replace github.com/up9inc/mizu/tap/dbgctl v0.0.0 => ../dbgctl
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
|
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
|
@ -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/expect8/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/expect11/amqp/\* expect
|
||||||
|
@ -9,7 +9,6 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.0 // indirect
|
github.com/davecgh/go-spew v1.1.0 // indirect
|
||||||
github.com/google/martian v2.1.0+incompatible // indirect
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
@ -276,22 +276,21 @@ func (d dissecting) Summarize(entry *api.Entry) *api.BaseEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &api.BaseEntry{
|
return &api.BaseEntry{
|
||||||
Id: entry.Id,
|
Id: entry.Id,
|
||||||
Protocol: entry.Protocol,
|
Protocol: entry.Protocol,
|
||||||
Capture: entry.Capture,
|
Capture: entry.Capture,
|
||||||
Summary: summary,
|
Summary: summary,
|
||||||
SummaryQuery: summaryQuery,
|
SummaryQuery: summaryQuery,
|
||||||
Status: 0,
|
Status: 0,
|
||||||
StatusQuery: "",
|
StatusQuery: "",
|
||||||
Method: method,
|
Method: method,
|
||||||
MethodQuery: methodQuery,
|
MethodQuery: methodQuery,
|
||||||
Timestamp: entry.Timestamp,
|
Timestamp: entry.Timestamp,
|
||||||
Source: entry.Source,
|
Source: entry.Source,
|
||||||
Destination: entry.Destination,
|
Destination: entry.Destination,
|
||||||
IsOutgoing: entry.Outgoing,
|
IsOutgoing: entry.Outgoing,
|
||||||
Latency: entry.ElapsedTime,
|
Latency: entry.ElapsedTime,
|
||||||
Rules: entry.Rules,
|
Rules: entry.Rules,
|
||||||
ContractStatus: entry.ContractStatus,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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/expect10/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/expect12/http/\* expect
|
||||||
|
@ -4,6 +4,7 @@ go 1.17
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/beevik/etree v1.1.0
|
github.com/beevik/etree v1.1.0
|
||||||
|
github.com/google/martian v2.1.0+incompatible
|
||||||
github.com/mertyildiran/gqlparser/v2 v2.4.6
|
github.com/mertyildiran/gqlparser/v2 v2.4.6
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/up9inc/mizu/tap/api v0.0.0
|
github.com/up9inc/mizu/tap/api v0.0.0
|
||||||
@ -12,7 +13,6 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/google/martian v2.1.0+incompatible // indirect
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
|
@ -32,7 +32,7 @@ func replaceForwardedFor(item *api.OutputChannelItem) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
request := item.Pair.Request.Payload.(api.HTTPPayload).Data.(*http.Request)
|
request := item.Pair.Request.Payload.(HTTPPayload).Data.(*http.Request)
|
||||||
|
|
||||||
forwardedFor := request.Header.Get("X-Forwarded-For")
|
forwardedFor := request.Header.Get("X-Forwarded-For")
|
||||||
if forwardedFor == "" {
|
if forwardedFor == "" {
|
||||||
|
@ -279,7 +279,7 @@ func (d dissecting) Analyze(item *api.OutputChannelItem, resolvedSource string,
|
|||||||
if elapsedTime < 0 {
|
if elapsedTime < 0 {
|
||||||
elapsedTime = 0
|
elapsedTime = 0
|
||||||
}
|
}
|
||||||
httpPair, _ := json.Marshal(item.Pair)
|
|
||||||
return &api.Entry{
|
return &api.Entry{
|
||||||
Protocol: item.Protocol,
|
Protocol: item.Protocol,
|
||||||
Capture: item.Capture,
|
Capture: item.Capture,
|
||||||
@ -302,7 +302,6 @@ func (d dissecting) Analyze(item *api.OutputChannelItem, resolvedSource string,
|
|||||||
Timestamp: item.Timestamp,
|
Timestamp: item.Timestamp,
|
||||||
StartTime: item.Pair.Request.CaptureTime,
|
StartTime: item.Pair.Request.CaptureTime,
|
||||||
ElapsedTime: elapsedTime,
|
ElapsedTime: elapsedTime,
|
||||||
HTTPPair: string(httpPair),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,22 +314,21 @@ func (d dissecting) Summarize(entry *api.Entry) *api.BaseEntry {
|
|||||||
statusQuery := fmt.Sprintf(`response.status == %d`, status)
|
statusQuery := fmt.Sprintf(`response.status == %d`, status)
|
||||||
|
|
||||||
return &api.BaseEntry{
|
return &api.BaseEntry{
|
||||||
Id: entry.Id,
|
Id: entry.Id,
|
||||||
Protocol: entry.Protocol,
|
Protocol: entry.Protocol,
|
||||||
Capture: entry.Capture,
|
Capture: entry.Capture,
|
||||||
Summary: summary,
|
Summary: summary,
|
||||||
SummaryQuery: summaryQuery,
|
SummaryQuery: summaryQuery,
|
||||||
Status: status,
|
Status: status,
|
||||||
StatusQuery: statusQuery,
|
StatusQuery: statusQuery,
|
||||||
Method: method,
|
Method: method,
|
||||||
MethodQuery: methodQuery,
|
MethodQuery: methodQuery,
|
||||||
Timestamp: entry.Timestamp,
|
Timestamp: entry.Timestamp,
|
||||||
Source: entry.Source,
|
Source: entry.Source,
|
||||||
Destination: entry.Destination,
|
Destination: entry.Destination,
|
||||||
IsOutgoing: entry.Outgoing,
|
IsOutgoing: entry.Outgoing,
|
||||||
Latency: entry.ElapsedTime,
|
Latency: entry.ElapsedTime,
|
||||||
Rules: entry.Rules,
|
Rules: entry.Rules,
|
||||||
ContractStatus: entry.ContractStatus,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ func (matcher *requestResponseMatcher) registerRequest(ident string, request *ht
|
|||||||
IsRequest: true,
|
IsRequest: true,
|
||||||
CaptureTime: captureTime,
|
CaptureTime: captureTime,
|
||||||
CaptureSize: captureSize,
|
CaptureSize: captureSize,
|
||||||
Payload: api.HTTPPayload{
|
Payload: HTTPPayload{
|
||||||
Type: TypeHttpRequest,
|
Type: TypeHttpRequest,
|
||||||
Data: request,
|
Data: request,
|
||||||
},
|
},
|
||||||
@ -53,7 +53,7 @@ func (matcher *requestResponseMatcher) registerResponse(ident string, response *
|
|||||||
IsRequest: false,
|
IsRequest: false,
|
||||||
CaptureTime: captureTime,
|
CaptureTime: captureTime,
|
||||||
CaptureSize: captureSize,
|
CaptureSize: captureSize,
|
||||||
Payload: api.HTTPPayload{
|
Payload: HTTPPayload{
|
||||||
Type: TypeHttpResponse,
|
Type: TypeHttpResponse,
|
||||||
Data: response,
|
Data: response,
|
||||||
},
|
},
|
||||||
|
@ -30,7 +30,7 @@ func IsIgnoredUserAgent(item *api.OutputChannelItem, options *api.TrafficFilteri
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
request := item.Pair.Request.Payload.(api.HTTPPayload).Data.(*http.Request)
|
request := item.Pair.Request.Payload.(HTTPPayload).Data.(*http.Request)
|
||||||
|
|
||||||
for headerKey, headerValues := range request.Header {
|
for headerKey, headerValues := range request.Header {
|
||||||
if strings.ToLower(headerKey) == userAgent {
|
if strings.ToLower(headerKey) == userAgent {
|
||||||
@ -50,8 +50,8 @@ func IsIgnoredUserAgent(item *api.OutputChannelItem, options *api.TrafficFilteri
|
|||||||
}
|
}
|
||||||
|
|
||||||
func FilterSensitiveData(item *api.OutputChannelItem, options *api.TrafficFilteringOptions) {
|
func FilterSensitiveData(item *api.OutputChannelItem, options *api.TrafficFilteringOptions) {
|
||||||
request := item.Pair.Request.Payload.(api.HTTPPayload).Data.(*http.Request)
|
request := item.Pair.Request.Payload.(HTTPPayload).Data.(*http.Request)
|
||||||
response := item.Pair.Response.Payload.(api.HTTPPayload).Data.(*http.Response)
|
response := item.Pair.Response.Payload.(HTTPPayload).Data.(*http.Response)
|
||||||
|
|
||||||
filterHeaders(&request.Header)
|
filterHeaders(&request.Header)
|
||||||
filterHeaders(&response.Header)
|
filterHeaders(&response.Header)
|
||||||
|
100
tap/extensions/http/structs.go
Normal file
100
tap/extensions/http/structs.go
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"sort"
|
||||||
|
|
||||||
|
"github.com/google/martian/har"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HTTPPayload struct {
|
||||||
|
Type uint8
|
||||||
|
Data interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type HTTPPayloader interface {
|
||||||
|
MarshalJSON() ([]byte, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type HTTPWrapper struct {
|
||||||
|
Method string `json:"method"`
|
||||||
|
Url string `json:"url"`
|
||||||
|
Details interface{} `json:"details"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h HTTPPayload) MarshalJSON() ([]byte, error) {
|
||||||
|
switch h.Type {
|
||||||
|
case TypeHttpRequest:
|
||||||
|
harRequest, err := har.NewRequest(h.Data.(*http.Request), true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Failed converting request to HAR")
|
||||||
|
}
|
||||||
|
sort.Slice(harRequest.Headers, func(i, j int) bool {
|
||||||
|
if harRequest.Headers[i].Name < harRequest.Headers[j].Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if harRequest.Headers[i].Name > harRequest.Headers[j].Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return harRequest.Headers[i].Value < harRequest.Headers[j].Value
|
||||||
|
})
|
||||||
|
sort.Slice(harRequest.QueryString, func(i, j int) bool {
|
||||||
|
if harRequest.QueryString[i].Name < harRequest.QueryString[j].Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if harRequest.QueryString[i].Name > harRequest.QueryString[j].Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return harRequest.QueryString[i].Value < harRequest.QueryString[j].Value
|
||||||
|
})
|
||||||
|
if harRequest.PostData != nil {
|
||||||
|
sort.Slice(harRequest.PostData.Params, func(i, j int) bool {
|
||||||
|
if harRequest.PostData.Params[i].Name < harRequest.PostData.Params[j].Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if harRequest.PostData.Params[i].Name > harRequest.PostData.Params[j].Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return harRequest.PostData.Params[i].Value < harRequest.PostData.Params[j].Value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return json.Marshal(&HTTPWrapper{
|
||||||
|
Method: harRequest.Method,
|
||||||
|
Url: "",
|
||||||
|
Details: harRequest,
|
||||||
|
})
|
||||||
|
case TypeHttpResponse:
|
||||||
|
harResponse, err := har.NewResponse(h.Data.(*http.Response), true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Failed converting response to HAR")
|
||||||
|
}
|
||||||
|
sort.Slice(harResponse.Headers, func(i, j int) bool {
|
||||||
|
if harResponse.Headers[i].Name < harResponse.Headers[j].Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if harResponse.Headers[i].Name > harResponse.Headers[j].Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return harResponse.Headers[i].Value < harResponse.Headers[j].Value
|
||||||
|
})
|
||||||
|
sort.Slice(harResponse.Cookies, func(i, j int) bool {
|
||||||
|
if harResponse.Cookies[i].Name < harResponse.Cookies[j].Name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if harResponse.Cookies[i].Name > harResponse.Cookies[j].Name {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return harResponse.Cookies[i].Value < harResponse.Cookies[j].Value
|
||||||
|
})
|
||||||
|
return json.Marshal(&HTTPWrapper{
|
||||||
|
Method: "",
|
||||||
|
Url: "",
|
||||||
|
Details: harResponse,
|
||||||
|
})
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("HTTP payload cannot be marshaled: %v", h.Type))
|
||||||
|
}
|
||||||
|
}
|
@ -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/expect9/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/expect11/kafka/\* expect
|
||||||
|
@ -14,7 +14,6 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.0 // indirect
|
github.com/davecgh/go-spew v1.1.0 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/martian v2.1.0+incompatible // indirect
|
|
||||||
github.com/klauspost/compress v1.14.2 // indirect
|
github.com/klauspost/compress v1.14.2 // indirect
|
||||||
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
|
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
@ -11,8 +11,6 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
|||||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
|
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
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/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||||
github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw=
|
github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw=
|
||||||
github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||||
|
@ -186,22 +186,21 @@ func (d dissecting) Summarize(entry *api.Entry) *api.BaseEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &api.BaseEntry{
|
return &api.BaseEntry{
|
||||||
Id: entry.Id,
|
Id: entry.Id,
|
||||||
Protocol: entry.Protocol,
|
Protocol: entry.Protocol,
|
||||||
Capture: entry.Capture,
|
Capture: entry.Capture,
|
||||||
Summary: summary,
|
Summary: summary,
|
||||||
SummaryQuery: summaryQuery,
|
SummaryQuery: summaryQuery,
|
||||||
Status: status,
|
Status: status,
|
||||||
StatusQuery: statusQuery,
|
StatusQuery: statusQuery,
|
||||||
Method: method,
|
Method: method,
|
||||||
MethodQuery: methodQuery,
|
MethodQuery: methodQuery,
|
||||||
Timestamp: entry.Timestamp,
|
Timestamp: entry.Timestamp,
|
||||||
Source: entry.Source,
|
Source: entry.Source,
|
||||||
Destination: entry.Destination,
|
Destination: entry.Destination,
|
||||||
IsOutgoing: entry.Outgoing,
|
IsOutgoing: entry.Outgoing,
|
||||||
Latency: entry.ElapsedTime,
|
Latency: entry.ElapsedTime,
|
||||||
Rules: entry.Rules,
|
Rules: entry.Rules,
|
||||||
ContractStatus: entry.ContractStatus,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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/expect8/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/expect11/redis/\* expect
|
||||||
|
@ -9,7 +9,6 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/davecgh/go-spew v1.1.0 // indirect
|
github.com/davecgh/go-spew v1.1.0 // indirect
|
||||||
github.com/google/martian v2.1.0+incompatible // indirect
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
github.com/up9inc/mizu/tap/dbgctl v0.0.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
@ -114,22 +114,21 @@ func (d dissecting) Summarize(entry *api.Entry) *api.BaseEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &api.BaseEntry{
|
return &api.BaseEntry{
|
||||||
Id: entry.Id,
|
Id: entry.Id,
|
||||||
Protocol: entry.Protocol,
|
Protocol: entry.Protocol,
|
||||||
Capture: entry.Capture,
|
Capture: entry.Capture,
|
||||||
Summary: summary,
|
Summary: summary,
|
||||||
SummaryQuery: summaryQuery,
|
SummaryQuery: summaryQuery,
|
||||||
Status: status,
|
Status: status,
|
||||||
StatusQuery: statusQuery,
|
StatusQuery: statusQuery,
|
||||||
Method: method,
|
Method: method,
|
||||||
MethodQuery: methodQuery,
|
MethodQuery: methodQuery,
|
||||||
Timestamp: entry.Timestamp,
|
Timestamp: entry.Timestamp,
|
||||||
Source: entry.Source,
|
Source: entry.Source,
|
||||||
Destination: entry.Destination,
|
Destination: entry.Destination,
|
||||||
IsOutgoing: entry.Outgoing,
|
IsOutgoing: entry.Outgoing,
|
||||||
Latency: entry.ElapsedTime,
|
Latency: entry.ElapsedTime,
|
||||||
Rules: entry.Rules,
|
Rules: entry.Rules,
|
||||||
ContractStatus: entry.ContractStatus,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ require (
|
|||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // 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/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
@ -68,8 +68,6 @@ 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/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||||
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||||
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/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
|
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
|
||||||
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
|
||||||
|
@ -147,10 +147,6 @@ export const EntryDetailed = () => {
|
|||||||
representation={entryData.representation}
|
representation={entryData.representation}
|
||||||
isRulesEnabled={entryData.isRulesEnabled}
|
isRulesEnabled={entryData.isRulesEnabled}
|
||||||
rulesMatched={entryData.rulesMatched}
|
rulesMatched={entryData.rulesMatched}
|
||||||
contractStatus={entryData.data.contractStatus}
|
|
||||||
requestReason={entryData.data.contractRequestReason}
|
|
||||||
responseReason={entryData.data.contractResponseReason}
|
|
||||||
contractContent={entryData.data.contractContent}
|
|
||||||
elapsedTime={entryData.data.elapsedTime}
|
elapsedTime={entryData.data.elapsedTime}
|
||||||
color={entryData.protocol.backgroundColor}
|
color={entryData.protocol.backgroundColor}
|
||||||
/>}
|
/>}
|
||||||
|
@ -364,27 +364,3 @@ export const EntryTablePolicySection: React.FC<EntryPolicySectionProps> = ({ tit
|
|||||||
}
|
}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EntryContractSectionProps {
|
|
||||||
color: string,
|
|
||||||
requestReason: string,
|
|
||||||
responseReason: string,
|
|
||||||
contractContent: string,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const EntryContractSection: React.FC<EntryContractSectionProps> = ({ color, requestReason, responseReason, contractContent }) => {
|
|
||||||
return <React.Fragment>
|
|
||||||
{requestReason && <EntrySectionContainer title="Request" color={color}>
|
|
||||||
{requestReason}
|
|
||||||
</EntrySectionContainer>}
|
|
||||||
{responseReason && <EntrySectionContainer title="Response" color={color}>
|
|
||||||
{responseReason}
|
|
||||||
</EntrySectionContainer>}
|
|
||||||
{contractContent && <EntrySectionContainer title="Contract" color={color}>
|
|
||||||
<SyntaxHighlighter
|
|
||||||
code={contractContent}
|
|
||||||
language={"yaml"}
|
|
||||||
/>
|
|
||||||
</EntrySectionContainer>}
|
|
||||||
</React.Fragment>
|
|
||||||
}
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, {useState} from 'react';
|
import React, {useState} from 'react';
|
||||||
import styles from './EntryViewer.module.sass';
|
import styles from './EntryViewer.module.sass';
|
||||||
import Tabs from "../../UI/Tabs/Tabs";
|
import Tabs from "../../UI/Tabs/Tabs";
|
||||||
import {EntryTableSection, EntryBodySection, EntryTablePolicySection, EntryContractSection} from "../EntrySections/EntrySections";
|
import {EntryTableSection, EntryBodySection, EntryTablePolicySection} from "../EntrySections/EntrySections";
|
||||||
|
|
||||||
enum SectionTypes {
|
enum SectionTypes {
|
||||||
SectionTable = "table",
|
SectionTable = "table",
|
||||||
@ -33,7 +33,7 @@ const SectionsRepresentation: React.FC<any> = ({data, color}) => {
|
|||||||
return <React.Fragment>{sections}</React.Fragment>;
|
return <React.Fragment>{sections}</React.Fragment>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AutoRepresentation: React.FC<any> = ({representation, isRulesEnabled, rulesMatched, contractStatus, requestReason, responseReason, contractContent, elapsedTime, color}) => {
|
const AutoRepresentation: React.FC<any> = ({representation, isRulesEnabled, rulesMatched, elapsedTime, color}) => {
|
||||||
var TABS = [
|
var TABS = [
|
||||||
{
|
{
|
||||||
tab: 'Request'
|
tab: 'Request'
|
||||||
@ -50,7 +50,6 @@ const AutoRepresentation: React.FC<any> = ({representation, isRulesEnabled, rule
|
|||||||
|
|
||||||
let responseTabIndex = 0;
|
let responseTabIndex = 0;
|
||||||
let rulesTabIndex = 0;
|
let rulesTabIndex = 0;
|
||||||
let contractTabIndex = 0;
|
|
||||||
|
|
||||||
if (response) {
|
if (response) {
|
||||||
TABS.push(
|
TABS.push(
|
||||||
@ -70,15 +69,6 @@ const AutoRepresentation: React.FC<any> = ({representation, isRulesEnabled, rule
|
|||||||
rulesTabIndex = TABS.length - 1;
|
rulesTabIndex = TABS.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contractStatus !== 0 && contractContent) {
|
|
||||||
TABS.push(
|
|
||||||
{
|
|
||||||
tab: 'Contract',
|
|
||||||
}
|
|
||||||
);
|
|
||||||
contractTabIndex = 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}>
|
||||||
@ -93,9 +83,6 @@ const AutoRepresentation: React.FC<any> = ({representation, isRulesEnabled, rule
|
|||||||
{isRulesEnabled && currentTab === TABS[rulesTabIndex].tab && <React.Fragment>
|
{isRulesEnabled && currentTab === TABS[rulesTabIndex].tab && <React.Fragment>
|
||||||
<EntryTablePolicySection title={'Rule'} color={color} latency={elapsedTime} arrayToIterate={rulesMatched ? rulesMatched : []}/>
|
<EntryTablePolicySection title={'Rule'} color={color} latency={elapsedTime} arrayToIterate={rulesMatched ? rulesMatched : []}/>
|
||||||
</React.Fragment>}
|
</React.Fragment>}
|
||||||
{contractStatus !== 0 && contractContent && currentTab === TABS[contractTabIndex].tab && <React.Fragment>
|
|
||||||
<EntryContractSection color={color} requestReason={requestReason} responseReason={responseReason} contractContent={contractContent}/>
|
|
||||||
</React.Fragment>}
|
|
||||||
</div>}
|
</div>}
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
@ -104,23 +91,15 @@ interface Props {
|
|||||||
representation: any;
|
representation: any;
|
||||||
isRulesEnabled: boolean;
|
isRulesEnabled: boolean;
|
||||||
rulesMatched: any;
|
rulesMatched: any;
|
||||||
contractStatus: number;
|
|
||||||
requestReason: string;
|
|
||||||
responseReason: string;
|
|
||||||
contractContent: string;
|
|
||||||
color: string;
|
color: string;
|
||||||
elapsedTime: number;
|
elapsedTime: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EntryViewer: React.FC<Props> = ({representation, isRulesEnabled, rulesMatched, contractStatus, requestReason, responseReason, contractContent, elapsedTime, color}) => {
|
const EntryViewer: React.FC<Props> = ({representation, isRulesEnabled, rulesMatched, elapsedTime, color}) => {
|
||||||
return <AutoRepresentation
|
return <AutoRepresentation
|
||||||
representation={representation}
|
representation={representation}
|
||||||
isRulesEnabled={isRulesEnabled}
|
isRulesEnabled={isRulesEnabled}
|
||||||
rulesMatched={rulesMatched}
|
rulesMatched={rulesMatched}
|
||||||
contractStatus={contractStatus}
|
|
||||||
requestReason={requestReason}
|
|
||||||
responseReason={responseReason}
|
|
||||||
contractContent={contractContent}
|
|
||||||
elapsedTime={elapsedTime}
|
elapsedTime={elapsedTime}
|
||||||
color={color}
|
color={color}
|
||||||
/>
|
/>
|
||||||
|
@ -38,7 +38,6 @@ interface Entry {
|
|||||||
isOutgoing?: boolean;
|
isOutgoing?: boolean;
|
||||||
latency: number;
|
latency: number;
|
||||||
rules: Rules;
|
rules: Rules;
|
||||||
contractStatus: number,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Rules {
|
interface Rules {
|
||||||
@ -117,26 +116,6 @@ export const EntryItem: React.FC<EntryProps> = ({entry, style, headingMode, name
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let contractEnabled = true;
|
|
||||||
let contractText = "";
|
|
||||||
switch (entry.contractStatus) {
|
|
||||||
case 0:
|
|
||||||
contractEnabled = false;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
additionalRulesProperties = styles.ruleSuccessRow
|
|
||||||
ruleSuccess = true
|
|
||||||
contractText = "No Breaches"
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
additionalRulesProperties = styles.ruleFailureRow
|
|
||||||
ruleSuccess = false
|
|
||||||
contractText = "Breach"
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const isStatusCodeEnabled = ((entry.proto.name === "http" && "status" in entry) || entry.status !== 0);
|
const isStatusCodeEnabled = ((entry.proto.name === "http" && "status" in entry) || entry.status !== 0);
|
||||||
|
|
||||||
@ -144,7 +123,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 && !contractEnabled ? styles.rowSelected : additionalRulesProperties}`}
|
${isSelected && !rule ? styles.rowSelected : additionalRulesProperties}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!setFocusedEntryId) return;
|
if (!setFocusedEntryId) return;
|
||||||
setFocusedEntryId(entry.id);
|
setFocusedEntryId(entry.id);
|
||||||
@ -210,18 +189,11 @@ export const EntryItem: React.FC<EntryProps> = ({entry, style, headingMode, name
|
|||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
rule ?
|
rule ?
|
||||||
<div className={`${styles.ruleNumberText} ${ruleSuccess ? styles.ruleNumberTextSuccess : styles.ruleNumberTextFailure} ${rule && contractEnabled ? styles.separatorRight : ""}`}>
|
<div className={`${styles.ruleNumberText} ${ruleSuccess ? styles.ruleNumberTextSuccess : styles.ruleNumberTextFailure} ${rule ? styles.separatorRight : ""}`}>
|
||||||
{`Rules (${numberOfRules})`}
|
{`Rules (${numberOfRules})`}
|
||||||
</div>
|
</div>
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
{
|
|
||||||
contractEnabled ?
|
|
||||||
<div className={`${styles.ruleNumberText} ${ruleSuccess ? styles.ruleNumberTextSuccess : styles.ruleNumberTextFailure} ${rule && contractEnabled ? styles.separatorLeft : ""}`}>
|
|
||||||
{contractText}
|
|
||||||
</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