Skip to content

feat(policies) add stateful policy and rule support #604

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Mar 12, 2025
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions sysdig/data_source_sysdig_secure_managed_policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import (
"os"
"strings"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
Expand All @@ -13,6 +14,18 @@
)

func TestAccManagedPolicyDataSource(t *testing.T) {
steps := []resource.TestStep{
{
Config: managedPolicyDataSource(),
},
}

if !strings.HasSuffix(os.Getenv("SYSDIG_SECURE_URL"), "ibm.com") {
steps = append(steps, resource.TestStep{

Check failure on line 24 in sysdig/data_source_sysdig_secure_managed_policy_test.go

View workflow job for this annotation

GitHub Actions / Test / Lint

ineffectual assignment to steps (ineffassign)
Config: managedStatefulPolicyDataSource(),
},
)
}
resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
if v := os.Getenv("SYSDIG_SECURE_API_TOKEN"); v == "" {
Expand Down Expand Up @@ -40,3 +53,12 @@
}
`
}

func managedStatefulPolicyDataSource() string {
return `
data "sysdig_secure_managed_policy" "stateful_example" {
name = "Sysdig AWS Behavioral Analytics Threat Detection"
enabled = false
type = "awscloudtrail_stateful"
`
}
15 changes: 9 additions & 6 deletions sysdig/internal/client/v2/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -520,12 +520,15 @@ type Rule struct {
}

const (
RuleTypeContainer = "CONTAINER"
RuleTypeFalco = "FALCO"
RuleTypeFilesystem = "FILESYSTEM"
RuleTypeNetwork = "NETWORK"
RuleTypeProcess = "PROCESS"
RuleTypeSyscall = "SYSCALL"
RuleTypeContainer = "CONTAINER"
RuleTypeFalco = "FALCO"
RuleTypeFilesystem = "FILESYSTEM"
RuleTypeNetwork = "NETWORK"
RuleTypeProcess = "PROCESS"
RuleTypeSyscall = "SYSCALL"
RuleTypeStatefulSequence = "STATEFUL_SEQUENCE"
StatefulUniqPercentRuleType = "STATEFUL_UNIQ_PERCENT"
StatefulCountRuleType = "STATEFUL_COUNT"
)

type Details struct {
Expand Down
101 changes: 96 additions & 5 deletions sysdig/internal/client/v2/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@ import (
)

const (
CreateRulePath = "%s/api/secure/rules?skipPolicyV2Msg=%t"
GetRuleByIDPath = "%s/api/secure/rules/%d"
UpdateRulePath = "%s/api/secure/rules/%d?skipPolicyV2Msg=%t"
DeleteURLPath = "%s/api/secure/rules/%d?skipPolicyV2Msg=%t"
GetRuleGroupPath = "%s/api/secure/rules/groups?name=%s&type=%s"
CreateRulePath = "%s/api/secure/rules?skipPolicyV2Msg=%t"
GetRuleByIDPath = "%s/api/secure/rules/%d"
UpdateRulePath = "%s/api/secure/rules/%d?skipPolicyV2Msg=%t"
DeleteURLPath = "%s/api/secure/rules/%d?skipPolicyV2Msg=%t"
GetRuleGroupPath = "%s/api/secure/rules/groups?name=%s&type=%s"
CreateStatefulRulePath = "%s/api/policies/v3/statefulRules"
UpdateStatefulRulePath = "%s/api/policies/v3/statefulRules/%d"
DeleteStatefulRulePath = "%s/api/policies/v3/statefulRules/%d"
GetStatefulRuleGroupPath = "%s/api/policies/v3/statefulRules/groups?name=%s&type=%s"
)

type RuleInterface interface {
Expand All @@ -22,6 +26,10 @@ type RuleInterface interface {
UpdateRule(ctx context.Context, rule Rule) (Rule, error)
DeleteRule(ctx context.Context, ruleID int) error
GetRuleGroup(ctx context.Context, ruleName string, ruleType string) ([]Rule, error)
CreateStatefulRule(ctx context.Context, rule Rule) (Rule, error)
UpdateStatefulRule(ctx context.Context, rule Rule) (Rule, error)
DeleteStatefulRule(ctx context.Context, ruleID int) error
GetStatefulRuleGroup(ctx context.Context, ruleName string, ruleType string) ([]Rule, error)
}

func (client *Client) CreateRule(ctx context.Context, rule Rule) (Rule, error) {
Expand Down Expand Up @@ -125,3 +133,86 @@ func (client *Client) DeleteRuleURL(ruleID int) string {
func (client *Client) GetRuleGroupURL(ruleName string, ruleType string) string {
return fmt.Sprintf(GetRuleGroupPath, client.config.url, url.QueryEscape(ruleName), url.QueryEscape(ruleType))
}

func (client *Client) CreateStatefulRuleURL() string {
return fmt.Sprintf(CreateStatefulRulePath, client.config.url)
}

func (client *Client) UpdateStatefulRuleURL(ruleID int) string {
return fmt.Sprintf(UpdateStatefulRulePath, client.config.url, ruleID)
}

func (client *Client) DeleteStatefulRuleURL(ruleID int) string {
return fmt.Sprintf(DeleteStatefulRulePath, client.config.url, ruleID)
}

func (client *Client) GetStatefulRuleGroupURL(ruleName string, ruleType string) string {
return fmt.Sprintf(GetStatefulRuleGroupPath, client.config.url, url.QueryEscape(ruleName), url.QueryEscape(ruleType))
}

func (client *Client) CreateStatefulRule(ctx context.Context, rule Rule) (Rule, error) {
payload, err := Marshal(rule)
if err != nil {
return Rule{}, err
}
response, err := client.requester.Request(ctx, http.MethodPost, client.CreateStatefulRuleURL(), payload)
if err != nil {
return Rule{}, err
}
defer response.Body.Close()

if response.StatusCode != http.StatusOK {
return Rule{}, client.ErrorFromResponse(response)
}

return Unmarshal[Rule](response.Body)
}

func (client *Client) UpdateStatefulRule(ctx context.Context, rule Rule) (Rule, error) {
payload, err := Marshal(rule)
if err != nil {
return Rule{}, err
}

response, err := client.requester.Request(ctx, http.MethodPut, client.UpdateStatefulRuleURL(rule.ID), payload)
if err != nil {
return Rule{}, err
}

defer response.Body.Close()

if response.StatusCode != http.StatusOK {
return Rule{}, client.ErrorFromResponse(response)
}

return Unmarshal[Rule](response.Body)
}

func (client *Client) DeleteStatefulRule(ctx context.Context, ruleID int) error {
fmt.Println("deleting stateful rule")
response, err := client.requester.Request(ctx, http.MethodDelete, client.DeleteStatefulRuleURL(ruleID), nil)
if err != nil {
return err
}
defer response.Body.Close()

if response.StatusCode != http.StatusNoContent && response.StatusCode != http.StatusOK {
return client.ErrorFromResponse(response)
}

return err
}

func (client *Client) GetStatefulRuleGroup(ctx context.Context, ruleName string, ruleType string) ([]Rule, error) {
response, err := client.requester.Request(ctx, http.MethodGet, client.GetStatefulRuleGroupURL(ruleName, ruleType), nil)
if err != nil {
return []Rule{}, err
}
defer response.Body.Close()

if response.StatusCode != http.StatusOK {
return []Rule{}, client.ErrorFromResponse(response)
}

return Unmarshal[[]Rule](response.Body)
}
1 change: 1 addition & 0 deletions sysdig/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ func (p *SysdigProvider) Provider() *schema.Provider {
"sysdig_secure_rule_process": resourceSysdigSecureRuleProcess(),
"sysdig_secure_rule_syscall": resourceSysdigSecureRuleSyscall(),
"sysdig_secure_rule_falco": resourceSysdigSecureRuleFalco(),
"sysdig_secure_rule_stateful": resourceSysdigSecureStatefulRule(),
"sysdig_secure_team": resourceSysdigSecureTeam(),
"sysdig_secure_list": resourceSysdigSecureList(),
"sysdig_secure_macro": resourceSysdigSecureMacro(),
Expand Down
1 change: 1 addition & 0 deletions sysdig/resource_sysdig_secure_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var validatePolicyType = validation.StringInSlice([]string{
"aws_machine_learning",
"machine_learning",
"guardduty",
"awscloudtrail_stateful",
}, false)

func resourceSysdigSecurePolicy() *schema.Resource {
Expand Down
Loading
Loading