Skip to content

Commit

Permalink
feat: add process based exceptions to drift policies
Browse files Browse the repository at this point in the history
Signed-off-by: Igor Eulalio <[email protected]>
  • Loading branch information
IgorEulalio committed Dec 16, 2024
1 parent e33ed88 commit 5668f0a
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 42 deletions.
12 changes: 7 additions & 5 deletions sysdig/internal/client/v2/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,11 +426,13 @@ type RuntimePolicyRuleList struct {
}

type DriftRuleDetails struct {
RuleType ElementType `json:"ruleType"`
Exceptions *RuntimePolicyRuleList `json:"exceptionList"`
ProhibitedBinaries *RuntimePolicyRuleList `json:"prohibitedBinaries"`
Mode string `json:"mode"`
Details `json:"-"`
RuleType ElementType `json:"ruleType"`
Exceptions *RuntimePolicyRuleList `json:"exceptionList"`
ProcessBasedExceptions *RuntimePolicyRuleList `json:"allowlistProcess"`
ProcessBasedDenylist *RuntimePolicyRuleList `json:"denylistProcess"`
ProhibitedBinaries *RuntimePolicyRuleList `json:"prohibitedBinaries"`
Mode string `json:"mode"`
Details `json:"-"`
}

func (p DriftRuleDetails) GetRuleType() ElementType {
Expand Down
18 changes: 10 additions & 8 deletions sysdig/resource_sysdig_secure_drift_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,16 @@ func resourceSysdigSecureDriftPolicy() *schema.Resource {
Required: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": ReadOnlyIntSchema(),
"name": ReadOnlyStringSchema(),
"description": DescriptionSchema(),
"tags": TagsSchema(),
"version": VersionSchema(),
"enabled": BoolSchema(), // Enable maps to mode rule attribute
"exceptions": ExceptionsSchema(),
"prohibited_binaries": ExceptionsSchema(),
"id": ReadOnlyIntSchema(),
"name": ReadOnlyStringSchema(),
"description": DescriptionSchema(),
"tags": TagsSchema(),
"version": VersionSchema(),
"enabled": BoolSchema(), // Enable maps to mode rule attribute
"exceptions": ExceptionsSchema(),
"prohibited_binaries": ExceptionsSchema(),
"process_based_exceptions": ExceptionsSchema(),
"process_based_prohibited_binaries": ExceptionsSchema(),
},
},
},
Expand Down
41 changes: 41 additions & 0 deletions sysdig/resource_sysdig_secure_drift_policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ func TestAccDriftPolicy(t *testing.T) {
{
Config: driftPolicyWithoutNotificationChannel(rText()),
},
{
Config: driftPolicyWithoutExceptions(rText()),
},
},
})
}
Expand All @@ -61,6 +64,9 @@ resource "sysdig_secure_drift_policy" "sample" {
prohibited_binaries {
items = ["/usr/bin/curl"]
}
process_based_exceptions {
items = ["/usr/bin/curl"]
}
}
actions {
Expand Down Expand Up @@ -94,6 +100,9 @@ resource "sysdig_secure_drift_policy" "sample" {
prohibited_binaries {
items = ["/usr/bin/curl"]
}
process_based_exceptions {
items = ["/usr/bin/curl"]
}
}
actions {
Expand Down Expand Up @@ -133,6 +142,9 @@ resource "sysdig_secure_drift_policy" "sample" {
prohibited_binaries {
items = ["/usr/bin/curl"]
}
process_based_exceptions {
items = ["/usr/bin/curl"]
}
}
actions {}
Expand Down Expand Up @@ -162,6 +174,9 @@ resource "sysdig_secure_drift_policy" "sample" {
prohibited_binaries {
items = ["/usr/bin/curl"]
}
process_based_exceptions {
items = ["/usr/bin/curl"]
}
}
actions {
Expand All @@ -171,3 +186,29 @@ resource "sysdig_secure_drift_policy" "sample" {
`, name)
}

func driftPolicyWithoutExceptions(name string) string {
return fmt.Sprintf(`
%s
resource "sysdig_secure_drift_policy" "sample" {
name = "Test Drift Policy %s"
description = "Test Drift Policy Description"
enabled = true
severity = 4
rule {
description = "Test Drift Rule Description"
enabled = true
}
actions {
prevent_drift = true
}
notification_channels = [sysdig_secure_notification_channel_email.sample_email.id]
}
`, secureNotificationChannelEmailWithName(name), name)
}
149 changes: 120 additions & 29 deletions sysdig/tfresource.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,38 +143,97 @@ func setTFResourcePolicyRulesDrift(d *schema.ResourceData, policy v2.PolicyRules
return errors.New("The policy must have at least one rule attached to it")
}

rules := []map[string]interface{}{}
var rules []map[string]interface{}
for _, rule := range policy.Rules {
// Only a single block of exceptions and prohibited binaries is allowed
exceptions := []map[string]interface{}{{
"items": rule.Details.(*v2.DriftRuleDetails).Exceptions.Items,
"match_items": rule.Details.(*v2.DriftRuleDetails).Exceptions.MatchItems,
}}
driftDetails, ok := rule.Details.(*v2.DriftRuleDetails)
if !ok {
return errors.New("unexpected rule details type, expected DriftRuleDetails")
}

// Directly use fields assuming backend returns zero values (not nil)
exceptionsItems := driftDetails.Exceptions.Items
exceptionsMatchItems := driftDetails.Exceptions.MatchItems

var exceptionsBlock []map[string]interface{}
if len(exceptionsItems) > 0 || exceptionsMatchItems {
exceptionsBlock = []map[string]interface{}{
{
"items": exceptionsItems,
"match_items": exceptionsMatchItems,
},
}
}

prohibitedBinaries := []map[string]interface{}{{
"items": rule.Details.(*v2.DriftRuleDetails).ProhibitedBinaries.Items,
"match_items": rule.Details.(*v2.DriftRuleDetails).ProhibitedBinaries.MatchItems,
}}
prohibitedItems := driftDetails.ProhibitedBinaries.Items
prohibitedMatchItems := driftDetails.ProhibitedBinaries.MatchItems

mode := rule.Details.(*v2.DriftRuleDetails).Mode
enabled := true
if mode == "disabled" {
enabled = false
var prohibitedBinariesBlock []map[string]interface{}
if len(prohibitedItems) > 0 || prohibitedMatchItems {
prohibitedBinariesBlock = []map[string]interface{}{
{
"items": prohibitedItems,
"match_items": prohibitedMatchItems,
},
}
}

rules = append(rules, map[string]interface{}{
"id": rule.Id,
"name": rule.Name,
"description": rule.Description,
"version": rule.Version,
"tags": rule.Tags,
"enabled": enabled,
"exceptions": exceptions,
"prohibited_binaries": prohibitedBinaries,
})
processBasedExceptionsItems := driftDetails.ProcessBasedExceptions.Items
processBasedExceptionMatchItems := driftDetails.ProcessBasedExceptions.MatchItems

var processBasedExceptionsBlock []map[string]interface{}
if len(processBasedExceptionsItems) > 0 || processBasedExceptionMatchItems {
processBasedExceptionsBlock = []map[string]interface{}{
{
"items": processBasedExceptionsItems,
"match_items": processBasedExceptionMatchItems,
},
}
}

processBasedProhibitedBinariesItems := driftDetails.ProcessBasedDenylist.Items
processBasedProhibitedBinariesMatchItems := driftDetails.ProcessBasedDenylist.MatchItems

var processBasedProhibitedBinariesBlock []map[string]interface{}
if len(processBasedProhibitedBinariesItems) > 0 || processBasedProhibitedBinariesMatchItems {
processBasedProhibitedBinariesBlock = []map[string]interface{}{
{
"items": processBasedProhibitedBinariesItems,
"match_items": processBasedProhibitedBinariesMatchItems,
},
}
}

mode := driftDetails.Mode
enabled := (mode != "disabled")

ruleMap := map[string]interface{}{
"id": rule.Id,
"name": rule.Name,
"description": rule.Description,
"version": rule.Version,
"tags": rule.Tags,
"enabled": enabled,
}

if exceptionsBlock != nil {
ruleMap["exceptions"] = exceptionsBlock
}
if prohibitedBinariesBlock != nil {
ruleMap["prohibited_binaries"] = prohibitedBinariesBlock
}
if processBasedExceptionsBlock != nil {
ruleMap["process_based_exceptions"] = processBasedExceptionsBlock
}
if processBasedProhibitedBinariesBlock != nil {
ruleMap["process_based_prohibited_binaries"] = processBasedProhibitedBinariesBlock
}

rules = append(rules, ruleMap)
}

_ = d.Set("rule", rules)
if err := d.Set("rule", rules); err != nil {
return err
}

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

// TODO: Extract into a function
prohibitedBinaries := &v2.RuntimePolicyRuleList{}
if _, ok := d.GetOk("rule.0.prohibited_binaries"); ok { // TODO: Do not hardcode the indexes
prohibitedBinaries.Items = schemaSetToList(d.Get("rule.0.prohibited_binaries.0.items"))
prohibitedBinaries.MatchItems = d.Get("rule.0.prohibited_binaries.0.match_items").(bool)
} else {
// initialize Items and MatchItems so we comply with structure and not generate drift
prohibitedBinaries.Items = []string{}
prohibitedBinaries.MatchItems = false
}

// TODO: Extract into a function
processBasedExceptions := &v2.RuntimePolicyRuleList{}
if _, ok := d.GetOk("rule.0.process_based_exceptions"); ok { // TODO: Do not hardcode the indexes
processBasedExceptions.Items = schemaSetToList(d.Get("rule.0.process_based_exceptions.0.items"))
processBasedExceptions.MatchItems = d.Get("rule.0.process_based_exceptions.0.match_items").(bool)
} else {
// initialize Items and MatchItems so we comply with structure and not generate drift
processBasedExceptions.Items = []string{}
processBasedExceptions.MatchItems = false
}

// TODO: Extract into a function
processBasedProhibitedBinaries := &v2.RuntimePolicyRuleList{}
if _, ok := d.GetOk("rule.0.process_based_prohibited_binaries"); ok { // TODO: Do not hardcode the indexes
processBasedProhibitedBinaries.Items = schemaSetToList(d.Get("rule.0.process_based_prohibited_binaries.0.items"))
processBasedProhibitedBinaries.MatchItems = d.Get("rule.0.process_based_prohibited_binaries.0.match_items").(bool)
} else {
// initialize Items and MatchItems so we comply with structure and not generate drift
processBasedProhibitedBinaries.Items = []string{}
processBasedProhibitedBinaries.MatchItems = false
}

tags := schemaSetToList(d.Get("rule.0.tags"))
Expand All @@ -445,10 +534,12 @@ func setPolicyRulesDrift(policy *v2.PolicyRulesComposite, d *schema.ResourceData
Description: d.Get("rule.0.description").(string),
Tags: tags,
Details: v2.DriftRuleDetails{
RuleType: v2.ElementType("DRIFT"), // TODO: Use const
Mode: mode,
Exceptions: exceptions,
ProhibitedBinaries: prohibitedBinaries,
RuleType: v2.ElementType("DRIFT"), // TODO: Use const
Mode: mode,
Exceptions: exceptions,
ProhibitedBinaries: prohibitedBinaries,
ProcessBasedExceptions: processBasedExceptions,
ProcessBasedDenylist: processBasedProhibitedBinaries,
},
}

Expand Down
4 changes: 4 additions & 0 deletions website/docs/r/secure_drift_policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ The rule block is required and supports:
* `items` - (Required) Specify comma separated list of exceptions, e.g. `/usr/bin/rm, /usr/bin/curl`.
* `prohibited_binaries` - (Optional) A prohibited binary can be a known harmful binary or one that facilitates discovery of your environment.
* `items` - (Required) Specify comma separated list of prohibited binaries, e.g. `/usr/bin/rm, /usr/bin/curl`.
* `process_based_exceptions` - (Optional) List of processes that will be able to execute a drifted file
* `items` - (Required) Specify comma separated list of processes, e.g. `/usr/bin/rm, /usr/bin/curl`.
* `process_based_prohibited_binaries` - (Optional) List of processes that will be prohibited to execute a drifted file
* `items` - (Required) Specify comma separated list of processes, e.g. `/usr/bin/rm, /usr/bin/curl`.



0 comments on commit 5668f0a

Please sign in to comment.