Skip to content

Commit a712a5b

Browse files
committed
pkg/metrics: add event for tracing policy metrics
This patch adds metrics for tracing policy events. It uses the policy name and a hook name as labels. As an example, with this policy: ``` apiVersion: cilium.io/v1alpha1 kind: TracingPolicy metadata: name: "kubectlexec-net" spec: kprobes: - call: "tcp_connect" syscall: false args: - index: 0 type: "sock" selectors: - matchPIDs: - operator: NotIn followForks: true isNamespacePID: true values: - 1 - call: "tcp_close" syscall: false args: - index: 0 type: "sock" selectors: - matchPIDs: - operator: NotIn followForks: true isNamespacePID: true values: - 1 - call: "tcp_sendmsg" syscall: false args: - index: 0 type: "sock" - index: 2 type: int # follow any non-init pids (e.g., exec into container) selectors: - matchPIDs: - operator: NotIn followForks: true isNamespacePID: true values: - 1 ``` We will see the following events: ``` tetragon_policy_stats{binary="/usr/bin/curl",hook="kprobe:tcp_close",namespace="default",pod="pizza",policy="kubectlexec-net"} 1 │ tetragon_policy_stats{binary="/usr/bin/curl",hook="kprobe:tcp_connect",namespace="default",pod="pizza",policy="kubectlexec-net"} 1 │ tetragon_policy_stats{binary="/usr/bin/curl",hook="kprobe:tcp_sendmsg",namespace="default",pod="pizza",policy="kubectlexec-net"} 1 ``` Signed-off-by: Kornilios Kourtis <[email protected]>
1 parent 51a8e99 commit a712a5b

File tree

9 files changed

+123
-34
lines changed

9 files changed

+123
-34
lines changed

pkg/grpc/tracing/tracing.go

+27
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
package tracing
44

