Skip to content

Commit

Permalink
refactor(plugins/k8saudit): do not return <NA> on missing field values
Browse files Browse the repository at this point in the history
In the legacy implementation, list values used to include the value <NA> whenever a given field could
not be extracted (see: falcosecurity/falco#1601). However, this makes the semantics
of missing values ambigue and not coherent. Instead, here we just skip missing values. If a value is not found
when extracted, the plugin framework is able to signal the "field is not present" info. For list values, missing
values are simply skipped now. This works as expected with operators such as `in` and `intersects`, for which
the <NA> string was ambiguous anyways. If a list field is accessed with an index argument, then the extracted
value can either be a list with a single value (the one actually extracted at the positional index of the arg),
or an empty string (which is interpreted by the framework as <NA> internally).

Signed-off-by: Jason Dellaluce <[email protected]>
  • Loading branch information
jasondellaluce authored and poiana committed Apr 22, 2022
1 parent e2ad7d1 commit d2cfa30
Showing 1 changed file with 16 additions and 32 deletions.
48 changes: 16 additions & 32 deletions plugins/k8saudit/pkg/k8saudit/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (

const (
noIndexFilter = -1
noValueString = "<NA>"
)

var (
Expand Down Expand Up @@ -226,7 +225,7 @@ func (e *AuditEventExtractor) ExtractFromJSON(req sdk.ExtractRequest, jsonValue
if err != nil {
return err
}
req.SetValue(e.arrayAsStringsWithDefault(arr, noValueString))
req.SetValue(e.arrayAsStringsSkipNil(arr))
case "ka.req.container.privileged":
arr, err := e.getValuesRecursive(jsonValue, noIndexFilter, "requestObject", "spec", "containers", "securityContext", "privileged")
if err != nil {
Expand All @@ -244,21 +243,21 @@ func (e *AuditEventExtractor) ExtractFromJSON(req sdk.ExtractRequest, jsonValue
if err != nil {
return err
}
req.SetValue(e.arrayAsStringsWithDefault(arr, noValueString))
req.SetValue(e.arrayAsStringsSkipNil(arr))
case "ka.req.pod.containers.read_only_fs":
arr, err := e.getValuesRecursive(jsonValue, e.argIndexFilter(req), "requestObject", "spec", "containers", "securityContext", "readOnlyRootFilesystem")
if err != nil {
return err
}
req.SetValue(e.arrayAsStringsWithDefault(arr, noValueString))
req.SetValue(e.arrayAsStringsSkipNil(arr))
case "ka.req.pod.run_as_user":
return e.extractFromKeys(req, jsonValue, "requestObject", "spec", "securityContext", "runAsUser")
case "ka.req.pod.containers.run_as_user":
arr, err := e.getValuesRecursive(jsonValue, e.argIndexFilter(req), "requestObject", "spec", "containers", "securityContext", "runAsUser")
if err != nil {
return err
}
req.SetValue(e.arrayAsStringsWithDefault(arr, noValueString))
req.SetValue(e.arrayAsStringsSkipNil(arr))
case "ka.req.pod.containers.eff_run_as_user":
indexFilter := e.argIndexFilter(req)
values, err := e.readFromContainerEffectively(jsonValue, indexFilter, "runAsUser")
Expand All @@ -273,7 +272,7 @@ func (e *AuditEventExtractor) ExtractFromJSON(req sdk.ExtractRequest, jsonValue
if err != nil {
return err
}
req.SetValue(e.arrayAsStringsWithDefault(arr, noValueString))
req.SetValue(e.arrayAsStringsSkipNil(arr))
case "ka.req.pod.containers.eff_run_as_group":
indexFilter := e.argIndexFilter(req)
values, err := e.readFromContainerEffectively(jsonValue, indexFilter, "runAsGroup")
Expand All @@ -286,7 +285,7 @@ func (e *AuditEventExtractor) ExtractFromJSON(req sdk.ExtractRequest, jsonValue
if err != nil {
return err
}
req.SetValue(e.arrayAsStringsWithDefault(arr, noValueString))
req.SetValue(e.arrayAsStringsSkipNil(arr))
case "ka.req.role.rules":
return e.extractFromKeys(req, jsonValue, "requestObject", "rules")
case "ka.req.role.rules.apiGroups":
Expand All @@ -306,7 +305,7 @@ func (e *AuditEventExtractor) ExtractFromJSON(req sdk.ExtractRequest, jsonValue
if err != nil {
return err
}
req.SetValue(e.arrayAsStringsWithDefault(arr, noValueString))
req.SetValue(e.arrayAsStringsSkipNil(arr))
case "ka.req.service.type":
return e.extractFromKeys(req, jsonValue, "requestObject", "spec", "type")
case "ka.req.service.ports":
Expand All @@ -315,27 +314,19 @@ func (e *AuditEventExtractor) ExtractFromJSON(req sdk.ExtractRequest, jsonValue
if err != nil {
return err
}
values, err := e.arrayAsStrings(arr)
if err != nil {
return err
}
req.SetValue(values)
req.SetValue(e.arrayAsStringsSkipNil(arr))
case "ka.req.volume.hostpath":
arr, err := e.getValuesRecursive(jsonValue, e.argIndexFilter(req), "requestObject", "spec", "volumes", "hostPath", "path")
if err != nil {
return err
}
values, err := e.arrayAsStringsSkipNil(arr)
if err != nil {
return err
}

// if the index key ends with a *, do a prefix match.
// Otherwise, compare for equality.
arg := req.ArgKey()
isPrefixSearch := strings.HasSuffix(arg, "*")
prefixSearch := arg[:len(arg)-1]
for _, v := range values {
for _, v := range e.arrayAsStringsSkipNil(arr) {
if isPrefixSearch && strings.HasPrefix(v, prefixSearch) || arg == v {
req.SetValue("true")
return nil
Expand All @@ -347,13 +338,13 @@ func (e *AuditEventExtractor) ExtractFromJSON(req sdk.ExtractRequest, jsonValue
if err != nil {
return err
}
req.SetValue(e.arrayAsStringsWithDefault(arr, noValueString))
req.SetValue(e.arrayAsStringsSkipNil(arr))
case "ka.req.pod.volumes.flexvolume_driver":
arr, err := e.getValuesRecursive(jsonValue, e.argIndexFilter(req), "requestObject", "spec", "volumes", "flexVolume", "driver")
if err != nil {
return err
}
req.SetValue(e.arrayAsStringsWithDefault(arr, noValueString))
req.SetValue(e.arrayAsStringsSkipNil(arr))
case "ka.req.pod.volumes.volume_type":
indexFilter := e.argIndexFilter(req)
arr, err := e.getValuesRecursive(jsonValue, indexFilter, "requestObject", "spec", "volumes")
Expand Down Expand Up @@ -440,18 +431,15 @@ func (e *AuditEventExtractor) arrayAsStrings(values []*fastjson.Value) ([]string
return res, nil
}

func (e *AuditEventExtractor) arrayAsStringsSkipNil(values []*fastjson.Value) ([]string, error) {
func (e *AuditEventExtractor) arrayAsStringsSkipNil(values []*fastjson.Value) []string {
var res []string
for _, v := range values {
if v != nil {
str, err := e.jsonValueAsString(v)
if err != nil {
return nil, err
}
str, err := e.jsonValueAsString(v)
if err == nil {
res = append(res, str)
}
}
return res, nil
return res
}

func (e *AuditEventExtractor) arrayAsStringsWithDefault(values []*fastjson.Value, defaultValue string) []string {
Expand Down Expand Up @@ -544,11 +532,7 @@ func (e *AuditEventExtractor) extractRulesField(req sdk.ExtractRequest, jsonValu
var values []string
for _, v := range arr {
if v != nil && v.Type() == fastjson.TypeArray {
strs, err := e.arrayAsStringsSkipNil(v.GetArray())
if err != nil {
return err
}
values = append(values, strs...)
values = append(values, e.arrayAsStringsSkipNil(v.GetArray())...)
}
}
req.SetValue(values)
Expand Down

0 comments on commit d2cfa30

Please sign in to comment.