tetragon

Форк
0
/
manager.go 
442 строки · 10.5 Кб
1
// SPDX-License-Identifier: Apache-2.0
2
// Copyright Authors of Tetragon
3

4
package sensors
5

6
import (
7
	"context"
8
	"errors"
9
	"fmt"
10
	"strings"
11

12
	"github.com/cilium/tetragon/api/v1/tetragon"
13
	"github.com/cilium/tetragon/pkg/k8s/apis/cilium.io/v1alpha1"
14
	"github.com/cilium/tetragon/pkg/logger"
15
	"github.com/cilium/tetragon/pkg/policyfilter"
16
	"github.com/cilium/tetragon/pkg/tracingpolicy"
17
)
18

19
type SensorStatus struct {
20
	Name       string
21
	Enabled    bool
22
	Collection string
23
}
24

25
// StartSensorManager initializes the sensorCtlHandle by spawning a sensor
26
// controller goroutine.
27
//
28
// The purpose of this goroutine is to serialize loading and unloading of
29
// sensors as requested from different goroutines (e.g., different GRPC
30
// clients).
31
//
32
// if waitChan is not nil, the serving of sensor requests will block until
33
// something is received. The intention of this is to allow the main function
34
// to first load the base sensor before the sensor manager starts loading other sensors.
35
func StartSensorManager(
36
	bpfDir string,
37
	waitChan chan struct{},
38
) (*Manager, error) {
39
	pfState, err := policyfilter.GetState()
40
	if err != nil {
41
		return nil, fmt.Errorf("failed to initialize policy filter state: %w", err)
42
	}
43

44
	colMap := newCollectionMap()
45

46
	handler, err := newHandler(pfState, colMap, bpfDir)
47
	if err != nil {
48
		return nil, err
49
	}
50

51
	// NB: pass handler.collections as a policy lister so that the manager can list policies
52
	// without having to go via the manager goroutine.
53
	return startSensorManager(handler, handler.collections, waitChan)
54
}
55

56
func startSensorManager(
57
	handler *handler,
58
	policyLister policyLister,
59
	waitChan chan struct{},
60
) (*Manager, error) {
61
	c := make(chan sensorOp)
62
	m := Manager{
63
		sensorCtl:    c,
64
		policyLister: policyLister,
65
	}
66

67
	go func() {
68

69
		// wait until start serving requests
70
		if waitChan != nil {
71
			logger.GetLogger().Infof("sensor controller waiting on channel")
72
			<-waitChan
73
			logger.GetLogger().Infof("sensor controller starts")
74
		}
75

76
		done := false
77
		for !done {
78
			op_ := <-c
79
			err := errors.New("BUG in SensorCtl: unset error value") // nolint
80
			switch op := op_.(type) {
81
			case *tracingPolicyAdd:
82
				err = handler.addTracingPolicy(op)
83
			case *tracingPolicyDelete:
84
				err = handler.deleteTracingPolicy(op)
85
			case *tracingPolicyEnable:
86
				err = handler.enableTracingPolicy(op)
87
			case *tracingPolicyDisable:
88
				err = handler.disableTracingPolicy(op)
89
			case *sensorAdd:
90
				err = handler.addSensor(op)
91
			case *sensorRemove:
92
				err = handler.removeSensor(op)
93
			case *sensorEnable:
94
				err = handler.enableSensor(op)
95
			case *sensorDisable:
96
				err = handler.disableSensor(op)
97
			case *sensorList:
98
				err = handler.listSensors(op)
99
			case *sensorCtlStop:
100
				logger.GetLogger().Debugf("stopping sensor controller...")
101
				done = true
102
				err = nil
103
			default:
104
				err = fmt.Errorf("unknown sensorOp: %v", op)
105
			}
106
			op_.sensorOpDone(err)
107
		}
108
	}()
109
	return &m, nil
110
}
111

112
/*
113
 * Sensor operations
114
 */
115

116
// EnableSensor enables a sensor by name
117
func (h *Manager) EnableSensor(ctx context.Context, name string) error {
118
	retc := make(chan error)
119
	op := &sensorEnable{
120
		ctx:     ctx,
121
		name:    name,
122
		retChan: retc,
123
	}
124

125
	h.sensorCtl <- op
126
	err := <-retc
127

128
	return err
129
}
130

131
// AddSensor adds a sensor
132
func (h *Manager) AddSensor(ctx context.Context, name string, sensor *Sensor) error {
133
	retc := make(chan error)
134
	op := &sensorAdd{
135
		ctx:     ctx,
136
		name:    name,
137
		sensor:  sensor,
138
		retChan: retc,
139
	}
140

141
	h.sensorCtl <- op
142
	return <-retc
143
}
144

