Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions docs/data-sources/alb_waf_configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "stackit_alb_waf_configuration Data Source - stackit"
subcategory: ""
description: |-
ALB WAF Custom Rule Group resource schema. Uses the default_region specified in the provider configuration as a fallback in case no region is defined on resource level.
~> This resource is in beta and may be subject to breaking changes in the future. Use with caution. See our guide https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources for how to opt-in to use beta resources.
---

# stackit_alb_waf_configuration (Data Source)

ALB WAF Custom Rule Group resource schema. Uses the `default_region` specified in the provider configuration as a fallback in case no `region` is defined on resource level.

~> This resource is in beta and may be subject to breaking changes in the future. Use with caution. See our [guide](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources) for how to opt-in to use beta resources.

## Example Usage

```terraform
data "stackit_alb_waf_configuration" "example" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "example-waf-configuration"
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `name` (String) The name of the WAF Configuration.
- `project_id` (String) STACKIT project ID to which the WAF Configuration is associated.

### Optional

- `region` (String) The resource region (e.g. eu01). If not defined, the provider region is used.

### Read-Only

- `custom_rule_group_name` (String) Name of the custom rule group for this WAF Configuration.
- `id` (String) Terraform's internal resource ID. It is structured as "`project_id`,`region`,`name`".
- `labels` (Map of String) User-defined metadata as key-value pairs. Should not exceed 64 entries.
- `managed_rule_set_name` (String) Name of the managed rule set configuration for this WAF Configuration.
42 changes: 42 additions & 0 deletions docs/resources/alb_waf_configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "stackit_alb_waf_configuration Resource - stackit"
subcategory: ""
description: |-
ALB WAF Custom Rule Group resource schema. Uses the default_region specified in the provider configuration as a fallback in case no region is defined on resource level.
~> This resource is in beta and may be subject to breaking changes in the future. Use with caution. See our guide https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources for how to opt-in to use beta resources.
---

# stackit_alb_waf_configuration (Resource)

ALB WAF Custom Rule Group resource schema. Uses the `default_region` specified in the provider configuration as a fallback in case no `region` is defined on resource level.

~> This resource is in beta and may be subject to breaking changes in the future. Use with caution. See our [guide](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources) for how to opt-in to use beta resources.

## Example Usage

```terraform
resource "stackit_alb_waf_configuration" "example" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "example-waf-configuration"
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `name` (String) The name of the WAF Configuration.
- `project_id` (String) STACKIT project ID to which the WAF Configuration is associated.

### Optional

- `custom_rule_group_name` (String) Name of the custom rule group for this WAF Configuration.
- `labels` (Map of String) User-defined metadata as key-value pairs. Should not exceed 64 entries.
- `managed_rule_set_name` (String) Name of the managed rule set configuration for this WAF Configuration.
- `region` (String) The resource region (e.g. eu01). If not defined, the provider region is used.

### Read-Only

- `id` (String) Terraform's internal resource ID. It is structured as "`project_id`,`region`,`name`".
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
data "stackit_alb_waf_configuration" "example" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "example-waf-configuration"
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resource "stackit_alb_waf_configuration" "example" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "example-waf-configuration"
}

225 changes: 224 additions & 1 deletion stackit/internal/services/albwaf/albwaf_acc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ var (

//go:embed testdata/managed-rule-set.tf
managedRuleSetConfig string

//go:embed testdata/resource-max.tf
wafMaxConfig string

//go:embed testdata/resource-min.tf
wafMinConfig string
)

