Skip to content

Commit 81ed4ca

Browse files
committed
feat: add process based exceptions to drift policies
Signed-off-by: Igor Eulalio <[email protected]>
1 parent 669ffeb commit 81ed4ca

File tree

5 files changed

+182
-42
lines changed

5 files changed

+182
-42
lines changed

sysdig/internal/client/v2/model.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -426,11 +426,13 @@ type RuntimePolicyRuleList struct {
426426
}
427427

428428
type DriftRuleDetails struct {
429-
RuleType ElementType `json:"ruleType"`
430-
Exceptions *RuntimePolicyRuleList `json:"exceptionList"`
431-
ProhibitedBinaries *RuntimePolicyRuleList `json:"prohibitedBinaries"`
432-
Mode string `json:"mode"`
433-
Details `json:"-"`
429+
RuleType ElementType `json:"ruleType"`
430+
Exceptions *RuntimePolicyRuleList `json:"exceptionList"`
431+
ProcessBasedExceptions *RuntimePolicyRuleList `json:"allowlistProcess"`
432+
ProcessBasedDenylist *RuntimePolicyRuleList `json:"denylistProcess"`
433+
ProhibitedBinaries *RuntimePolicyRuleList `json:"prohibitedBinaries"`
434+
Mode string `json:"mode"`
435+
Details `json:"-"`
434436
}
435437

