From f4a7fb621634239337f52231c523e4ecf2fc52d4 Mon Sep 17 00:00:00 2001 From: Fede Barcelona Date: Tue, 22 Jul 2025 11:15:27 +0200 Subject: [PATCH 1/4] feat: add vulnerability policy resource --- sysdig/internal/client/v2/sysdig.go | 34 +- .../client/v2/vulnerability_policy.go | 116 +++++++ .../client/v2/vulnerability_policy_model.go | 23 ++ sysdig/provider.go | 1 + ...urce_sysdig_secure_vulnerability_policy.go | 304 ++++++++++++++++++ ...sysdig_secure_vulnerability_policy_test.go | 86 +++++ website/docs/r/secure_vulnerability_policy.md | 59 ++++ 7 files changed, 608 insertions(+), 15 deletions(-) create mode 100644 sysdig/internal/client/v2/vulnerability_policy.go create mode 100644 sysdig/internal/client/v2/vulnerability_policy_model.go create mode 100644 sysdig/resource_sysdig_secure_vulnerability_policy.go create mode 100644 sysdig/resource_sysdig_secure_vulnerability_policy_test.go create mode 100644 website/docs/r/secure_vulnerability_policy.md diff --git a/sysdig/internal/client/v2/sysdig.go b/sysdig/internal/client/v2/sysdig.go index beb55e97a..65b092ebd 100644 --- a/sysdig/internal/client/v2/sysdig.go +++ b/sysdig/internal/client/v2/sysdig.go @@ -18,39 +18,43 @@ type SysdigRequest struct { type SysdigCommon interface { Common - GroupMappingInterface - GroupMappingConfigInterface + CustomRoleInterface CustomRolePermissionInterface - TeamServiceAccountInterface - IPFiltersInterface + GroupMappingConfigInterface + GroupMappingInterface IPFilteringSettingsInterface + IPFiltersInterface + TeamServiceAccountInterface } type SysdigMonitor interface { SysdigCommon MonitorCommon + CloudAccountMonitorInterface } type SysdigSecure interface { SysdigCommon SecureCommon - PolicyInterface - CompositePolicyInterface - RuleInterface - ListInterface - MacroInterface - DeprecatedScanningPolicyInterface - DeprecatedScanningPolicyAssignmentInterface - DeprecatedVulnerabilityExceptionListInterface - DeprecatedVulnerabilityExceptionInterface + CloudAccountSecureInterface - CloudauthAccountSecureInterface - OrganizationSecureInterface CloudauthAccountComponentSecureInterface CloudauthAccountFeatureSecureInterface + CloudauthAccountSecureInterface + CompositePolicyInterface + DeprecatedScanningPolicyAssignmentInterface + DeprecatedScanningPolicyInterface + DeprecatedVulnerabilityExceptionInterface + DeprecatedVulnerabilityExceptionListInterface + ListInterface + MacroInterface OnboardingSecureInterface + OrganizationSecureInterface + PolicyInterface + RuleInterface + VulnerabilityPolicyClient } func (sr *SysdigRequest) Request(ctx context.Context, method string, url string, payload io.Reader) (*http.Response, error) { diff --git a/sysdig/internal/client/v2/vulnerability_policy.go b/sysdig/internal/client/v2/vulnerability_policy.go new file mode 100644 index 000000000..621980d1c --- /dev/null +++ b/sysdig/internal/client/v2/vulnerability_policy.go @@ -0,0 +1,116 @@ +package v2 + +import ( + "context" + "errors" + "fmt" + "net/http" + "strconv" +) + +const ( + vulnerabilityPoliciesPath = "%s/secure/vulnerability/v1/policies" + vulnerabilityPolicyPath = "%s/secure/vulnerability/v1/policies/%s" +) + +type VulnerabilityPolicyClient interface { + CreateVulnerabilityPolicy(ctx context.Context, vulnerabilityPolicy VulnerabilityPolicy) (VulnerabilityPolicy, error) + GetVulnerabilityPolicyByID(ctx context.Context, vulnerabilityPolicyID string) (VulnerabilityPolicy, error) + UpdateVulnerabilityPolicy(ctx context.Context, vulnerabilityPolicy VulnerabilityPolicy) (VulnerabilityPolicy, error) + DeleteVulnerabilityPolicyByID(ctx context.Context, vulnerabilityPolicyID string) error +} + +func (c *Client) CreateVulnerabilityPolicy(ctx context.Context, vulnerabilityPolicy VulnerabilityPolicy) (policy VulnerabilityPolicy, err error) { + payload, err := Marshal(vulnerabilityPolicy) + if err != nil { + return VulnerabilityPolicy{}, err + } + + response, err := c.requester.Request(ctx, http.MethodPost, c.vulnerabilityPoliciesURL(), payload) + if err != nil { + return VulnerabilityPolicy{}, err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusCreated { + return VulnerabilityPolicy{}, c.ErrorFromResponse(response) + } + + return Unmarshal[VulnerabilityPolicy](response.Body) +} + +func (c *Client) GetVulnerabilityPolicyByID(ctx context.Context, vulnerabilityPolicyID string) (policy VulnerabilityPolicy, err error) { + response, err := c.requester.Request(ctx, http.MethodGet, c.vulnerabilityPolicyURL(vulnerabilityPolicyID), nil) + if err != nil { + return VulnerabilityPolicy{}, err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode != http.StatusOK { + return VulnerabilityPolicy{}, c.ErrorFromResponse(response) + } + + return Unmarshal[VulnerabilityPolicy](response.Body) +} + +func (c *Client) UpdateVulnerabilityPolicy(ctx context.Context, vulnerabilityPolicy VulnerabilityPolicy) (policy VulnerabilityPolicy, err error) { + if vulnerabilityPolicy.ID == nil { + return VulnerabilityPolicy{}, errors.New("policy id was null") + } + + payload, err := Marshal(vulnerabilityPolicy) + if err != nil { + return VulnerabilityPolicy{}, err + } + + idAsStr := strconv.Itoa(int(*vulnerabilityPolicy.ID)) + response, err := c.requester.Request(ctx, http.MethodPut, c.vulnerabilityPolicyURL(idAsStr), payload) + if err != nil { + return VulnerabilityPolicy{}, err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode != http.StatusOK { + return VulnerabilityPolicy{}, c.ErrorFromResponse(response) + } + + return Unmarshal[VulnerabilityPolicy](response.Body) +} + +func (c *Client) DeleteVulnerabilityPolicyByID(ctx context.Context, vulnerabilityPolicyID string) (err error) { + response, err := c.requester.Request(ctx, http.MethodDelete, c.vulnerabilityPolicyURL(vulnerabilityPolicyID), nil) + if err != nil { + return err + } + defer func() { + if dErr := response.Body.Close(); dErr != nil { + err = fmt.Errorf("unable to close response body: %w", dErr) + } + }() + + if response.StatusCode != http.StatusNoContent && response.StatusCode != http.StatusOK { + return c.ErrorFromResponse(response) + } + + return err +} + +func (c *Client) vulnerabilityPoliciesURL() string { + return fmt.Sprintf(vulnerabilityPoliciesPath, c.config.url) +} + +func (c *Client) vulnerabilityPolicyURL(vulnerabilityPolicyID string) string { + return fmt.Sprintf(vulnerabilityPolicyPath, c.config.url, vulnerabilityPolicyID) +} diff --git a/sysdig/internal/client/v2/vulnerability_policy_model.go b/sysdig/internal/client/v2/vulnerability_policy_model.go new file mode 100644 index 000000000..6b122df0b --- /dev/null +++ b/sysdig/internal/client/v2/vulnerability_policy_model.go @@ -0,0 +1,23 @@ +package v2 + +type VulnerabilityPolicy struct { + Bundles []Bundle `json:"bundles"` + Description string `json:"description"` + Name string `json:"name"` + Stages []Stage `json:"stages,omitempty"` + ID *int32 `json:"id",omitempty` + Identifier *string `json:"identifier",omitempty` +} + +type Bundle struct { + ID int64 `json:"id"` +} + +type Stage struct { + Name string `json:"name"` + Configuration []Configuration `json:"configuration",omitempty` +} + +type Configuration struct { + Scope string `json:"scope"` +} diff --git a/sysdig/provider.go b/sysdig/provider.go index 7e52960ef..8d0623b4a 100644 --- a/sysdig/provider.go +++ b/sysdig/provider.go @@ -199,6 +199,7 @@ func (p *SysdigProvider) Provider() *schema.Provider { "sysdig_secure_rule_syscall": resourceSysdigSecureRuleSyscall(), "sysdig_secure_team": resourceSysdigSecureTeam(), "sysdig_secure_vulnerability_accept_risk": resourceSysdigSecureVulnerabilityAcceptRisk(), + "sysdig_secure_vulnerability_policy": resourceSysdigSecureVulnerabilityPolicy(), "sysdig_secure_zone": resourceSysdigSecureZone(), }, DataSourcesMap: map[string]*schema.Resource{ diff --git a/sysdig/resource_sysdig_secure_vulnerability_policy.go b/sysdig/resource_sysdig_secure_vulnerability_policy.go new file mode 100644 index 000000000..1a767d408 --- /dev/null +++ b/sysdig/resource_sysdig_secure_vulnerability_policy.go @@ -0,0 +1,304 @@ +package sysdig + +import ( + "context" + "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 resourceSysdigSecureVulnerabilityPolicy() *schema.Resource { + timeout := 5 * time.Minute + + return &schema.Resource{ + CreateContext: resourceSysdigVulnerabilityPolicyCreate, + ReadContext: resourceSysdigVulnerabilityPolicyRead, + UpdateContext: resourceSysdigVulnerabilityPolicyUpdate, + DeleteContext: resourceSysdigVulnerabilityPolicyDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(timeout), + Delete: schema.DefaultTimeout(timeout), + Update: schema.DefaultTimeout(timeout), + Read: schema.DefaultTimeout(timeout), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: "Policy name", + }, + "description": { + Type: schema.TypeString, + Optional: true, + Description: "Policy description", + }, + "identifier": { + Type: schema.TypeString, + Computed: true, + Description: "External identifier", + }, + "bundles": { + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + + "stages": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + Description: "Stage name: pipeline, registry, admission_control o runtime", + ValidateDiagFunc: validation.ToDiagFunc( + validation.StringInSlice([]string{ + "pipeline", + "registry", + "runtime", + }, false)), + }, + "configuration": { + Type: schema.TypeSet, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "scope": { + Type: schema.TypeString, + Required: true, + Description: "Scope expression for this stage", + }, + }, + }, + }, + }, + }, + }, + }, + } +} + +func getSecureVulnerabilityPolicyClient(c SysdigClients) (v2.VulnerabilityPolicyClient, error) { + return c.sysdigSecureClientV2() +} + +func resourceSysdigVulnerabilityPolicyCreate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + client, err := getSecureVulnerabilityPolicyClient(meta.(SysdigClients)) + if err != nil { + return diag.FromErr(err) + } + + scanningPolicy, err := vulnerabilityPolicyFromResourceData(d) + if err != nil { + return diag.FromErr(err) + } + + scanningPolicy, err = client.CreateVulnerabilityPolicy(ctx, scanningPolicy) + if err != nil { + return diag.FromErr(err) + } + + vulnerabilityPolicyToResourceData(&scanningPolicy, d) + + return nil +} + +func resourceSysdigVulnerabilityPolicyUpdate(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + client, err := getSecureVulnerabilityPolicyClient(meta.(SysdigClients)) + if err != nil { + return diag.FromErr(err) + } + + scanningPolicy, err := vulnerabilityPolicyFromResourceData(d) + if err != nil { + return diag.FromErr(err) + } + + _, err = client.UpdateVulnerabilityPolicy(ctx, scanningPolicy) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func resourceSysdigVulnerabilityPolicyRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + client, err := getSecureVulnerabilityPolicyClient(meta.(SysdigClients)) + if err != nil { + return diag.FromErr(err) + } + + scanningPolicy, err := client.GetVulnerabilityPolicyByID(ctx, d.Id()) + if err != nil { + return diag.FromErr(err) + } + + vulnerabilityPolicyToResourceData(&scanningPolicy, d) + + return nil +} + +func resourceSysdigVulnerabilityPolicyDelete(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + client, err := getSecureVulnerabilityPolicyClient(meta.(SysdigClients)) + if err != nil { + return diag.FromErr(err) + } + + err = client.DeleteVulnerabilityPolicyByID(ctx, d.Id()) + if err != nil { + return diag.FromErr(err) + } + + return nil +} + +func vulnerabilityPolicyToResourceData(scanningPolicy *v2.VulnerabilityPolicy, d *schema.ResourceData) { + if scanningPolicy.ID == nil { + d.SetId("") // id is nil, let's destroy the resource + return + } + + d.SetId(strconv.Itoa(int(*scanningPolicy.ID))) + _ = d.Set("name", scanningPolicy.Name) + _ = d.Set("description", scanningPolicy.Description) + + if scanningPolicy.Identifier != nil { + _ = d.Set("identifier", *scanningPolicy.Identifier) + } + + _ = d.Set("bundles", vulnerabilityPolicyBundlesToData(scanningPolicy)) + + stages := vulnerabilityPolicyStagesToMap(scanningPolicy.Stages) + _ = d.Set("stages", stages) +} + +func vulnerabilityPolicyStagesToMap(policyStages []v2.Stage) []map[string]any { + var stages []map[string]any + + for _, stage := range policyStages { + var configsMap []map[string]any + + for _, stageconfig := range stage.Configuration { + newConfig := map[string]any{ + "scope": stageconfig.Scope, + } + configsMap = append(configsMap, newConfig) + } + + stages = append(stages, map[string]any{ + "name": stage.Name, + "configuration": configsMap, + }) + } + + return stages +} + +func vulnerabilityPolicyBundlesToData(scanningPolicy *v2.VulnerabilityPolicy) []string { + var bundles []string + + for _, policyBundle := range scanningPolicy.Bundles { + bundle := strconv.Itoa(int(policyBundle.ID)) + + bundles = append(bundles, bundle) + } + + return bundles +} + +func vulnerabilityPolicyFromResourceData(d *schema.ResourceData) (v2.VulnerabilityPolicy, error) { + stringPtr := func(d *schema.ResourceData, key string) *string { + if value, ok := d.GetOk(key); ok && value.(string) != "" { + valueAsString := value.(string) + return &valueAsString + } + return nil + } + + int32PtrFromID := func(d *schema.ResourceData) *int32 { + id := d.Id() + if id == "" { + return nil + } + + idAsInt, err := strconv.Atoi(id) + if err != nil { + return nil + } + + i32 := int32(idAsInt) + return &i32 + } + + bundles, err := vulnerabilityPolicyBundlesFromList(d.Get("bundles").(*schema.Set)) + if err != nil { + return v2.VulnerabilityPolicy{}, err + } + + stages, err := vulnerabilityPolicyStagesFromSet(d.Get("stages").(*schema.Set)) + if err != nil { + return v2.VulnerabilityPolicy{}, err + } + + return v2.VulnerabilityPolicy{ + ID: int32PtrFromID(d), + Identifier: stringPtr(d, "identifier"), + Name: d.Get("name").(string), + Description: d.Get("description").(string), + Bundles: bundles, + Stages: stages, + }, nil +} + +func vulnerabilityPolicyBundlesFromList(list *schema.Set) ([]v2.Bundle, error) { + var out []v2.Bundle + + for _, idRaw := range list.List() { + id, err := strconv.Atoi(idRaw.(string)) + if err != nil { + return nil, err + } + + out = append(out, v2.Bundle{ID: int64(id)}) + } + + return out, nil +} + +func vulnerabilityPolicyStagesFromSet(set *schema.Set) ([]v2.Stage, error) { + var out []v2.Stage + + for _, raw := range set.List() { + rawMap := raw.(map[string]any) + + out = append(out, v2.Stage{ + Name: rawMap["name"].(string), + Configuration: vulnerabilityPolicyConfigsFromSet(rawMap["configuration"].(*schema.Set)), + }) + } + + return out, nil +} + +func vulnerabilityPolicyConfigsFromSet(set *schema.Set) []v2.Configuration { + var out []v2.Configuration + + for _, raw := range set.List() { + rawMap := raw.(map[string]any) + + out = append(out, v2.Configuration{Scope: rawMap["scope"].(string)}) + } + + return out +} diff --git a/sysdig/resource_sysdig_secure_vulnerability_policy_test.go b/sysdig/resource_sysdig_secure_vulnerability_policy_test.go new file mode 100644 index 000000000..0ed667e56 --- /dev/null +++ b/sysdig/resource_sysdig_secure_vulnerability_policy_test.go @@ -0,0 +1,86 @@ +//go:build tf_acc_sysdig_secure || tf_acc_vulnerability_scanning + +package sysdig_test + +import ( + "fmt" + "os" + "testing" + + "github.com/draios/terraform-provider-sysdig/sysdig" + "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" +) + +func TestAccVulnerabilityPolicy(t *testing.T) { + random := func() string { return 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: minimalVulnerabilityPolicyConfig(random()), + }, + { + Config: vulnerabilityPolicyConfig(random()), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("sysdig_secure_vulnerability_policy.sample", "bundles.#", "1"), + resource.TestCheckResourceAttr("sysdig_secure_vulnerability_policy.sample", "bundles.0", "1"), + resource.TestCheckResourceAttr("sysdig_secure_vulnerability_policy.sample", "stages.#", "3"), + ), + }, + { + ResourceName: "sysdig_secure_vulnerability_policy.sample", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func minimalVulnerabilityPolicyConfig(suffix string) string { + return fmt.Sprintf(` +resource "sysdig_secure_vulnerability_policy" "sample" { + name = "TERRAFORM TEST %s" + bundles = [ "1" ] +} +`, suffix) +} + +func vulnerabilityPolicyConfig(suffix string) string { + return fmt.Sprintf(` +resource "sysdig_secure_vulnerability_policy" "sample" { + name = "TERRAFORM TEST %s" + description = "Acceptance test for bundles as ordered list %s" + + bundles = [ "1" ] + + stages { + name = "pipeline" + configuration { + scope = "pullstring = \"foobar\"" + } + } + stages { + name = "registry" + configuration { + scope = "pullstring != \"foobar\"" + } + } + stages { + name = "runtime" + configuration { + scope = "agent.tag.cluster = \"my-cluster\"" + } + } +} +`, suffix, suffix) +} diff --git a/website/docs/r/secure_vulnerability_policy.md b/website/docs/r/secure_vulnerability_policy.md new file mode 100644 index 000000000..b4e2ecc3d --- /dev/null +++ b/website/docs/r/secure_vulnerability_policy.md @@ -0,0 +1,59 @@ +--- +subcategory: "Sysdig Secure" +layout: "sysdig" +page_title: "Sysdig: sysdig_secure_vulnerability_policy" +description: |- + Creates a Sysdig Secure Vulnerability Policy. +--- + +# Resource: sysdig_secure_vulnerability_policy + +Creates a Sysdig Secure Vulnerability 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_vulnerability_policy" "vulnerability_policy_example" { + name = "Vulnerability Policy Name" + description = "Vulnerability Policy Description" + bundles = ["1"] + + stages { + name = "pipeline" + configuration { + scope = "container.image != ''" + } + } +} +``` + +## Argument Reference + +* `name` - (Required) The unique name of the vulnerability policy. +* `description` - (Optional) A description of the vulnerability policy. +* `bundles` - (Required) Set of bundle IDs associated with the policy. +* `stages` - (Optional) Set defining stages of vulnerability detection. + +### Stages block + +* `name` - (Required) Must be one of `pipeline`, `registry`, or `runtime`. +* `configuration` - (Optional) Configuration block for the stage. If no configuration is provided, it will apply to any workload in this stage. + +### Configuration block + +* `scope` - (Required) Scope expression defining the stage applicability. + +## Attributes Reference + +* `identifier` - The external identifier computed after creation. + +## Import + +Secure vulnerability policies can be imported using the policy ID, e.g.: + +``` +$ terraform import sysdig_secure_vulnerability_policy.example policy_123456 +``` + From a742e3c24ced738fb8a8482c4c7318ba0995e9d7 Mon Sep 17 00:00:00 2001 From: Fede Barcelona Date: Tue, 22 Jul 2025 11:27:40 +0200 Subject: [PATCH 2/4] fix: use parseint to solve atoi problems --- sysdig/resource_sysdig_secure_vulnerability_policy.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysdig/resource_sysdig_secure_vulnerability_policy.go b/sysdig/resource_sysdig_secure_vulnerability_policy.go index 1a767d408..af2d7f4dc 100644 --- a/sysdig/resource_sysdig_secure_vulnerability_policy.go +++ b/sysdig/resource_sysdig_secure_vulnerability_policy.go @@ -232,7 +232,7 @@ func vulnerabilityPolicyFromResourceData(d *schema.ResourceData) (v2.Vulnerabili return nil } - idAsInt, err := strconv.Atoi(id) + idAsInt, err := strconv.ParseInt(id, 10, 32) if err != nil { return nil } From b5be9bc078d776c262277c845db7c9621812d6ef Mon Sep 17 00:00:00 2001 From: Fede Barcelona Date: Tue, 22 Jul 2025 11:31:17 +0200 Subject: [PATCH 3/4] fix: correct the usage of json tags in model --- sysdig/internal/client/v2/vulnerability_policy_model.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sysdig/internal/client/v2/vulnerability_policy_model.go b/sysdig/internal/client/v2/vulnerability_policy_model.go index 6b122df0b..dffbaa385 100644 --- a/sysdig/internal/client/v2/vulnerability_policy_model.go +++ b/sysdig/internal/client/v2/vulnerability_policy_model.go @@ -5,8 +5,8 @@ type VulnerabilityPolicy struct { Description string `json:"description"` Name string `json:"name"` Stages []Stage `json:"stages,omitempty"` - ID *int32 `json:"id",omitempty` - Identifier *string `json:"identifier",omitempty` + ID *int32 `json:"id,omitempty"` + Identifier *string `json:"identifier,omitempty"` } type Bundle struct { @@ -15,7 +15,7 @@ type Bundle struct { type Stage struct { Name string `json:"name"` - Configuration []Configuration `json:"configuration",omitempty` + Configuration []Configuration `json:"configuration,omitempty"` } type Configuration struct { From fa63aa3b7cac46df3bd2b4ba3701fd01e38011c8 Mon Sep 17 00:00:00 2001 From: Fede Barcelona Date: Tue, 22 Jul 2025 11:44:53 +0200 Subject: [PATCH 4/4] fix(docs): add required line to attributes --- website/docs/r/secure_vulnerability_policy.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/website/docs/r/secure_vulnerability_policy.md b/website/docs/r/secure_vulnerability_policy.md index b4e2ecc3d..52c7a27fe 100644 --- a/website/docs/r/secure_vulnerability_policy.md +++ b/website/docs/r/secure_vulnerability_policy.md @@ -47,6 +47,8 @@ resource "sysdig_secure_vulnerability_policy" "vulnerability_policy_example" { ## Attributes Reference +In addition to all arguments above, the following attributes are exported: + * `identifier` - The external identifier computed after creation. ## Import