Skip to content

Commit 75eb3d8

Browse files
authored
feat: Add support for Falco exceptions (#110)
1 parent 6a9f09c commit 75eb3d8

File tree

5 files changed

+161
-16
lines changed

5 files changed

+161
-16
lines changed

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ github.com/hashicorp/go-getter v1.4.0/go.mod h1:7qxyCd8rBfcShwsvxgIguu4KbS3l8bUC
218218
github.com/hashicorp/go-getter v1.5.0/go.mod h1:a7z7NPPfNQpJWcn4rSWFtdrSldqLdLPEF3d8nFMsSLM=
219219
github.com/hashicorp/go-getter v1.5.2 h1:XDo8LiAcDisiqZdv0TKgz+HtX3WN7zA2JD1R1tjsabE=
220220
github.com/hashicorp/go-getter v1.5.2/go.mod h1:orNH3BTYLu/fIxGIdLjLoAJHWMDQ/UKQr5O4m3iBuoo=
221+
github.com/hashicorp/go-getter v1.5.3 h1:NF5+zOlQegim+w/EUhSLh6QhXHmZMEeHLQzllkQ3ROU=
221222
github.com/hashicorp/go-getter v1.5.3/go.mod h1:BrrV/1clo8cCYu6mxvboYg+KutTiFnXjMEgDD8+i7ZI=
222223
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
223224
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
@@ -263,9 +264,11 @@ github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI
263264
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
264265
github.com/hashicorp/terraform-exec v0.13.0 h1:1Pth+pdWJAufJuWWjaVOVNEkoRTOjGn3hQpAqj4aPdg=
265266
github.com/hashicorp/terraform-exec v0.13.0/go.mod h1:SGhto91bVRlgXQWcJ5znSz+29UZIa8kpBbkGwQ+g9E8=
267+
github.com/hashicorp/terraform-exec v0.14.0 h1:UQoUcxKTZZXhyyK68Cwn4mApT4mnFPmEXPiqaHL9r+w=
266268
github.com/hashicorp/terraform-exec v0.14.0/go.mod h1:qrAASDq28KZiMPDnQ02sFS9udcqEkRly002EA2izXTA=
267269
github.com/hashicorp/terraform-json v0.8.0 h1:XObQ3PgqU52YLQKEaJ08QtUshAfN3yu4u8ebSW0vztc=
268270
github.com/hashicorp/terraform-json v0.8.0/go.mod h1:3defM4kkMfttwiE7VakJDwCd4R+umhSQnvJwORXbprE=
271+
github.com/hashicorp/terraform-json v0.12.0 h1:8czPgEEWWPROStjkWPUnTQDXmpmZPlkQAwYYLETaTvw=
269272
github.com/hashicorp/terraform-json v0.12.0/go.mod h1:pmbq9o4EuL43db5+0ogX10Yofv1nozM+wskr/bGFJpI=
270273
github.com/hashicorp/terraform-plugin-go v0.2.1 h1:EW/R8bB2Zbkjmugzsy1d27yS8/0454b3MtYHkzOknqA=
271274
github.com/hashicorp/terraform-plugin-go v0.2.1/go.mod h1:10V6F3taeDWVAoLlkmArKttR3IULlRWFAGtQIQTIDr4=
@@ -446,6 +449,7 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh
446449
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
447450
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
448451
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
452+
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg=
449453
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
450454
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
451455
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=

sysdig/internal/client/secure/models.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,12 @@ type Details struct {
149149
Syscalls *Syscalls `json:"syscalls,omitempty"`
150150

151151
// Falco
152-
Append *bool `json:"append,omitempty"`
153-
Source string `json:"source,omitempty"`
154-
Output string `json:"output"`
155-
Condition *Condition `json:"condition,omitempty"`
156-
Priority string `json:"priority,omitempty"`
152+
Append *bool `json:"append,omitempty"`
153+
Source string `json:"source,omitempty"`
154+
Output string `json:"output"`
155+
Condition *Condition `json:"condition,omitempty"`
156+
Priority string `json:"priority,omitempty"`
157+
Exceptions []*Exception `json:"exceptions,omitempty"`
157158

158159
RuleType string `json:"ruleType"`
159160
}
@@ -197,6 +198,13 @@ type Condition struct {
197198
Components []interface{} `json:"components"`
198199
}
199200

201+
type Exception struct {
202+
Name string `json:"name"`
203+
Fields interface{} `json:"fields"`
204+
Comps interface{} `json:"comps"`
205+
Values interface{} `json:"values,omitempty"`
206+
}
207+
200208
func (r *Rule) ToJSON() io.Reader {
201209
payload, _ := json.Marshal(r)
202210
return bytes.NewBuffer(payload)

sysdig/resource_sysdig_secure_rule_falco.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package sysdig
22

33
import (
44
"context"
5+
"encoding/json"
56
"errors"
67
"strconv"
78
"strings"
@@ -10,6 +11,7 @@ import (
1011
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1112
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1213
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
14+
"github.com/spf13/cast"
1315

1416
"github.com/draios/terraform-provider-sysdig/sysdig/internal/client/secure"
1517
)
@@ -60,6 +62,32 @@ func resourceSysdigSecureRuleFalco() *schema.Resource {
6062
Optional: true,
6163
Default: false,
6264
},
65+
"exceptions": {
66+
Type: schema.TypeList,
67+
Optional: true,
68+
Elem: &schema.Resource{
69+
Schema: map[string]*schema.Schema{
70+
"name": {
71+
Type: schema.TypeString,
72+
Required: true,
73+
},
74+
"comps": {
75+
Type: schema.TypeList,
76+
Required: true,
77+
Elem: &schema.Schema{Type: schema.TypeString},
78+
},
79+
"values": {
80+
Type: schema.TypeString,
81+
Required: true,
82+
},
83+
"fields": {
84+
Type: schema.TypeList,
85+
Required: true,
86+
Elem: &schema.Schema{Type: schema.TypeString},
87+
},
88+
},
89+
},
90+
},
6391
}),
6492
}
6593
}
@@ -193,5 +221,40 @@ func resourceSysdigRuleFalcoFromResourceData(d *schema.ResourceData) (secure.Rul
193221
Components: []interface{}{},
194222
}
195223