145
// DisableSensor disables a sensor by name
146
func (h *Manager) DisableSensor(ctx context.Context, name string) error {
147
	retc := make(chan error)
148
	op := &sensorDisable{
149
		ctx:     ctx,
150
		name:    name,
151
		retChan: retc,
152
	}
153

154
	h.sensorCtl <- op
155
	return <-retc
156
}
157

158
func (h *Manager) ListSensors(ctx context.Context) (*[]SensorStatus, error) {
159
	retc := make(chan error)
160
	op := &sensorList{
161
		ctx:     ctx,
162
		retChan: retc,
163
	}
164

165
	h.sensorCtl <- op
166
	err := <-retc
167
	if err == nil {
168
		return op.result, nil
169
	}
170

171
	return nil, err
172
}
173

174
// TracingPolicy is an interface for a tracing policy
175
// This is implemented by v1alpha1.types.TracingPolicy and
176
// config.GenericTracingConf. The former is what is the k8s API server uses,
177
// and the latter is used when we load files directly (e.g., via the cli).
178
type TracingPolicy interface {
179
	// TpName returns the name of the policy.
180
	TpName() string
181
	// TpSpec  returns the specification of the policy
182
	TpSpec() *v1alpha1.TracingPolicySpec
183
	// TpInfo returns a description of the policy
184
	TpInfo() string
185
}
186

187
// AddTracingPolicy adds a new sensor based on a tracing policy
188
// NB: if tp implements tracingpolicy.TracingPolicyNamespaced, it will be
189
// treated as a namespaced policy
190
func (h *Manager) AddTracingPolicy(ctx context.Context, tp tracingpolicy.TracingPolicy) error {
191
	retc := make(chan error)
192
	var namespace string
193
	if tpNs, ok := tp.(tracingpolicy.TracingPolicyNamespaced); ok {
194
		namespace = tpNs.TpNamespace()
195
	}
196
	ck := collectionKey{tp.TpName(), namespace}
197
	op := &tracingPolicyAdd{
198
		ctx:     ctx,
199
		ck:      ck,
200
		tp:      tp,
201
		retChan: retc,
202
	}
203

204
	h.sensorCtl <- op
205
	err := <-retc
206

207
	return err
208
}
209

210
// DeleteTracingPolicy deletes a new sensor based on a tracing policy
211
func (h *Manager) DeleteTracingPolicy(ctx context.Context, name string, namespace string) error {
212
	retc := make(chan error)
213
	ck := collectionKey{name, namespace}
214
	op := &tracingPolicyDelete{
215
		ctx:     ctx,
216
		ck:      ck,
217
		retChan: retc,
218
	}
219

220
	h.sensorCtl <- op
221
	err := <-retc
222

223
	return err
224
}
225

226
func (h *Manager) EnableTracingPolicy(ctx context.Context, name, namespace string) error {
227
	ck := collectionKey{name, namespace}
228
	retc := make(chan error)
229
	op := &tracingPolicyEnable{
230
		ctx:     ctx,
231
		ck:      ck,
232
		retChan: retc,
233
	}
234

235
	h.sensorCtl <- op
236
	err := <-retc
237

238
	return err
239
}
240

241
func (h *Manager) DisableTracingPolicy(ctx context.Context, name, namespace string) error {
242
	ck := collectionKey{name, namespace}
243
	retc := make(chan error)
244
	op := &tracingPolicyDisable{
245
		ctx:     ctx,
246
		ck:      ck,
247
		retChan: retc,
248
	}
249

250
	h.sensorCtl <- op
251
	err := <-retc
252

253
	return err
254
}
255

256
// ListTracingPolicies returns a list of the active tracing policies
257
func (h *Manager) ListTracingPolicies(_ context.Context) (*tetragon.ListTracingPoliciesResponse, error) {
258
	ret := &tetragon.ListTracingPoliciesResponse{}
259
	ret.Policies = h.listPolicies()
260
	return ret, nil
261
}
262

263
func (h *Manager) RemoveSensor(ctx context.Context, sensorName string) error {
264
	retc := make(chan error)
265
	op := &sensorRemove{
266
		ctx:     ctx,
267
		name:    sensorName,
268
		retChan: retc,
269
	}
270

271
	h.sensorCtl <- op
272
	err := <-retc
273

274
	return err
275
}
276

277
func (h *Manager) RemoveAllSensors(ctx context.Context) error {
278
	retc := make(chan error)
279
	op := &sensorRemove{
280
		ctx:     ctx,
281
		all:     true,
282
		retChan: retc,
283
	}
284

285
	h.sensorCtl <- op
286
	err := <-retc
287

288
	return err
289
}
290

291
func (h *Manager) StopSensorManager(ctx context.Context) error {
292
	retc := make(chan error)
293
	op := &sensorCtlStop{
294
		ctx:     ctx,
295
		retChan: retc,
296
	}
297

298
	h.sensorCtl <- op
299
	return <-retc
300
}
301

