mirror of
https://github.com/kubeshark/kubeshark.git
synced 2026-03-07 21:22:14 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e358aa4c8f | ||
|
|
03b1313a9f | ||
|
|
32dfe40e18 | ||
|
|
12aaa762f6 | ||
|
|
a75bac181d | ||
|
|
2d78785558 |
@@ -304,11 +304,10 @@ func cleanupCommand(cmd *exec.Cmd) error {
|
||||
}
|
||||
|
||||
func getPods(tapStatusInterface interface{}) ([]map[string]interface{}, error) {
|
||||
tapStatus := tapStatusInterface.(map[string]interface{})
|
||||
podsInterface := tapStatus["pods"].([]interface{})
|
||||
tapPodsInterface := tapStatusInterface.([]interface{})
|
||||
|
||||
var pods []map[string]interface{}
|
||||
for _, podInterface := range podsInterface {
|
||||
for _, podInterface := range tapPodsInterface {
|
||||
pods = append(pods, podInterface.(map[string]interface{}))
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ import (
|
||||
"path/filepath"
|
||||
"plugin"
|
||||
"sort"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -468,11 +467,7 @@ func startMizuTapperSyncer(ctx context.Context, provider *kubernetes.Provider) (
|
||||
}
|
||||
providers.TapStatus = shared.TapStatus{Pods: kubernetes.GetPodInfosForPods(tapperSyncer.CurrentlyTappedPods)}
|
||||
|
||||
tappedPodsStatus := make([]shared.TappedPodStatus, 0)
|
||||
for _, pod := range providers.TapStatus.Pods {
|
||||
isTapped := strings.ToLower(providers.TappersStatus[pod.NodeName].Status) == "started"
|
||||
tappedPodsStatus = append(tappedPodsStatus, shared.TappedPodStatus{Name: pod.Name, Namespace: pod.Namespace, IsTapped: isTapped})
|
||||
}
|
||||
tappedPodsStatus := utils.GetTappedPodsStatus()
|
||||
|
||||
serializedTapStatus, err := json.Marshal(shared.CreateWebSocketStatusMessage(tappedPodsStatus))
|
||||
if err != nil {
|
||||
|
||||
@@ -3,18 +3,17 @@ package controllers
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/up9inc/mizu/shared"
|
||||
"github.com/up9inc/mizu/shared/logger"
|
||||
"mizuserver/pkg/api"
|
||||
"mizuserver/pkg/config"
|
||||
"mizuserver/pkg/holder"
|
||||
"mizuserver/pkg/providers"
|
||||
"mizuserver/pkg/up9"
|
||||
"mizuserver/pkg/utils"
|
||||
"mizuserver/pkg/validation"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/up9inc/mizu/shared"
|
||||
"github.com/up9inc/mizu/shared/logger"
|
||||
)
|
||||
|
||||
func HealthCheck(c *gin.Context) {
|
||||
@@ -54,11 +53,7 @@ func PostTappedPods(c *gin.Context) {
|
||||
}
|
||||
|
||||
func broadcastTappedPodsStatus() {
|
||||
tappedPodsStatus := make([]shared.TappedPodStatus, 0)
|
||||
for _, pod := range providers.TapStatus.Pods {
|
||||
isTapped := strings.ToLower(providers.TappersStatus[pod.NodeName].Status) == "started"
|
||||
tappedPodsStatus = append(tappedPodsStatus, shared.TappedPodStatus{Name: pod.Name, Namespace: pod.Namespace, IsTapped: isTapped})
|
||||
}
|
||||
tappedPodsStatus := utils.GetTappedPodsStatus()
|
||||
|
||||
message := shared.CreateWebSocketStatusMessage(tappedPodsStatus)
|
||||
if jsonBytes, err := json.Marshal(message); err != nil {
|
||||
@@ -101,11 +96,7 @@ func GetAuthStatus(c *gin.Context) {
|
||||
}
|
||||
|
||||
func GetTappingStatus(c *gin.Context) {
|
||||
tappedPodsStatus := make([]shared.TappedPodStatus, 0)
|
||||
for _, pod := range providers.TapStatus.Pods {
|
||||
isTapped := strings.ToLower(providers.TappersStatus[pod.NodeName].Status) == "started"
|
||||
tappedPodsStatus = append(tappedPodsStatus, shared.TappedPodStatus{Name: pod.Name, Namespace: pod.Namespace, IsTapped: isTapped})
|
||||
}
|
||||
tappedPodsStatus := utils.GetTappedPodsStatus()
|
||||
c.JSON(http.StatusOK, tappedPodsStatus)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,12 @@ package utils
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"mizuserver/pkg/providers"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/signal"
|
||||
"reflect"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -44,15 +45,13 @@ func StartServer(app *gin.Engine) {
|
||||
}
|
||||
}
|
||||
|
||||
func ReverseSlice(data interface{}) {
|
||||
value := reflect.ValueOf(data)
|
||||
valueLen := value.Len()
|
||||
for i := 0; i <= int((valueLen-1)/2); i++ {
|
||||
reverseIndex := valueLen - 1 - i
|
||||
tmp := value.Index(reverseIndex).Interface()
|
||||
value.Index(reverseIndex).Set(value.Index(i))
|
||||
value.Index(i).Set(reflect.ValueOf(tmp))
|
||||
func GetTappedPodsStatus() []shared.TappedPodStatus {
|
||||
tappedPodsStatus := make([]shared.TappedPodStatus, 0)
|
||||
for _, pod := range providers.TapStatus.Pods {
|
||||
isTapped := strings.ToLower(providers.TappersStatus[pod.NodeName].Status) == "started"
|
||||
tappedPodsStatus = append(tappedPodsStatus, shared.TappedPodStatus{Name: pod.Name, Namespace: pod.Namespace, IsTapped: isTapped})
|
||||
}
|
||||
return tappedPodsStatus
|
||||
}
|
||||
|
||||
func CheckErr(e error) {
|
||||
|
||||
38
tap/source/discoverer_util.go
Normal file
38
tap/source/discoverer_util.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package source
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/up9inc/mizu/shared/logger"
|
||||
)
|
||||
|
||||
var numberRegex = regexp.MustCompile("[0-9]+")
|
||||
|
||||
func getSingleValueFromEnvironmentVariableFile(filePath string, variableName string) (string, error) {
|
||||
bytes, err := ioutil.ReadFile(filePath)
|
||||
|
||||
if err != nil {
|
||||
logger.Log.Warningf("Error reading environment file %v - %v", filePath, err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
envs := strings.Split(string(bytes), string([]byte{0}))
|
||||
|
||||
for _, env := range envs {
|
||||
if !strings.Contains(env, "=") {
|
||||
continue
|
||||
}
|
||||
|
||||
parts := strings.Split(env, "=")
|
||||
varName := parts[0]
|
||||
value := parts[1]
|
||||
|
||||
if variableName == varName {
|
||||
return value, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/up9inc/mizu/shared/logger"
|
||||
@@ -13,8 +12,6 @@ import (
|
||||
|
||||
const envoyBinary = "/envoy"
|
||||
|
||||
var numberRegex = regexp.MustCompile("[0-9]+")
|
||||
|
||||
func discoverRelevantEnvoyPids(procfs string, pods []v1.Pod) ([]string, error) {
|
||||
result := make([]string, 0)
|
||||
|
||||
@@ -36,7 +33,7 @@ func discoverRelevantEnvoyPids(procfs string, pods []v1.Pod) ([]string, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
if checkPid(procfs, pid.Name(), pods) {
|
||||
if checkEnvoyPid(procfs, pid.Name(), pods) {
|
||||
result = append(result, pid.Name())
|
||||
}
|
||||
}
|
||||
@@ -46,7 +43,7 @@ func discoverRelevantEnvoyPids(procfs string, pods []v1.Pod) ([]string, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func checkPid(procfs string, pid string, pods []v1.Pod) bool {
|
||||
func checkEnvoyPid(procfs string, pid string, pods []v1.Pod) bool {
|
||||
execLink := fmt.Sprintf("%v/%v/exe", procfs, pid)
|
||||
exec, err := os.Readlink(execLink)
|
||||
|
||||
@@ -63,7 +60,7 @@ func checkPid(procfs string, pid string, pods []v1.Pod) bool {
|
||||
}
|
||||
|
||||
environmentFile := fmt.Sprintf("%v/%v/environ", procfs, pid)
|
||||
podIp, err := readEnvironmentVariable(environmentFile, "INSTANCE_IP")
|
||||
podIp, err := getSingleValueFromEnvironmentVariableFile(environmentFile, "INSTANCE_IP")
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
@@ -84,30 +81,3 @@ func checkPid(procfs string, pid string, pods []v1.Pod) bool {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func readEnvironmentVariable(file string, name string) (string, error) {
|
||||
bytes, err := ioutil.ReadFile(file)
|
||||
|
||||
if err != nil {
|
||||
logger.Log.Warningf("Error reading environment file %v - %v", file, err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
envs := strings.Split(string(bytes), string([]byte{0}))
|
||||
|
||||
for _, env := range envs {
|
||||
if !strings.Contains(env, "=") {
|
||||
continue
|
||||
}
|
||||
|
||||
parts := strings.Split(env, "=")
|
||||
varName := parts[0]
|
||||
value := parts[1]
|
||||
|
||||
if name == varName {
|
||||
return value, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
83
tap/source/linkerd_discoverer.go
Normal file
83
tap/source/linkerd_discoverer.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package source
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/up9inc/mizu/shared/logger"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
const linkerdBinary = "/linkerd2-proxy"
|
||||
|
||||
func discoverRelevantLinkerdPids(procfs string, pods []v1.Pod) ([]string, error) {
|
||||
result := make([]string, 0)
|
||||
|
||||
pids, err := ioutil.ReadDir(procfs)
|
||||
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
logger.Log.Infof("Starting linkerd auto discoverer %v %v - scanning %v potential pids",
|
||||
procfs, pods, len(pids))
|
||||
|
||||
for _, pid := range pids {
|
||||
if !pid.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
if !numberRegex.MatchString(pid.Name()) {
|
||||
continue
|
||||
}
|
||||
|
||||
if checkLinkerdPid(procfs, pid.Name(), pods) {
|
||||
result = append(result, pid.Name())
|
||||
}
|
||||
}
|
||||
|
||||
logger.Log.Infof("Found %v relevant linkerd processes - %v", len(result), result)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func checkLinkerdPid(procfs string, pid string, pods []v1.Pod) bool {
|
||||
execLink := fmt.Sprintf("%v/%v/exe", procfs, pid)
|
||||
exec, err := os.Readlink(execLink)
|
||||
|
||||
if err != nil {
|
||||
// Debug on purpose - it may happen due to many reasons and we only care
|
||||
// for it during troubleshooting
|
||||
//
|
||||
logger.Log.Debugf("Unable to read link %v - %v\n", execLink, err)
|
||||
return false
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(exec, linkerdBinary) {
|
||||
return false
|
||||
}
|
||||
|
||||
environmentFile := fmt.Sprintf("%v/%v/environ", procfs, pid)
|
||||
podName, err := getSingleValueFromEnvironmentVariableFile(environmentFile, "_pod_name")
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if podName == "" {
|
||||
logger.Log.Debugf("Found a linkerd process without _pod_name variable %v\n", pid)
|
||||
return false
|
||||
}
|
||||
|
||||
logger.Log.Infof("Found linkerd pid %v with pod name %v", pid, podName)
|
||||
|
||||
for _, pod := range pods {
|
||||
if pod.Name == podName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
@@ -16,7 +16,7 @@ type PacketSourceManager struct {
|
||||
}
|
||||
|
||||
func NewPacketSourceManager(procfs string, pids string, filename string, interfaceName string,
|
||||
istio bool, pods []v1.Pod, behaviour TcpPacketSourceBehaviour) (*PacketSourceManager, error) {
|
||||
mtls bool, pods []v1.Pod, behaviour TcpPacketSourceBehaviour) (*PacketSourceManager, error) {
|
||||
sources := make([]*tcpPacketSource, 0)
|
||||
sources, err := createHostSource(sources, filename, interfaceName, behaviour)
|
||||
|
||||
@@ -25,7 +25,8 @@ func NewPacketSourceManager(procfs string, pids string, filename string, interfa
|
||||
}
|
||||
|
||||
sources = createSourcesFromPids(sources, procfs, pids, interfaceName, behaviour)
|
||||
sources = createSourcesFromEnvoy(sources, istio, procfs, pods, interfaceName, behaviour)
|
||||
sources = createSourcesFromEnvoy(sources, mtls, procfs, pods, interfaceName, behaviour)
|
||||
sources = createSourcesFromLinkerd(sources, mtls, procfs, pods, interfaceName, behaviour)
|
||||
|
||||
return &PacketSourceManager{
|
||||
sources: sources,
|
||||
@@ -54,13 +55,13 @@ func createSourcesFromPids(sources []*tcpPacketSource, procfs string, pids strin
|
||||
return sources
|
||||
}
|
||||
|
||||
func createSourcesFromEnvoy(sources []*tcpPacketSource, istio bool, procfs string, clusterIps []v1.Pod,
|
||||
func createSourcesFromEnvoy(sources []*tcpPacketSource, mtls bool, procfs string, pods []v1.Pod,
|
||||
interfaceName string, behaviour TcpPacketSourceBehaviour) []*tcpPacketSource {
|
||||
if !istio {
|
||||
if !mtls {
|
||||
return sources
|
||||
}
|
||||
|
||||
envoyPids, err := discoverRelevantEnvoyPids(procfs, clusterIps)
|
||||
envoyPids, err := discoverRelevantEnvoyPids(procfs, pods)
|
||||
|
||||
if err != nil {
|
||||
logger.Log.Warningf("Unable to discover envoy pids - %v", err)
|
||||
@@ -73,6 +74,25 @@ func createSourcesFromEnvoy(sources []*tcpPacketSource, istio bool, procfs strin
|
||||
return sources
|
||||
}
|
||||
|
||||
func createSourcesFromLinkerd(sources []*tcpPacketSource, mtls bool, procfs string, pods []v1.Pod,
|
||||
interfaceName string, behaviour TcpPacketSourceBehaviour) []*tcpPacketSource {
|
||||
if !mtls {
|
||||
return sources
|
||||
}
|
||||
|
||||
linkerdPids, err := discoverRelevantLinkerdPids(procfs, pods)
|
||||
|
||||
if err != nil {
|
||||
logger.Log.Warningf("Unable to discover linkerd pids - %v", err)
|
||||
return sources
|
||||
}
|
||||
|
||||
netnsSources := newNetnsPacketSources(procfs, linkerdPids, interfaceName, behaviour)
|
||||
sources = append(sources, netnsSources...)
|
||||
|
||||
return sources
|
||||
}
|
||||
|
||||
func newHostPacketSource(filename string, interfaceName string,
|
||||
behaviour TcpPacketSourceBehaviour) (*tcpPacketSource, error) {
|
||||
var name string
|
||||
|
||||
@@ -65,11 +65,11 @@ func (a *tcpAssembler) processPackets(dumpPacket bool, packets <-chan source.Tcp
|
||||
|
||||
for packetInfo := range packets {
|
||||
packetsCount := diagnose.AppStats.IncPacketsCount()
|
||||
|
||||
if packetsCount % PACKETS_SEEN_LOG_THRESHOLD == 0 {
|
||||
|
||||
if packetsCount%PACKETS_SEEN_LOG_THRESHOLD == 0 {
|
||||
logger.Log.Debugf("Packets seen: #%d", packetsCount)
|
||||
}
|
||||
|
||||
|
||||
packet := packetInfo.Packet
|
||||
data := packet.Data()
|
||||
diagnose.AppStats.UpdateProcessedBytes(uint64(len(data)))
|
||||
@@ -91,7 +91,6 @@ func (a *tcpAssembler) processPackets(dumpPacket bool, packets <-chan source.Tcp
|
||||
CaptureInfo: packet.Metadata().CaptureInfo,
|
||||
}
|
||||
diagnose.InternalStats.Totalsz += len(tcp.Payload)
|
||||
logger.Log.Debugf("%s:%v -> %s:%v", packet.NetworkLayer().NetworkFlow().Src(), tcp.SrcPort, packet.NetworkLayer().NetworkFlow().Dst(), tcp.DstPort)
|
||||
a.assemblerMutex.Lock()
|
||||
a.AssembleWithContext(packet.NetworkLayer().NetworkFlow(), tcp, &c)
|
||||
a.assemblerMutex.Unlock()
|
||||
|
||||
@@ -2,7 +2,6 @@ package tap
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
@@ -75,7 +74,7 @@ func (t *tcpStream) Accept(tcp *layers.TCP, ci gopacket.CaptureInfo, dir reassem
|
||||
}
|
||||
|
||||
func (t *tcpStream) ReassembledSG(sg reassembly.ScatterGather, ac reassembly.AssemblerContext) {
|
||||
dir, start, end, skip := sg.Info()
|
||||
dir, _, _, skip := sg.Info()
|
||||
length, saved := sg.Lengths()
|
||||
// update stats
|
||||
sgStats := sg.Stats()
|
||||
@@ -103,13 +102,6 @@ func (t *tcpStream) ReassembledSG(sg reassembly.ScatterGather, ac reassembly.Ass
|
||||
diagnose.InternalStats.OverlapBytes += sgStats.OverlapBytes
|
||||
diagnose.InternalStats.OverlapPackets += sgStats.OverlapPackets
|
||||
|
||||
var ident string
|
||||
if dir == reassembly.TCPDirClientToServer {
|
||||
ident = fmt.Sprintf("%v %v(%s): ", t.net, t.transport, dir)
|
||||
} else {
|
||||
ident = fmt.Sprintf("%v %v(%s): ", t.net.Reverse(), t.transport.Reverse(), dir)
|
||||
}
|
||||
diagnose.TapErrors.Debug("%s: SG reassembled packet with %d bytes (start:%v,end:%v,skip:%d,saved:%d,nb:%d,%d,overlap:%d,%d)", ident, length, start, end, skip, saved, sgStats.Packets, sgStats.Chunks, sgStats.OverlapBytes, sgStats.OverlapPackets)
|
||||
if skip == -1 && *allowmissinginit {
|
||||
// this is allowed
|
||||
} else if skip != 0 {
|
||||
@@ -174,7 +166,6 @@ func (t *tcpStream) ReassembledSG(sg reassembly.ScatterGather, ac reassembly.Ass
|
||||
}
|
||||
|
||||
func (t *tcpStream) ReassemblyComplete(ac reassembly.AssemblerContext) bool {
|
||||
diagnose.TapErrors.Debug("%s: Connection closed", t.ident)
|
||||
if t.isTapTarget && !t.isClosed {
|
||||
t.Close()
|
||||
}
|
||||
|
||||
@@ -54,7 +54,6 @@ func NewTcpStreamFactory(emitter api.Emitter, streamsMap *tcpStreamMap, opts *Ta
|
||||
}
|
||||
|
||||
func (factory *tcpStreamFactory) New(net, transport gopacket.Flow, tcp *layers.TCP, ac reassembly.AssemblerContext) reassembly.Stream {
|
||||
logger.Log.Debugf("* NEW: %s %s", net, transport)
|
||||
fsmOptions := reassembly.TCPSimpleFSMOptions{
|
||||
SupportMissingEstablishment: *allowmissinginit,
|
||||
}
|
||||
@@ -153,21 +152,16 @@ func inArrayPod(pods []v1.Pod, address string) bool {
|
||||
func (factory *tcpStreamFactory) getStreamProps(srcIP string, srcPort string, dstIP string, dstPort string) *streamProps {
|
||||
if factory.opts.HostMode {
|
||||
if inArrayPod(factory.opts.FilterAuthorities, fmt.Sprintf("%s:%s", dstIP, dstPort)) {
|
||||
logger.Log.Debugf("getStreamProps %s", fmt.Sprintf("+ host1 %s:%s", dstIP, dstPort))
|
||||
return &streamProps{isTapTarget: true, isOutgoing: false}
|
||||
} else if inArrayPod(factory.opts.FilterAuthorities, dstIP) {
|
||||
logger.Log.Debugf("getStreamProps %s", fmt.Sprintf("+ host2 %s", dstIP))
|
||||
return &streamProps{isTapTarget: true, isOutgoing: false}
|
||||
} else if inArrayPod(factory.opts.FilterAuthorities, fmt.Sprintf("%s:%s", srcIP, srcPort)) {
|
||||
logger.Log.Debugf("getStreamProps %s", fmt.Sprintf("+ host3 %s:%s", srcIP, srcPort))
|
||||
return &streamProps{isTapTarget: true, isOutgoing: true}
|
||||
} else if inArrayPod(factory.opts.FilterAuthorities, srcIP) {
|
||||
logger.Log.Debugf("getStreamProps %s", fmt.Sprintf("+ host4 %s", srcIP))
|
||||
return &streamProps{isTapTarget: true, isOutgoing: true}
|
||||
}
|
||||
return &streamProps{isTapTarget: false, isOutgoing: false}
|
||||
} else {
|
||||
logger.Log.Debugf("getStreamProps %s", fmt.Sprintf("+ notHost3 %s:%s -> %s:%s", srcIP, srcPort, dstIP, dstPort))
|
||||
return &streamProps{isTapTarget: true}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,12 +10,14 @@ import ProtobufDecoder from "protobuf-decoder";
|
||||
interface EntryViewLineProps {
|
||||
label: string;
|
||||
value: number | string;
|
||||
updateQuery: any;
|
||||
selector: string;
|
||||
updateQuery?: any;
|
||||
selector?: string;
|
||||
overrideQueryValue?: string;
|
||||
displayIconOnMouseOver?: boolean;
|
||||
useTooltip?: boolean;
|
||||
}
|
||||
|
||||
const EntryViewLine: React.FC<EntryViewLineProps> = ({label, value, updateQuery, selector, overrideQueryValue}) => {
|
||||
const EntryViewLine: React.FC<EntryViewLineProps> = ({label, value, updateQuery = null, selector = "", overrideQueryValue = "", displayIconOnMouseOver = true, useTooltip = true}) => {
|
||||
let query: string;
|
||||
if (!selector) {
|
||||
query = "";
|
||||
@@ -34,7 +36,8 @@ const EntryViewLine: React.FC<EntryViewLineProps> = ({label, value, updateQuery,
|
||||
style={{float: "right", height: "18px"}}
|
||||
iconStyle={{marginRight: "20px"}}
|
||||
flipped={true}
|
||||
displayIconOnMouseOver={true}
|
||||
useTooltip={useTooltip}
|
||||
displayIconOnMouseOver={displayIconOnMouseOver}
|
||||
>
|
||||
{label}
|
||||
</Queryable>
|
||||
@@ -55,30 +58,47 @@ const EntryViewLine: React.FC<EntryViewLineProps> = ({label, value, updateQuery,
|
||||
interface EntrySectionCollapsibleTitleProps {
|
||||
title: string,
|
||||
color: string,
|
||||
isExpanded: boolean,
|
||||
expanded: boolean,
|
||||
setExpanded: any,
|
||||
query?: string,
|
||||
updateQuery?: any,
|
||||
}
|
||||
|
||||
const EntrySectionCollapsibleTitle: React.FC<EntrySectionCollapsibleTitleProps> = ({title, color, isExpanded}) => {
|
||||
const EntrySectionCollapsibleTitle: React.FC<EntrySectionCollapsibleTitleProps> = ({title, color, expanded, setExpanded, query = "", updateQuery = null}) => {
|
||||
return <div className={styles.title}>
|
||||
<div className={`${styles.button} ${isExpanded ? styles.expanded : ''}`} style={{backgroundColor: color}}>
|
||||
{isExpanded ? '-' : '+'}
|
||||
<div
|
||||
className={`${styles.button} ${expanded ? styles.expanded : ''}`}
|
||||
style={{backgroundColor: color}}
|
||||
onClick={() => {
|
||||
setExpanded(!expanded)
|
||||
}}
|
||||
>
|
||||
{expanded ? '-' : '+'}
|
||||
</div>
|
||||
<span>{title}</span>
|
||||
<Queryable
|
||||
query={query}
|
||||
updateQuery={updateQuery}
|
||||
useTooltip={updateQuery ? true : false}
|
||||
displayIconOnMouseOver={updateQuery ? true : false}
|
||||
>
|
||||
<span>{title}</span>
|
||||
</Queryable>
|
||||
</div>
|
||||
}
|
||||
|
||||
interface EntrySectionContainerProps {
|
||||
title: string,
|
||||
color: string,
|
||||
query?: string,
|
||||
updateQuery?: any,
|
||||
}
|
||||
|
||||
export const EntrySectionContainer: React.FC<EntrySectionContainerProps> = ({title, color, children}) => {
|
||||
export const EntrySectionContainer: React.FC<EntrySectionContainerProps> = ({title, color, children, query = "", updateQuery = null}) => {
|
||||
const [expanded, setExpanded] = useState(true);
|
||||
return <CollapsibleContainer
|
||||
className={styles.collapsibleContainer}
|
||||
isExpanded={expanded}
|
||||
onClick={() => setExpanded(!expanded)}
|
||||
title={<EntrySectionCollapsibleTitle title={title} color={color} isExpanded={expanded}/>}
|
||||
expanded={expanded}
|
||||
title={<EntrySectionCollapsibleTitle title={title} color={color} expanded={expanded} setExpanded={setExpanded} query={query} updateQuery={updateQuery}/>}
|
||||
>
|
||||
{children}
|
||||
</CollapsibleContainer>
|
||||
@@ -133,11 +153,16 @@ export const EntryBodySection: React.FC<EntryBodySectionProps> = ({
|
||||
}
|
||||
|
||||
return <React.Fragment>
|
||||
{content && content?.length > 0 && <EntrySectionContainer title='Body' color={color}>
|
||||
{content && content?.length > 0 && <EntrySectionContainer
|
||||
title='Body'
|
||||
color={color}
|
||||
query={`${selector} == r".*"`}
|
||||
updateQuery={updateQuery}
|
||||
>
|
||||
<table>
|
||||
<tbody>
|
||||
<EntryViewLine label={'Mime type'} value={contentType} updateQuery={updateQuery} selector={selector} overrideQueryValue={`r".*"`}/>
|
||||
{encoding && <EntryViewLine label={'Encoding'} value={encoding} updateQuery={updateQuery} selector={selector} overrideQueryValue={`r".*"`}/>}
|
||||
<EntryViewLine label={'Mime type'} value={contentType} useTooltip={false}/>
|
||||
{encoding && <EntryViewLine label={'Encoding'} value={encoding} useTooltip={false}/>}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -195,13 +220,20 @@ interface EntryPolicySectionProps {
|
||||
interface EntryPolicySectionCollapsibleTitleProps {
|
||||
label: string;
|
||||
matched: string;
|
||||
isExpanded: boolean;
|
||||
expanded: boolean;
|
||||
setExpanded: any;
|
||||
}
|
||||
|
||||
const EntryPolicySectionCollapsibleTitle: React.FC<EntryPolicySectionCollapsibleTitleProps> = ({label, matched, isExpanded}) => {
|
||||
const EntryPolicySectionCollapsibleTitle: React.FC<EntryPolicySectionCollapsibleTitleProps> = ({label, matched, expanded, setExpanded}) => {
|
||||
return <div className={styles.title}>
|
||||
<span className={`${styles.button} ${isExpanded ? styles.expanded : ''}`}>
|
||||
{isExpanded ? '-' : '+'}
|
||||
<span
|
||||
className={`${styles.button}
|
||||
${expanded ? styles.expanded : ''}`}
|
||||
onClick={() => {
|
||||
setExpanded(!expanded)
|
||||
}}
|
||||
>
|
||||
{expanded ? '-' : '+'}
|
||||
</span>
|
||||
<span>
|
||||
<tr className={styles.dataLine}>
|
||||
@@ -222,9 +254,8 @@ export const EntryPolicySectionContainer: React.FC<EntryPolicySectionContainerPr
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
return <CollapsibleContainer
|
||||
className={styles.collapsibleContainer}
|
||||
isExpanded={expanded}
|
||||
onClick={() => setExpanded(!expanded)}
|
||||
title={<EntryPolicySectionCollapsibleTitle label={label} matched={matched} isExpanded={expanded}/>}
|
||||
expanded={expanded}
|
||||
title={<EntryPolicySectionCollapsibleTitle label={label} matched={matched} expanded={expanded} setExpanded={setExpanded}/>}
|
||||
>
|
||||
{children}
|
||||
</CollapsibleContainer>
|
||||
|
||||
@@ -92,3 +92,13 @@
|
||||
|
||||
.ip
|
||||
margin-left: 5px
|
||||
|
||||
@media (max-width: 1760px)
|
||||
.timestamp
|
||||
display: none
|
||||
.separatorRight
|
||||
border-right: 0px
|
||||
|
||||
@media (max-width: 1340px)
|
||||
.separatorRight
|
||||
display: none
|
||||
|
||||
@@ -91,7 +91,7 @@ export const TrafficPage: React.FC<TrafficPageProps> = ({setAnalyzeStatus, onTLS
|
||||
|
||||
useEffect(() => {
|
||||
handleQueryChange(query);
|
||||
}, [query]);
|
||||
}, [query, handleQueryChange]);
|
||||
|
||||
useEffect(() => {
|
||||
if (query) {
|
||||
|
||||
@@ -1,38 +1,25 @@
|
||||
import React, {useState} from "react";
|
||||
import React from "react";
|
||||
import collapsedImg from "../assets/collapsed.svg";
|
||||
import expandedImg from "../assets/expanded.svg";
|
||||
import "./style/CollapsibleContainer.sass";
|
||||
|
||||
interface Props {
|
||||
title: string | React.ReactNode,
|
||||
onClick?: (e: React.SyntheticEvent) => void,
|
||||
isExpanded?: boolean,
|
||||
expanded: boolean,
|
||||
titleClassName?: string,
|
||||
stickyHeader?: boolean,
|
||||
className?: string,
|
||||
initialExpanded?: boolean;
|
||||
passiveOnClick?: boolean; //whether specifying onClick overrides internal _isExpanded state handling
|
||||
stickyHeader?: boolean,
|
||||
}
|
||||
|
||||
const CollapsibleContainer: React.FC<Props> = ({title, children, isExpanded, onClick, titleClassName, stickyHeader = false, className, initialExpanded = true, passiveOnClick}) => {
|
||||
const [_isExpanded, _setExpanded] = useState(initialExpanded);
|
||||
let expanded = isExpanded !== undefined ? isExpanded : _isExpanded;
|
||||
const CollapsibleContainer: React.FC<Props> = ({title, children, expanded, titleClassName, className, stickyHeader = false}) => {
|
||||
const classNames = `CollapsibleContainer ${expanded ? "CollapsibleContainer-Expanded" : "CollapsibleContainer-Collapsed"} ${className ? className : ''}`;
|
||||
|
||||
// This is needed to achieve the sticky header feature.
|
||||
// This is needed to achieve the sticky header feature.
|
||||
// It is needed an un-contained component for the css to work properly.
|
||||
const content = <React.Fragment>
|
||||
<div
|
||||
className={`CollapsibleContainer-Header ${stickyHeader ? "CollapsibleContainer-Header-Sticky" : ""}
|
||||
className={`CollapsibleContainer-Header ${stickyHeader ? "CollapsibleContainer-Header-Sticky" : ""}
|
||||
${expanded ? "CollapsibleContainer-Header-Expanded" : ""}`}
|
||||
onClick={(e) => {
|
||||
if (onClick) {
|
||||
onClick(e)
|
||||
if (passiveOnClick !== true)
|
||||
return;
|
||||
}
|
||||
_setExpanded(!_isExpanded)
|
||||
}}
|
||||
>
|
||||
{
|
||||
React.isValidElement(title)?
|
||||
|
||||
Reference in New Issue
Block a user