224+
if exceptionsField, ok := d.GetOk("exceptions"); ok {
225+
falcoExceptions := []*secure.Exception{}
226+
for _, exception := range exceptionsField.([]interface{}) {
227+
exceptionMap := exception.(map[string]interface{})
228+
newFalcoException := &secure.Exception{
229+
Name: exceptionMap["name"].(string),
230+
}
231+
232+
comps := cast.ToStringSlice(exceptionMap["comps"])
233+
if len(comps) == 1 {
234+
newFalcoException.Comps = comps[0]
235+
}
236+
if len(comps) > 1 {
237+
newFalcoException.Comps = comps
238+
}
239+
240+
values := cast.ToString(exceptionMap["values"])
241+
err := json.Unmarshal([]byte(values), &newFalcoException.Values)
242+
if err != nil {
243+
return secure.Rule{}, err
244+
}
245+
246+
fields := cast.ToStringSlice(exceptionMap["fields"])
247+
if len(fields) == 1 {
248+
newFalcoException.Fields = fields[0]
249+
}
250+
if len(fields) > 1 {
251+
newFalcoException.Fields = fields
252+
}
253+
254+
falcoExceptions = append(falcoExceptions, newFalcoException)
255+
}
256+
rule.Details.Exceptions = falcoExceptions
257+
}
258+
196259
return rule, nil
197260
}

