github.com/cilium/cilium@v1.16.2/pkg/hubble/metrics/policy/handler.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package policy
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"strings"
    10  
    11  	"github.com/prometheus/client_golang/prometheus"
    12  
    13  	flowpb "github.com/cilium/cilium/api/v1/flow"
    14  	"github.com/cilium/cilium/pkg/hubble/metrics/api"
    15  	"github.com/cilium/cilium/pkg/identity"
    16  	monitorAPI "github.com/cilium/cilium/pkg/monitor/api"
    17  )
    18  
    19  type policyHandler struct {
    20  	verdicts *prometheus.CounterVec
    21  	context  *api.ContextOptions
    22  }
    23  
    24  func (d *policyHandler) Init(registry *prometheus.Registry, options api.Options) error {
    25  	c, err := api.ParseContextOptions(options)
    26  	if err != nil {
    27  		return err
    28  	}
    29  	d.context = c
    30  
    31  	labels := []string{"direction", "match", "action"}
    32  	labels = append(labels, d.context.GetLabelNames()...)
    33  
    34  	d.verdicts = prometheus.NewCounterVec(prometheus.CounterOpts{
    35  		Namespace: api.DefaultPrometheusNamespace,
    36  		Name:      "policy_verdicts_total",
    37  		Help:      "Total number of Cilium network policy verdicts",
    38  	}, labels)
    39  
    40  	registry.MustRegister(d.verdicts)
    41  	return nil
    42  }
    43  
    44  func (d *policyHandler) Status() string {
    45  	return d.context.Status()
    46  }
    47  
    48  func (d *policyHandler) Context() *api.ContextOptions {
    49  	return d.context
    50  }
    51  
    52  func (d *policyHandler) ListMetricVec() []*prometheus.MetricVec {
    53  	return []*prometheus.MetricVec{d.verdicts.MetricVec}
    54  }
    55  
    56  func (d *policyHandler) ProcessFlow(ctx context.Context, flow *flowpb.Flow) error {
    57  	if flow.GetEventType().GetType() == monitorAPI.MessageTypePolicyVerdict {
    58  		return d.ProcessFlowL3L4(ctx, flow)
    59  	}
    60  
    61  	if flow.GetEventType().GetType() == monitorAPI.MessageTypeAccessLog {
    62  		return d.ProcessFlowL7(ctx, flow)
    63  	}
    64  
    65  	return nil
    66  }
    67  
    68  func (d *policyHandler) ProcessFlowL3L4(ctx context.Context, flow *flowpb.Flow) error {
    69  	// ignore verdict if the source is host since host is allowed to connect to any local endpoints.
    70  	if flow.GetSource().GetIdentity() == uint32(identity.ReservedIdentityHost) {
    71  		return nil
    72  	}
    73  	labelValues, err := d.context.GetLabelValues(flow)
    74  	if err != nil {
    75  		return err
    76  	}
    77  
    78  	direction := strings.ToLower(flow.GetTrafficDirection().String())
    79  	match := strings.ToLower(monitorAPI.PolicyMatchType(flow.GetPolicyMatchType()).String())
    80  	action := strings.ToLower(flow.Verdict.String())
    81  	labels := []string{direction, match, action}
    82  	labels = append(labels, labelValues...)
    83  
    84  	d.verdicts.WithLabelValues(labels...).Inc()
    85  	return nil
    86  }
    87  
    88  func (d *policyHandler) ProcessFlowL7(ctx context.Context, flow *flowpb.Flow) error {
    89  	labelValues, err := d.context.GetLabelValues(flow)
    90  	if err != nil {
    91  		return err
    92  	}
    93  
    94  	direction := strings.ToLower(flow.GetTrafficDirection().String())
    95  	var subType string
    96  	if l7 := flow.GetL7(); l7 != nil {
    97  		switch {
    98  		case l7.GetDns() != nil:
    99  			subType = "dns"
   100  		case l7.GetHttp() != nil:
   101  			subType = "http"
   102  		case l7.GetKafka() != nil:
   103  			subType = "kafka"
   104  		}
   105  	}
   106  	match := fmt.Sprintf("l7/%s", subType)
   107  	action := strings.ToLower(flow.Verdict.String())
   108  	labels := []string{direction, match, action}
   109  	labels = append(labels, labelValues...)
   110  
   111  	d.verdicts.WithLabelValues(labels...).Inc()
   112  	return nil
   113  }