55
import (
6+
"fmt"
7+
68
"github.com/cilium/tetragon/api/v1/tetragon"
79
"github.com/cilium/tetragon/pkg/api/processapi"
810
"github.com/cilium/tetragon/pkg/api/tracingapi"
@@ -18,6 +20,7 @@ import (
1820
"github.com/cilium/tetragon/pkg/reader/node"
1921
"github.com/cilium/tetragon/pkg/reader/notify"
2022
"github.com/cilium/tetragon/pkg/reader/path"
23+
"github.com/cilium/tetragon/pkg/tracingpolicy"
2124
"google.golang.org/protobuf/types/known/wrapperspb"
2225
)
2326

@@ -224,6 +227,7 @@ type MsgGenericTracepointUnix struct {
224227
Subsys string
225228
Event string
226229
Args []tracingapi.MsgGenericTracepointArg
230+
PolicyName string
227231
}
228232

229233
func (msg *MsgGenericTracepointUnix) Notify() bool {
@@ -314,6 +318,13 @@ func (msg *MsgGenericTracepointUnix) Cast(o interface{}) notify.Message {
314318
return &t
315319
}
316320

321+
func (msg *MsgGenericTracepointUnix) PolicyInfo() tracingpolicy.PolicyInfo {
322+
return tracingpolicy.PolicyInfo{
323+
Name: msg.PolicyName,
324+
Hook: fmt.Sprintf("tracepoint:%s/%s", msg.Subsys, msg.Event),
325+
}
326+
}
327+
317328
type MsgGenericKprobeUnix struct {
318329
Common processapi.MsgCommon
319330
ProcessKey processapi.MsgExecveKey
@@ -323,6 +334,7 @@ type MsgGenericKprobeUnix struct {
323334
Action uint64
324335
FuncName string
325336
Args []tracingapi.MsgGenericKprobeArg
337+
PolicyName string
326338
}
327339

328340
func (msg *MsgGenericKprobeUnix) Notify() bool {
@@ -354,6 +366,13 @@ func (msg *MsgGenericKprobeUnix) Cast(o interface{}) notify.Message {
354366
return &t
355367
}
356368

369+
func (msg *MsgGenericKprobeUnix) PolicyInfo() tracingpolicy.PolicyInfo {
370+
return tracingpolicy.PolicyInfo{
371+
Name: msg.PolicyName,
372+
Hook: fmt.Sprintf("kprobe:%s", msg.FuncName),
373+
}
374+
}
375+
357376
type MsgProcessLoaderUnix struct {
358377
ProcessKey processapi.MsgExecveKey
359378
Path string
@@ -440,12 +459,20 @@ type MsgGenericUprobeUnix struct {
440459
ProcessKey processapi.MsgExecveKey
441460
Path string
442461
Symbol string
462+
PolicyName string
443463
}
444464

445465
func (msg *MsgGenericUprobeUnix) Notify() bool {
446466
return true
447467
}
448468

469+
func (msg *MsgGenericUprobeUnix) PolicyInfo() tracingpolicy.PolicyInfo {
470+
return tracingpolicy.PolicyInfo{
471+
Name: msg.PolicyName,
472+
Hook: fmt.Sprintf("uprobe:%s/%s", msg.Path, msg.Symbol),
473+
}
474+
}
475+
449476
func (msg *MsgGenericUprobeUnix) RetryInternal(ev notify.Event, timestamp uint64) (*process.ProcessInternal, error) {
450477
return eventcache.HandleGenericInternal(ev, msg.ProcessKey.Pid, timestamp)
451478
}

pkg/metrics/eventmetrics/eventmetrics.go

+20-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/cilium/tetragon/pkg/metrics/syscallmetrics"
1515
v1 "github.com/cilium/tetragon/pkg/oldhubble/api/v1"
1616
"github.com/cilium/tetragon/pkg/reader/exec"
17+
"github.com/cilium/tetragon/pkg/tracingpolicy"
1718
"github.com/prometheus/client_golang/prometheus"
1819
"github.com/prometheus/client_golang/prometheus/promauto"
1920
)
@@ -34,6 +35,12 @@ var (
3435
Help: "The total number of events dropped because listener buffer was full",
3536
ConstLabels: nil,
3637
}, nil)
38+
39+
policyStats = promauto.NewCounterVec(prometheus.CounterOpts{
40+
Name: consts.MetricNamePrefix + "policy_stats",
41+
Help: "Policy events calls observed.",
42+
ConstLabels: nil,
43+
}, []string{"policy", "hook", "namespace", "pod", "binary"})
3744
)
3845

3946
func GetProcessInfo(process *tetragon.Process) (binary, pod, namespace string) {
@@ -60,7 +67,7 @@ func handleOriginalEvent(originalEvent interface{}) {
6067
}
6168
}
6269

63-
func handleProcessedEvent(processedEvent interface{}) {
70+
func handleProcessedEvent(pInfo *tracingpolicy.PolicyInfo, processedEvent interface{}) {
6471
var eventType, namespace, pod, binary string
6572
switch ev := processedEvent.(type) {
6673
case *tetragon.GetEventsResponse:
@@ -75,10 +82,21 @@ func handleProcessedEvent(processedEvent interface{}) {
7582
eventType = "unknown"
7683
}
7784
EventsProcessed.WithLabelValues(eventType, namespace, pod, binary).Inc()
85+
if pInfo != nil && pInfo.Name != "" {
86+
policyStats.
87+
WithLabelValues(pInfo.Name, pInfo.Hook, namespace, pod, binary).
88+
Inc()
89+
}
7890
}
7991

8092
func ProcessEvent(originalEvent interface{}, processedEvent interface{}) {
8193
handleOriginalEvent(originalEvent)
82-
handleProcessedEvent(processedEvent)
94+
95+
var policyInfo tracingpolicy.PolicyInfo
96+
if policyEv, ok := originalEvent.(tracingpolicy.PolicyEvent); ok {
97+
policyInfo = policyEv.PolicyInfo()
98+
}
99+
100+
handleProcessedEvent(&policyInfo, processedEvent)
83101
syscallmetrics.Handle(processedEvent)
84102
}

pkg/metrics/eventmetrics/eventmetrics_test.go

+13-13
Original file line numberDiff line numberDiff line change
@@ -16,47 +16,47 @@ import (
1616

1717
func TestHandleProcessedEvent(t *testing.T) {
1818
assert.NoError(t, testutil.CollectAndCompare(EventsProcessed, strings.NewReader("")))
19-
handleProcessedEvent(nil)
19+
handleProcessedEvent(nil, nil)
2020
// empty process
21-
handleProcessedEvent(&tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessKprobe{ProcessKprobe: &tetragon.ProcessKprobe{}}})
22-
handleProcessedEvent(&tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessExec{ProcessExec: &tetragon.ProcessExec{}}})
23-
handleProcessedEvent(&tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessTracepoint{ProcessTracepoint: &tetragon.ProcessTracepoint{}}})
24-
handleProcessedEvent(&tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessExit{ProcessExit: &tetragon.ProcessExit{}}})
21+
handleProcessedEvent(nil, &tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessKprobe{ProcessKprobe: &tetragon.ProcessKprobe{}}})
22+
handleProcessedEvent(nil, &tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessExec{ProcessExec: &tetragon.ProcessExec{}}})
23+
handleProcessedEvent(nil, &tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessTracepoint{ProcessTracepoint: &tetragon.ProcessTracepoint{}}})
24+
handleProcessedEvent(nil, &tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessExit{ProcessExit: &tetragon.ProcessExit{}}})
2525

