Fix the issues in analysis and representation of HTTP/2 (gRPC) protocol

This commit is contained in:
M. Mert Yildiran 2021-08-22 19:50:27 +03:00
parent 820dc09976
commit e90fd58d5e
No known key found for this signature in database
GPG Key ID: D42ADB236521BF7A
7 changed files with 25 additions and 12 deletions

View File

@ -118,7 +118,7 @@ type BaseEntryDetails struct {
RequestSenderIp string `json:"request_sender_ip,omitempty"` RequestSenderIp string `json:"request_sender_ip,omitempty"`
Service string `json:"service,omitempty"` Service string `json:"service,omitempty"`
Summary string `json:"summary,omitempty"` Summary string `json:"summary,omitempty"`
StatusCode int `json:"status_code,omitempty"` StatusCode int `json:"status_code"`
Method string `json:"method,omitempty"` Method string `json:"method,omitempty"`
Timestamp int64 `json:"timestamp,omitempty"` Timestamp int64 `json:"timestamp,omitempty"`
SourceIp string `json:"source_ip,omitempty"` SourceIp string `json:"source_ip,omitempty"`

View File

@ -209,7 +209,7 @@ func (d dissecting) Dissect(b *bufio.Reader, isClient bool, tcpID *api.TcpID, em
func (d dissecting) Analyze(item *api.OutputChannelItem, entryId string, resolvedSource string, resolvedDestination string) *api.MizuEntry { func (d dissecting) Analyze(item *api.OutputChannelItem, entryId string, resolvedSource string, resolvedDestination string) *api.MizuEntry {
request := item.Pair.Request.Payload.(map[string]interface{}) request := item.Pair.Request.Payload.(map[string]interface{})
reqDetails := request["details"].(map[string]interface{}) reqDetails := request["details"].(map[string]interface{})
service := fmt.Sprintf("amqp") service := "amqp"
summary := "" summary := ""
switch request["method"] { switch request["method"] {

View File

@ -102,29 +102,43 @@ func (d dissecting) Dissect(b *bufio.Reader, isClient bool, tcpID *api.TcpID, em
} }
func (d dissecting) Analyze(item *api.OutputChannelItem, entryId string, resolvedSource string, resolvedDestination string) *api.MizuEntry { func (d dissecting) Analyze(item *api.OutputChannelItem, entryId string, resolvedSource string, resolvedDestination string) *api.MizuEntry {
var host string var host, scheme, authority, path, service string
for _, header := range item.Pair.Request.Payload.(map[string]interface{})["headers"].([]interface{}) { for _, header := range item.Pair.Request.Payload.(map[string]interface{})["headers"].([]interface{}) {
h := header.(map[string]interface{}) h := header.(map[string]interface{})
if h["name"] == "Host" { if h["name"] == "Host" {
host = h["value"].(string) host = h["value"].(string)
} }
if h["name"] == ":authority" {
authority = h["value"].(string)
}
if h["name"] == ":scheme" {
scheme = h["value"].(string)
}
if h["name"] == ":path" {
path = h["value"].(string)
}
} }
request := item.Pair.Request.Payload.(map[string]interface{}) request := item.Pair.Request.Payload.(map[string]interface{})
response := item.Pair.Response.Payload.(map[string]interface{}) response := item.Pair.Response.Payload.(map[string]interface{})
entryBytes, _ := json.Marshal(item.Pair) entryBytes, _ := json.Marshal(item.Pair)
service := fmt.Sprintf("http://%s", host) if item.Protocol.Version == "2.0" {
service = fmt.Sprintf("(gRPC) %s://%s", scheme, authority)
} else {
service = fmt.Sprintf("http://%s", host)
path = request["url"].(string)
}
return &api.MizuEntry{ return &api.MizuEntry{
ProtocolName: protocol.Name, ProtocolName: protocol.Name,
ProtocolVersion: item.Protocol.Version, ProtocolVersion: item.Protocol.Version,
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, path),
Method: request["method"].(string), Method: request["method"].(string),
Status: int(response["status"].(float64)), Status: int(response["status"].(float64)),
RequestSenderIp: item.ConnectionInfo.ClientIP, RequestSenderIp: item.ConnectionInfo.ClientIP,
Service: service, Service: service,
Timestamp: item.Timestamp, Timestamp: item.Timestamp,
Path: request["url"].(string), Path: path,
ResolvedSource: resolvedSource, ResolvedSource: resolvedSource,
ResolvedDestination: resolvedDestination, ResolvedDestination: resolvedDestination,
SourceIp: item.ConnectionInfo.ClientIP, SourceIp: item.ConnectionInfo.ClientIP,

View File

@ -48,7 +48,7 @@ func (d dissecting) Dissect(b *bufio.Reader, isClient bool, tcpID *api.TcpID, em
func (d dissecting) Analyze(item *api.OutputChannelItem, entryId string, resolvedSource string, resolvedDestination string) *api.MizuEntry { func (d dissecting) Analyze(item *api.OutputChannelItem, entryId string, resolvedSource string, resolvedDestination string) *api.MizuEntry {
request := item.Pair.Request.Payload.(map[string]interface{}) request := item.Pair.Request.Payload.(map[string]interface{})
reqDetails := request["details"].(map[string]interface{}) reqDetails := request["details"].(map[string]interface{})
service := fmt.Sprintf("kafka") service := "kafka"
apiKey := ApiKey(reqDetails["ApiKey"].(float64)) apiKey := ApiKey(reqDetails["ApiKey"].(float64))
summary := "" summary := ""

View File

@ -77,7 +77,7 @@ export const HarEntry: React.FC<HAREntryProps> = ({entry, setFocusedEntryId, isS
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} horizontal={false}/> <Protocol protocol={entry.protocol} horizontal={false}/>
{entry.status_code && <div> {((entry.protocol.name === "http" && "status_code" in entry) || entry.status_code !== 0) && <div>
<StatusCode statusCode={entry.status_code}/> <StatusCode statusCode={entry.status_code}/>
</div>} </div>}
<div className={styles.endpointServiceContainer}> <div className={styles.endpointServiceContainer}>

View File

@ -57,7 +57,7 @@ const HarEntrySummary: React.FC<any> = ({har}) => {
const {response, request} = JSON.parse(entries[0].entry); const {response, request} = JSON.parse(entries[0].entry);
return <div className={classes.entrySummary}> return <div className={classes.entrySummary}>
{response.payload && response.payload.status && <div style={{marginRight: 8}}> {response?.payload && "status" in response.payload && <div style={{marginRight: 8}}>
<StatusCode statusCode={response.payload.status}/> <StatusCode statusCode={response.payload.status}/>
</div>} </div>}
<div style={{flexGrow: 1, overflow: 'hidden'}}> <div style={{flexGrow: 1, overflow: 'hidden'}}>

View File

@ -7,7 +7,6 @@ export enum StatusCodeClassification {
NEUTRAL = "neutral" NEUTRAL = "neutral"
} }
interface HAREntryProps { interface HAREntryProps {
statusCode: number statusCode: number
} }
@ -26,9 +25,9 @@ const StatusCode: React.FC<HAREntryProps> = ({statusCode}) => {
export function getClassification(statusCode: number): string { export function getClassification(statusCode: number): string {
let classification = StatusCodeClassification.NEUTRAL; let classification = StatusCodeClassification.NEUTRAL;
if (statusCode >= 200 && statusCode <= 399) { if ((statusCode >= 200 && statusCode <= 399) || statusCode === 0) {
classification = StatusCodeClassification.SUCCESS; classification = StatusCodeClassification.SUCCESS;
} else if (statusCode >= 400) { } else if (statusCode >= 400 || (statusCode >= 1 && statusCode <= 16)) {
classification = StatusCodeClassification.FAILURE; classification = StatusCodeClassification.FAILURE;
} }