436438
func (p DriftRuleDetails) GetRuleType() ElementType {

sysdig/resource_sysdig_secure_drift_policy.go

+10-8
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,16 @@ func resourceSysdigSecureDriftPolicy() *schema.Resource {
5656
Required: true,
5757
Elem: &schema.Resource{
5858
Schema: map[string]*schema.Schema{
59-
"id": ReadOnlyIntSchema(),
60-
"name": ReadOnlyStringSchema(),
61-
"description": DescriptionSchema(),
62-
"tags": TagsSchema(),
63-
"version": VersionSchema(),
64-
"enabled": BoolSchema(), // Enable maps to mode rule attribute
65-
"exceptions": ExceptionsSchema(),
66-
"prohibited_binaries": ExceptionsSchema(),
59+
"id": ReadOnlyIntSchema(),
60+
"name": ReadOnlyStringSchema(),
61+
"description": DescriptionSchema(),
62+
"tags": TagsSchema(),
63+
"version": VersionSchema(),
64+
"enabled": BoolSchema(), // Enable maps to mode rule attribute
65+
"exceptions": ExceptionsSchema(),
66+
"prohibited_binaries": ExceptionsSchema(),
67+
"process_based_exceptions": ExceptionsSchema(),
68+
"process_based_prohibited_binaries": ExceptionsSchema(),
6769
},
6870
},
6971
},

sysdig/resource_sysdig_secure_drift_policy_test.go

+41
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ func TestAccDriftPolicy(t *testing.T) {
3636
{
3737
Config: driftPolicyWithoutNotificationChannel(rText()),
3838
},
39+
{
40+
Config: driftPolicyWithoutExceptions(rText()),
41+
},
3942
},
4043
})
4144
}
@@ -61,6 +64,9 @@ resource "sysdig_secure_drift_policy" "sample" {
6164
prohibited_binaries {
6265
items = ["/usr/bin/curl"]
6366
}
67+
process_based_exceptions {
68+
items = ["/usr/bin/curl"]
69+
}
6470
}
6571
6672
actions {
@@ -94,6 +100,9 @@ resource "sysdig_secure_drift_policy" "sample" {
94100
prohibited_binaries {
95101
items = ["/usr/bin/curl"]
96102
}
103+
process_based_exceptions {
104+
items = ["/usr/bin/curl"]
105+
}
97106
}
98107
99108
actions {
@@ -133,6 +142,9 @@ resource "sysdig_secure_drift_policy" "sample" {
133142
prohibited_binaries {
134143
items = ["/usr/bin/curl"]
135144
}
145+
process_based_exceptions {
146+
items = ["/usr/bin/curl"]
147+
}
136148
}
137149
138150
actions {}
@@ -162,6 +174,9 @@ resource "sysdig_secure_drift_policy" "sample" {
162174
prohibited_binaries {
163175
items = ["/usr/bin/curl"]
164176
}
177+
process_based_exceptions {
178+
items = ["/usr/bin/curl"]
179+
}
165180
}
166181
167182
actions {
@@ -171,3 +186,29 @@ resource "sysdig_secure_drift_policy" "sample" {
171186
172187
`, name)
173188
}
189+
190+
func driftPolicyWithoutExceptions(name string) string {
191+
return fmt.Sprintf(`
192+
%s
193+
194+
resource "sysdig_secure_drift_policy" "sample" {
195+
name = "Test Drift Policy %s"
196+
description = "Test Drift Policy Description"
197+
enabled = true
198+
severity = 4
199+
200+
rule {
201+
description = "Test Drift Rule Description"
202+
203+
enabled = true
204+
}
205+
206+
actions {
207+
prevent_drift = true
208+
}
209+
210+
notification_channels = [sysdig_secure_notification_channel_email.sample_email.id]
211+
}
212+
213+
`, secureNotificationChannelEmailWithName(name), name)
214+
}

sysdig/tfresource.go

+120-29
Original file line numberDiff line numberDiff line change
@@ -143,38 +143,97 @@ func setTFResourcePolicyRulesDrift(d *schema.ResourceData, policy v2.PolicyRules
143143
return errors.New("The policy must have at least one rule attached to it")
144144
}
145145

146-
rules := []map[string]interface{}{}
146+
var rules []map[string]interface{}
147147
for _, rule := range policy.Rules {
148-
// Only a single block of exceptions and prohibited binaries is allowed
149-
exceptions := []map[string]interface{}{{
150-
"items": rule.Details.(*v2.DriftRuleDetails).Exceptions.Items,
151-
"match_items": rule.Details.(*v2.DriftRuleDetails).Exceptions.MatchItems,
152-
}}
148+
driftDetails, ok := rule.Details.(*v2.DriftRuleDetails)
149+
if !ok {
150+
return errors.New("unexpected rule details type, expected DriftRuleDetails")
151+
}
152+
153+
// Directly use fields assuming backend returns zero values (not nil)
154+
exceptionsItems := driftDetails.Exceptions.Items
155+
exceptionsMatchItems := driftDetails.Exceptions.MatchItems
156+
157+
var exceptionsBlock []map[string]interface{}
158+
if len(exceptionsItems) > 0 || exceptionsMatchItems {
159+
exceptionsBlock = []map[string]interface{}{
160+
{
161+
"items": exceptionsItems,
162+
"match_items": exceptionsMatchItems,
163+
},
164+
}
165+
}
153166

154-
prohibitedBinaries := []map[string]interface{}{{
155-
"items": rule.Details.(*v2.DriftRuleDetails).ProhibitedBinaries.Items,
156-
"match_items": rule.Details.(*v2.DriftRuleDetails).ProhibitedBinaries.MatchItems,
157-
}}
167+
prohibitedItems := driftDetails.ProhibitedBinaries.Items
168+
prohibitedMatchItems := driftDetails.ProhibitedBinaries.MatchItems
158169

159-
mode := rule.Details.(*v2.DriftRuleDetails).Mode
160-
enabled := true
161-
if mode == "disabled" {
162-
enabled = false
170+
var prohibitedBinariesBlock []map[string]interface{}
171+
if len(prohibitedItems) > 0 || prohibitedMatchItems {
172+
prohibitedBinariesBlock = []map[string]interface{}{
173+
{
174+
"items": prohibitedItems,
175+
"match_items": prohibitedMatchItems,
176+
},
177+
}
163178
}
164179

165-
rules = append(rules, map[string]interface{}{
166-
"id": rule.Id,
167-
"name": rule.Name,
168-
"description": rule.Description,
169-
"version": rule.Version,
170-
"tags": rule.Tags,
171-
"enabled": enabled,
172-
"exceptions": exceptions,
173-
"prohibited_binaries": prohibitedBinaries,
174-
})
180+
processBasedExceptionsItems := driftDetails.ProcessBasedExceptions.Items
181+
processBasedExceptionMatchItems := driftDetails.ProcessBasedExceptions.MatchItems
182+
183+
var processBasedExceptionsBlock []map[string]interface{}
184+
if len(processBasedExceptionsItems) > 0 || processBasedExceptionMatchItems {
185+
processBasedExceptionsBlock = []map[string]interface{}{
186+
{
187+
"items": processBasedExceptionsItems,
188+
"match_items": processBasedExceptionMatchItems,
189+
},
190+
}
191+
}
192+
193+
processBasedProhibitedBinariesItems := driftDetails.ProcessBasedDenylist.Items
194+
processBasedProhibitedBinariesMatchItems := driftDetails.ProcessBasedDenylist.MatchItems
195+
196+
var processBasedProhibitedBinariesBlock []map[string]interface{}
197+
if len(processBasedProhibitedBinariesItems) > 0 || processBasedProhibitedBinariesMatchItems {
198+
processBasedProhibitedBinariesBlock = []map[string]interface{}{
199+
{
200+
"items": processBasedProhibitedBinariesItems,
201+
"match_items": processBasedProhibitedBinariesMatchItems,
202+
},
203+
}
204+
}
205+
206+
mode := driftDetails.Mode
207+
enabled := (mode != "disabled")
208+
209+
ruleMap := map[string]interface{}{
210+
"id": rule.Id,
211+
"name": rule.Name,
212+
"description": rule.Description,
213+
"version": rule.Version,
214+
"tags": rule.Tags,
215+
"enabled": enabled,
216+
}
217+
218+
if exceptionsBlock != nil {
219+
ruleMap["exceptions"] = exceptionsBlock
220+
}
221+
if prohibitedBinariesBlock != nil {
222+
ruleMap["prohibited_binaries"] = prohibitedBinariesBlock
223+
}
224+
if processBasedExceptionsBlock != nil {
225+
ruleMap["process_based_exceptions"] = processBasedExceptionsBlock
226+
}
227+
if processBasedProhibitedBinariesBlock != nil {
228+
ruleMap["process_based_prohibited_binaries"] = processBasedProhibitedBinariesBlock
229+
}
230+
231+
rules = append(rules, ruleMap)
175232
}
176233

177-
_ = d.Set("rule", rules)
234+
if err := d.Set("rule", rules); err != nil {
235+
return err
236+
}
178237

179238
return nil
180239
}
@@ -418,13 +477,43 @@ func setPolicyRulesDrift(policy *v2.PolicyRulesComposite, d *schema.ResourceData
418477
if _, ok := d.GetOk("rule.0.exceptions"); ok { // TODO: Do not hardcode the indexes
419478
exceptions.Items = schemaSetToList(d.Get("rule.0.exceptions.0.items"))
420479
exceptions.MatchItems = d.Get("rule.0.exceptions.0.match_items").(bool)
480+
} else {
481+
// initialize Items and MatchItems so we comply with structure and not generate drift
482+
exceptions.Items = []string{}
483+
exceptions.MatchItems = false
421484
}
422485

423486
// TODO: Extract into a function
424487
prohibitedBinaries := &v2.RuntimePolicyRuleList{}
425488
if _, ok := d.GetOk("rule.0.prohibited_binaries"); ok { // TODO: Do not hardcode the indexes
426489
prohibitedBinaries.Items = schemaSetToList(d.Get("rule.0.prohibited_binaries.0.items"))
427490
prohibitedBinaries.MatchItems = d.Get("rule.0.prohibited_binaries.0.match_items").(bool)
491+
} else {
492+
// initialize Items and MatchItems so we comply with structure and not generate drift
493+
prohibitedBinaries.Items = []string{}
494+
prohibitedBinaries.MatchItems = false
495+
}
496+
497+
// TODO: Extract into a function
498+
processBasedExceptions := &v2.RuntimePolicyRuleList{}
499+
if _, ok := d.GetOk("rule.0.process_based_exceptions"); ok { // TODO: Do not hardcode the indexes
500+
processBasedExceptions.Items = schemaSetToList(d.Get("rule.0.process_based_exceptions.0.items"))
501+
processBasedExceptions.MatchItems = d.Get("rule.0.process_based_exceptions.0.match_items").(bool)
502+
} else {
503+
// initialize Items and MatchItems so we comply with structure and not generate drift
504+
processBasedExceptions.Items = []string{}
505+
processBasedExceptions.MatchItems = false
506+
}
507+
508+
// TODO: Extract into a function
509+
processBasedProhibitedBinaries := &v2.RuntimePolicyRuleList{}
510+
if _, ok := d.GetOk("rule.0.process_based_prohibited_binaries"); ok { // TODO: Do not hardcode the indexes
511+
processBasedProhibitedBinaries.Items = schemaSetToList(d.Get("rule.0.process_based_prohibited_binaries.0.items"))
512+
processBasedProhibitedBinaries.MatchItems = d.Get("rule.0.process_based_prohibited_binaries.0.match_items").(bool)
513+
} else {
514+
// initialize Items and MatchItems so we comply with structure and not generate drift
515+
processBasedProhibitedBinaries.Items = []string{}
516+
processBasedProhibitedBinaries.MatchItems = false
428517
}
429518

430519
tags := schemaSetToList(d.Get("rule.0.tags"))
@@ -445,10 +534,12 @@ func setPolicyRulesDrift(policy *v2.PolicyRulesComposite, d *schema.ResourceData
445534
Description: d.Get("rule.0.description").(string),
446535
Tags: tags,
447536
Details: v2.DriftRuleDetails{
448-
RuleType: v2.ElementType("DRIFT"), // TODO: Use const
449-
Mode: mode,
450-
Exceptions: exceptions,
451-
ProhibitedBinaries: prohibitedBinaries,
537+
RuleType: v2.ElementType("DRIFT"), // TODO: Use const
538+
Mode: mode,
539+
Exceptions: exceptions,
540+
ProhibitedBinaries: prohibitedBinaries,
541+
ProcessBasedExceptions: processBasedExceptions,
542+
ProcessBasedDenylist: processBasedProhibitedBinaries,
452543
},
453544
}
454545

website/docs/r/secure_drift_policy.md

+4
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ The rule block is required and supports:
118118
* `items` - (Required) Specify comma separated list of exceptions, e.g. `/usr/bin/rm, /usr/bin/curl`.
119119
* `prohibited_binaries` - (Optional) A prohibited binary can be a known harmful binary or one that facilitates discovery of your environment.
120120
* `items` - (Required) Specify comma separated list of prohibited binaries, e.g. `/usr/bin/rm, /usr/bin/curl`.
121+
* `process_based_exceptions` - (Optional) List of processes that will be able to execute a drifted file
122+
* `items` - (Required) Specify comma separated list of processes, e.g. `/usr/bin/rm, /usr/bin/curl`.
123+
* `process_based_prohibited_binaries` - (Optional) List of processes that will be prohibited to execute a drifted file
124+
* `items` - (Required) Specify comma separated list of processes, e.g. `/usr/bin/rm, /usr/bin/curl`.
121125

122126

123127

0 commit comments

Comments
 (0)