From df22c77f99bfa777fd0237bee5b197bb9ddab280 Mon Sep 17 00:00:00 2001 From: Harsham Patel Date: Wed, 29 Oct 2025 17:34:15 -0700 Subject: [PATCH 1/6] Add terraform support to Okta ML Policy --- .vscode/launch.json | 15 ++ ...ata_source_sysdig_secure_okta_ml_policy.go | 74 ++++++ ...ource_sysdig_secure_okta_ml_policy_test.go | 63 +++++ sysdig/internal/client/v2/model.go | 12 + sysdig/provider.go | 2 + .../resource_sysdig_secure_okta_ml_policy.go | 218 ++++++++++++++++++ ...ource_sysdig_secure_okta_ml_policy_test.go | 82 +++++++ sysdig/tfresource.go | 87 +++++++ website/docs/d/secure_okta_ml_policy.md | 65 ++++++ website/docs/r/secure_okta_ml_policy.md | 64 +++++ 10 files changed, 682 insertions(+) create mode 100644 .vscode/launch.json create mode 100644 sysdig/data_source_sysdig_secure_okta_ml_policy.go create mode 100644 sysdig/data_source_sysdig_secure_okta_ml_policy_test.go create mode 100644 sysdig/resource_sysdig_secure_okta_ml_policy.go create mode 100644 sysdig/resource_sysdig_secure_okta_ml_policy_test.go create mode 100644 website/docs/d/secure_okta_ml_policy.md create mode 100644 website/docs/r/secure_okta_ml_policy.md diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..2ba986f6 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "request": "launch", + "name": "Launch Chrome against localhost", + "url": "http://localhost:8080", + "webRoot": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/sysdig/data_source_sysdig_secure_okta_ml_policy.go b/sysdig/data_source_sysdig_secure_okta_ml_policy.go new file mode 100644 index 00000000..b9bc2d1f --- /dev/null +++ b/sysdig/data_source_sysdig_secure_okta_ml_policy.go @@ -0,0 +1,74 @@ +package sysdig + +import ( + "context" + "time" + + v2 "github.com/draios/terraform-provider-sysdig/sysdig/internal/client/v2" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataSourceSysdigSecureOktaMLPolicy() *schema.Resource { + timeout := 5 * time.Minute + + return &schema.Resource{ + ReadContext: dataSourceSysdigSecureOktaMLPolicyRead, + + Timeouts: &schema.ResourceTimeout{ + Read: schema.DefaultTimeout(timeout), + }, + + Schema: createOktaMLPolicyDataSourceSchema(), + } +} + +func dataSourceSysdigSecureOktaMLPolicyRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + return oktaMLPolicyDataSourceRead(ctx, d, meta, "custom Okta ML policy", isCustomCompositePolicy) +} + +func createOktaMLPolicyDataSourceSchema() map[string]*schema.Schema { + return map[string]*schema.Schema{ + // IMPORTANT: Type is implicit: It's automatically added upon conversion to JSON + "type": { + Type: schema.TypeString, + Computed: true, + }, + "name": NameSchema(), + "description": DescriptionComputedSchema(), + "enabled": EnabledComputedSchema(), + "severity": SeverityComputedSchema(), + "scope": ScopeComputedSchema(), + "version": VersionSchema(), + "notification_channels": NotificationChannelsComputedSchema(), + "runbook": RunbookComputedSchema(), + "rule": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": ReadOnlyIntSchema(), + "name": ReadOnlyStringSchema(), + "description": DescriptionComputedSchema(), + "tags": TagsSchema(), + "version": VersionSchema(), + "anomalous_console_login": MLRuleThresholdAndSeverityComputedSchema(), + }, + }, + }, + } +} + +func oktaMLPolicyDataSourceRead(ctx context.Context, d *schema.ResourceData, meta any, resourceName string, validationFunc func(v2.PolicyRulesComposite) bool) diag.Diagnostics { + policy, err := compositePolicyDataSourceRead(ctx, d, meta, resourceName, policyTypeOktaML, validationFunc) + if err != nil { + return diag.FromErr(err) + } + + err = oktaMLPolicyToResourceData(policy, d) + if err != nil { + return diag.FromErr(err) + } + + return nil +} diff --git a/sysdig/data_source_sysdig_secure_okta_ml_policy_test.go b/sysdig/data_source_sysdig_secure_okta_ml_policy_test.go new file mode 100644 index 00000000..ae63a7ca --- /dev/null +++ b/sysdig/data_source_sysdig_secure_okta_ml_policy_test.go @@ -0,0 +1,63 @@ +//go:build tf_acc_sysdig_secure || tf_acc_policies || tf_acc_policies_okta + +package sysdig_test + +import ( + "fmt" + "os" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/draios/terraform-provider-sysdig/sysdig" +) + +func TestAccOktaMLPolicyDataSource(t *testing.T) { + rText := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + if v := os.Getenv("SYSDIG_SECURE_API_TOKEN"); v == "" { + t.Fatal("SYSDIG_SECURE_API_TOKEN must be set for acceptance tests") + } + }, + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: oktaOktaMLPolicyDataSource(rText), + }, + }, + }) +} + +func oktaOktaMLPolicyDataSource(name string) string { + return fmt.Sprintf(` +resource "sysdig_secure_okta_ml_policy" "policy_1" { + name = "Test Okta ML Policy %s" + description = "Test Okta ML Policy Description %s" + enabled = true + severity = 4 + + rule { + description = "Test Okta ML Rule Description" + + anomalous_console_login { + enabled = true + threshold = 2 + } + } + +} + +data "sysdig_secure_okta_ml_policy" "policy_2" { + name = sysdig_secure_okta_ml_policy.policy_1.name + depends_on = [sysdig_secure_okta_ml_policy.policy_1] +} +`, name, name) +} diff --git a/sysdig/internal/client/v2/model.go b/sysdig/internal/client/v2/model.go index db241d49..3002bed3 100644 --- a/sysdig/internal/client/v2/model.go +++ b/sysdig/internal/client/v2/model.go @@ -337,6 +337,8 @@ func (r *RuntimePolicyRule) UnmarshalJSON(b []byte) error { d = &MLRuleDetails{} case "AWS_MACHINE_LEARNING": d = &AWSMLRuleDetails{} + case "OKTA_MACHINE_LEARNING": + d = &OktaMLRuleDetails{} case "MALWARE": d = &MalwareRuleDetails{} default: @@ -440,6 +442,16 @@ func (p AWSMLRuleDetails) GetRuleType() ElementType { return p.RuleType } +type OktaMLRuleDetails struct { + RuleType ElementType `json:"ruleType" yaml:"ruleType"` + AnomalousConsoleLogin *MLRuleThresholdAndSeverity `json:"anomalousConsoleLogin" yaml:"anomalousConsoleLogin"` + Details `json:"-"` +} + +func (p OktaMLRuleDetails) GetRuleType() ElementType { + return p.RuleType +} + type PolicyRule struct { Name string `json:"ruleName"` Enabled bool `json:"enabled"` diff --git a/sysdig/provider.go b/sysdig/provider.go index 67dfe93a..7c1fcc6e 100644 --- a/sysdig/provider.go +++ b/sysdig/provider.go @@ -151,6 +151,7 @@ func (p *SysdigProvider) Provider() *schema.Provider { "sysdig_monitor_team": resourceSysdigMonitorTeam(), "sysdig_secure_aws_ml_policy": resourceSysdigSecureAWSMLPolicy(), + "sysdig_secure_okta_ml_policy": resourceSysdigSecureOktaMLPolicy(), "sysdig_secure_cloud_account": resourceSysdigSecureCloudAccount(), "sysdig_secure_cloud_auth_account": resourceSysdigSecureCloudauthAccount(), "sysdig_secure_cloud_auth_account_component": resourceSysdigSecureCloudauthAccountComponent(), @@ -217,6 +218,7 @@ func (p *SysdigProvider) Provider() *schema.Provider { "sysdig_secure_agentless_scanning_assets": dataSourceSysdigSecureAgentlessScanningAssets(), "sysdig_secure_aws_ml_policy": dataSourceSysdigSecureAWSMLPolicy(), + "sysdig_secure_okta_ml_policy": dataSourceSysdigSecureOktaMLPolicy(), "sysdig_secure_cloud_ingestion_assets": dataSourceSysdigSecureCloudIngestionAssets(), "sysdig_secure_connection": dataSourceSysdigSecureConnection(), "sysdig_secure_custom_policy": dataSourceSysdigSecureCustomPolicy(), diff --git a/sysdig/resource_sysdig_secure_okta_ml_policy.go b/sysdig/resource_sysdig_secure_okta_ml_policy.go new file mode 100644 index 00000000..ade2275d --- /dev/null +++ b/sysdig/resource_sysdig_secure_okta_ml_policy.go @@ -0,0 +1,218 @@ +package sysdig + +import ( + "context" + "errors" + "net/http" + "strconv" + "time" + + v2 "github.com/draios/terraform-provider-sysdig/sysdig/internal/client/v2" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" +) + +func resourceSysdigSecureOktaMLPolicy() *schema.Resource { + timeout := 5 * time.Minute + + return &schema.Resource{ + CreateContext: resourceSysdigOktaMLPolicyCreate, + ReadContext: resourceSysdigOktaMLPolicyRead, + UpdateContext: resourceSysdigOktaMLPolicyUpdate, + DeleteContext: resourceSysdigOktaMLPolicyDelete, + Importer: &schema.ResourceImporter{ + StateContext: resourceSysdigSecureOktaMLPolicyImportState, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(timeout), + Delete: schema.DefaultTimeout(timeout), + Update: schema.DefaultTimeout(timeout), + Read: schema.DefaultTimeout(timeout), + }, + // IMPORTANT: composite.Policy.Rules and composite.Policy.RuleNames are read-only attributes. + // They're not used as a source for rule updates, so it's okay to drop those attributes in TF. + // To update the rules, composite.Rules values are used instead. + // https://github.com/draios/secure-backend/blob/main/policies/api/handler_policies.go#L1120 + Schema: map[string]*schema.Schema{ + // IMPORTANT: Type is implicit: It's automatically added upon conversion to JSON + "type": { + Type: schema.TypeString, + Optional: true, + Default: policyTypeOktaML, + ValidateDiagFunc: validateDiagFunc(validation.StringInSlice([]string{policyTypeOktaML}, false)), + }, + "name": NameSchema(), + "description": DescriptionSchema(), + "enabled": EnabledSchema(), + "severity": SeveritySchema(), + "scope": ScopeSchema(), + "version": VersionSchema(), + "notification_channels": NotificationChannelsSchema(), + "runbook": RunbookSchema(), + "rule": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": ReadOnlyIntSchema(), + "name": ReadOnlyStringSchema(), + // Do not allow switching off individual rules + // "enabled": EnabledSchema(), + "description": DescriptionSchema(), + "tags": TagsSchema(), + "version": VersionSchema(), + "anomalous_console_login": MLRuleThresholdAndSeveritySchema(), + }, + }, + }, + }, // Schema end + } +} + +func oktaMLPolicyFromResourceData(d *schema.ResourceData) (v2.PolicyRulesComposite, error) { + policy := &v2.PolicyRulesComposite{ + Policy: &v2.Policy{}, + Rules: []*v2.RuntimePolicyRule{}, + } + err := oktaMLPolicyReducer(policy, d) + if err != nil { + return *policy, err + } + + return *policy, nil +} + +func oktaMLPolicyToResourceData(policy *v2.PolicyRulesComposite, d *schema.ResourceData) error { + return oktaMLTFResourceReducer(d, *policy) +} + +func resourceSysdigOktaMLPolicyCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + sysdigClients := meta.(SysdigClients) + client, err := getSecureCompositePolicyClient(sysdigClients) + if err != nil { + return diag.FromErr(err) + } + + policy, err := oktaMLPolicyFromResourceData(d) + if err != nil { + return diag.FromErr(err) + } + + policy, err = client.CreateCompositePolicy(ctx, policy) + if err != nil { + return diag.FromErr(err) + } + + err = oktaMLPolicyToResourceData(&policy, d) + if err != nil { + return diag.FromErr(err) + } + + sysdigClients.AddCleanupHook(sendPoliciesToAgents) + + return nil +} + +func resourceSysdigOktaMLPolicyUpdate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + sysdigClients := meta.(SysdigClients) + client, err := getSecureCompositePolicyClient(sysdigClients) + if err != nil { + return diag.FromErr(err) + } + + policy, err := oktaMLPolicyFromResourceData(d) + if err != nil { + return diag.FromErr(err) + } + + _, err = client.UpdateCompositePolicy(ctx, policy) + if err != nil { + return diag.FromErr(err) + } + sysdigClients.AddCleanupHook(sendPoliciesToAgents) + + return nil +} + +func resourceSysdigOktaMLPolicyRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + client, err := getSecureCompositePolicyClient(meta.(SysdigClients)) + if err != nil { + return diag.FromErr(err) + } + + id, _ := strconv.Atoi(d.Id()) + policy, statusCode, err := client.GetCompositePolicyByID(ctx, id) + if err != nil { + if statusCode == http.StatusNotFound { + d.SetId("") + } else { + return diag.FromErr(err) + } + } + + err = oktaMLPolicyToResourceData(&policy, d) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func resourceSysdigOktaMLPolicyDelete(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + sysdigClients := meta.(SysdigClients) + client, err := getSecureCompositePolicyClient(sysdigClients) + if err != nil { + return diag.FromErr(err) + } + + policy, err := oktaMLPolicyFromResourceData(d) + if err != nil { + return diag.FromErr(err) + } + + if policy.Policy.ID == 0 { + return diag.FromErr(errors.New("policy ID is missing")) + } + + err = client.DeleteCompositePolicy(ctx, policy.Policy.ID) + if err != nil { + return diag.FromErr(err) + } + sysdigClients.AddCleanupHook(sendPoliciesToAgents) + + return nil +} + +func resourceSysdigSecureOktaMLPolicyImportState(ctx context.Context, d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) { + client, err := getSecureCompositePolicyClient(meta.(SysdigClients)) + if err != nil { + return nil, err + } + + policy, err := oktaMLPolicyFromResourceData(d) + if err != nil { + return nil, err + } + + if policy.Policy.ID == 0 { + return nil, errors.New("policy ID is missing") + } + + policy, _, err = client.GetCompositePolicyByID(ctx, policy.Policy.ID) + if err != nil { + return nil, err + } + + if policy.Policy.IsDefault || policy.Policy.TemplateID != 0 { + return nil, errors.New("unable to import policy that is not a custom policy") + } + + err = oktaMLPolicyToResourceData(&policy, d) + if err != nil { + return nil, err + } + + return []*schema.ResourceData{d}, nil +} diff --git a/sysdig/resource_sysdig_secure_okta_ml_policy_test.go b/sysdig/resource_sysdig_secure_okta_ml_policy_test.go new file mode 100644 index 00000000..9240958d --- /dev/null +++ b/sysdig/resource_sysdig_secure_okta_ml_policy_test.go @@ -0,0 +1,82 @@ +//go:build tf_acc_sysdig_secure || tf_acc_policies || tf_acc_policies_okta + +package sysdig_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + "github.com/draios/terraform-provider-sysdig/sysdig" +) + +func TestAccOktaMLPolicy(t *testing.T) { + rText := func() string { return acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) } + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: preCheckAnyEnv(t, SysdigSecureApiTokenEnv), + ProviderFactories: map[string]func() (*schema.Provider, error){ + "sysdig": func() (*schema.Provider, error) { + return sysdig.Provider(), nil + }, + }, + Steps: []resource.TestStep{ + { + Config: oktaMLPolicyWithName(rText()), + }, + { + Config: oktaMLPolicyWithoutNotificationChannel(rText()), + }, + }, + }) +} + +func oktaMLPolicyWithName(name string) string { + return fmt.Sprintf(` +%s + +resource "sysdig_secure_okta_ml_policy" "sample" { + name = "Test Okta ML Policy %s" + description = "Test Okta ML Policy Description" + enabled = true + severity = 4 + + rule { + description = "Test Okta ML Rule Description" + + anomalous_console_login { + enabled = true + threshold = 2 + } + } + + notification_channels = [sysdig_secure_notification_channel_email.sample_email.id] +} + +`, secureNotificationChannelEmailWithName(name), name) +} + +func oktaMLPolicyWithoutNotificationChannel(name string) string { + return fmt.Sprintf(` +resource "sysdig_secure_okta_ml_policy" "sample" { + name = "Test Okta ML Policy %s" + description = "Test Okta ML Policy Description" + enabled = true + severity = 4 + + rule { + description = "Test Okta ML Rule Description" + + anomalous_console_login { + enabled = true + threshold = 2 + } + } + +} + +`, name) +} diff --git a/sysdig/tfresource.go b/sysdig/tfresource.go index 4a6e5a5c..b9d476ec 100644 --- a/sysdig/tfresource.go +++ b/sysdig/tfresource.go @@ -16,6 +16,7 @@ const ( policyTypeDrift = "drift" policyTypeML = "machine_learning" policyTypeAWSML = "aws_machine_learning" + policyTypeOktaML = "okta_machine_learning" preventMalwareKey = "prevent_malware" preventDriftKey = "prevent_drift" @@ -313,6 +314,33 @@ func setTFResourcePolicyRulesAWSML(d *schema.ResourceData, policy v2.PolicyRules return nil } +func setTFResourcePolicyRulesOktaML(d *schema.ResourceData, policy v2.PolicyRulesComposite) error { + if len(policy.Rules) == 0 { + return errors.New("the policy must have at least one rule attached to it") + } + + rules := []map[string]any{} + for _, rule := range policy.Rules { + anomalousLogin := []map[string]any{{ + "enabled": rule.Details.(*v2.OktaMLRuleDetails).AnomalousConsoleLogin.Enabled, + "threshold": rule.Details.(*v2.OktaMLRuleDetails).AnomalousConsoleLogin.Threshold, + }} + + rules = append(rules, map[string]any{ + "id": rule.ID, + "name": rule.Name, + "description": rule.Description, + "version": rule.Version, + "tags": rule.Tags, + "anomalous_console_login": anomalousLogin, + }) + } + + _ = d.Set("rule", rules) + + return nil +} + // TODO: Split this func into smaller composable functions func setTFResourcePolicyActions(key string) func(d *schema.ResourceData, policy v2.PolicyRulesComposite) error { return func(d *schema.ResourceData, policy v2.PolicyRulesComposite) error { @@ -381,6 +409,12 @@ var awsMLTFResourceReducer = Reducer( setTFResourcePolicyRulesAWSML, ) +var oktaMLTFResourceReducer = Reducer( + setTFResourceBaseAttrs, + setTFResourcePolicyType(policyTypeOktaML), + setTFResourcePolicyRulesOktaML, +) + func setPolicyBaseAttrs(policyType string) func(policy *v2.PolicyRulesComposite, d *schema.ResourceData) error { return func(policy *v2.PolicyRulesComposite, d *schema.ResourceData) error { id, err := strconv.Atoi(d.Id()) @@ -668,6 +702,54 @@ func setPolicyRulesAWSML(policy *v2.PolicyRulesComposite, d *schema.ResourceData return nil } +func setPolicyRulesOktaML(policy *v2.PolicyRulesComposite, d *schema.ResourceData) error { + policy.Policy.Rules = []*v2.PolicyRule{} + policy.Rules = []*v2.RuntimePolicyRule{} + if _, ok := d.GetOk("rule"); ok { + // TODO: Iterate over a list of rules instead of hard-coding the index values + // TODO: Should we assume that only a single Malware rule can be attached to a policy? + + anomalousLogin := &v2.MLRuleThresholdAndSeverity{} + if _, ok := d.GetOk("rule.0.anomalous_console_login"); ok { // TODO: Do not hardcode the indexes + anomalousLogin.Enabled = d.Get("rule.0.anomalous_console_login.0.enabled").(bool) + anomalousLogin.Threshold = float64(d.Get("rule.0.anomalous_console_login.0.threshold").(int)) + } + + tags := schemaSetToList(d.Get("rule.0.tags")) + // Set default tags as field tags must not be null + if len(tags) == 0 { + tags = []string{defaultMLTag} + } + + rule := &v2.RuntimePolicyRule{ + // TODO: Do not hardcode the indexes + Name: d.Get("rule.0.name").(string), + Description: d.Get("rule.0.description").(string), + // IMPORTANT: In order to update an ML policy, + // correct version number must be provided + Tags: tags, + Details: v2.OktaMLRuleDetails{ + RuleType: v2.ElementType("OKTA_MACHINE_LEARNING"), // TODO: Use const + AnomalousConsoleLogin: anomalousLogin, + }, + } + + id := v2.FlexInt(d.Get("rule.0.id").(int)) + if int(id) != 0 { + rule.ID = &id + } + + v := toIntPtr(d.Get("rule.0.version")) + if *v != 0 { + // Version can only be provided when updating existing rules + rule.Version = v + } + + policy.Rules = append(policy.Rules, rule) + } + return nil +} + var malwarePolicyReducer = Reducer( setPolicyBaseAttrs(policyTypeMalware), setPolicyActions, @@ -689,3 +771,8 @@ var awsMLPolicyReducer = Reducer( setPolicyBaseAttrs(policyTypeAWSML), setPolicyRulesAWSML, ) + +var oktaMLPolicyReducer = Reducer( + setPolicyBaseAttrs(policyTypeOktaML), + setPolicyRulesOktaML, +) diff --git a/website/docs/d/secure_okta_ml_policy.md b/website/docs/d/secure_okta_ml_policy.md new file mode 100644 index 00000000..36764796 --- /dev/null +++ b/website/docs/d/secure_okta_ml_policy.md @@ -0,0 +1,65 @@ +--- +subcategory: "Sysdig Secure" +layout: "sysdig" +page_title: "Sysdig: sysdig_secure_okta_ml_policy" +description: |- + Retrieves a Sysdig Secure Okta ML Policy. +--- + +# Data Source: sysdig_secure_okta_ml_policy + +Retrieves information about an existing Sysdig Secure Okta ML Policy. + +-> **Note:** Sysdig Terraform Provider is under rapid development at this point. If you experience any issue or discrepancy while using it, please make sure you have the latest version. If the issue persists, or you have a Feature Request to support an additional set of resources, please open a [new issue](https://github.com/sysdiglabs/terraform-provider-sysdig/issues/new) in the GitHub repository. + +## Example Usage + +```terraform +data "sysdig_secure_okta_ml_policy" "policy" { + name = "My Okta ML Policy" +} +``` + +## Argument Reference + +* `name` - (Required) The name of the Secure Okta ML policy. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The id for the policy. + +* `type` - The type of the policy. Always set to "okta_machine_learning". + +* `description` - The description for the policy. + +* `severity` - The severity of Secure policy. The accepted values + are: 0, 1, 2, 3 (High), 4, 5 (Medium), 6 (Low) and 7 (Info). + +* `enabled` - Whether the policy is enabled or not. + +* `runbook` - Customer provided url that provides a runbook for a given policy. + +* `scope` - The application scope for the policy. + +* `notification_channels` - IDs of the notification channels to send alerts to + when the policy is fired. + +### `rule` block + +The rule block contains: + +* `id` - The ID of the rule. + +* `name` - The name of the rule. + +* `description` - Rule description. + +* `tags` - Tags associated with the rule. + +* `version` - The version of the rule. + +* `anomalous_console_login` - Anomaly detection settings for logins. + * `enabled` - Whether anomaly detection is enabled. + * `threshold` - Confidence level threshold for triggering alerts. diff --git a/website/docs/r/secure_okta_ml_policy.md b/website/docs/r/secure_okta_ml_policy.md new file mode 100644 index 00000000..eea22601 --- /dev/null +++ b/website/docs/r/secure_okta_ml_policy.md @@ -0,0 +1,64 @@ +--- +subcategory: "Sysdig Secure" +layout: "sysdig" +page_title: "Sysdig: sysdig_secure_okta_ml_policy" +description: |- + Retrieves a Sysdig Secure Okta ML Policy. +--- + +# Resource: sysdig_secure_okta_ml_policy + +Retrieves the information of an existing Sysdig Secure Okta ML Policy. + +-> **Note:** Sysdig Terraform Provider is under rapid development at this point. If you experience any issue or discrepancy while using it, please make sure you have the latest version. If the issue persists, or you have a Feature Request to support an additional set of resources, please open a [new issue](https://github.com/sysdiglabs/terraform-provider-sysdig/issues/new) in the GitHub repository. + +## Example Usage + +```terraform +resource "sysdig_secure_okta_ml_policy" "policy" { + name = "Test Okta ML Policy 1" + description = "Test Okta ML Policy Description" + enabled = true + severity = 4 + + rule { + description = "Test Okta ML Rule Description" + + anomalous_console_login { + enabled = true + threshold = 1 + } +} +``` + +## Argument Reference + +* `name` - (Required) The name of the Secure managed policy. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The id for the policy. + +* `description` - The description for the managed policy. + +* `severity` - The severity of Secure policy. The accepted values + are: 0, 1, 2, 3 (High), 4, 5 (Medium), 6 (Low) and 7 (Info). + +* `enabled` - Whether the policy is enabled or not. + +* `runbook` - Customer provided url that provides a runbook for a given policy. + +* `scope` - The application scope for the policy. + +* `notification_channels` - IDs of the notification channels to send alerts to + when the policy is fired. + +### `rule` block + +The rule block is required and supports: + +* `description` - (Required) Rule description. +* `anomalous_console_login` - (Required) This attribute allows you to activate anomaly detection for logins and adjust its settings. + * `threshold` - (Required) Trigger at or above confidence level. From 9fd8297924ffc15380f1dced7c50c47e3fdf9020 Mon Sep 17 00:00:00 2001 From: Harsham Patel Date: Thu, 30 Oct 2025 10:08:22 -0700 Subject: [PATCH 2/6] Handle error and git ignore vscode --- .gitignore | 2 +- sysdig/resource_sysdig_secure_okta_ml_policy.go | 6 +++++- sysdig/tfresource.go | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index c4a42665..1605ac60 100644 --- a/.gitignore +++ b/.gitignore @@ -46,7 +46,7 @@ junit-report.xml # Binaries terraform-provider-sysdig oanc -.vscode/settings.json +.vscode/ # goland .run .run/ diff --git a/sysdig/resource_sysdig_secure_okta_ml_policy.go b/sysdig/resource_sysdig_secure_okta_ml_policy.go index ade2275d..75ae076e 100644 --- a/sysdig/resource_sysdig_secure_okta_ml_policy.go +++ b/sysdig/resource_sysdig_secure_okta_ml_policy.go @@ -142,7 +142,11 @@ func resourceSysdigOktaMLPolicyRead(ctx context.Context, d *schema.ResourceData, return diag.FromErr(err) } - id, _ := strconv.Atoi(d.Id()) + id, err := strconv.Atoi(d.Id()) + if err != nil { + return diag.FromErr(err) + } + policy, statusCode, err := client.GetCompositePolicyByID(ctx, id) if err != nil { if statusCode == http.StatusNotFound { diff --git a/sysdig/tfresource.go b/sysdig/tfresource.go index b9d476ec..9defc213 100644 --- a/sysdig/tfresource.go +++ b/sysdig/tfresource.go @@ -336,7 +336,9 @@ func setTFResourcePolicyRulesOktaML(d *schema.ResourceData, policy v2.PolicyRule }) } - _ = d.Set("rule", rules) + if err := d.Set("rule", rules); err != nil { + return err + } return nil } From c509dba6a12d9f9cdc20833c3817f25e5f617c95 Mon Sep 17 00:00:00 2001 From: Harsham Patel Date: Thu, 30 Oct 2025 10:17:30 -0700 Subject: [PATCH 3/6] Remove pointer and pass &policy --- sysdig/provider.go | 1 - sysdig/resource_sysdig_secure_okta_ml_policy.go | 8 ++++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/sysdig/provider.go b/sysdig/provider.go index 7c1fcc6e..694a47c9 100644 --- a/sysdig/provider.go +++ b/sysdig/provider.go @@ -152,7 +152,6 @@ func (p *SysdigProvider) Provider() *schema.Provider { "sysdig_secure_aws_ml_policy": resourceSysdigSecureAWSMLPolicy(), "sysdig_secure_okta_ml_policy": resourceSysdigSecureOktaMLPolicy(), - "sysdig_secure_cloud_account": resourceSysdigSecureCloudAccount(), "sysdig_secure_cloud_auth_account": resourceSysdigSecureCloudauthAccount(), "sysdig_secure_cloud_auth_account_component": resourceSysdigSecureCloudauthAccountComponent(), "sysdig_secure_cloud_auth_account_feature": resourceSysdigSecureCloudauthAccountFeature(), diff --git a/sysdig/resource_sysdig_secure_okta_ml_policy.go b/sysdig/resource_sysdig_secure_okta_ml_policy.go index 75ae076e..9a8a9a0b 100644 --- a/sysdig/resource_sysdig_secure_okta_ml_policy.go +++ b/sysdig/resource_sysdig_secure_okta_ml_policy.go @@ -72,16 +72,16 @@ func resourceSysdigSecureOktaMLPolicy() *schema.Resource { } func oktaMLPolicyFromResourceData(d *schema.ResourceData) (v2.PolicyRulesComposite, error) { - policy := &v2.PolicyRulesComposite{ + policy := v2.PolicyRulesComposite{ Policy: &v2.Policy{}, Rules: []*v2.RuntimePolicyRule{}, } - err := oktaMLPolicyReducer(policy, d) + err := oktaMLPolicyReducer(&policy, d) if err != nil { - return *policy, err + return policy, err } - return *policy, nil + return policy, nil } func oktaMLPolicyToResourceData(policy *v2.PolicyRulesComposite, d *schema.ResourceData) error { From 62d78099b214203709380efdc1783abdeb1cd856 Mon Sep 17 00:00:00 2001 From: Harsham Patel Date: Thu, 30 Oct 2025 17:06:48 -0700 Subject: [PATCH 4/6] Updated documentations --- .vscode/launch.json | 15 --------------- sysdig/tfresource.go | 2 -- website/docs/d/secure_aws_ml_policy.md | 2 +- website/docs/d/secure_okta_ml_policy.md | 2 +- website/docs/r/secure_aws_ml_policy.md | 3 ++- website/docs/r/secure_okta_ml_policy.md | 3 ++- 6 files changed, 6 insertions(+), 21 deletions(-) delete mode 100644 .vscode/launch.json diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 2ba986f6..00000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "chrome", - "request": "launch", - "name": "Launch Chrome against localhost", - "url": "http://localhost:8080", - "webRoot": "${workspaceFolder}" - } - ] -} \ No newline at end of file diff --git a/sysdig/tfresource.go b/sysdig/tfresource.go index 9defc213..bc9f9378 100644 --- a/sysdig/tfresource.go +++ b/sysdig/tfresource.go @@ -708,8 +708,6 @@ func setPolicyRulesOktaML(policy *v2.PolicyRulesComposite, d *schema.ResourceDat policy.Policy.Rules = []*v2.PolicyRule{} policy.Rules = []*v2.RuntimePolicyRule{} if _, ok := d.GetOk("rule"); ok { - // TODO: Iterate over a list of rules instead of hard-coding the index values - // TODO: Should we assume that only a single Malware rule can be attached to a policy? anomalousLogin := &v2.MLRuleThresholdAndSeverity{} if _, ok := d.GetOk("rule.0.anomalous_console_login"); ok { // TODO: Do not hardcode the indexes diff --git a/website/docs/d/secure_aws_ml_policy.md b/website/docs/d/secure_aws_ml_policy.md index 0b29c76b..7e20825d 100644 --- a/website/docs/d/secure_aws_ml_policy.md +++ b/website/docs/d/secure_aws_ml_policy.md @@ -50,5 +50,5 @@ The rule block is required and supports: * `description` - (Required) Rule description. * `anomalous_console_login` - (Required) This attribute allows you to activate anomaly detection for console logins and adjust its settings. - * `threshold` - (Required) Trigger at or above confidence level. + * `threshold` - (Required) Trigger at or above confidence level. Valid values are: 1 (High), 2 (Medium), 3 (Low). diff --git a/website/docs/d/secure_okta_ml_policy.md b/website/docs/d/secure_okta_ml_policy.md index 36764796..da9ea4e6 100644 --- a/website/docs/d/secure_okta_ml_policy.md +++ b/website/docs/d/secure_okta_ml_policy.md @@ -62,4 +62,4 @@ The rule block contains: * `anomalous_console_login` - Anomaly detection settings for logins. * `enabled` - Whether anomaly detection is enabled. - * `threshold` - Confidence level threshold for triggering alerts. + * `threshold` - Confidence level threshold for triggering alerts. Valid values are: 1 (High), 2 (Medium), 3 (Low). diff --git a/website/docs/r/secure_aws_ml_policy.md b/website/docs/r/secure_aws_ml_policy.md index ff97c8ad..276a36e2 100644 --- a/website/docs/r/secure_aws_ml_policy.md +++ b/website/docs/r/secure_aws_ml_policy.md @@ -61,5 +61,6 @@ The rule block is required and supports: * `description` - (Required) Rule description. * `anomalous_console_login` - (Required) This attribute allows you to activate anomaly detection for console logins and adjust its settings. - * `threshold` - (Required) Trigger at or above confidence level. + * `enabled` - (Optional) Whether anomaly detection is enabled. Defaults to `true`. + * `threshold` - (Required) Trigger at or above confidence level. Valid values are: 1 (High), 2 (Medium), 3 (Low). diff --git a/website/docs/r/secure_okta_ml_policy.md b/website/docs/r/secure_okta_ml_policy.md index eea22601..2d1bfac7 100644 --- a/website/docs/r/secure_okta_ml_policy.md +++ b/website/docs/r/secure_okta_ml_policy.md @@ -61,4 +61,5 @@ The rule block is required and supports: * `description` - (Required) Rule description. * `anomalous_console_login` - (Required) This attribute allows you to activate anomaly detection for logins and adjust its settings. - * `threshold` - (Required) Trigger at or above confidence level. + * `enabled` - (Optional) Whether anomaly detection is enabled. Defaults to `true`. + * `threshold` - (Required) Trigger at or above confidence level. Valid values are: 1 (High), 2 (Medium), 3 (Low). From 8443bcdcb6a8c98eb3c3515697bb23ff71300802 Mon Sep 17 00:00:00 2001 From: Harsham Patel Date: Thu, 30 Oct 2025 18:30:06 -0700 Subject: [PATCH 5/6] docs: update threshold descriptions to Default/High/Higher Changed threshold value descriptions from 'High/Medium/Low' to 'Default/High/Higher' for ML policies --- website/docs/d/secure_aws_ml_policy.md | 2 +- website/docs/d/secure_okta_ml_policy.md | 2 +- website/docs/r/secure_aws_ml_policy.md | 2 +- website/docs/r/secure_okta_ml_policy.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/website/docs/d/secure_aws_ml_policy.md b/website/docs/d/secure_aws_ml_policy.md index 7e20825d..013bb50d 100644 --- a/website/docs/d/secure_aws_ml_policy.md +++ b/website/docs/d/secure_aws_ml_policy.md @@ -50,5 +50,5 @@ The rule block is required and supports: * `description` - (Required) Rule description. * `anomalous_console_login` - (Required) This attribute allows you to activate anomaly detection for console logins and adjust its settings. - * `threshold` - (Required) Trigger at or above confidence level. Valid values are: 1 (High), 2 (Medium), 3 (Low). + * `threshold` - (Required) Trigger at or above confidence level. Valid values are: 1 (Default), 2 (High), 3 (Higher). diff --git a/website/docs/d/secure_okta_ml_policy.md b/website/docs/d/secure_okta_ml_policy.md index da9ea4e6..0c90f2b0 100644 --- a/website/docs/d/secure_okta_ml_policy.md +++ b/website/docs/d/secure_okta_ml_policy.md @@ -62,4 +62,4 @@ The rule block contains: * `anomalous_console_login` - Anomaly detection settings for logins. * `enabled` - Whether anomaly detection is enabled. - * `threshold` - Confidence level threshold for triggering alerts. Valid values are: 1 (High), 2 (Medium), 3 (Low). + * `threshold` - Confidence level threshold for triggering alerts. Valid values are: 1 (Default), 2 (High), 3 (Higher). diff --git a/website/docs/r/secure_aws_ml_policy.md b/website/docs/r/secure_aws_ml_policy.md index 276a36e2..515c59fa 100644 --- a/website/docs/r/secure_aws_ml_policy.md +++ b/website/docs/r/secure_aws_ml_policy.md @@ -62,5 +62,5 @@ The rule block is required and supports: * `description` - (Required) Rule description. * `anomalous_console_login` - (Required) This attribute allows you to activate anomaly detection for console logins and adjust its settings. * `enabled` - (Optional) Whether anomaly detection is enabled. Defaults to `true`. - * `threshold` - (Required) Trigger at or above confidence level. Valid values are: 1 (High), 2 (Medium), 3 (Low). + * `threshold` - (Required) Trigger at or above confidence level. Valid values are: 1 (Default), 2 (High), 3 (Higher). diff --git a/website/docs/r/secure_okta_ml_policy.md b/website/docs/r/secure_okta_ml_policy.md index 2d1bfac7..bdaf7e9e 100644 --- a/website/docs/r/secure_okta_ml_policy.md +++ b/website/docs/r/secure_okta_ml_policy.md @@ -62,4 +62,4 @@ The rule block is required and supports: * `description` - (Required) Rule description. * `anomalous_console_login` - (Required) This attribute allows you to activate anomaly detection for logins and adjust its settings. * `enabled` - (Optional) Whether anomaly detection is enabled. Defaults to `true`. - * `threshold` - (Required) Trigger at or above confidence level. Valid values are: 1 (High), 2 (Medium), 3 (Low). + * `threshold` - (Required) Trigger at or above confidence level. Valid values are: 1 (Default), 2 (High), 3 (Higher). From a8855e05a3c7e122db830e7e18ca06f9dc7bb7e3 Mon Sep 17 00:00:00 2001 From: Fede Barcelona Date: Mon, 3 Nov 2025 11:47:29 +0100 Subject: [PATCH 6/6] chore: empty commit to re-run CI