mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-07-29 23:41:06 +00:00
Display the protocol name inside the details layout
This commit is contained in:
parent
3dff8b48f7
commit
03099edfc1
@ -7,6 +7,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"mizuserver/pkg/api"
|
"mizuserver/pkg/api"
|
||||||
|
"mizuserver/pkg/controllers"
|
||||||
"mizuserver/pkg/models"
|
"mizuserver/pkg/models"
|
||||||
"mizuserver/pkg/routes"
|
"mizuserver/pkg/routes"
|
||||||
"mizuserver/pkg/utils"
|
"mizuserver/pkg/utils"
|
||||||
@ -144,6 +145,7 @@ func loadExtensions() {
|
|||||||
allOutboundPorts = mergeUnique(allOutboundPorts, extension.Protocol.OutboundPorts)
|
allOutboundPorts = mergeUnique(allOutboundPorts, extension.Protocol.OutboundPorts)
|
||||||
allInboundPorts = mergeUnique(allInboundPorts, extension.Protocol.InboundPorts)
|
allInboundPorts = mergeUnique(allInboundPorts, extension.Protocol.InboundPorts)
|
||||||
}
|
}
|
||||||
|
controllers.InitExtensionsMap(extensionsMap)
|
||||||
log.Printf("allOutboundPorts: %v\n", allOutboundPorts)
|
log.Printf("allOutboundPorts: %v\n", allOutboundPorts)
|
||||||
log.Printf("allInboundPorts: %v\n", allInboundPorts)
|
log.Printf("allInboundPorts: %v\n", allInboundPorts)
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,12 @@ import (
|
|||||||
tapApi "github.com/up9inc/mizu/tap/api"
|
tapApi "github.com/up9inc/mizu/tap/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var extensionsMap map[string]*tapApi.Extension // global
|
||||||
|
|
||||||
|
func InitExtensionsMap(ref map[string]*tapApi.Extension) {
|
||||||
|
extensionsMap = ref
|
||||||
|
}
|
||||||
|
|
||||||
func GetEntries(c *gin.Context) {
|
func GetEntries(c *gin.Context) {
|
||||||
entriesFilter := &models.EntriesFilter{}
|
entriesFilter := &models.EntriesFilter{}
|
||||||
|
|
||||||
@ -230,7 +236,10 @@ func GetEntry(c *gin.Context) {
|
|||||||
// "msg": "Can't get entry details",
|
// "msg": "Can't get entry details",
|
||||||
// })
|
// })
|
||||||
// }
|
// }
|
||||||
c.JSON(http.StatusOK, entryData)
|
c.JSON(http.StatusOK, tapApi.MizuEntryWrapper{
|
||||||
|
Protocol: extensionsMap[entryData.ProtocolName].Protocol,
|
||||||
|
Data: entryData,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteAllEntries(c *gin.Context) {
|
func DeleteAllEntries(c *gin.Context) {
|
||||||
|
@ -88,6 +88,7 @@ type MizuEntry struct {
|
|||||||
ID uint `gorm:"primarykey"`
|
ID uint `gorm:"primarykey"`
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
UpdatedAt time.Time
|
UpdatedAt time.Time
|
||||||
|
ProtocolName string `json:"protocol_key" gorm:"column:protocolKey"`
|
||||||
Entry string `json:"entry,omitempty" gorm:"column:entry"`
|
Entry string `json:"entry,omitempty" gorm:"column:entry"`
|
||||||
EntryId string `json:"entryId" gorm:"column:entryId"`
|
EntryId string `json:"entryId" gorm:"column:entryId"`
|
||||||
Url string `json:"url" gorm:"column:url"`
|
Url string `json:"url" gorm:"column:url"`
|
||||||
@ -107,6 +108,11 @@ type MizuEntry struct {
|
|||||||
EstimatedSizeBytes int `json:"-" gorm:"column:estimatedSizeBytes"`
|
EstimatedSizeBytes int `json:"-" gorm:"column:estimatedSizeBytes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MizuEntryWrapper struct {
|
||||||
|
Protocol Protocol `json:"protocol"`
|
||||||
|
Data MizuEntry `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
type BaseEntryDetails struct {
|
type BaseEntryDetails struct {
|
||||||
Id string `json:"id,omitempty"`
|
Id string `json:"id,omitempty"`
|
||||||
Protocol Protocol `json:"protocol,omitempty"`
|
Protocol Protocol `json:"protocol,omitempty"`
|
||||||
|
@ -116,6 +116,7 @@ func (d dissecting) Analyze(item *api.OutputChannelItem, entryId string, resolve
|
|||||||
entryBytes, _ := json.Marshal(item.Pair)
|
entryBytes, _ := json.Marshal(item.Pair)
|
||||||
service := fmt.Sprintf("http://%s", host)
|
service := fmt.Sprintf("http://%s", host)
|
||||||
return &api.MizuEntry{
|
return &api.MizuEntry{
|
||||||
|
ProtocolName: protocol.Name,
|
||||||
EntryId: entryId,
|
EntryId: entryId,
|
||||||
Entry: string(entryBytes),
|
Entry: string(entryBytes),
|
||||||
Url: fmt.Sprintf("%s%s", service, request["url"].(string)),
|
Url: fmt.Sprintf("%s%s", service, request["url"].(string)),
|
||||||
|
@ -76,7 +76,7 @@ export const HarEntry: React.FC<HAREntryProps> = ({entry, setFocusedEntryId, isS
|
|||||||
onClick={() => setFocusedEntryId(entry.id)}
|
onClick={() => setFocusedEntryId(entry.id)}
|
||||||
style={{border: isSelected ? `1px ${entry.protocol.background_color} solid` : "1px transparent solid"}}
|
style={{border: isSelected ? `1px ${entry.protocol.background_color} solid` : "1px transparent solid"}}
|
||||||
>
|
>
|
||||||
<Protocol protocol={entry.protocol}/>
|
<Protocol protocol={entry.protocol} horizontal={false}/>
|
||||||
{entry.status_code && <div>
|
{entry.status_code && <div>
|
||||||
<StatusCode statusCode={entry.status_code}/>
|
<StatusCode statusCode={entry.status_code}/>
|
||||||
</div>}
|
</div>}
|
||||||
|
@ -3,16 +3,26 @@ import {singleEntryToHAR} from "./utils";
|
|||||||
import styles from './style/HarEntryDetailed.module.sass';
|
import styles from './style/HarEntryDetailed.module.sass';
|
||||||
import HAREntryViewer from "./HarEntryViewer/HAREntryViewer";
|
import HAREntryViewer from "./HarEntryViewer/HAREntryViewer";
|
||||||
import {makeStyles} from "@material-ui/core";
|
import {makeStyles} from "@material-ui/core";
|
||||||
|
import Protocol, {ProtocolInterface} from "./Protocol"
|
||||||
import StatusCode from "./StatusCode";
|
import StatusCode from "./StatusCode";
|
||||||
import {EndpointPath} from "./EndpointPath";
|
import {EndpointPath} from "./EndpointPath";
|
||||||
|
|
||||||
const useStyles = makeStyles(() => ({
|
const useStyles = makeStyles(() => ({
|
||||||
entryTitle: {
|
entryTitle: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
minHeight: 46,
|
minHeight: 20,
|
||||||
maxHeight: 46,
|
maxHeight: 46,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
marginBottom: 8,
|
marginBottom: 4,
|
||||||
|
padding: 2,
|
||||||
|
paddingBottom: 0
|
||||||
|
},
|
||||||
|
entrySummary: {
|
||||||
|
display: 'flex',
|
||||||
|
minHeight: 36,
|
||||||
|
maxHeight: 46,
|
||||||
|
alignItems: 'center',
|
||||||
|
marginBottom: 4,
|
||||||
padding: 5,
|
padding: 5,
|
||||||
paddingBottom: 0
|
paddingBottom: 0
|
||||||
}
|
}
|
||||||
@ -25,33 +35,47 @@ interface HarEntryDetailedProps {
|
|||||||
|
|
||||||
export const formatSize = (n: number) => n > 1000 ? `${Math.round(n / 1000)}KB` : `${n} B`;
|
export const formatSize = (n: number) => n > 1000 ? `${Math.round(n / 1000)}KB` : `${n} B`;
|
||||||
|
|
||||||
const HarEntryTitle: React.FC<any> = ({har}) => {
|
const HarEntryTitle: React.FC<any> = ({protocol, har}) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
|
||||||
|
const {log: {entries}} = har;
|
||||||
|
const {response} = JSON.parse(entries[0].entry);
|
||||||
|
const {bodySize} = response.payload;
|
||||||
|
|
||||||
|
|
||||||
|
return <div className={classes.entryTitle}>
|
||||||
|
<Protocol protocol={protocol} horizontal={true}/>
|
||||||
|
<div style={{right: "30px", position: "absolute", display: "flex"}}>
|
||||||
|
<div style={{margin: "0 18px", opacity: 0.5}}>{formatSize(bodySize)}</div>
|
||||||
|
<div style={{opacity: 0.5}}>{'rulesMatched' in entries[0] ? entries[0].rulesMatched?.length : '0'} Rules Applied</div>
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const HarEntrySummary: React.FC<any> = ({har}) => {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
const {log: {entries}} = har;
|
const {log: {entries}} = har;
|
||||||
const {response, request} = JSON.parse(entries[0].entry);
|
const {response, request} = JSON.parse(entries[0].entry);
|
||||||
const {status, statusText, bodySize} = response;
|
const {status} = response.payload;
|
||||||
|
|
||||||
|
|
||||||
return <div className={classes.entryTitle}>
|
return <div className={classes.entrySummary}>
|
||||||
{status && <div style={{marginRight: 8}}>
|
{status && <div style={{marginRight: 8}}>
|
||||||
<StatusCode statusCode={status}/>
|
<StatusCode statusCode={status}/>
|
||||||
</div>}
|
</div>}
|
||||||
<div style={{flexGrow: 1, overflow: 'hidden'}}>
|
<div style={{flexGrow: 1, overflow: 'hidden'}}>
|
||||||
<EndpointPath method={request?.method} path={request?.url}/>
|
<EndpointPath method={request?.payload.method} path={request?.payload.url}/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{margin: "0 18px", opacity: 0.5}}>{formatSize(bodySize)}</div>
|
|
||||||
<div style={{marginRight: 18, opacity: 0.5}}>{status} {statusText}</div>
|
|
||||||
{/* <div style={{marginRight: 18, opacity: 0.5}}>{Math.round(receive)}ms</div> */}
|
|
||||||
<div style={{opacity: 0.5}}>{'rulesMatched' in entries[0] ? entries[0].rulesMatched?.length : '0'} Rules Applied</div>
|
|
||||||
</div>;
|
</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const HAREntryDetailed: React.FC<HarEntryDetailedProps> = ({classes, harEntry}) => {
|
export const HAREntryDetailed: React.FC<HarEntryDetailedProps> = ({classes, harEntry}) => {
|
||||||
const har = singleEntryToHAR(harEntry);
|
const har = singleEntryToHAR(harEntry.data);
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
{har && <HarEntryTitle har={har}/>}
|
<HarEntryTitle protocol={harEntry.protocol} har={har}/>
|
||||||
|
{har && <HarEntrySummary har={har}/>}
|
||||||
<>
|
<>
|
||||||
{har && <HAREntryViewer
|
{har && <HAREntryViewer
|
||||||
harObject={har}
|
harObject={har}
|
||||||
|
@ -7,8 +7,6 @@ const MIME_TYPE_KEY = 'mimeType';
|
|||||||
|
|
||||||
const HAREntryDisplay: React.FC<any> = ({har, entry, isCollapsed: initialIsCollapsed, isResponseMocked}) => {
|
const HAREntryDisplay: React.FC<any> = ({har, entry, isCollapsed: initialIsCollapsed, isResponseMocked}) => {
|
||||||
const {request, response} = JSON.parse(entry);
|
const {request, response} = JSON.parse(entry);
|
||||||
console.log('request:', request)
|
|
||||||
console.log('response:', response)
|
|
||||||
const rulesMatched = har.log.entries[0].rulesMatched
|
const rulesMatched = har.log.entries[0].rulesMatched
|
||||||
const TABS = [
|
const TABS = [
|
||||||
{tab: 'request'},
|
{tab: 'request'},
|
||||||
|
@ -1,27 +1,42 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import internal from "stream";
|
|
||||||
import styles from './style/Protocol.module.sass';
|
import styles from './style/Protocol.module.sass';
|
||||||
|
|
||||||
export interface ProtocolInterface {
|
export interface ProtocolInterface {
|
||||||
name: string,
|
name: string
|
||||||
long_name: string,
|
long_name: string
|
||||||
abbreviation: string,
|
abbreviation: string
|
||||||
background_color: string,
|
background_color: string
|
||||||
foreground_color: string,
|
foreground_color: string
|
||||||
font_size: number,
|
font_size: number
|
||||||
reference_link: string,
|
reference_link: string
|
||||||
outbound_ports: string[],
|
outbound_ports: string[]
|
||||||
inbound_ports: string,
|
inbound_ports: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ProtocolProps {
|
interface ProtocolProps {
|
||||||
protocol: ProtocolInterface
|
protocol: ProtocolInterface
|
||||||
|
horizontal: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const Protocol: React.FC<ProtocolProps> = ({protocol}) => {
|
const Protocol: React.FC<ProtocolProps> = ({protocol, horizontal}) => {
|
||||||
|
if (horizontal) {
|
||||||
return <a target="_blank" rel="noopener noreferrer" href={protocol.reference_link}>
|
return <a target="_blank" rel="noopener noreferrer" href={protocol.reference_link}>
|
||||||
<span
|
<span
|
||||||
className={`${styles.base}`}
|
className={`${styles.base} ${styles.horizontal}`}
|
||||||
|
style={{
|
||||||
|
backgroundColor: protocol.background_color,
|
||||||
|
color: protocol.foreground_color,
|
||||||
|
fontSize: protocol.font_size * 1.3,
|
||||||
|
}}
|
||||||
|
title={protocol.abbreviation}
|
||||||
|
>
|
||||||
|
{protocol.long_name}
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
} else {
|
||||||
|
return <a target="_blank" rel="noopener noreferrer" href={protocol.reference_link}>
|
||||||
|
<span
|
||||||
|
className={`${styles.base} ${styles.vertical}`}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: protocol.background_color,
|
backgroundColor: protocol.background_color,
|
||||||
color: protocol.foreground_color,
|
color: protocol.foreground_color,
|
||||||
@ -32,6 +47,7 @@ const Protocol: React.FC<ProtocolProps> = ({protocol}) => {
|
|||||||
{protocol.abbreviation}
|
{protocol.abbreviation}
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Protocol;
|
export default Protocol;
|
||||||
|
@ -1,20 +1,27 @@
|
|||||||
@import 'variables.module'
|
@import 'variables.module'
|
||||||
|
|
||||||
.base
|
.base
|
||||||
// border-radius: 4px
|
|
||||||
border-radius: 4px 0 0 4px
|
|
||||||
width: 22px
|
|
||||||
height: 48px
|
|
||||||
font-size: 10px
|
|
||||||
display: inline-block
|
display: inline-block
|
||||||
text-align: center
|
text-align: center
|
||||||
line-height: 22px
|
font-size: 10px
|
||||||
font-weight: 600
|
font-weight: 600
|
||||||
writing-mode: vertical-lr;
|
|
||||||
// transform: rotate(-180deg);
|
|
||||||
text-orientation: upright;
|
|
||||||
// letter-spacing: 2px;
|
// letter-spacing: 2px;
|
||||||
background-color: #000
|
background-color: #000
|
||||||
color: #fff
|
color: #fff
|
||||||
margin-left: -8px;
|
margin-left: -8px;
|
||||||
margin-bottom: -4px;
|
margin-bottom: -4px;
|
||||||
|
|
||||||
|
.vertical
|
||||||
|
line-height: 22px
|
||||||
|
width: 22px
|
||||||
|
height: 48px
|
||||||
|
border-radius: 4px 0 0 4px
|
||||||
|
writing-mode: vertical-lr;
|
||||||
|
// transform: rotate(-180deg);
|
||||||
|
text-orientation: upright;
|
||||||
|
|
||||||
|
.horizontal
|
||||||
|
border-radius: 4px
|
||||||
|
font-size: 22px
|
||||||
|
padding: 5px 10px
|
||||||
|
font-weight: 600
|
||||||
|
Loading…
Reference in New Issue
Block a user