diff --git a/.envrc b/.envrc new file mode 100644 index 000000000..bacbcba87 --- /dev/null +++ b/.envrc @@ -0,0 +1,6 @@ +export TF_ACC=true +export TF_LOG=DEBUG +dotenv_if_exists .env # You can create a .env file with your env vars for this project. You can also use .secrets if you are using act. See the line below. +dotenv_if_exists .secrets # Used by [act](https://nektosact.com/) to load secrets into the pipelines +strict_env +env_vars_required SYSDIG_SECURE_API_TOKEN SYSDIG_MONITOR_API_TOKEN diff --git a/.envrc.template b/.envrc.template deleted file mode 100644 index 1de083324..000000000 --- a/.envrc.template +++ /dev/null @@ -1,12 +0,0 @@ -# export SYSDIG_SECURE_URL=https://secure.sysdig.com - -# credentials -export SYSDIG_SECURE_API_TOKEN= -export SYSDIG_MONITOR_API_TOKEN= - - -# whether to run local acc test -export TF_ACC=false - -# terraform log level -export TF_LOG=DEBUG \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1605ac60b..05a012097 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ *.dll *.exe .DS_Store -.envrc .env +.secrets .direnv/ example.tf terraform.tfplan @@ -54,4 +54,4 @@ oanc # Local test folder local-terraform-test/ dist/ -.secrets + diff --git a/sysdig/internal/client/v2/vulnerability_policy_model.go b/sysdig/internal/client/v2/vulnerability_policy_model.go index dffbaa385..20b30ad66 100644 --- a/sysdig/internal/client/v2/vulnerability_policy_model.go +++ b/sysdig/internal/client/v2/vulnerability_policy_model.go @@ -19,5 +19,7 @@ type Stage struct { } type Configuration struct { - Scope string `json:"scope"` + Scope string `json:"scope"` + Behaviour string `json:"behaviour,omitempty"` + UnknownImageAction string `json:"unknownImageAction,omitempty"` } diff --git a/sysdig/resource_sysdig_secure_vulnerability_policy.go b/sysdig/resource_sysdig_secure_vulnerability_policy.go index af2d7f4dc..6144ed98b 100644 --- a/sysdig/resource_sysdig_secure_vulnerability_policy.go +++ b/sysdig/resource_sysdig_secure_vulnerability_policy.go @@ -56,6 +56,10 @@ func resourceSysdigSecureVulnerabilityPolicy() *schema.Resource { "stages": { Type: schema.TypeSet, Optional: true, + Set: func(a any) int { + in := a.(map[string]any) + return schema.HashString(in["name"]) + }, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "name": { @@ -67,6 +71,7 @@ func resourceSysdigSecureVulnerabilityPolicy() *schema.Resource { "pipeline", "registry", "runtime", + "admission_control", }, false)), }, "configuration": { @@ -79,6 +84,18 @@ func resourceSysdigSecureVulnerabilityPolicy() *schema.Resource { Required: true, Description: "Scope expression for this stage", }, + "failure_action": { + Type: schema.TypeString, + Optional: true, + Description: "Required for `admission_control` stage only. Policy Failure Action. What should happen if the policy fails (aka: there's a rule vioation)", + ValidateFunc: validation.StringInSlice([]string{"reject", "warn"}, false), + }, + "unknown_image_action": { + Type: schema.TypeString, + Optional: true, + Description: "Required for `admission_control` stage only. Unknown Image Action. What should happen if the image is unknown.", + ValidateFunc: validation.StringInSlice([]string{"reject", "rejectAndScan", "warn"}, false), + }, }, }, }, @@ -193,6 +210,14 @@ func vulnerabilityPolicyStagesToMap(policyStages []v2.Stage) []map[string]any { newConfig := map[string]any{ "scope": stageconfig.Scope, } + + if stageconfig.Behaviour != "" { + newConfig["failure_action"] = stageconfig.Behaviour + } + + if stageconfig.UnknownImageAction != "" { + newConfig["unknown_image_action"] = stageconfig.UnknownImageAction + } configsMap = append(configsMap, newConfig) } @@ -297,7 +322,19 @@ func vulnerabilityPolicyConfigsFromSet(set *schema.Set) []v2.Configuration { for _, raw := range set.List() { rawMap := raw.(map[string]any) - out = append(out, v2.Configuration{Scope: rawMap["scope"].(string)}) + config := v2.Configuration{ + Scope: rawMap["scope"].(string), + } + + if raw, ok := rawMap["failure_action"]; ok { + config.Behaviour = raw.(string) + } + + if raw, ok := rawMap["unknown_image_action"]; ok { + config.UnknownImageAction = raw.(string) + } + + out = append(out, config) } return out diff --git a/sysdig/resource_sysdig_secure_vulnerability_policy_test.go b/sysdig/resource_sysdig_secure_vulnerability_policy_test.go index 2fbad888f..42734aefc 100644 --- a/sysdig/resource_sysdig_secure_vulnerability_policy_test.go +++ b/sysdig/resource_sysdig_secure_vulnerability_policy_test.go @@ -34,7 +34,7 @@ func TestAccVulnerabilityPolicy(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("sysdig_secure_vulnerability_policy.sample", "bundles.#", "2"), resource.TestCheckResourceAttr("sysdig_secure_vulnerability_policy.sample", "bundles.0", "1"), - resource.TestCheckResourceAttr("sysdig_secure_vulnerability_policy.sample", "stages.#", "3"), + resource.TestCheckResourceAttr("sysdig_secure_vulnerability_policy.sample", "stages.#", "4"), ), }, { @@ -90,6 +90,14 @@ resource "sysdig_secure_vulnerability_policy" "sample" { scope = "agent.tag.cluster = \"my-cluster\"" } } + stages { + name = "admission_control" + configuration { + scope = "not kubernetes.namespace.name in (\"sysdig\", \"sysdig-agent\")" + failure_action = "reject" + unknown_image_action = "rejectAndScan" + } + } } `, suffix, suffix, suffix) } diff --git a/website/docs/r/secure_vulnerability_policy.md b/website/docs/r/secure_vulnerability_policy.md index 52c7a27fe..4b096e3e1 100644 --- a/website/docs/r/secure_vulnerability_policy.md +++ b/website/docs/r/secure_vulnerability_policy.md @@ -26,6 +26,15 @@ resource "sysdig_secure_vulnerability_policy" "vulnerability_policy_example" { scope = "container.image != ''" } } + + stages { + name = "admission_control" + configuration { + scope = "kubernetes.cluster.name = 'my-cluster'" + failure_action = "reject" + unknown_image_action = "rejectAndScan" + } + } } ``` @@ -38,12 +47,14 @@ resource "sysdig_secure_vulnerability_policy" "vulnerability_policy_example" { ### Stages block -* `name` - (Required) Must be one of `pipeline`, `registry`, or `runtime`. +* `name` - (Required) Must be one of `pipeline`, `registry`, `runtime`, or `admission_control`. * `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. +* `failure_action` - (Optional) Required for `admission_control` stage only. Policy Failure Action. What should happen if the policy fails (aka: there's a rule vioation). Must be one of `reject` or `warn`. +* `unknown_image_action` - (Optional) Required for `admission_control` stage only. Unknown Image Action. What should happen if the image is unknown. Must be one of `reject`, `rejectAndScan`, or `warn`. ## Attributes Reference