var testCustomRuleGroupMin = config.Variables{
Expand Down Expand Up @@ -89,6 +95,40 @@ var testManagedRuleSetUpdated = func() config.Variables {
return updatedConfig
}

var testConfigVarsMax = config.Variables{
"project_id": config.StringVariable(testutil.ProjectId),
"waf_configuration_name": config.StringVariable("tf-acc-" + acctest.RandStringFromCharSet(8, acctest.CharSetAlpha)),
"rule_set_name": config.StringVariable("tf-acc-" + acctest.RandStringFromCharSet(8, acctest.CharSetAlpha)),
"type": config.StringVariable("TYPE_OWASP_CRS"),
"waf_configuration_label": config.StringVariable("some-label"),
"custom_rule_group_name": config.StringVariable("tf-acc-" + acctest.RandStringFromCharSet(8, acctest.CharSetAlpha)),
"action": config.StringVariable("ACTION_DENY"),
"operator_type": config.StringVariable("OPERATOR_VALIDATE_UTF8_ENCODING"),
"variable_type": config.StringVariable("VARIABLE_RESPONSE_STATUS"),
}

var testConfigVarsMaxUpdated = func() config.Variables {
updatedConfig := config.Variables{}
maps.Copy(updatedConfig, testConfigVarsMax)
updatedConfig["waf_configuration_name"] = config.StringVariable(fmt.Sprintf("%s-updated", testutil.ConvertConfigVariable(updatedConfig["waf_configuration_name"])))
updatedConfig["rule_set_name"] = config.StringVariable(fmt.Sprintf("%s-updated", testutil.ConvertConfigVariable(updatedConfig["rule_set_name"])))
updatedConfig["custom_rule_group_name"] = config.StringVariable(fmt.Sprintf("%s-updated", testutil.ConvertConfigVariable(updatedConfig["custom_rule_group_name"])))
updatedConfig["waf_configuration_label"] = config.StringVariable(fmt.Sprintf("%s-updated", testutil.ConvertConfigVariable(updatedConfig["waf_configuration_label"])))
return updatedConfig
}

var testConfigVarsMin = config.Variables{
"project_id": config.StringVariable(testutil.ProjectId),
"waf_configuration_name": config.StringVariable("tf-acc-" + acctest.RandStringFromCharSet(8, acctest.CharSetAlpha)),
}

var testConfigVarsMinUpdated = func() config.Variables {
updatedConfig := config.Variables{}
maps.Copy(updatedConfig, testConfigVarsMin)
updatedConfig["waf_configuration_name"] = config.StringVariable(fmt.Sprintf("%s-updated", testutil.ConvertConfigVariable(updatedConfig["waf_configuration_name"])))
return updatedConfig
}

func TestAccCustomRuleGroupMin(t *testing.T) {
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
Expand Down Expand Up @@ -345,7 +385,6 @@ func TestAccCustomRuleGroupMax(t *testing.T) {
},
})
}

func TestAccManagedRuleSet(t *testing.T) {
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
Expand Down Expand Up @@ -428,6 +467,190 @@ func TestAccManagedRuleSet(t *testing.T) {
})
}

func TestAccWafConfigurationMin(t *testing.T) {
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
CheckDestroy: testAccCheckDestroy,
Steps: []resource.TestStep{
// Creation
{
ConfigVariables: testConfigVarsMin,
Config: fmt.Sprintf("%s\n%s", testutil.NewConfigBuilder().EnableBetaResources(true).BuildProviderConfig(), wafMinConfig),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("stackit_alb_waf_configuration.waf_instance", "project_id", testutil.ProjectId),
resource.TestCheckResourceAttr("stackit_alb_waf_configuration.waf_instance", "region", testutil.Region),
resource.TestCheckResourceAttrSet("stackit_alb_waf_configuration.waf_instance", "id"),
resource.TestCheckResourceAttr("stackit_alb_waf_configuration.waf_instance", "name", testutil.ConvertConfigVariable(testConfigVarsMin["waf_configuration_name"])),
),
},
// Data source
{
ConfigVariables: testConfigVarsMin,
Config: fmt.Sprintf(`
%s
%s
data "stackit_alb_waf_configuration" "waf" {
project_id = stackit_alb_waf_configuration.waf_instance.project_id
name = stackit_alb_waf_configuration.waf_instance.name
}
`,
testutil.NewConfigBuilder().EnableBetaResources(true).BuildProviderConfig(), wafMinConfig,
),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("data.stackit_alb_waf_configuration.waf", "project_id", testutil.ProjectId),
resource.TestCheckResourceAttr("data.stackit_alb_waf_configuration.waf", "region", testutil.Region),
resource.TestCheckResourceAttrPair(
"data.stackit_alb_waf_configuration.waf", "id",
"stackit_alb_waf_configuration.waf_instance", "id",
),
resource.TestCheckResourceAttr("data.stackit_alb_waf_configuration.waf", "name", testutil.ConvertConfigVariable(testConfigVarsMin["waf_configuration_name"])),
),
},
// Import
{
ConfigVariables: testConfigVarsMin,
ResourceName: "stackit_alb_waf_configuration.waf_instance",
ImportStateIdFunc: func(s *terraform.State) (string, error) {
r, ok := s.RootModule().Resources["stackit_alb_waf_configuration.waf_instance"]
if !ok {
return "", fmt.Errorf("couldn't find resource stackit_alb_waf_configuration.waf_instance")
}
name, ok := r.Primary.Attributes["name"]
if !ok {
return "", fmt.Errorf("couldn't find attribute name")
}
return fmt.Sprintf("%s,%s,%s", testutil.ProjectId, testutil.Region, name), nil
},
ImportState: true,
ImportStateVerify: true,
},
// Update
{
ConfigVariables: testConfigVarsMinUpdated(),
Config: fmt.Sprintf("%s\n%s", testutil.NewConfigBuilder().EnableBetaResources(true).BuildProviderConfig(), wafMinConfig),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectResourceAction("stackit_alb_waf_configuration.waf_instance", plancheck.ResourceActionReplace),
},
},
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("stackit_alb_waf_configuration.waf_instance", "project_id", testutil.ProjectId),
resource.TestCheckResourceAttr("stackit_alb_waf_configuration.waf_instance", "region", testutil.Region),
resource.TestCheckResourceAttrSet("stackit_alb_waf_configuration.waf_instance", "id"),
resource.TestCheckResourceAttr("stackit_alb_waf_configuration.waf_instance", "name", testutil.ConvertConfigVariable(testConfigVarsMinUpdated()["waf_configuration_name"])),
),
},
// Deletion is done by the framework implicitly
},
})
}

