github.com/fafucoder/cilium@v1.6.11/pkg/monitor/logrecord.go (about) 1 // Copyright 2018 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package monitor 16 17 import ( 18 "encoding/json" 19 "fmt" 20 "strings" 21 22 "github.com/cilium/cilium/pkg/proxy/accesslog" 23 "github.com/miekg/dns" 24 ) 25 26 // LogRecordNotify is a proxy access log notification 27 type LogRecordNotify struct { 28 accesslog.LogRecord 29 } 30 31 func (l *LogRecordNotify) direction() string { 32 switch l.ObservationPoint { 33 case accesslog.Ingress: 34 return "<-" 35 case accesslog.Egress: 36 return "->" 37 default: 38 return "??" 39 } 40 } 41 42 func (l *LogRecordNotify) l7Proto() string { 43 if l.HTTP != nil { 44 return "http" 45 } 46 47 if l.Kafka != nil { 48 return "kafka" 49 } 50 51 if l.DNS != nil { 52 return "dns" 53 } 54 55 if l.L7 != nil { 56 return l.L7.Proto 57 } 58 59 return "unknown-l7" 60 } 61 62 // DumpInfo dumps an access log notification 63 func (l *LogRecordNotify) DumpInfo() { 64 switch l.Type { 65 case accesslog.TypeRequest: 66 fmt.Printf("%s %s %s from %d (%s) to %d (%s), identity %d->%d, verdict %s", 67 l.direction(), l.Type, l.l7Proto(), l.SourceEndpoint.ID, l.SourceEndpoint.Labels, 68 l.DestinationEndpoint.ID, l.DestinationEndpoint.Labels, 69 l.SourceEndpoint.Identity, l.DestinationEndpoint.Identity, 70 l.Verdict) 71 72 case accesslog.TypeResponse: 73 fmt.Printf("%s %s %s to %d (%s) from %d (%s), identity %d->%d, verdict %s", 74 l.direction(), l.Type, l.l7Proto(), l.SourceEndpoint.ID, l.SourceEndpoint.Labels, 75 l.DestinationEndpoint.ID, l.DestinationEndpoint.Labels, 76 l.SourceEndpoint.Identity, l.DestinationEndpoint.Identity, 77 l.Verdict) 78 } 79 80 if http := l.HTTP; http != nil { 81 url := "" 82 if http.URL != nil { 83 url = http.URL.String() 84 } 85 86 fmt.Printf(" %s %s => %d\n", http.Method, url, http.Code) 87 } 88 89 if kafka := l.Kafka; kafka != nil { 90 fmt.Printf(" %s topic %s => %d\n", kafka.APIKey, kafka.Topic.Topic, kafka.ErrorCode) 91 } 92 93 if l.DNS != nil { 94 types := []string{} 95 for _, t := range l.DNS.QTypes { 96 types = append(types, dns.TypeToString[t]) 97 } 98 qTypeStr := strings.Join(types, ",") 99 100 switch { 101 case l.Type == accesslog.TypeRequest: 102 fmt.Printf(" DNS Query: %s %s", l.DNS.Query, qTypeStr) 103 104 case l.Type == accesslog.TypeResponse: 105 sourceType := "Query" 106 if l.DNS.ObservationSource == accesslog.DNSSourceAgentPoller { 107 sourceType = "Poll" 108 } 109 110 fmt.Printf(" DNS %s: %s %s", sourceType, l.DNS.Query, qTypeStr) 111 112 ips := make([]string, 0, len(l.DNS.IPs)) 113 for _, ip := range l.DNS.IPs { 114 ips = append(ips, ip.String()) 115 } 116 fmt.Printf(" TTL: %d Answer: '%s'", l.DNS.TTL, strings.Join(ips, ",")) 117 118 if len(l.DNS.CNAMEs) > 0 { 119 fmt.Printf(" CNAMEs: %s", strings.Join(l.DNS.CNAMEs, ",")) 120 } 121 } 122 fmt.Printf("\n") 123 } 124 125 if l7 := l.L7; l7 != nil { 126 status := "" 127 for k, v := range l7.Fields { 128 if k == "status" { 129 status = v 130 } else { 131 fmt.Printf(" %s:%s", k, v) 132 } 133 } 134 if status != "" { 135 fmt.Printf(" => status:%s", status) 136 } 137 fmt.Printf("\n") 138 } 139 } 140 141 func (l *LogRecordNotify) getJSON() (string, error) { 142 v := LogRecordNotifyToVerbose(l) 143 144 ret, err := json.Marshal(v) 145 return string(ret), err 146 } 147 148 // DumpJSON prints notification in json format 149 func (l *LogRecordNotify) DumpJSON() { 150 resp, err := l.getJSON() 151 if err == nil { 152 fmt.Println(resp) 153 } 154 } 155 156 // LogRecordNotifyVerbose represents a json notification printed by monitor 157 type LogRecordNotifyVerbose struct { 158 Type string `json:"type"` 159 ObservationPoint accesslog.ObservationPoint `json:"observationPoint"` 160 FlowType accesslog.FlowType `json:"flowType"` 161 L7Proto string `json:"l7Proto"` 162 SrcEpID uint64 `json:"srcEpID"` 163 SrcEpLabels []string `json:"srcEpLabels"` 164 SrcIdentity uint64 `json:"srcIdentity"` 165 DstEpID uint64 `json:"dstEpID"` 166 DstEpLabels []string `json:"dstEpLabels"` 167 DstIdentity uint64 `json:"dstIdentity"` 168 Verdict accesslog.FlowVerdict `json:"verdict"` 169 HTTP *accesslog.LogRecordHTTP `json:"http,omitempty"` 170 Kafka *accesslog.LogRecordKafka `json:"kafka,omitempty"` 171 DNS *accesslog.LogRecordDNS `json:"dns,omitempty"` 172 L7 *accesslog.LogRecordL7 `json:"l7,omitempty"` 173 } 174 175 // LogRecordNotifyToVerbose turns LogRecordNotify into json-friendly Verbose structure 176 func LogRecordNotifyToVerbose(n *LogRecordNotify) LogRecordNotifyVerbose { 177 return LogRecordNotifyVerbose{ 178 Type: "logRecord", 179 ObservationPoint: n.ObservationPoint, 180 FlowType: n.Type, 181 L7Proto: n.l7Proto(), 182 SrcEpID: n.SourceEndpoint.ID, 183 SrcEpLabels: n.SourceEndpoint.Labels, 184 SrcIdentity: n.SourceEndpoint.Identity, 185 DstEpID: n.DestinationEndpoint.ID, 186 DstEpLabels: n.DestinationEndpoint.Labels, 187 DstIdentity: n.DestinationEndpoint.Identity, 188 Verdict: n.Verdict, 189 HTTP: n.HTTP, 190 Kafka: n.Kafka, 191 DNS: n.DNS, 192 L7: n.L7, 193 } 194 }