github.com/cilium/cilium@v1.16.2/pkg/monitor/datapath_policy.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package monitor 5 6 import ( 7 "bufio" 8 "fmt" 9 "os" 10 11 "github.com/cilium/cilium/pkg/byteorder" 12 "github.com/cilium/cilium/pkg/identity" 13 "github.com/cilium/cilium/pkg/monitor/api" 14 "github.com/cilium/cilium/pkg/policy" 15 ) 16 17 const ( 18 // PolicyVerdictNotifyLen is the amount of packet data provided in a Policy notification 19 PolicyVerdictNotifyLen = 32 20 21 // The values below are for parsing PolicyVerdictNotify. They need to be consistent 22 // with what are defined in data plane. 23 24 // PolicyVerdictNotifyFlagDirection is the bit mask in Flags that 25 // corresponds to the direction of a traffic 26 PolicyVerdictNotifyFlagDirection = 0x3 27 28 // PolicyVerdictNotifyFlagIsIPv6 is the bit mask in Flags that 29 // corresponds to whether the traffic is IPv6 or not 30 PolicyVerdictNotifyFlagIsIPv6 = 0x4 31 32 // PolicyVerdictNotifyFlagMatchType is the bit mask in Flags that 33 // corresponds to the policy match type 34 PolicyVerdictNotifyFlagMatchType = 0x38 35 36 // PolicyVerdictNotifyFlagIsAudited is the bit mask in Flags that 37 // corresponds to whether the traffic was allowed due to the audit mode 38 PolicyVerdictNotifyFlagIsAudited = 0x40 39 40 // PolicyVerdictNotifyFlagMatchTypeBitOffset is the bit offset in Flags that 41 // corresponds to the policy match type 42 PolicyVerdictNotifyFlagMatchTypeBitOffset = 3 43 ) 44 45 // PolicyVerdictNotify is the message format of a policy verdict notification in the bpf ring buffer 46 type PolicyVerdictNotify struct { 47 Type uint8 48 SubType uint8 49 Source uint16 50 Hash uint32 51 OrigLen uint32 52 CapLen uint16 53 Version uint16 54 RemoteLabel identity.NumericIdentity 55 Verdict int32 56 DstPort uint16 57 Proto uint8 58 Flags uint8 59 AuthType uint8 60 Pad1 uint8 61 Pad2 uint16 62 // data 63 } 64 65 // DecodePolicyVerdictNotify will decode 'data' into the provided PolicyVerdictNotify structure 66 func DecodePolicyVerdictNotify(data []byte, pvn *PolicyVerdictNotify) error { 67 return pvn.decodePolicyVerdictNotify(data) 68 } 69 70 func (n *PolicyVerdictNotify) decodePolicyVerdictNotify(data []byte) error { 71 if l := len(data); l < PolicyVerdictNotifyLen { 72 return fmt.Errorf("unexpected PolicyVerdictNotify data length, expected %d but got %d", PolicyVerdictNotifyLen, l) 73 } 74 75 n.Type = data[0] 76 n.SubType = data[1] 77 n.Source = byteorder.Native.Uint16(data[2:4]) 78 n.Hash = byteorder.Native.Uint32(data[4:8]) 79 n.OrigLen = byteorder.Native.Uint32(data[8:12]) 80 n.CapLen = byteorder.Native.Uint16(data[12:14]) 81 n.Version = byteorder.Native.Uint16(data[14:16]) 82 n.RemoteLabel = identity.NumericIdentity(byteorder.Native.Uint32(data[16:20])) 83 n.Verdict = int32(byteorder.Native.Uint32(data[20:24])) 84 n.DstPort = byteorder.Native.Uint16(data[24:26]) 85 n.Proto = data[26] 86 n.Flags = data[27] 87 n.AuthType = data[28] 88 n.Pad1 = data[29] 89 n.Pad2 = byteorder.Native.Uint16(data[30:32]) 90 91 return nil 92 } 93 94 // IsTrafficIngress returns true if this notify is for an ingress traffic 95 func (n *PolicyVerdictNotify) IsTrafficIngress() bool { 96 return n.Flags&PolicyVerdictNotifyFlagDirection == api.PolicyIngress 97 } 98 99 // IsTrafficIPv6 returns true if this notify is for IPv6 traffic 100 func (n *PolicyVerdictNotify) IsTrafficIPv6() bool { 101 return (n.Flags&PolicyVerdictNotifyFlagIsIPv6 > 0) 102 } 103 104 // GetPolicyMatchType returns how the traffic matched the policy 105 func (n *PolicyVerdictNotify) GetPolicyMatchType() api.PolicyMatchType { 106 return api.PolicyMatchType((n.Flags & PolicyVerdictNotifyFlagMatchType) >> 107 PolicyVerdictNotifyFlagMatchTypeBitOffset) 108 } 109 110 // IsTrafficAudited returns true if this notify is for traffic that 111 // was allowed due to the audit mode 112 func (n *PolicyVerdictNotify) IsTrafficAudited() bool { 113 return (n.Flags&PolicyVerdictNotifyFlagIsAudited > 0) 114 } 115 116 // GetPolicyActionString returns the action string corresponding to the action 117 func GetPolicyActionString(verdict int32, audit bool) string { 118 if audit { 119 return "audit" 120 } 121 122 if verdict < 0 { 123 return "deny" 124 } else if verdict > 0 { 125 return "redirect" 126 } 127 return "allow" 128 } 129 130 // GetAuthType returns string for the authentication method applied (for success verdict) 131 // or required (for drops). 132 func (n *PolicyVerdictNotify) GetAuthType() policy.AuthType { 133 return policy.AuthType(n.AuthType) 134 } 135 136 // DumpInfo prints a summary of the policy notify messages. 137 func (n *PolicyVerdictNotify) DumpInfo(data []byte, numeric DisplayFormat) { 138 buf := bufio.NewWriter(os.Stdout) 139 dir := "egress" 140 if n.IsTrafficIngress() { 141 dir = "ingress" 142 } 143 fmt.Fprintf(buf, "Policy verdict log: flow %#x local EP ID %d", n.Hash, n.Source) 144 if numeric { 145 fmt.Fprintf(buf, ", remote ID %d", n.RemoteLabel) 146 } else { 147 fmt.Fprintf(buf, ", remote ID %s", n.RemoteLabel) 148 } 149 fmt.Fprintf(buf, ", proto %d, %s, action %s, auth: %s, match %s, %s\n", n.Proto, dir, 150 GetPolicyActionString(n.Verdict, n.IsTrafficAudited()), 151 n.GetAuthType(), n.GetPolicyMatchType(), 152 GetConnectionSummary(data[PolicyVerdictNotifyLen:])) 153 buf.Flush() 154 }