2626
// empty pod
27-
handleProcessedEvent(&tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessKprobe{ProcessKprobe: &tetragon.ProcessKprobe{
27+
handleProcessedEvent(nil, &tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessKprobe{ProcessKprobe: &tetragon.ProcessKprobe{
2828
Process: &tetragon.Process{Binary: "binary_a"},
2929
}}})
30-
handleProcessedEvent(&tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessExec{ProcessExec: &tetragon.ProcessExec{
30+
handleProcessedEvent(nil, &tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessExec{ProcessExec: &tetragon.ProcessExec{
3131
Process: &tetragon.Process{Binary: "binary_b"},
3232
}}})
33-
handleProcessedEvent(&tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessTracepoint{ProcessTracepoint: &tetragon.ProcessTracepoint{
33+
handleProcessedEvent(nil, &tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessTracepoint{ProcessTracepoint: &tetragon.ProcessTracepoint{
3434
Process: &tetragon.Process{Binary: "binary_c"},
3535
}}})
36-
handleProcessedEvent(&tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessExit{ProcessExit: &tetragon.ProcessExit{
36+
handleProcessedEvent(nil, &tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessExit{ProcessExit: &tetragon.ProcessExit{
3737
Process: &tetragon.Process{Binary: "binary_e"},
3838
}}})
3939

4040
// with pod
41-
handleProcessedEvent(&tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessKprobe{ProcessKprobe: &tetragon.ProcessKprobe{
41+
handleProcessedEvent(nil, &tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessKprobe{ProcessKprobe: &tetragon.ProcessKprobe{
4242
Process: &tetragon.Process{
4343
Binary: "binary_a",
4444
Pod: &tetragon.Pod{Namespace: "namespace_a", Name: "pod_a"},
4545
},
4646
}}})
47-
handleProcessedEvent(&tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessExec{ProcessExec: &tetragon.ProcessExec{
47+
handleProcessedEvent(nil, &tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessExec{ProcessExec: &tetragon.ProcessExec{
4848
Process: &tetragon.Process{
4949
Binary: "binary_b",
5050
Pod: &tetragon.Pod{Namespace: "namespace_b", Name: "pod_b"},
5151
},
5252
}}})
53-
handleProcessedEvent(&tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessTracepoint{ProcessTracepoint: &tetragon.ProcessTracepoint{
53+
handleProcessedEvent(nil, &tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessTracepoint{ProcessTracepoint: &tetragon.ProcessTracepoint{
5454
Process: &tetragon.Process{
5555
Binary: "binary_c",
5656
Pod: &tetragon.Pod{Namespace: "namespace_c", Name: "pod_c"},
5757
},
5858
}}})
59-
handleProcessedEvent(&tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessExit{ProcessExit: &tetragon.ProcessExit{
59+
handleProcessedEvent(nil, &tetragon.GetEventsResponse{Event: &tetragon.GetEventsResponse_ProcessExit{ProcessExit: &tetragon.ProcessExit{
6060
Process: &tetragon.Process{
6161
Binary: "binary_e",
6262
Pod: &tetragon.Pod{Namespace: "namespace_e", Name: "pod_e"},

pkg/sensors/tracing/generickprobe.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ type genericKprobe struct {
114114
actionArgs idtable.Table
115115

116116
pinPathPrefix string
117+
118+
// policyName is the name of the policy that this tracepoint belongs to
119+
policyName string
117120
}
118121

119122
// pendingEvent is an event waiting to be merged with another event.
@@ -326,7 +329,12 @@ func flagsString(flags uint32) string {
326329
return s
327330
}
328331

329-
func createGenericKprobeSensor(name string, kprobes []v1alpha1.KProbeSpec, policyID policyfilter.PolicyID) (*sensors.Sensor, error) {
332+
func createGenericKprobeSensor(
333+
name string,
334+
kprobes []v1alpha1.KProbeSpec,
335+
policyID policyfilter.PolicyID,
336+
policyName string,
337+
) (*sensors.Sensor, error) {
330338
var progs []*program.Program
331339
var maps []*program.Map
332340
var multiIDs, multiRetIDs []idtable.EntryID
@@ -479,6 +487,7 @@ func createGenericKprobeSensor(name string, kprobes []v1alpha1.KProbeSpec, polic
479487
funcName: funcName,
480488
pendingEvents: nil,
481489
tableId: idtable.UninitializedEntryID,
490+
policyName: policyName,
482491
}
483492

484493
// Parse Filters into kernel filter logic
@@ -855,6 +864,7 @@ func handleGenericKprobe(r *bytes.Reader) ([]observer.Event, error) {
855864
unix.FuncName = gk.funcName
856865
unix.Namespaces = m.Namespaces
857866
unix.Capabilities = m.Capabilities
867+
unix.PolicyName = gk.policyName
858868

859869
returnEvent := m.Common.Flags > 0
860870

pkg/sensors/tracing/generictracepoint.go

+22-7
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ type genericTracepoint struct {
7878
actionArgs idtable.Table
7979

8080
pinPathPrefix string
81+
82+
// policyName is the name of the policy that this tracepoint belongs to
83+
policyName string
8184
}
8285

8386
// genericTracepointArg is the internal representation of an output value of a
@@ -293,7 +296,12 @@ func buildGenericTracepointArgs(info *tracepoint.Tracepoint, specArgs []v1alpha1
293296

294297
// createGenericTracepoint creates the genericTracepoint information based on
295298
// the user-provided configuration
296-
func createGenericTracepoint(sensorName string, conf *GenericTracepointConf, policyID policyfilter.PolicyID) (*genericTracepoint, error) {
299+
func createGenericTracepoint(
300+
sensorName string,
301+
conf *GenericTracepointConf,
302+
policyID policyfilter.PolicyID,
303+
policyName string,
304+
) (*genericTracepoint, error) {
297305
tp := tracepoint.Tracepoint{
298306
Subsys: conf.Subsystem,
299307
Event: conf.Event,
@@ -309,10 +317,11 @@ func createGenericTracepoint(sensorName string, conf *GenericTracepointConf, pol
309317
}
310318

311319
ret := &genericTracepoint{
312-
Info: &tp,
313-
Spec: conf,
314-
args: tpArgs,
315-
policyID: policyID,
320+
Info: &tp,
321+
Spec: conf,
322+
args: tpArgs,
323+
policyID: policyID,
324+
policyName: policyName,
316325
}
317326

318327
genericTracepointTable.addTracepoint(ret)
@@ -321,11 +330,16 @@ func createGenericTracepoint(sensorName string, conf *GenericTracepointConf, pol
321330
}
322331

323332
// createGenericTracepointSensor will create a sensor that can be loaded based on a generic tracepoint configuration
324-
func createGenericTracepointSensor(name string, confs []GenericTracepointConf, policyID policyfilter.PolicyID) (*sensors.Sensor, error) {
333+
func createGenericTracepointSensor(
334+
name string,
335+
confs []GenericTracepointConf,
336+
policyID policyfilter.PolicyID,
337+
policyName string,
338+
) (*sensors.Sensor, error) {
325339

326340
tracepoints := make([]*genericTracepoint, 0, len(confs))
327341
for i := range confs {
328-
tp, err := createGenericTracepoint(name, &confs[i], policyID)
342+
tp, err := createGenericTracepoint(name, &confs[i], policyID, policyName)
329343
if err != nil {
330344
return nil, err
331345
}
@@ -604,6 +618,7 @@ func handleGenericTracepoint(r *bytes.Reader) ([]observer.Event, error) {
604618

605619
unix.Subsys = tp.Info.Subsys
606620
unix.Event = tp.Info.Event
621+
unix.PolicyName = tp.policyName
607622

608623
for idx, out := range tp.args {
609624

pkg/sensors/tracing/genericuprobe.go

+15-7
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ type genericUprobe struct {
4444
path string
4545
symbol string
4646
selectors *selectors.KernelSelectorState
47+
// policyName is the name of the policy that this uprobe belongs to
48+
policyName string
4749
}
4850

4951
func (g *genericUprobe) SetID(id idtable.EntryID) {
@@ -169,7 +171,11 @@ func isValidUprobeSelectors(selectors []v1alpha1.KProbeSelector) error {
169171
return nil
170172
}
171173

172-
func createGenericUprobeSensor(name string, uprobes []v1alpha1.UProbeSpec) (*sensors.Sensor, error) {
174+
func createGenericUprobeSensor(
175+
name string,
176+
uprobes []v1alpha1.UProbeSpec,
177+
policyName string,
178+
) (*sensors.Sensor, error) {
173179
var progs []*program.Program
174180
var maps []*program.Map
175181

@@ -199,11 +205,12 @@ func createGenericUprobeSensor(name string, uprobes []v1alpha1.UProbeSpec) (*sen
199205
}
200206

201207
uprobeEntry := &genericUprobe{
202-
tableId: idtable.UninitializedEntryID,
203-
config: config,
204-
path: spec.Path,
205-
symbol: spec.Symbol,
206-
selectors: uprobeSelectorState,
208+
tableId: idtable.UninitializedEntryID,
209+
config: config,
210+
path: spec.Path,
211+
symbol: spec.Symbol,
212+
selectors: uprobeSelectorState,
213+
policyName: policyName,
207214
}
208215

209216
uprobeTable.AddEntry(uprobeEntry)
@@ -264,5 +271,6 @@ func (k *observerUprobeSensor) PolicyHandler(
264271
}
265272

266273
name := fmt.Sprintf("gup-sensor-%d", atomic.AddUint64(&sensorCounter, 1))
267-
return createGenericUprobeSensor(name, spec.UProbes)
274+
policyName := p.TpName()
275+
return createGenericUprobeSensor(name, spec.UProbes, policyName)
268276
}

pkg/sensors/tracing/policyhandler.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ func (h policyHandler) PolicyHandler(
2121
policyID policyfilter.PolicyID,
2222
) (*sensors.Sensor, error) {
2323

24+
policyName := policy.TpName()
2425
spec := policy.TpSpec()
2526
if len(spec.KProbes) > 0 && len(spec.Tracepoints) > 0 {
2627
return nil, errors.New("tracing policies with both kprobes and tracepoints are not currently supported")
@@ -31,11 +32,11 @@ func (h policyHandler) PolicyHandler(
3132
if err != nil {
3233
return nil, err
3334
}
34-
return createGenericKprobeSensor(name, spec.KProbes, policyID)
35+
return createGenericKprobeSensor(name, spec.KProbes, policyID, policyName)
3536
}
3637
if len(spec.Tracepoints) > 0 {
3738
name := fmt.Sprintf("gtp-sensor-%d", atomic.AddUint64(&sensorCounter, 1))
38-
return createGenericTracepointSensor(name, spec.Tracepoints, policyID)
39+
return createGenericTracepointSensor(name, spec.Tracepoints, policyID, policyName)
3940
}
4041
return nil, nil
4142
}

pkg/sensors/tracing/tracepoint_test.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
lc "github.com/cilium/tetragon/pkg/matchers/listmatcher"
2121
smatcher "github.com/cilium/tetragon/pkg/matchers/stringmatcher"
2222
"github.com/cilium/tetragon/pkg/observer"
23+
"github.com/cilium/tetragon/pkg/policyfilter"
2324
"github.com/cilium/tetragon/pkg/sensors"
2425
testsensor "github.com/cilium/tetragon/pkg/sensors/test"
2526
tus "github.com/cilium/tetragon/pkg/testutils/sensors"
@@ -65,7 +66,7 @@ func TestGenericTracepointSimple(t *testing.T) {
6566

6667
sm := tus.StartTestSensorManager(ctx, t)
6768
// create and add sensor
68-
sensor, err := createGenericTracepointSensor("GtpLseekTest", []GenericTracepointConf{lseekConf}, 0)
69+
sensor, err := createGenericTracepointSensor("GtpLseekTest", []GenericTracepointConf{lseekConf}, policyfilter.NoFilterID, "policyName")
6970
if err != nil {
7071
t.Fatalf("failed to create generic tracepoint sensor: %s", err)
7172
}
@@ -124,7 +125,7 @@ func doTestGenericTracepointPidFilter(t *testing.T, conf GenericTracepointConf,
124125

125126
sm := tus.StartTestSensorManager(ctx, t)
126127
// create and add sensor
127-
sensor, err := createGenericTracepointSensor("GtpLseekTest", []GenericTracepointConf{conf}, 0)
128+
sensor, err := createGenericTracepointSensor("GtpLseekTest", []GenericTracepointConf{conf}, policyfilter.NoFilterID, "policyName")
128129
if err != nil {
129130
t.Fatalf("failed to create generic tracepoint sensor: %s", err)
130131
}

0 commit comments

Comments
 (0)