302
func (h *Manager) LogSensorsAndProbes(ctx context.Context) {
303
	log := logger.GetLogger()
304
	sensors, err := h.ListSensors(ctx)
305
	if err != nil {
306
		log.WithError(err).Warn("failed to list sensors")
307
	}
308

309
	names := []string{}
310
	for _, s := range *sensors {
311
		names = append(names, s.Name)
312
	}
313
	log.WithField("sensors", strings.Join(names, ", ")).Info("Available sensors")
314

315
	names = []string{}
316
	for n := range registeredPolicyHandlers {
317
		names = append(names, n)
318
	}
319
	log.WithField("policy-handlers", strings.Join(names, ", ")).Info("Registered sensors (policy-handlers)")
320

321
	names = []string{}
322
	for n := range registeredProbeLoad {
323
		names = append(names, n)
324
	}
325
	log.WithField("types", strings.Join(names, ", ")).Info("Registered probe types")
326
}
327

328
// policyLister allows read-only access to the collections map
329
type policyLister interface {
330
	listPolicies() []*tetragon.TracingPolicyStatus
331
}
332

333
// Manager handles dynamic sensor management, such as adding / removing sensors
334
// at runtime.
335
type Manager struct {
336
	// channel to communicate with the controller goroutine
337
	sensorCtl sensorCtlHandle
338
	// policyLister is used to list policies without going via the controller goroutine by
339
	// directly accessing the collection.
340
	policyLister
341
}
342

343
// There are 6 commands that can be passed to the controller goroutine:
344
// - tracingPolicyAdd
345
// - tracingPolicyDel
346
// - sensorList
347
// - sensorEnable
348
// - sensorDisable
349
// - sensorRemove
350
// - sensorCtlStop
351

352
// tracingPolicyAdd adds a sensor based on a the provided tracing policy
353
type tracingPolicyAdd struct {
354
	ctx     context.Context
355
	ck      collectionKey
356
	tp      tracingpolicy.TracingPolicy
357
	retChan chan error
358
}
359

360
type tracingPolicyDelete struct {
361
	ctx     context.Context
362
	ck      collectionKey
363
	retChan chan error
364
}
365

366
type tracingPolicyDisable struct {
367
	ctx     context.Context
368
	ck      collectionKey
369
	retChan chan error
370
}
371

372
type tracingPolicyEnable struct {
373
	ctx     context.Context
374
	ck      collectionKey
375
	retChan chan error
376
}
377

378
// sensorOp is an interface for the sensor operations.
379
// Not strictly needed but allows for better type checking.
380
type sensorOp interface {
381
	sensorOpDone(error)
382
}
383

384
// sensorAdd adds a sensor
385
type sensorAdd struct {
386
	ctx     context.Context
387
	name    string
388
	sensor  *Sensor
389
	retChan chan error
390
}
391

392
// sensorRemove removes a sensor (for now, used only for tracing policies)
393
type sensorRemove struct {
394
	ctx     context.Context
395
	name    string
396
	all     bool
397
	retChan chan error
398
}
399

400
// sensorEnable enables a sensor
401
type sensorEnable struct {
402
	ctx     context.Context
403
	name    string
404
	retChan chan error
405
}
406

407
// sensorDisable disables a sensor
408
type sensorDisable struct {
409
	ctx     context.Context
410
	name    string
411
	retChan chan error
412
}
413

414
// sensorList returns a list of the active sensors
415
type sensorList struct {
416
	ctx     context.Context
417
	result  *[]SensorStatus
418
	retChan chan error
419
}
420

421
// sensorCtlStop stops the controller
422
type sensorCtlStop struct {
423
	ctx     context.Context
424
	retChan chan error
425
}
426

427
type LoadArg struct{}
428
type UnloadArg = LoadArg
429

430
// trivial sensorOpDone implementations for commands
431
func (s *tracingPolicyAdd) sensorOpDone(e error)     { s.retChan <- e }
432
func (s *tracingPolicyDelete) sensorOpDone(e error)  { s.retChan <- e }
433
func (s *tracingPolicyEnable) sensorOpDone(e error)  { s.retChan <- e }
434
func (s *tracingPolicyDisable) sensorOpDone(e error) { s.retChan <- e }
435
func (s *sensorAdd) sensorOpDone(e error)            { s.retChan <- e }
436
func (s *sensorRemove) sensorOpDone(e error)         { s.retChan <- e }
437
func (s *sensorEnable) sensorOpDone(e error)         { s.retChan <- e }
438
func (s *sensorDisable) sensorOpDone(e error)        { s.retChan <- e }
439
func (s *sensorList) sensorOpDone(e error)           { s.retChan <- e }
440
func (s *sensorCtlStop) sensorOpDone(e error)        { s.retChan <- e }
441

442
type sensorCtlHandle = chan<- sensorOp
443

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.