Skip to content

Commit aeac8bf

Browse files
committed
Introduce scope_field for process scope
1 parent d2791dd commit aeac8bf

File tree

16 files changed

+265
-47
lines changed

16 files changed

+265
-47
lines changed

pkg/security/probe/field_handlers_ebpf.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ func (fh *EBPFFieldHandlers) ResolveProcessCacheEntry(ev *model.Event, newEntryC
6868
return ev.ProcessCacheEntry, true
6969
}
7070

71+
// ResolveProcessCacheEntryFromPID queries the ProcessResolver to retrieve the ProcessContext of the provided PID
72+
func (fh *EBPFFieldHandlers) ResolveProcessCacheEntryFromPID(pid uint32) *model.ProcessCacheEntry {
73+
return fh.resolvers.ProcessResolver.Resolve(pid, pid, 0, true, nil)
74+
}
75+
7176
// ResolveFilePath resolves the inode to a full path
7277
func (fh *EBPFFieldHandlers) ResolveFilePath(ev *model.Event, f *model.FileEvent) string {
7378
if !f.IsPathnameStrResolved && len(f.PathnameStr) == 0 {

pkg/security/probe/field_handlers_ebpfless.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ func (fh *EBPFLessFieldHandlers) ResolveProcessCacheEntry(ev *model.Event, _ fun
5757
return ev.ProcessCacheEntry, true
5858
}
5959

60+
// ResolveProcessCacheEntryFromPID queries the ProcessResolver to retrieve the ProcessContext of the provided PID
61+
func (fh *EBPFLessFieldHandlers) ResolveProcessCacheEntryFromPID(pid uint32) *model.ProcessCacheEntry {
62+
// not supported yet, we're missing NSID
63+
return nil
64+
}
65+
6066
// ResolveFilePath resolves the inode to a full path
6167
func (fh *EBPFLessFieldHandlers) ResolveFilePath(_ *model.Event, f *model.FileEvent) string {
6268
return f.PathnameStr

pkg/security/probe/field_handlers_windows.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ func (fh *FieldHandlers) ResolveProcessCacheEntry(ev *model.Event, _ func(*model
9090
return ev.ProcessCacheEntry, true
9191
}
9292

93+
// ResolveProcessCacheEntryFromPID queries the ProcessResolver to retrieve the ProcessContext of the provided PID
94+
func (fh *FieldHandlers) ResolveProcessCacheEntryFromPID(pid uint32) *ProcessCacheEntry {
95+
return fh.resolvers.ProcessResolver.Resolve(pid)
96+
}
97+
9398
// ResolveProcessCmdLineScrubbed returns a scrubbed version of the cmdline
9499
func (fh *FieldHandlers) ResolveProcessCmdLineScrubbed(_ *model.Event, e *model.Process) string {
95100
return fh.resolvers.ProcessResolver.GetProcessCmdLineScrubbed(e)

pkg/security/secl/compiler/eval/variables.go

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,17 @@ type ScopedVariable interface {
4747
type MutableVariable interface {
4848
Set(ctx *Context, value interface{}) error
4949
Append(ctx *Context, value interface{}) error
50-
GetVariableOpts() VariableOpts
51-
SetVariableOpts(opts VariableOpts)
50+
}
51+
52+
// MutableScopedVariable is the interface for scoped variables whose value can be changed
53+
type MutableScopedVariable interface {
54+
Set(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error
55+
Append(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error
5256
}
5357

5458
// settableVariable describes a SECL variable
5559
type settableVariable struct {
56-
setFnc func(ctx *Context, value interface{}) error
60+
setFnc func(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error
5761
opts VariableOpts
5862
}
5963

@@ -62,16 +66,16 @@ type expirableVariable interface {
6266
}
6367

6468
// Set the variable with the specified value
65-
func (v *settableVariable) Set(ctx *Context, value interface{}) error {
69+
func (v *settableVariable) Set(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error {
6670
if v.setFnc == nil {
6771
return errors.New("variable is not mutable")
6872
}
6973

70-
return v.setFnc(ctx, value)
74+
return v.setFnc(ctx, value, scopeFieldEvaluator)
7175
}
7276

7377
// Append a value to the variable
74-
func (v *settableVariable) Append(_ *Context, _ interface{}) error {
78+
func (v *settableVariable) Append(_ *Context, _ interface{}, _ Evaluator) error {
7579
return errAppendNotSupported
7680
}
7781

@@ -112,7 +116,7 @@ func (i *ScopedIntVariable) GetValue(ctx *Context) (interface{}, bool) {
112116
}
113117

114118
// NewScopedIntVariable returns a new integer variable
115-
func NewScopedIntVariable(intFnc func(ctx *Context) (int, bool), setFnc func(ctx *Context, value interface{}) error) *ScopedIntVariable {
119+
func NewScopedIntVariable(intFnc func(ctx *Context) (int, bool), setFnc func(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error) *ScopedIntVariable {
116120
return &ScopedIntVariable{
117121
settableVariable: settableVariable{
118122
setFnc: setFnc,
@@ -147,7 +151,7 @@ func (s *ScopedStringVariable) GetValue(ctx *Context) (interface{}, bool) {
147151
}
148152

149153
// NewScopedStringVariable returns a new scoped string variable
150-
func NewScopedStringVariable(strFnc func(ctx *Context) (string, bool), setFnc func(ctx *Context, value interface{}) error) *ScopedStringVariable {
154+
func NewScopedStringVariable(strFnc func(ctx *Context) (string, bool), setFnc func(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error) *ScopedStringVariable {
151155
return &ScopedStringVariable{
152156
strFnc: strFnc,
153157
settableVariable: settableVariable{
@@ -181,7 +185,7 @@ func (b *ScopedBoolVariable) GetValue(ctx *Context) (interface{}, bool) {
181185
}
182186

183187
// NewScopedBoolVariable returns a new boolean variable
184-
func NewScopedBoolVariable(boolFnc func(ctx *Context) (bool, bool), setFnc func(ctx *Context, value interface{}) error) *ScopedBoolVariable {
188+
func NewScopedBoolVariable(boolFnc func(ctx *Context) (bool, bool), setFnc func(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error) *ScopedBoolVariable {
185189
return &ScopedBoolVariable{
186190
boolFnc: boolFnc,
187191
settableVariable: settableVariable{
@@ -215,7 +219,7 @@ func (i *ScopedIPVariable) GetValue(ctx *Context) (interface{}, bool) {
215219
}
216220

217221
// NewScopedIPVariable returns a new scoped IP variable
218-
func NewScopedIPVariable(ipFnc func(ctx *Context) (net.IPNet, bool), setFnc func(ctx *Context, value interface{}) error) *ScopedIPVariable {
222+
func NewScopedIPVariable(ipFnc func(ctx *Context) (net.IPNet, bool), setFnc func(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error) *ScopedIPVariable {
219223
return &ScopedIPVariable{
220224
ipFnc: ipFnc,
221225
settableVariable: settableVariable{
@@ -249,24 +253,24 @@ func (s *ScopedStringArrayVariable) GetValue(ctx *Context) (interface{}, bool) {
249253
}
250254

251255
// Set the array values
252-
func (s *ScopedStringArrayVariable) Set(ctx *Context, value interface{}) error {
256+
func (s *ScopedStringArrayVariable) Set(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error {
253257
if s, ok := value.(string); ok {
254258
value = []string{s}
255259
}
256-
return s.settableVariable.Set(ctx, value)
260+
return s.settableVariable.Set(ctx, value, scopeFieldEvaluator)
257261
}
258262

259263
// Append a value to the array
260-
func (s *ScopedStringArrayVariable) Append(ctx *Context, value interface{}) error {
264+
func (s *ScopedStringArrayVariable) Append(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error {
261265
if val, ok := value.(string); ok {
262266
value = []string{val}
263267
}
264268
values, _ := s.strFnc(ctx)
265-
return s.Set(ctx, append(values, value.([]string)...))
269+
return s.Set(ctx, append(values, value.([]string)...), scopeFieldEvaluator)
266270
}
267271

268272
// NewScopedStringArrayVariable returns a new scoped string array variable
269-
func NewScopedStringArrayVariable(strFnc func(ctx *Context) ([]string, bool), setFnc func(ctx *Context, value interface{}) error) *ScopedStringArrayVariable {
273+
func NewScopedStringArrayVariable(strFnc func(ctx *Context) ([]string, bool), setFnc func(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error) *ScopedStringArrayVariable {
270274
return &ScopedStringArrayVariable{
271275
strFnc: strFnc,
272276
settableVariable: settableVariable{
@@ -300,24 +304,24 @@ func (v *ScopedIntArrayVariable) GetValue(ctx *Context) (interface{}, bool) {
300304
}
301305

302306
// Set the array values
303-
func (v *ScopedIntArrayVariable) Set(ctx *Context, value interface{}) error {
307+
func (v *ScopedIntArrayVariable) Set(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error {
304308
if i, ok := value.(int); ok {
305309
value = []int{i}
306310
}
307-
return v.settableVariable.Set(ctx, value)
311+
return v.settableVariable.Set(ctx, value, scopeFieldEvaluator)
308312
}
309313

310314
// Append a value to the array
311-
func (v *ScopedIntArrayVariable) Append(ctx *Context, value interface{}) error {
315+
func (v *ScopedIntArrayVariable) Append(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error {
312316
if val, ok := value.(int); ok {
313317
value = []int{val}
314318
}
315319
values, _ := v.intFnc(ctx)
316-
return v.Set(ctx, append(values, value.([]int)...))
320+
return v.Set(ctx, append(values, value.([]int)...), scopeFieldEvaluator)
317321
}
318322

319323
// NewScopedIntArrayVariable returns a new integer array variable
320-
func NewScopedIntArrayVariable(intFnc func(ctx *Context) ([]int, bool), setFnc func(ctx *Context, value interface{}) error) *ScopedIntArrayVariable {
324+
func NewScopedIntArrayVariable(intFnc func(ctx *Context) ([]int, bool), setFnc func(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error) *ScopedIntArrayVariable {
321325
return &ScopedIntArrayVariable{
322326
intFnc: intFnc,
323327
settableVariable: settableVariable{
@@ -351,24 +355,24 @@ func (i *ScopedIPArrayVariable) GetValue(ctx *Context) (interface{}, bool) {
351355
}
352356

353357
// Set the array values
354-
func (i *ScopedIPArrayVariable) Set(ctx *Context, value interface{}) error {
358+
func (i *ScopedIPArrayVariable) Set(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error {
355359
if ip, ok := value.(net.IPNet); ok {
356360
value = []net.IPNet{ip}
357361
}
358-
return i.settableVariable.Set(ctx, value)
362+
return i.settableVariable.Set(ctx, value, scopeFieldEvaluator)
359363
}
360364

361365
// Append a value to the array
362-
func (i *ScopedIPArrayVariable) Append(ctx *Context, value interface{}) error {
366+
func (i *ScopedIPArrayVariable) Append(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error {
363367
if val, ok := value.(net.IPNet); ok {
364368
value = []net.IPNet{val}
365369
}
366370
values, _ := i.ipFnc(ctx)
367-
return i.Set(ctx, append(values, value.([]net.IPNet)...))
371+
return i.Set(ctx, append(values, value.([]net.IPNet)...), scopeFieldEvaluator)
368372
}
369373

370374
// NewScopedIPArrayVariable returns a new IP array variable
371-
func NewScopedIPArrayVariable(ipFnc func(ctx *Context) ([]net.IPNet, bool), setFnc func(ctx *Context, value interface{}) error) *ScopedIPArrayVariable {
375+
func NewScopedIPArrayVariable(ipFnc func(ctx *Context) ([]net.IPNet, bool), setFnc func(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error) *ScopedIPArrayVariable {
372376
return &ScopedIPArrayVariable{
373377
ipFnc: ipFnc,
374378
settableVariable: settableVariable{
@@ -952,7 +956,7 @@ type VariableScope interface {
952956
}
953957

954958
// Scoper maps a variable to the entity its scoped to
955-
type Scoper func(ctx *Context) VariableScope
959+
type Scoper func(ctx *Context, scopeFieldEvaluator Evaluator) VariableScope
956960

957961
// Variables holds a set of variables
958962
type Variables struct {
@@ -1042,7 +1046,7 @@ func (v *ScopedVariables) Len() int {
10421046
// NewSECLVariable returns new variable of the type of the specified value
10431047
func (v *ScopedVariables) NewSECLVariable(name string, value interface{}, opts VariableOpts) (SECLVariable, error) {
10441048
getVariable := func(ctx *Context) MutableSECLVariable {
1045-
scope := v.scoper(ctx)
1049+
scope := v.scoper(ctx, nil)
10461050
if scope == nil {
10471051
return nil
10481052
}
@@ -1060,8 +1064,8 @@ func (v *ScopedVariables) NewSECLVariable(name string, value interface{}, opts V
10601064
return vars[name]
10611065
}
10621066

1063-
setVariable := func(ctx *Context, value interface{}) error {
1064-
scope := v.scoper(ctx)
1067+
setVariable := func(ctx *Context, value interface{}, scopeFieldEvaluator Evaluator) error {
1068+
scope := v.scoper(ctx, scopeFieldEvaluator)
10651069
if scope == nil {
10661070
return fmt.Errorf("failed to scope variable '%s'", name)
10671071
}

pkg/security/secl/model/model.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,7 @@ type AWSSecurityCredentials struct {
610610
// BaseExtraFieldHandlers handlers not hold by any field
611611
type BaseExtraFieldHandlers interface {
612612
ResolveProcessCacheEntry(ev *Event, newEntryCb func(*ProcessCacheEntry, error)) (*ProcessCacheEntry, bool)
613+
ResolveProcessCacheEntryFromPID(pid uint32) *ProcessCacheEntry
613614
ResolveContainerContext(ev *Event) (*ContainerContext, bool)
614615
}
615616

@@ -621,6 +622,11 @@ func (dfh *FakeFieldHandlers) ResolveProcessCacheEntry(ev *Event, _ func(*Proces
621622
return nil, false
622623
}
623624

625+
// ResolveProcessCacheEntryFromPID stub implementation
626+
func (fh *FakeFieldHandlers) ResolveProcessCacheEntryFromPID(pid uint32) *ProcessCacheEntry {
627+
return GetPlaceholderProcessCacheEntry(pid, pid, false)
628+
}
629+
624630
// ResolveContainerContext stub implementation
625631
func (dfh *FakeFieldHandlers) ResolveContainerContext(_ *Event) (*ContainerContext, bool) {
626632
return nil, false

pkg/security/secl/model/model_windows.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ func NewFakeEvent() *Event {
3737
}
3838
}
3939

40+
var processContextZero = ProcessCacheEntry{}
41+
42+
// GetPlaceholderProcessCacheEntry returns an empty process cache entry for failed process resolutions
43+
func GetPlaceholderProcessCacheEntry(pid uint32) *ProcessCacheEntry {
44+
processContextZero.Pid = pid
45+
return &processContextZero
46+
}
47+
4048
// ValidateField validates the value of a field
4149
func (m *Model) ValidateField(field eval.Field, fieldValue eval.FieldValue) error {
4250
if m.ExtraValidateFieldFnc != nil {

pkg/security/secl/rules/actions.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ import (
1919
// Action represents the action to take when a rule is triggered
2020
// It can either come from policy a definition or be an internal callback
2121
type Action struct {
22-
Def *ActionDefinition
23-
InternalCallback *InternalCallbackDefinition
24-
FilterEvaluator *eval.RuleEvaluator
22+
Def *ActionDefinition
23+
InternalCallback *InternalCallbackDefinition
24+
FilterEvaluator *eval.RuleEvaluator
25+
ScopeFieldEvaluator eval.Evaluator
2526
}
2627

2728
// Check returns an error if the action in invalid
@@ -59,6 +60,10 @@ func (a *ActionDefinition) Check(opts PolicyLoaderOpts) error {
5960
if a.Set.Inherited && a.Set.Scope != "process" {
6061
return fmt.Errorf("only variables scoped to process can be marked as inherited")
6162
}
63+
64+
if len(a.Set.ScopeField) > 0 && a.Set.Scope != "process" {
65+
return fmt.Errorf("only variables scoped to process can have a custom scope_field")
66+
}
6267
} else if a.Kill != nil {
6368
if opts.DisableEnforcement {
6469
a.Kill = nil
@@ -103,6 +108,21 @@ func (a *Action) CompileFilter(parsingContext *ast.ParsingContext, model eval.Mo
103108
return nil
104109
}
105110

111+
// CompileScopeField compiles the scope field
112+
func (a *Action) CompileScopeField(model eval.Model) error {
113+
if a.Def.Set == nil || len(a.Def.Set.ScopeField) == 0 {
114+
return nil
115+
}
116+
117+
evaluator, err := model.GetEvaluator(a.Def.Set.ScopeField, "", 0)
118+
if err != nil {
119+
return &ErrScopeField{Expression: a.Def.Set.ScopeField, Err: err}
120+
}
121+
122+
a.ScopeFieldEvaluator = evaluator
123+
return nil
124+
}
125+
106126
// IsAccepted returns whether a filter is accepted and has to be executed
107127
func (a *Action) IsAccepted(ctx *eval.Context) bool {
108128
return a.FilterEvaluator == nil || a.FilterEvaluator.Eval(ctx)

pkg/security/secl/rules/errors.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,16 @@ func (e ErrActionFilter) Error() string {
176176
return fmt.Sprintf("filter `%s` error: %s", e.Expression, e.Err)
177177
}
178178

179+
// ErrScopeField is return on scope field definition error
180+
type ErrScopeField struct {
181+
Expression string
182+
Err error
183+
}
184+
185+
func (e ErrScopeField) Error() string {
186+
return fmt.Sprintf("scope_field `%s` error: %s", e.Expression, e.Err)
187+
}
188+
179189
// ErrFieldNotAvailable is returned when a field is not available
180190
type ErrFieldNotAvailable struct {
181191
Field eval.Field

pkg/security/secl/rules/model.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ type SetDefinition struct {
146146
Expression string `yaml:"expression" json:"expression,omitempty"`
147147
Append bool `yaml:"append" json:"append,omitempty"`
148148
Scope Scope `yaml:"scope" json:"scope,omitempty" jsonschema:"enum=process,enum=container,enum=cgroup"`
149+
ScopeField string `yaml:"scope_field" json:"scope_field,omitempty"`
149150
Size int `yaml:"size" json:"size,omitempty"`
150151
TTL *HumanReadableDuration `yaml:"ttl" json:"ttl,omitempty"`
151152
Private bool `yaml:"private" json:"private,omitempty"`

0 commit comments

Comments
 (0)