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  }