func TestAccWafConfigurationMax(t *testing.T) {
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
CheckDestroy: testAccCheckDestroy,
Steps: []resource.TestStep{
// Creation
{
ConfigVariables: testConfigVarsMax,
Config: fmt.Sprintf("%s\n%s", testutil.NewConfigBuilder().EnableBetaResources(true).BuildProviderConfig(), wafMaxConfig),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("stackit_alb_waf_managed_rule_set.managed_rule_set", "name", testutil.ConvertConfigVariable(testConfigVarsMax["rule_set_name"])),
resource.TestCheckResourceAttr("stackit_alb_waf_custom_rule_group.custom_rule_group", "name", testutil.ConvertConfigVariable(testConfigVarsMax["custom_rule_group_name"])),

resource.TestCheckResourceAttr("stackit_alb_waf_configuration.waf_instance", "project_id", testutil.ProjectId),
resource.TestCheckResourceAttr("stackit_alb_waf_configuration.waf_instance", "region", testutil.Region),
resource.TestCheckResourceAttrSet("stackit_alb_waf_configuration.waf_instance", "id"),
resource.TestCheckResourceAttr("stackit_alb_waf_configuration.waf_instance", "name", testutil.ConvertConfigVariable(testConfigVarsMax["waf_configuration_name"])),
resource.TestCheckResourceAttrPair("stackit_alb_waf_configuration.waf_instance", "managed_rule_set_name", "stackit_alb_waf_managed_rule_set.managed_rule_set", "name"),
resource.TestCheckResourceAttr("stackit_alb_waf_configuration.waf_instance", "labels.label1", testutil.ConvertConfigVariable(testConfigVarsMax["waf_configuration_label"])),
),
},
// Data source
{
ConfigVariables: testConfigVarsMax,
Config: fmt.Sprintf(`
%s
%s

data "stackit_alb_waf_custom_rule_group" "custom_rule_group" {
project_id = stackit_alb_waf_custom_rule_group.custom_rule_group.project_id
name = stackit_alb_waf_custom_rule_group.custom_rule_group.name
}

data "stackit_alb_waf_managed_rule_set" "managed_rule_set" {
project_id = stackit_alb_waf_managed_rule_set.managed_rule_set.project_id
name = stackit_alb_waf_managed_rule_set.managed_rule_set.name
}

data "stackit_alb_waf_configuration" "waf" {
project_id = stackit_alb_waf_configuration.waf_instance.project_id
name = stackit_alb_waf_configuration.waf_instance.name
}
`,
testutil.NewConfigBuilder().EnableBetaResources(true).BuildProviderConfig(), wafMaxConfig,
),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrPair(
"data.stackit_alb_waf_managed_rule_set.managed_rule_set", "id",
"stackit_alb_waf_managed_rule_set.managed_rule_set", "id",
),
resource.TestCheckResourceAttr("data.stackit_alb_waf_managed_rule_set.managed_rule_set", "name", testutil.ConvertConfigVariable(testConfigVarsMax["rule_set_name"])),

resource.TestCheckResourceAttr("data.stackit_alb_waf_configuration.waf", "project_id", testutil.ProjectId),
resource.TestCheckResourceAttr("data.stackit_alb_waf_configuration.waf", "region", testutil.Region),
resource.TestCheckResourceAttrPair(
"data.stackit_alb_waf_configuration.waf", "id",
"stackit_alb_waf_configuration.waf_instance", "id",
),
resource.TestCheckResourceAttr("data.stackit_alb_waf_configuration.waf", "name", testutil.ConvertConfigVariable(testConfigVarsMax["waf_configuration_name"])),
resource.TestCheckResourceAttrPair("data.stackit_alb_waf_configuration.waf", "managed_rule_set_name", "data.stackit_alb_waf_managed_rule_set.managed_rule_set", "name"),
resource.TestCheckResourceAttr("data.stackit_alb_waf_configuration.waf", "labels.label1", testutil.ConvertConfigVariable(testConfigVarsMax["waf_configuration_label"])),
),
},
// Import
{
ConfigVariables: testConfigVarsMax,
ResourceName: "stackit_alb_waf_configuration.waf_instance",
ImportStateIdFunc: func(s *terraform.State) (string, error) {
r, ok := s.RootModule().Resources["stackit_alb_waf_configuration.waf_instance"]
if !ok {
return "", fmt.Errorf("couldn't find resource stackit_alb_waf_configuration.waf_instance")
}
name, ok := r.Primary.Attributes["name"]
if !ok {
return "", fmt.Errorf("couldn't find attribute name")
}
return fmt.Sprintf("%s,%s,%s", testutil.ProjectId, testutil.Region, name), nil
},
ImportState: true,
ImportStateVerify: true,
},
// Update
{
ConfigVariables: testConfigVarsMaxUpdated(),
Config: fmt.Sprintf("%s\n%s", testutil.NewConfigBuilder().EnableBetaResources(true).BuildProviderConfig(), wafMaxConfig),
ConfigPlanChecks: resource.ConfigPlanChecks{
PreApply: []plancheck.PlanCheck{
plancheck.ExpectResourceAction("stackit_alb_waf_configuration.waf_instance", plancheck.ResourceActionReplace),
},
},
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("stackit_alb_waf_configuration.waf_instance", "project_id", testutil.ProjectId),
resource.TestCheckResourceAttr("stackit_alb_waf_configuration.waf_instance", "region", testutil.Region),
resource.TestCheckResourceAttrSet("stackit_alb_waf_configuration.waf_instance", "id"),
resource.TestCheckResourceAttr("stackit_alb_waf_configuration.waf_instance", "name", testutil.ConvertConfigVariable(testConfigVarsMaxUpdated()["waf_configuration_name"])),
resource.TestCheckResourceAttr("stackit_alb_waf_configuration.waf_instance", "labels.label1", testutil.ConvertConfigVariable(testConfigVarsMaxUpdated()["waf_configuration_label"])),

resource.TestCheckResourceAttr("stackit_alb_waf_managed_rule_set.managed_rule_set", "name", testutil.ConvertConfigVariable(testConfigVarsMaxUpdated()["rule_set_name"])),
resource.TestCheckResourceAttr("stackit_alb_waf_custom_rule_group.custom_rule_group", "name", testutil.ConvertConfigVariable(testConfigVarsMaxUpdated()["custom_rule_group_name"])),
),
},
// Deletion is done by the framework implicitly
},
})
}

