From 514d341c6009e895af9186d5d5561206e5b98d3f Mon Sep 17 00:00:00 2001 From: Axton Grams Date: Fri, 14 Oct 2022 08:50:06 -0500 Subject: [PATCH] New Data Source: wiz_cloud_config_rules (#28) This change adds a new data source, wiz_cloud_config_rules, that can be used to filter and return details for Wiz Cloud Configuration Rules. --- docs/data-sources/cloud_config_rules.md | 138 +++ docs/index.md | 2 +- .../wiz_cloud_config_rules/data-source.tf | 19 + .../provider/data_source_cloud_accounts.go | 33 +- .../data_source_cloud_accounts_test.go | 8 +- .../data_source_cloud_configuration_rules.go | 823 ++++++++++++++++++ ...a_source_cloud_configuration_rules_test.go | 294 +++++++ internal/provider/provider.go | 5 +- internal/vendor/wiz.go | 89 +- templates/index.md.tmpl | 2 +- 10 files changed, 1377 insertions(+), 36 deletions(-) create mode 100644 docs/data-sources/cloud_config_rules.md create mode 100644 examples/data-sources/wiz_cloud_config_rules/data-source.tf create mode 100644 internal/provider/data_source_cloud_configuration_rules.go create mode 100644 internal/provider/data_source_cloud_configuration_rules_test.go diff --git a/docs/data-sources/cloud_config_rules.md b/docs/data-sources/cloud_config_rules.md new file mode 100644 index 0000000..4bf8e4c --- /dev/null +++ b/docs/data-sources/cloud_config_rules.md @@ -0,0 +1,138 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "wiz_cloud_config_rules Data Source - terraform-provider-wiz" +subcategory: "" +description: |- + Query cloud configuration rules. +--- + +# wiz_cloud_config_rules (Data Source) + +Query cloud configuration rules. + +## Example Usage + +```terraform +# get aws cloud configuration rules for access keys +data "wiz_cloud_config_rules" "aws_access_key" { + search = "Access key" + cloud_provider = [ + "AWS", + ] +} + +# get high and critical aws cloud configuration rules that have remediation +data "wiz_cloud_config_rules" "aws_critical" { + cloud_provider = [ + "AWS", + ] + severity = [ + "CRITICAL", + "HIGH", + ] + has_remediation = true +} +``` + + +## Schema + +### Optional + +- `cloud_provider` (List of String) Find CSPM rules related to cloud provider. + - Allowed values: + - GCP + - AWS + - Azure + - OCI + - Alibaba + - vSphere + - OpenShift + - Kubernetes +- `created_by` (List of String) Search rules by user. +- `enabled` (Boolean) CSPM Rule enabled status. +- `first` (Number) How many results to return + - Defaults to `500`. +- `framework_category` (List of String) Search rules by any of securityFramework | securitySubCategory | securityCategory. +- `function_as_control` (Boolean) Search by function as control. +- `has_auto_remediation` (Boolean) Rule has auto remediation. +- `has_remediation` (Boolean) Rule has remediation. +- `ids` (List of String) GetSearch by IDs. +- `is_opa_policy` (Boolean) Search by opaPolicy presence. +- `matcher_type` (List of String) Search rules by target native type. + - Allowed values: + - CLOUD + - TERRAFORM + - CLOUD_FORMATION + - KUBERNETES + - AZURE_RESOURCE_MANAGER + - DOCKER_FILE +- `project` (List of String) Search by project. +- `risk_equals_all` (List of String) +- `risk_equals_any` (List of String) +- `scope_account_ids` (List of String) Find CSPM rules applied on cloud account IDs. +- `search` (String) Free text search on CSPM name or resource ID. +- `service_type` (List of String) Find CSPM rules related to the service. + - Allowed values: + - AWS + - Azure + - GCP + - OCI + - Alibaba + - AKS + - EKS + - GKE + - Kubernetes + - OKE +- `severity` (List of String) CSPM Rule severity. + - Allowed values: + - INFORMATIONAL + - LOW + - MEDIUM + - HIGH + - CRITICAL +- `subject_entity_type` (List of String) Find rules by their entity type subject. +- `target_native_type` (List of String) Search rules by target native type. + +### Read-Only + +- `cloud_configuration_rules` (Set of Object) The returned cloud configuration rules. (see [below for nested schema](#nestedatt--cloud_configuration_rules)) +- `id` (String) Internal identifier for the data. + + +### Nested Schema for `cloud_configuration_rules` + +Read-Only: + +- `builtin` (Boolean) +- `cloud_provider` (String) +- `control_id` (String) +- `description` (String) +- `enabled` (Boolean) +- `external_references` (Set of Object) (see [below for nested schema](#nestedobjatt--cloud_configuration_rules--external_references)) +- `function_as_control` (Boolean) +- `graph_id` (String) +- `has_auto_remediation` (Boolean) +- `iac_matcher_ids` (List of String) +- `id` (String) +- `name` (String) +- `opa_policy` (String) +- `remediation_instructions` (String) +- `scope_accounts` (List of String) +- `security_sub_category_ids` (List of String) +- `service_type` (String) +- `severity` (String) +- `short_id` (String) +- `subject_entity_type` (String) +- `supports_nrt` (Boolean) +- `target_native_types` (List of String) + + +### Nested Schema for `cloud_configuration_rules.external_references` + +Read-Only: + +- `id` (String) +- `name` (String) + + diff --git a/docs/index.md b/docs/index.md index e421b84..23a0c11 100644 --- a/docs/index.md +++ b/docs/index.md @@ -6,7 +6,7 @@ description: |- # terraform-provider-wiz -The Wiz Terraform provider is designed to work with [Wiz](https://app.wiz.io/). +The Wiz Terraform provider is designed to work with [Wiz](https://wiz.io/). The "wiz" provider manages resources typically manually managed in the [Wiz web interface](https://app.wiz.io/). You must configure the provider with the proper credentials before you can use it. diff --git a/examples/data-sources/wiz_cloud_config_rules/data-source.tf b/examples/data-sources/wiz_cloud_config_rules/data-source.tf new file mode 100644 index 0000000..b5d88e7 --- /dev/null +++ b/examples/data-sources/wiz_cloud_config_rules/data-source.tf @@ -0,0 +1,19 @@ +# get aws cloud configuration rules for access keys +data "wiz_cloud_config_rules" "aws_access_key" { + search = "Access key" + cloud_provider = [ + "AWS", + ] +} + +# get high and critical aws cloud configuration rules that have remediation +data "wiz_cloud_config_rules" "aws_critical" { + cloud_provider = [ + "AWS", + ] + severity = [ + "CRITICAL", + "HIGH", + ] + has_remediation = true +} diff --git a/internal/provider/data_source_cloud_accounts.go b/internal/provider/data_source_cloud_accounts.go index 6d5e2e0..b474d3e 100644 --- a/internal/provider/data_source_cloud_accounts.go +++ b/internal/provider/data_source_cloud_accounts.go @@ -6,6 +6,7 @@ import ( "crypto/sha1" "encoding/hex" "fmt" + "sort" "github.com/hashicorp/terraform-plugin-log/tflog" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" @@ -322,7 +323,10 @@ func dataSourceWizCloudAccountsRead(ctx context.Context, d *schema.ResourceData, if b { filterBy.Search = utils.ConvertListToString(a.([]interface{})) } - filterBy.ProjectID = d.Get("project_id").(string) + a, b = d.GetOk("project_id") + if b { + filterBy.ProjectID = a.(string) + } a, b = d.GetOk("cloud_provider") if b { filterBy.CloudProvider = utils.ConvertListToString(a.([]interface{})) @@ -339,8 +343,14 @@ func dataSourceWizCloudAccountsRead(ctx context.Context, d *schema.ResourceData, if b { filterBy.ConnectorIssueID = utils.ConvertListToString(a.([]interface{})) } - filterBy.AssignedToProject = utils.ConvertBoolToPointer(d.Get("assigned_to_project").(bool)) - filterBy.HasMultipleConnectorSources = utils.ConvertBoolToPointer(d.Get("has_multiple_connector_sources").(bool)) + a, b = d.GetOk("assigned_to_project") + if b { + filterBy.AssignedToProject = utils.ConvertBoolToPointer(a.(bool)) + } + a, b = d.GetOk("has_multiple_connector_sources") + if b { + filterBy.HasMultipleConnectorSources = utils.ConvertBoolToPointer(a.(bool)) + } vars.FilterBy = filterBy // process the request @@ -356,8 +366,6 @@ func dataSourceWizCloudAccountsRead(ctx context.Context, d *schema.ResourceData, return append(diags, diag.FromErr(err)...) } - tflog.Debug(ctx, "Finished") - return diags } @@ -380,6 +388,11 @@ func flattenCloudAccounts(ctx context.Context, nodes *[]*vendor.CloudAccount) [] output = append(output, accountMap) } + // sort the return slice to avoid unwanted diffs + sort.Slice(output, func(i, j int) bool { + return output[i].(map[string]interface{})["id"].(string) < output[j].(map[string]interface{})["id"].(string) + }) + tflog.Debug(ctx, fmt.Sprintf("flattenCloudAccounts output: %s", utils.PrettyPrint(output))) return output @@ -396,6 +409,11 @@ func flattenProjectIDs(ctx context.Context, projects *[]*vendor.Project) []inter output = append(output, b.ID) } + // sort the return slice to avoid unwanted diffs + sort.Slice(output, func(i, j int) bool { + return output[i].(string) < output[j].(string) + }) + tflog.Debug(ctx, fmt.Sprintf("flattenProjectIDs output: %s", utils.PrettyPrint(output))) return output @@ -412,6 +430,11 @@ func flattenSourceConnectorIDs(ctx context.Context, connectors *[]vendor.Connect output = append(output, b.ID) } + // sort the return slice to avoid unwanted diffs + sort.Slice(output, func(i, j int) bool { + return output[i].(string) < output[j].(string) + }) + tflog.Debug(ctx, fmt.Sprintf("flattenSourceConnectorIDs output: %s", utils.PrettyPrint(output))) return output diff --git a/internal/provider/data_source_cloud_accounts_test.go b/internal/provider/data_source_cloud_accounts_test.go index aa698e2..566adbd 100644 --- a/internal/provider/data_source_cloud_accounts_test.go +++ b/internal/provider/data_source_cloud_accounts_test.go @@ -18,8 +18,8 @@ func TestFlattenCloudAccounts(t *testing.T) { "cloud_provider": "0767b7a3-d540-4b9c-8afd-a018aa7da0fb", "status": "9b6e7ae9-e0f6-4748-8171-a6b7a8f385ec", "linked_project_ids": []interface{}{ - "55e9138d-e48f-4155-a2ac-364eb00005db", "3d9ef88a-84f9-4a84-9a67-e5cdd28ad35f", + "55e9138d-e48f-4155-a2ac-364eb00005db", }, "source_connector_ids": []interface{}{ "7ac2f620-3882-4c35-91f0-7631eef430c6", @@ -68,8 +68,8 @@ func TestFlattenCloudAccounts(t *testing.T) { func TestFlattenProjectIDs(t *testing.T) { ctx := context.Background() expected := []interface{}{ - "b0a03462-697e-4ef8-af52-0e8122c6eb7f", "225697ef-8d21-42e1-8195-46d29b285ee6", + "b0a03462-697e-4ef8-af52-0e8122c6eb7f", "d24f22fb-088d-4586-ba8a-9524260f7427", } @@ -99,9 +99,9 @@ func TestFlattenProjectIDs(t *testing.T) { func TestFlattenSourceConnectorIDs(t *testing.T) { ctx := context.Background() expected := []interface{}{ - "d84b87ad-a38f-4ff1-9ee3-761521fbbaab", - "796def2c-70c6-4dc6-85a1-991616a98f4a", "317d6352-69e0-47e0-a280-76dd3e2e9659", + "796def2c-70c6-4dc6-85a1-991616a98f4a", + "d84b87ad-a38f-4ff1-9ee3-761521fbbaab", } var connectors = &[]vendor.Connector{ diff --git a/internal/provider/data_source_cloud_configuration_rules.go b/internal/provider/data_source_cloud_configuration_rules.go new file mode 100644 index 0000000..c4c1b02 --- /dev/null +++ b/internal/provider/data_source_cloud_configuration_rules.go @@ -0,0 +1,823 @@ +package provider + +import ( + "bytes" + "context" + "crypto/sha1" + "encoding/hex" + "fmt" + "sort" + + "github.com/hashicorp/terraform-plugin-log/tflog" + "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" + + "wiz.io/hashicorp/terraform-provider-wiz/internal" + "wiz.io/hashicorp/terraform-provider-wiz/internal/client" + "wiz.io/hashicorp/terraform-provider-wiz/internal/utils" + "wiz.io/hashicorp/terraform-provider-wiz/internal/vendor" +) + +func dataSourceWizCloudConfigurationRules() *schema.Resource { + return &schema.Resource{ + Description: "Query cloud configuration rules.", + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: "Internal identifier for the data.", + }, + "first": { + Type: schema.TypeInt, + Optional: true, + Default: 500, + Description: "How many results to return", + }, + "search": { + Type: schema.TypeString, + Optional: true, + Description: "Free text search on CSPM name or resource ID.", + }, + "scope_account_ids": { + Type: schema.TypeList, + Optional: true, + Description: "Find CSPM rules applied on cloud account IDs.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "cloud_provider": { + Type: schema.TypeList, + Optional: true, + Description: fmt.Sprintf("Find CSPM rules related to cloud provider.\n - Allowed values: %s", + utils.SliceOfStringToMDUList( + vendor.CloudProvider, + ), + ), + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: validation.ToDiagFunc( + validation.StringInSlice( + vendor.CloudProvider, + false, + ), + ), + }, + }, + "service_type": { + Type: schema.TypeList, + Optional: true, + Description: fmt.Sprintf("Find CSPM rules related to the service.\n - Allowed values: %s", + utils.SliceOfStringToMDUList( + vendor.CloudConfigurationRuleServiceType, + ), + ), + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: validation.ToDiagFunc( + validation.StringInSlice( + vendor.CloudConfigurationRuleServiceType, + false, + ), + ), + }, + }, + "subject_entity_type": { + Type: schema.TypeList, + Optional: true, + Description: "Find rules by their entity type subject.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "severity": { + Type: schema.TypeList, + Optional: true, + Description: fmt.Sprintf("CSPM Rule severity.\n - Allowed values: %s", + utils.SliceOfStringToMDUList( + vendor.Severity, + ), + ), + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: validation.ToDiagFunc( + validation.StringInSlice( + vendor.Severity, + false, + ), + ), + }, + }, + "enabled": { + Type: schema.TypeBool, + Optional: true, + Description: "CSPM Rule enabled status.", + }, + "has_auto_remediation": { + Type: schema.TypeBool, + Optional: true, + Description: "Rule has auto remediation.", + }, + "has_remediation": { + Type: schema.TypeBool, + Optional: true, + Description: "Rule has remediation.", + }, + "framework_category": { + Type: schema.TypeList, + Optional: true, + Description: "Search rules by any of securityFramework | securitySubCategory | securityCategory.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "target_native_type": { + Type: schema.TypeList, + Optional: true, + Description: "Search rules by target native type.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "created_by": { + Type: schema.TypeList, + Optional: true, + Description: "Search rules by user.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "is_opa_policy": { + Type: schema.TypeBool, + Optional: true, + Description: "Search by opaPolicy presence.", + }, + "project": { + Type: schema.TypeList, + Optional: true, + Description: "Search by project.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "matcher_type": { + Type: schema.TypeList, + Optional: true, + Description: fmt.Sprintf("Search rules by target native type.\n - Allowed values: %s", + utils.SliceOfStringToMDUList( + vendor.CloudConfigurationRuleMatcherTypeFilter, + ), + ), + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: validation.ToDiagFunc( + validation.StringInSlice( + vendor.CloudConfigurationRuleMatcherTypeFilter, + false, + ), + ), + }, + }, + "ids": { + Type: schema.TypeList, + Optional: true, + Description: "GetSearch by IDs.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "function_as_control": { + Type: schema.TypeBool, + Optional: true, + Description: "Search by function as control.", + }, + "risk_equals_any": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "risk_equals_all": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "cloud_configuration_rules": { + Type: schema.TypeSet, + Computed: true, + Description: "The returned cloud configuration rules.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + Description: "Wiz UUID.", + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "short_id": { + Type: schema.TypeString, + Computed: true, + }, + "description": { + Type: schema.TypeString, + Computed: true, + }, + "enabled": { + Type: schema.TypeBool, + Computed: true, + Description: "Rule enabled status.", + }, + "severity": { + Type: schema.TypeString, + Computed: true, + Description: "Rule severity will outcome to finding severity. This filed initial value is set as the severity of the CSPM rule.", + }, + "external_references": { + Type: schema.TypeSet, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + "target_native_types": { + Type: schema.TypeList, + Optional: true, + Description: "The identifier types of the objects targeted by this rule, as seen on the cloud provider service. e.g. 'ec2'.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "supports_nrt": { + Type: schema.TypeBool, + Computed: true, + Description: "Rule enabled status.", + }, + "subject_entity_type": { + Type: schema.TypeString, + Computed: true, + Description: "The rule subject entity type, as represented on Wiz Security Graph.", + }, + "cloud_provider": { + Type: schema.TypeString, + Computed: true, + Description: "The cloud provider this rule is relevant to.", + }, + "service_type": { + Type: schema.TypeString, + Computed: true, + Description: "The service this rule is relevant to.", + }, + "scope_accounts": { + Type: schema.TypeList, + Optional: true, + Description: "Scope of subscription IDs for automatically asses with this rule on. If set to empty array rule will run on all environment", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "security_sub_category_ids": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "builtin": { + Type: schema.TypeBool, + Computed: true, + Description: "Indication whether the rule is built-in or custom.", + }, + "opa_policy": { + Type: schema.TypeString, + Computed: true, + Description: "OPA rego policy that this rule runs. Undefined for built-in code based configuration rules.", + }, + "function_as_control": { + Type: schema.TypeBool, + Computed: true, + Description: "Make this rule also function as a control which means findings by this control will also trigger Issues.", + }, + "control_id": { + Type: schema.TypeString, + Computed: true, + Description: "In case this rule also functions as a control, this property will contain its details.", + }, + "graph_id": { + Type: schema.TypeString, + Computed: true, + Description: "The vertex id of this rule on the graph.", + }, + "has_auto_remediation": { + Type: schema.TypeBool, + Computed: true, + }, + "remediation_instructions": { + Type: schema.TypeString, + Computed: true, + }, + "iac_matcher_ids": { + Type: schema.TypeList, + Optional: true, + Description: "OPA rego policies that this rule runs (Cloud / IaC rules).", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + ReadContext: dataSourceWizCloudConfigurationRuleRead, + } +} + +// ReadCloudConfigurationRules struct +type ReadCloudConfigurationRules struct { + CloudConfigurationRules vendor.CloudConfigurationRuleConnection `json:"cloudConfigurationRules"` +} + +func dataSourceWizCloudConfigurationRuleRead(ctx context.Context, d *schema.ResourceData, m interface{}) (diags diag.Diagnostics) { + tflog.Info(ctx, "dataSourceWizCloudConfigurationRuleRead called...") + + // generate the id for this resource + // id must be deterministic, so the id is based on a hash of the search parameters + var identifier bytes.Buffer + + a, b := d.GetOk("first") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("search") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("scope_account_ids") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("service_type") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("subject_entity_type") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("severity") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("enabled") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("has_auto_remediation") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("has_remediation") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("framework_category") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("target_native_type") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("created_by") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("is_opa_policy") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("project") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("matcher_type") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("ids") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("function_as_control") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("risk_equals_any") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + a, b = d.GetOk("risk_equals_all") + if b { + identifier.WriteString(utils.PrettyPrint(a)) + } + + h := sha1.New() + h.Write([]byte(identifier.String())) + hashID := hex.EncodeToString(h.Sum(nil)) + + // Set the id + d.SetId(hashID) + + // define the graphql query + query := `query cloudConfigurationRules( + $filterBy: CloudConfigurationRuleFilters + $first: Int + $after: String + $orderBy: CloudConfigurationRuleOrder + ) { + cloudConfigurationRules( + filterBy: $filterBy + first: $first + after: $after + orderBy: $orderBy + ) { + nodes { + id + name + shortId + description + enabled + severity + externalReferences{ + id + name + } + targetNativeTypes + supportsNRT + subjectEntityType + cloudProvider + serviceType + scopeAccounts { + id + } + securitySubCategories { + id + } + builtin + opaPolicy + functionAsControl + control { + id + } + graphId + hasAutoRemediation + remediationInstructions + iacMatchers { + id + } + } + pageInfo { + hasNextPage + endCursor + } + totalCount + } + }` + + // set the resource parameters + err := d.Set("first", d.Get("first").(int)) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + err = d.Set("search", d.Get("search").(string)) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + err = d.Set("scope_account_ids", d.Get("scope_account_ids").([]interface{})) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + err = d.Set("cloud_provider", d.Get("cloud_provider").([]interface{})) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + err = d.Set("service_type", d.Get("service_type").([]interface{})) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + err = d.Set("subject_entity_type", d.Get("subject_entity_type").([]interface{})) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + err = d.Set("severity", d.Get("severity").([]interface{})) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + a, b = d.GetOk("enabled") + if b { + err = d.Set("enabled", a.(bool)) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + } + a, b = d.GetOk("has_auto_remediation") + if b { + err = d.Set("has_auto_remediation", a.(bool)) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + } + a, b = d.GetOk("has_remediation") + if b { + err = d.Set("has_remediation", a.(bool)) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + } + err = d.Set("framework_category", d.Get("framework_category").([]interface{})) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + err = d.Set("target_native_type", d.Get("target_native_type").([]interface{})) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + err = d.Set("created_by", d.Get("created_by").([]interface{})) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + a, b = d.GetOk("is_opa_policy") + if b { + err = d.Set("is_opa_policy", a.(bool)) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + } + err = d.Set("project", d.Get("project").([]interface{})) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + err = d.Set("matcher_type", d.Get("matcher_type").([]interface{})) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + err = d.Set("ids", d.Get("ids").([]interface{})) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + a, b = d.GetOk("function_as_control") + if b { + err = d.Set("function_as_control", a.(bool)) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + } + err = d.Set("risk_equals_any", d.Get("risk_equals_any").([]interface{})) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + err = d.Set("risk_equals_all", d.Get("risk_equals_all").([]interface{})) + if err != nil { + return append(diags, diag.FromErr(err)...) + } + + // populate the graphql variables + vars := &internal.QueryVariables{} + vars.First = d.Get("first").(int) + filterBy := &vendor.CloudConfigurationRuleFilters{} + a, b = d.GetOk("search") + if b { + filterBy.Search = a.(string) + } + a, b = d.GetOk("scope_account_ids") + if b { + filterBy.ScopeAccountIDs = utils.ConvertListToString(a.([]interface{})) + } + a, b = d.GetOk("cloud_provider") + if b { + filterBy.CloudProvider = utils.ConvertListToString(a.([]interface{})) + } + a, b = d.GetOk("service_type") + if b { + filterBy.ServiceType = utils.ConvertListToString(a.([]interface{})) + } + a, b = d.GetOk("subject_entity_type") + if b { + filterBy.SubjectEntityType = utils.ConvertListToString(a.([]interface{})) + } + a, b = d.GetOk("severity") + if b { + filterBy.Severity = utils.ConvertListToString(a.([]interface{})) + } + a, b = d.GetOk("enabled") + if b { + filterBy.Enabled = utils.ConvertBoolToPointer(a.(bool)) + } + a, b = d.GetOk("has_auto_remediation") + if b { + filterBy.HasAutoRemediation = utils.ConvertBoolToPointer(a.(bool)) + } + a, b = d.GetOk("has_remediation") + if b { + filterBy.HasRemediation = utils.ConvertBoolToPointer(a.(bool)) + } + a, b = d.GetOk("framework_category") + if b { + filterBy.FrameworkCategory = utils.ConvertListToString(a.([]interface{})) + } + a, b = d.GetOk("target_native_type") + if b { + filterBy.TargetNativeType = utils.ConvertListToString(a.([]interface{})) + } + a, b = d.GetOk("created_by") + if b { + filterBy.CreatedBy = utils.ConvertListToString(a.([]interface{})) + } + a, b = d.GetOk("is_opa_policy") + if b { + filterBy.IsOPAPolicy = utils.ConvertBoolToPointer(a.(bool)) + } + a, b = d.GetOk("project") + if b { + filterBy.Project = utils.ConvertListToString(a.([]interface{})) + } + a, b = d.GetOk("matcher_type") + if b { + filterBy.MatcherType = utils.ConvertListToString(a.([]interface{})) + } + a, b = d.GetOk("ids") + if b { + filterBy.ID = utils.ConvertListToString(a.([]interface{})) + } + a, b = d.GetOk("function_as_control") + if b { + filterBy.FunctionAsControl = utils.ConvertBoolToPointer(a.(bool)) + } + a, b = d.GetOk("risk_equals_any") + if b { + filterBy.RiskEqualsAny = utils.ConvertListToString(a.([]interface{})) + } + a, b = d.GetOk("risk_equals_all") + if b { + filterBy.RiskEqualsAll = utils.ConvertListToString(a.([]interface{})) + } + + vars.FilterBy = filterBy + + // process the request + data := &ReadCloudConfigurationRules{} + requestDiags := client.ProcessRequest(ctx, m, vars, data, query, "cloud_config_rules", "read") + diags = append(diags, requestDiags...) + if len(diags) > 0 { + return diags + } + + cloudConfigurationRules := flattenCloudConfigurationRules(ctx, &data.CloudConfigurationRules.Nodes) + if err := d.Set("cloud_configuration_rules", cloudConfigurationRules); err != nil { + return append(diags, diag.FromErr(err)...) + } + + return diags +} + +func flattenCloudConfigurationRules(ctx context.Context, nodes *[]*vendor.CloudConfigurationRule) []interface{} { + tflog.Info(ctx, "flattenCloudConfigurationRules called...") + tflog.Debug(ctx, fmt.Sprintf("CloudConfigurationRules: %s", utils.PrettyPrint(nodes))) + + // walk the slice and construct the list + var output = make([]interface{}, 0, 0) + for _, b := range *nodes { + tflog.Debug(ctx, fmt.Sprintf("b: %T %s", b, utils.PrettyPrint(b))) + ruleMap := make(map[string]interface{}) + ruleMap["id"] = b.ID + ruleMap["name"] = b.Name + ruleMap["short_id"] = b.ShortID + ruleMap["description"] = b.Description + ruleMap["enabled"] = *b.Enabled + ruleMap["severity"] = b.Severity + ruleMap["external_references"] = flattenExternalReferences(ctx, &b.ExternalReferences) + ruleMap["target_native_types"] = b.TargetNativeTypes + ruleMap["supports_nrt"] = *b.SupportsNRT + ruleMap["subject_entity_type"] = b.SubjectEntityType + ruleMap["cloud_provider"] = b.CloudProvider + ruleMap["service_type"] = b.ServiceType + ruleMap["scope_accounts"] = flattenScopeAccounts(ctx, &b.ScopeAccounts) + ruleMap["security_sub_category_ids"] = flattenSecuritySubCategoryIDs(ctx, &b.SecuritySubCategories) + ruleMap["builtin"] = *b.Builtin + ruleMap["opa_policy"] = b.OPAPolicy + ruleMap["function_as_control"] = *b.FunctionAsControl + ruleMap["control_id"] = b.Control.ID + ruleMap["graph_id"] = b.GraphID + ruleMap["has_auto_remediation"] = *b.HasAutoRemediation + ruleMap["remediation_instructions"] = b.RemediationInstructions + ruleMap["iac_matcher_ids"] = flattenIACMatcherIDs(ctx, &b.IACMatchers) + + output = append(output, ruleMap) + } + + tflog.Debug(ctx, fmt.Sprintf("flattenCloudConfigurationRules output: %s", utils.PrettyPrint(output))) + + return output +} + +func flattenExternalReferences(ctx context.Context, refs *[]*vendor.CloudConfigurationRuleExternalReference) []interface{} { + tflog.Info(ctx, "flattenExternalReferences called...") + tflog.Debug(ctx, fmt.Sprintf("External References: %s", utils.PrettyPrint(refs))) + + // walk the slice and construct the list + var output = make([]interface{}, 0, 0) + for _, b := range *refs { + tflog.Debug(ctx, fmt.Sprintf("b: %T %s", b, utils.PrettyPrint(b))) + refMap := make(map[string]interface{}) + refMap["id"] = b.ID + refMap["name"] = b.Name + output = append(output, refMap) + } + + // sort the return slice to avoid unwanted diffs + sort.Slice(output, func(i, j int) bool { + return output[i].(map[string]interface{})["id"].(string) < output[j].(map[string]interface{})["id"].(string) + }) + + tflog.Debug(ctx, fmt.Sprintf("flattenExternalReferences output: %s", utils.PrettyPrint(output))) + + return output +} + +func flattenScopeAccounts(ctx context.Context, accounts *[]*vendor.CloudAccount) []interface{} { + tflog.Info(ctx, "flattenScopeAccounts called...") + tflog.Debug(ctx, fmt.Sprintf("ScopeAccounts: %s", utils.PrettyPrint(accounts))) + + // walk the slice and construct the list + var output = make([]interface{}, 0, 0) + for _, b := range *accounts { + tflog.Debug(ctx, fmt.Sprintf("b: %T %s", b, utils.PrettyPrint(b))) + output = append(output, b.ID) + } + + // sort the return slice to avoid unwanted diffs + sort.Slice(output, func(i, j int) bool { + return output[i].(string) < output[j].(string) + }) + + tflog.Debug(ctx, fmt.Sprintf("flattenScopeAccounts output: %s", utils.PrettyPrint(output))) + + return output +} + +func flattenSecuritySubCategoryIDs(ctx context.Context, subCats *[]*vendor.SecuritySubCategory) []interface{} { + tflog.Info(ctx, "flattenSecuritySubCategoryIDs called...") + tflog.Debug(ctx, fmt.Sprintf("SecuritySubCategories: %s", utils.PrettyPrint(subCats))) + + // walk the slice and construct the list + var output = make([]interface{}, 0, 0) + for _, b := range *subCats { + tflog.Debug(ctx, fmt.Sprintf("b: %T %s", b, utils.PrettyPrint(b))) + output = append(output, b.ID) + } + + // sort the return slice to avoid unwanted diffs + sort.Slice(output, func(i, j int) bool { + return output[i].(string) < output[j].(string) + }) + + tflog.Debug(ctx, fmt.Sprintf("flattenSecuritySubCategoryIDs output: %s", utils.PrettyPrint(output))) + + return output +} + +func flattenIACMatcherIDs(ctx context.Context, matchers *[]*vendor.CloudConfigurationRuleMatcher) []interface{} { + tflog.Info(ctx, "flattenIACMatchers called...") + tflog.Debug(ctx, fmt.Sprintf("flattenIACMatchers: %s", utils.PrettyPrint(matchers))) + + // walk the slice and construct the list + var output = make([]interface{}, 0, 0) + for _, b := range *matchers { + tflog.Debug(ctx, fmt.Sprintf("b: %T %s", b, utils.PrettyPrint(b))) + output = append(output, b.ID) + } + + // sort the return slice to avoid unwanted diffs + sort.Slice(output, func(i, j int) bool { + return output[i].(string) < output[j].(string) + }) + + tflog.Debug(ctx, fmt.Sprintf("flattenIACMatchers output: %s", utils.PrettyPrint(output))) + + return output +} diff --git a/internal/provider/data_source_cloud_configuration_rules_test.go b/internal/provider/data_source_cloud_configuration_rules_test.go new file mode 100644 index 0000000..5bca7af --- /dev/null +++ b/internal/provider/data_source_cloud_configuration_rules_test.go @@ -0,0 +1,294 @@ +package provider + +import ( + "context" + "reflect" + "testing" + + "wiz.io/hashicorp/terraform-provider-wiz/internal/utils" + "wiz.io/hashicorp/terraform-provider-wiz/internal/vendor" +) + +func TestFlattenCloudConfigurationRules(t *testing.T) { + ctx := context.Background() + expected := []interface{}{ + map[string]interface{}{ + "id": "efc0d7e9-6a84-45f6-869c-529e337db6a8", + "name": "1d401010-0e50-4101-93c7-35b7f9226997", + "short_id": "ce84a427-7358-4fb8-853e-29fbdd4f3f55", + "description": "27669d80-612d-4e25-9c85-369625e2e990", + "enabled": false, + "severity": "565a7bb8-9f08-4e4f-96e0-da5af64e446a", + "target_native_types": []string{ + "a3f18510-600c-42a0-854a-117e83965f31", + "5bcf4cca-8bc1-46bf-8dbc-404486397885", + "d88ccf3b-3c58-4209-b2cb-57291512b093", + }, + "supports_nrt": false, + "subject_entity_type": "c53b5b06-5565-48e4-9ad7-2ecdb9596681", + "cloud_provider": "62c7de2d-d884-4b68-ae8b-f920ed1d60ba", + "service_type": "d65d3e25-36ed-45db-bf6b-50dc91c2bfc3", + "builtin": false, + "opa_policy": "49d5692f-7681-435d-8eb5-e5f22758ffb2", + "function_as_control": false, + "control_id": "ef708a85-0c78-4a50-b5eb-f44501dc5fc2", + "graph_id": "a81dc546-e3e3-4fbc-83c4-0ed5edbfa0c9", + "has_auto_remediation": false, + "remediation_instructions": "eb3e8071-49dd-4679-90d6-46bdf4387ee8", + "external_references": []interface{}{ + map[string]interface{}{ + "id": "0bbe2b15-31f1-4786-b2b9-c57704c10fbf", + "name": "7afbbec4-76c6-40e2-aeda-24e89f616df0", + }, + map[string]interface{}{ + "id": "43960b7b-09b3-4db7-90e7-7ad471071ba2", + "name": "0bb079f6-d315-4432-9192-d64a30c2cf0f", + }, + map[string]interface{}{ + "id": "f60d29dd-a16f-4fc0-949b-981b95dcdc16", + "name": "8feb5283-1e99-4ba5-b963-1ad631632be3", + }, + }, + "scope_accounts": []interface{}{ + "42cecee6-45ec-41d0-8d66-b0571e2b6f62", + "868eb547-5b76-4b5e-b9a1-9aecec79846d", + "a9caf002-b075-43e9-b1cb-9cce1c809083", + }, + "security_sub_category_ids": []interface{}{ + "26b40cb3-5730-4097-a61f-c12ed69970bc", + "49817d03-5a33-4c52-b7bc-51d800d173de", + "83abe403-dc4d-43a1-b5e5-8a6d4b9f5182", + }, + "iac_matcher_ids": []interface{}{ + "4256c551-a971-4fd6-948c-d883c4964fae", + "4d5e2d5c-1157-487b-b9c1-7aa10bc83f83", + "56344421-3a12-42da-9c83-8377e3420733", + }, + }, + } + + var configRules = &[]*vendor.CloudConfigurationRule{ + { + Builtin: utils.ConvertBoolToPointer(false), + CloudProvider: "62c7de2d-d884-4b68-ae8b-f920ed1d60ba", + Control: &vendor.Control{ + ID: "ef708a85-0c78-4a50-b5eb-f44501dc5fc2", + }, + CreatedBy: &vendor.User{ + ID: "7aa9f806-18b2-48fd-83d1-2c151d462ea7", + }, + Description: "27669d80-612d-4e25-9c85-369625e2e990", + Enabled: utils.ConvertBoolToPointer(false), + ExternalReferences: []*vendor.CloudConfigurationRuleExternalReference{ + { + ID: "0bbe2b15-31f1-4786-b2b9-c57704c10fbf", + Name: "7afbbec4-76c6-40e2-aeda-24e89f616df0", + }, + { + ID: "f60d29dd-a16f-4fc0-949b-981b95dcdc16", + Name: "8feb5283-1e99-4ba5-b963-1ad631632be3", + }, + { + ID: "43960b7b-09b3-4db7-90e7-7ad471071ba2", + Name: "0bb079f6-d315-4432-9192-d64a30c2cf0f", + }, + }, + FunctionAsControl: utils.ConvertBoolToPointer(false), + GraphID: "a81dc546-e3e3-4fbc-83c4-0ed5edbfa0c9", + HasAutoRemediation: utils.ConvertBoolToPointer(false), + IACMatchers: []*vendor.CloudConfigurationRuleMatcher{ + { + ID: "4d5e2d5c-1157-487b-b9c1-7aa10bc83f83", + }, + { + ID: "4256c551-a971-4fd6-948c-d883c4964fae", + }, + { + ID: "56344421-3a12-42da-9c83-8377e3420733", + }, + }, + ID: "efc0d7e9-6a84-45f6-869c-529e337db6a8", + Name: "1d401010-0e50-4101-93c7-35b7f9226997", + OPAPolicy: "49d5692f-7681-435d-8eb5-e5f22758ffb2", + RemediationInstructions: "eb3e8071-49dd-4679-90d6-46bdf4387ee8", + ScopeAccounts: []*vendor.CloudAccount{ + { + ID: "42cecee6-45ec-41d0-8d66-b0571e2b6f62", + }, + { + ID: "a9caf002-b075-43e9-b1cb-9cce1c809083", + }, + { + ID: "868eb547-5b76-4b5e-b9a1-9aecec79846d", + }, + }, + SecuritySubCategories: []*vendor.SecuritySubCategory{ + { + ID: "49817d03-5a33-4c52-b7bc-51d800d173de", + }, + { + ID: "83abe403-dc4d-43a1-b5e5-8a6d4b9f5182", + }, + { + ID: "26b40cb3-5730-4097-a61f-c12ed69970bc", + }, + }, + ServiceType: "d65d3e25-36ed-45db-bf6b-50dc91c2bfc3", + Severity: "565a7bb8-9f08-4e4f-96e0-da5af64e446a", + ShortID: "ce84a427-7358-4fb8-853e-29fbdd4f3f55", + SubjectEntityType: "c53b5b06-5565-48e4-9ad7-2ecdb9596681", + SupportsNRT: utils.ConvertBoolToPointer(false), + TargetNativeTypes: []string{ + "a3f18510-600c-42a0-854a-117e83965f31", + "5bcf4cca-8bc1-46bf-8dbc-404486397885", + "d88ccf3b-3c58-4209-b2cb-57291512b093", + }, + }, + } + + flattened := flattenCloudConfigurationRules(ctx, configRules) + + if !reflect.DeepEqual(flattened, expected) { + t.Fatalf( + "Got:\n\n%#v\n\nExpected:\n\n%#v\n", + flattened, + expected, + ) + } +} + +func TestFlattenExternalReferences(t *testing.T) { + ctx := context.Background() + expected := []interface{}{ + map[string]interface{}{ + "id": "39475a03-cba0-4aa3-867d-41494b9c4ad7", + "name": "7f5fa936-402f-4885-8b79-874ce3db8fb2", + }, + map[string]interface{}{ + "id": "6362a2a5-a7fc-48fd-9f38-f5a1e9c560d8", + "name": "284aab9b-88a5-4e13-a182-212de84989af", + }, + map[string]interface{}{ + "id": "9c5d545a-bcb2-41ac-89f9-7dcca90483b7", + "name": "b9f72ab5-ac09-4f5b-a57f-6691c55bcbdb", + }, + } + + var refs = &[]*vendor.CloudConfigurationRuleExternalReference{ + { + ID: "6362a2a5-a7fc-48fd-9f38-f5a1e9c560d8", + Name: "284aab9b-88a5-4e13-a182-212de84989af", + }, + { + ID: "9c5d545a-bcb2-41ac-89f9-7dcca90483b7", + Name: "b9f72ab5-ac09-4f5b-a57f-6691c55bcbdb", + }, + { + ID: "39475a03-cba0-4aa3-867d-41494b9c4ad7", + Name: "7f5fa936-402f-4885-8b79-874ce3db8fb2", + }, + } + + flattened := flattenExternalReferences(ctx, refs) + + if !reflect.DeepEqual(flattened, expected) { + t.Fatalf( + "Got:\n\n%#v\n\nExpected:\n\n%#v\n", + flattened, + expected, + ) + } +} + +func TestFlattenScopeAccounts(t *testing.T) { + ctx := context.Background() + expected := []interface{}{ + "39475a03-cba0-4aa3-867d-41494b9c4ad7", + "6362a2a5-a7fc-48fd-9f38-f5a1e9c560d8", + "9c5d545a-bcb2-41ac-89f9-7dcca90483b7", + } + + var accounts = &[]*vendor.CloudAccount{ + { + ID: "6362a2a5-a7fc-48fd-9f38-f5a1e9c560d8", + }, + { + ID: "9c5d545a-bcb2-41ac-89f9-7dcca90483b7", + }, + { + ID: "39475a03-cba0-4aa3-867d-41494b9c4ad7", + }, + } + + flattened := flattenScopeAccounts(ctx, accounts) + + if !reflect.DeepEqual(flattened, expected) { + t.Fatalf( + "Got:\n\n%#v\n\nExpected:\n\n%#v\n", + flattened, + expected, + ) + } +} + +func TestFlattenSecuritySubCategoryIDs(t *testing.T) { + ctx := context.Background() + expected := []interface{}{ + "39475a03-cba0-4aa3-867d-41494b9c4ad7", + "6362a2a5-a7fc-48fd-9f38-f5a1e9c560d8", + "9c5d545a-bcb2-41ac-89f9-7dcca90483b7", + } + + var cats = &[]*vendor.SecuritySubCategory{ + { + ID: "6362a2a5-a7fc-48fd-9f38-f5a1e9c560d8", + }, + { + ID: "9c5d545a-bcb2-41ac-89f9-7dcca90483b7", + }, + { + ID: "39475a03-cba0-4aa3-867d-41494b9c4ad7", + }, + } + + flattened := flattenSecuritySubCategoryIDs(ctx, cats) + + if !reflect.DeepEqual(flattened, expected) { + t.Fatalf( + "Got:\n\n%#v\n\nExpected:\n\n%#v\n", + flattened, + expected, + ) + } +} + +func TestFlattenIACMatcherIDs(t *testing.T) { + ctx := context.Background() + expected := []interface{}{ + "39475a03-cba0-4aa3-867d-41494b9c4ad7", + "6362a2a5-a7fc-48fd-9f38-f5a1e9c560d8", + "9c5d545a-bcb2-41ac-89f9-7dcca90483b7", + } + + var matchers = &[]*vendor.CloudConfigurationRuleMatcher{ + { + ID: "6362a2a5-a7fc-48fd-9f38-f5a1e9c560d8", + }, + { + ID: "9c5d545a-bcb2-41ac-89f9-7dcca90483b7", + }, + { + ID: "39475a03-cba0-4aa3-867d-41494b9c4ad7", + }, + } + + flattened := flattenIACMatcherIDs(ctx, matchers) + + if !reflect.DeepEqual(flattened, expected) { + t.Fatalf( + "Got:\n\n%#v\n\nExpected:\n\n%#v\n", + flattened, + expected, + ) + } +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 4588a33..6243402 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -249,8 +249,9 @@ yLyKQXhw2W2Xs0qLeC1etA+jTGDK4UfLeC0SF7FSi8o5LL21L8IzApar2pR/ }, }, DataSourcesMap: map[string]*schema.Resource{ - "wiz_cloud_accounts": dataSourceWizCloudAccounts(), - "wiz_organizations": dataSourceWizOrganizations(), + "wiz_cloud_accounts": dataSourceWizCloudAccounts(), + "wiz_cloud_config_rules": dataSourceWizCloudConfigurationRules(), + "wiz_organizations": dataSourceWizOrganizations(), }, ResourcesMap: map[string]*schema.Resource{ "wiz_automation_action": resourceWizAutomationAction(), diff --git a/internal/vendor/wiz.go b/internal/vendor/wiz.go index 7bf3159..af70605 100644 --- a/internal/vendor/wiz.go +++ b/internal/vendor/wiz.go @@ -1149,28 +1149,30 @@ var CloudConfigurationRuleServiceType = []string{ // CloudConfigurationRule struct -- updates type CloudConfigurationRule struct { - Builtin *bool `json:"builtin"` - CloudProvider string `json:"cloudProvider,omitempty"` // enum CloudProvider - Control *Control `json:"control,omitempty"` - CreatedBy *User `json:"createdBy,omitempty"` - Description string `json:"description,omitempty"` - Enabled *bool `json:"enabled"` - FunctionAsControl *bool `json:"functionAsControl"` - GraphID string `json:"graphId"` - HasAutoRemediation *bool `json:"hasAutoRemediation"` - IACMatchers []*CloudConfigurationRuleMatcher `json:"iacMatchers,omitempty"` - ID string `json:"id"` - Name string `json:"name"` - OPAPolicy string `json:"opaPolicy,omitempty"` - RemediationInstructions string `json:"remediationInstructions,omitempty"` - ScopeAccounts []*CloudAccount `json:"scopeAccounts"` // removed omitempty - SecuritySubCategories []*SecuritySubCategory `json:"securitySubCategories"` - ServiceType string `json:"serviceType,omitempty"` // enum CloudConfigurationRuleServiceType - Severity string `json:"severity"` // enum Severity - ShortID string `json:"shortId"` - SupportsNRT *bool `json:"supportsNRT"` - TargetNativeType string `json:"targetNativeType,omitempty"` - TargetNativeTypes []string `json:"targetNativeTypes,omitempty"` + Builtin *bool `json:"builtin"` + CloudProvider string `json:"cloudProvider,omitempty"` // enum CloudProvider + Control *Control `json:"control,omitempty"` + CreatedBy *User `json:"createdBy,omitempty"` + Description string `json:"description,omitempty"` + Enabled *bool `json:"enabled"` + ExternalReferences []*CloudConfigurationRuleExternalReference `json:"externalReferences,omitempty"` + FunctionAsControl *bool `json:"functionAsControl"` + GraphID string `json:"graphId"` + HasAutoRemediation *bool `json:"hasAutoRemediation"` + IACMatchers []*CloudConfigurationRuleMatcher `json:"iacMatchers,omitempty"` + ID string `json:"id"` + Name string `json:"name"` + OPAPolicy string `json:"opaPolicy,omitempty"` + RemediationInstructions string `json:"remediationInstructions,omitempty"` + ScopeAccounts []*CloudAccount `json:"scopeAccounts"` // removed omitempty + SecuritySubCategories []*SecuritySubCategory `json:"securitySubCategories"` + ServiceType string `json:"serviceType,omitempty"` // enum CloudConfigurationRuleServiceType + Severity string `json:"severity"` // enum Severity + ShortID string `json:"shortId"` + SubjectEntityType string `json:"subjectEntityType"` + SupportsNRT *bool `json:"supportsNRT"` + TargetNativeType string `json:"targetNativeType,omitempty"` + TargetNativeTypes []string `json:"targetNativeTypes,omitempty"` } // SecurityFramework struct -- updates @@ -1830,7 +1832,7 @@ type CloudConfigurationRuleFilters struct { CloudProvider []string `json:"cloudProvider,omitempty"` // enum CloudProvider ServiceType []string `json:"serviceType,omitempty"` // enum CloudConfigurationRuleServiceType SubjectEntityType []string `json:"subjectEntityType,omitempty"` // enum GraphEntityTypeValue - Severity string `json:"severity,omitempty"` // enum Severity + Severity []string `json:"severity,omitempty"` // enum Severity Enabled *bool `json:"enabled,omitempty"` HasAutoRemediation *bool `json:"hasAutoRemediation,omitempty"` HasRemediation *bool `json:"hasRemediation,omitempty"` @@ -2117,3 +2119,44 @@ type CloudAccountEdge struct { Cursor string `json:"cursor"` Node CloudAccount `json:"node"` } + +// CloudConfigurationRuleOrder struct +type CloudConfigurationRuleOrder struct { + Direction string `json:"direction"` // enum OrderDirection + Field string `json:"field"` // enum CloudConfigurationRuleOrderField +} + +// OrderDirection enum +var OrderDirection = []string{ + "ASC", + "DESC", +} + +// CloudConfigurationRuleOrderField enum +var CloudConfigurationRuleOrderField = []string{ + "FAILED_CHECK_COUNT", + "SEVERITY", + "NAME", +} + +// CloudConfigurationRuleConnection struct +type CloudConfigurationRuleConnection struct { + AnalyticsUpdatedAt string `json:"analyticsUpdatedAt"` + Edges []*CloudConfigurationRuleEdge `json:"edges,omitempty"` + EnabledAsControlCount int `json:"enabledAsControlCount"` + Nodes []*CloudConfigurationRule `json:"nodes,omitempty"` + PageInfo PageInfo `json:"pageInfo"` + TotalCount int `json:"totalCount"` +} + +// CloudConfigurationRuleEdge struct +type CloudConfigurationRuleEdge struct { + Cursor string `json:"cursor"` + Node CloudConfigurationRule `json:"node"` +} + +// CloudConfigurationRuleExternalReference struct +type CloudConfigurationRuleExternalReference struct { + ID string `json:"id"` + Name string `json:"name"` +} diff --git a/templates/index.md.tmpl b/templates/index.md.tmpl index ac0316f..da52a97 100644 --- a/templates/index.md.tmpl +++ b/templates/index.md.tmpl @@ -6,7 +6,7 @@ description: |- # {{.ProviderName}} -The Wiz Terraform provider is designed to work with [Wiz](https://app.wiz.io/). +The Wiz Terraform provider is designed to work with [Wiz](https://wiz.io/). The "wiz" provider manages resources typically manually managed in the [Wiz web interface](https://app.wiz.io/). You must configure the provider with the proper credentials before you can use it.