sysdig/resource_sysdig_secure_rule_falco_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ func TestAccRuleFalco(t *testing.T) {
6666
Config: ruleFalcoTerminalShellWithMissingSource(rText()),
6767
ExpectError: regexp.MustCompile("source must be set when append = false"),
6868
},
69+
{
70+
Config: ruleFalcoWithExceptions(rText()),
71+
},
6972
},
7073
})
7174
}
@@ -146,3 +149,36 @@ resource "sysdig_secure_rule_falco" "terminal_shell_append" {
146149
append = true
147150
}`)
148151
}
152+
153+
func ruleFalcoWithExceptions(name string) string {
154+
return fmt.Sprintf(`
155+
resource "sysdig_secure_rule_falco" "attach_to_cluster_admin_role" {
156+
name = "TERRAFORM TEST %s - Attach to cluster-admin Role"
157+
condition = "kevt and clusterrolebinding and kcreate and ka.req.binding.role=cluster-admin"
158+
description = "Detect any attempt to create a ClusterRoleBinding to the cluster-admin user"
159+
160+
output = "Cluster Role Binding to cluster-admin role (user=%%ka.user.name subject=%%ka.req.binding.subjects)"
161+
tags = ["NIST_800-53_AC-2(12)(a)", "NIST_800-53_AU-6(8)", "NIST_800-53_SI-7(11)", "k8s", "SOC2_CC6.3", "NIST_800-53_AC-3", "NIST_800-53", "NIST_800-53_AC-2d", "SOC2"]
162+
source = "k8s_audit"
163+
164+
exceptions {
165+
name = "subjects_with_in"
166+
fields = ["ka.req.binding.subjects", "ka.req.binding.role"]
167+
comps = ["in", "="]
168+
values = jsonencode([ [["sysdig", "sysdiglabs"], "falco"] ])
169+
}
170+
exceptions {
171+
name = "subjects_equal"
172+
fields = ["ka.req.binding.subjects", "ka.req.binding.role"]
173+
comps = ["=", "="]
174+
values = jsonencode([ ["foo", "bar"] ])
175+
}
176+
exceptions {
177+
name = "only_one_field"
178+
fields = ["ka.req.binding.subjects"]
179+
comps = ["in"]
180+
values = jsonencode(["foo"])
181+
}
182+
}
183+
`, name)
184+
}

website/docs/r/sysdig_secure_rule_falco.md

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,42 @@ Creates a Sysdig Secure Falco Rule.
1616

1717
```hcl
1818
resource "sysdig_secure_rule_falco" "example" {
19-
name = "Terminal shell in container" // ID
19+
name = "Terminal shell in container" // ID
2020
description = "A shell was used as the entrypoint/exec point into a container with an attached terminal."
21-
tags = ["container", "shell", "mitre_execution"]
21+
tags = ["container", "shell", "mitre_execution"]
2222
2323
condition = "spawned_process and container and shell_procs and proc.tty != 0 and container_entrypoint"
24-
output = "A shell was spawned in a container with an attached terminal (user=%user.name %container.info shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline terminal=%proc.tty container_id=%container.id image=%container.image.repository)"
25-
priority = "notice"
26-
source = "syscall" // syscall or k8s_audit
24+
output = "A shell was spawned in a container with an attached terminal (user=%user.name %container.info shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline terminal=%proc.tty container_id=%container.id image=%container.image.repository)"
25+
priority = "notice"
26+
source = "syscall" // syscall or k8s_audit
27+
28+
29+
exceptions {
30+
name = "proc_names"
31+
fields = ["proc.name"]
32+
comps = ["in"]
33+
values = jsonencode(["python", "python2", "python3"]) # If only one element is provided, do not specify it a list of lists.
34+
}
35+
36+
exceptions {
37+
name = "container_proc_name"
38+
fields = ["container.id", "proc.name"]
39+
comps = ["=", "in"]
40+
values = jsonencode([ # If more than one element is provided, you need to specify a list of lists.
41+
["host", ["docker_binaries", "k8s_binaries", "lxd_binaries", "nsenter"]]
42+
])
43+
}
44+
45+
exceptions {
46+
name = "proc_cmdline"
47+
fields = ["proc.name", "proc.cmdline"]
48+
comps = ["in", "contains"]
49+
values = jsonencode([ # In this example, we are providing a pair of values for proc_cmdline, each one in a line.
50+
[["python", "python2", "python3"], "/opt/draios/bin/sdchecks"],
51+
[["java"], "sdjagent.jar"]
52+
])
53+
}
2754
}
28-
2955
```
3056

3157
## Argument Reference
@@ -35,17 +61,25 @@ The following arguments are supported:
3561
* `name` - (Required) The name of the Secure rule. It must be unique.
3662
* `description` - (Optional) The description of Secure rule. By default is empty.
3763
* `tags` - (Optional) A list of tags for this rule.
38-
39-
- - -
40-
41-
### Conditions
42-
4364
* `condition` - (Required) A [Falco condition](https://falco.org/docs/rules/) is simply a Boolean predicate on Sysdig events expressed using the Sysdig [filter syntax](http://www.sysdig.org/wiki/sysdig-user-guide/#filtering) and macro terms.
4465
* `output` - (Optional) Add additional information to each Falco notification's output. Required if append is false.
4566
* `priority` - (Optional) The priority of the Falco rule. It can be: "emergency", "alert", "critical", "error", "warning", "notice", "info" or "debug". By default is "warning".
4667
* `source` - (Optional) The source of the event. It can be either "syscall", "k8s_audit" or "aws_cloudtrail". Required if append is false.
68+
* `exceptions` - (Optional) The exceptions key is a list of identifier plus list of tuples of filtercheck fields. See below for details.
4769
* `append` - (Optional) This indicates that the rule being created appends the condition to an existing Sysdig-provided rule. By default this is false. Appending to user-created rules is not supported by the API.
4870

71+
### Exceptions
72+
73+
Starting in 0.28.0, Falco supports an optional exceptions property to rules. The exceptions key is a list of identifier plus list of tuples of filtercheck fields.
74+
For more information about the syntax of the exceptions, check the [official Falco documentation](https://falco.org/docs/rules/exceptions/).
75+
76+
Supported fields for exceptions:
77+
78+
* `name` - (Required) The name of the exception. Only used to provide a handy name, and to potentially link together values in a later rule that has `append = true`.
79+
* `fields` - (Required) Contains one or more fields that will extract a value from the syscall/k8s_audit events.
80+
* `comps` - (Required) Contains comparison operators that align 1-1 with the items in the fields property.
81+
* `values` - (Required) Contains tuples of values. Each item in the tuple should align 1-1 with the corresponding field and comparison operator. Since the value can be a string, a list of strings or a list of a list of strings, the value of this field must be supplied in JSON format. You can use the default `jsonencode` function to provide this value. See the usage example on the top.
82+
4983
## Attributes Reference
5084

5185
In addition to all arguments above, the following attributes are exported:

0 commit comments

Comments
 (0)