func createClient() (*albWaf.APIClient, error) {
client, err := albWaf.NewAPIClient(testutil.NewConfigBuilder().BuildClientOptions(testutil.AlbWafCustomEndpoint, false)...)
if err != nil {
Expand Down
21 changes: 21 additions & 0 deletions stackit/internal/services/albwaf/managed_rule_set/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,27 @@ func (r *managedRuleSetResource) ModifyPlan(ctx context.Context, req resource.Mo
return
}

// Warn the user if the name is changing, as this triggers a replacement.
// Deletion of the old resource will fail if another resource (e.g. stackit_alb_waf_configuration)
// still references this managed rule set.
if !req.State.Raw.IsNull() {
var stateModel Model
resp.Diagnostics.Append(req.State.Get(ctx, &stateModel)...)
if !resp.Diagnostics.HasError() && !stateModel.Name.IsNull() && !stateModel.Name.IsUnknown() {
if !planModel.Name.Equal(stateModel.Name) {
resp.Diagnostics.AddWarning(
"Managed Rule Set name change requires resource replacement",
fmt.Sprintf(
"Changing the \"name\" attribute from %q to %q will destroy and recreate this resource. "+
"If another resource (e.g. \"stackit_alb_waf_configuration\") references this managed rule set "+
"by name, the replacement will fail. Remove or update that dependency before applying this change.",
stateModel.Name.ValueString(), planModel.Name.ValueString(),
),
)
}
}
}

resp.Diagnostics.Append(resp.Plan.Set(ctx, planModel)...)
if resp.Diagnostics.HasError() {
return
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

variable "project_id" {}
variable "type" {}
variable "name" {}
Expand Down
Loading
Loading