Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resource/cloudflare_api_shield_schema_validation_settings #2841

Merged
merged 2 commits into from
Oct 30, 2023
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
3 changes: 3 additions & 0 deletions .changelog/2841.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
cloudflare_api_shield_schema_validation_settings
```
37 changes: 37 additions & 0 deletions docs/resources/api_shield_schema_validation_settings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
page_title: "cloudflare_api_shield_schema_validation_settings Resource - Cloudflare"
subcategory: ""
description: |-
Provides a resource to manage settings in API Shield Schema Validation 2.0.
---

# cloudflare_api_shield_schema_validation_settings (Resource)

Provides a resource to manage settings in API Shield Schema Validation 2.0.

## Example Usage

```terraform
resource "cloudflare_api_shield_schema_validation_settings" "example" {
zone_id = "0da42c8d2132a9ddaf714f9e7c920711"
validation_default_mitigation_action = "log"
validation_override_mitigation_action = "none"
}
```
<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `validation_default_mitigation_action` (String) The default mitigation action used when there is no mitigation action defined on the operation.
- `zone_id` (String) The zone identifier to target for the resource. **Modifying this attribute will force creation of a new resource.**

### Optional

- `validation_override_mitigation_action` (String) When set, this overrides both zone level and operation level mitigation actions.

### Read-Only

- `id` (String) The ID of this resource.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which ID are we talking about?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is auto-generated from the docs,it's mapped to the zone ID



Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resource "cloudflare_api_shield_schema_validation_settings" "example" {
zone_id = "0da42c8d2132a9ddaf714f9e7c920711"
validation_default_mitigation_action = "log"
validation_override_mitigation_action = "none"
}
1 change: 1 addition & 0 deletions internal/sdkv2provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ func New(version string) func() *schema.Provider {
"cloudflare_api_shield": resourceCloudflareAPIShield(),
"cloudflare_api_shield_operation": resourceCloudflareAPIShieldOperation(),
"cloudflare_api_shield_schema": resourceCloudflareAPIShieldSchemas(),
"cloudflare_api_shield_schema_validation_settings": resourceCloudflareAPIShieldSchemaValidationSettings(),
"cloudflare_api_token": resourceCloudflareApiToken(),
"cloudflare_argo": resourceCloudflareArgo(),
"cloudflare_authenticated_origin_pulls_certificate": resourceCloudflareAuthenticatedOriginPullsCertificate(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package sdkv2provider

import (
"context"
"fmt"

"github.com/pkg/errors"

"github.com/MakeNowJust/heredoc/v2"
"github.com/cloudflare/cloudflare-go"
"github.com/cloudflare/terraform-provider-cloudflare/internal/consts"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func resourceCloudflareAPIShieldSchemaValidationSettings() *schema.Resource {
return &schema.Resource{
Schema: resourceCloudflareAPIShieldSchemaValidationSettingsSchema(),
CreateContext: resourceCloudflareAPIShieldSchemaValidationSettingsCreate,
ReadContext: resourceCloudflareAPIShieldSchemaValidationSettingsRead,
UpdateContext: resourceCloudflareAPIShieldSchemaValidationSettingsUpdate,
DeleteContext: resourceCloudflareAPIShieldSchemaValidationSettingsDelete,
Importer: &schema.ResourceImporter{
StateContext: nil,
},
Description: heredoc.Doc(`
Provides a resource to manage settings in API Shield Schema Validation 2.0.
`),
}
}

func resourceCloudflareAPIShieldSchemaValidationSettingsCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
return resourceCloudflareAPIShieldSchemaValidationSettingsUpdate(ctx, d, meta)
}

func resourceCloudflareAPIShieldSchemaValidationSettingsUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*cloudflare.API)
zoneID := d.Get(consts.ZoneIDSchemaKey).(string)

dm := d.Get("validation_default_mitigation_action").(string)

var overrideAction *string
if oa, ok := d.GetOk("validation_override_mitigation_action"); ok {
overrideAction = cloudflare.StringPtr(oa.(string))
}

_, err := client.UpdateAPIShieldSchemaValidationSettings(
ctx,
cloudflare.ZoneIdentifier(zoneID),
cloudflare.UpdateAPIShieldSchemaValidationSettingsParams{
DefaultMitigationAction: &dm,
OverrideMitigationAction: overrideAction,
},
)

if err != nil {
return diag.FromErr(errors.Wrap(err, "failed to create API Shield Schema Validation Settings"))
}

// Settings are configured at the zone level so using the zoneID as the ID
d.SetId(zoneID)
return resourceCloudflareAPIShieldSchemaValidationSettingsRead(ctx, d, meta)
}

func resourceCloudflareAPIShieldSchemaValidationSettingsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(*cloudflare.API)
zoneID := d.Get(consts.ZoneIDSchemaKey).(string)

settings, err := client.GetAPIShieldSchemaValidationSettings(
ctx,
cloudflare.ZoneIdentifier(zoneID),
)

if err != nil {
return diag.FromErr(fmt.Errorf("failed to fetch API Shield Schema Validation Settings: %w", err))
}

if err := d.Set("validation_default_mitigation_action", settings.DefaultMitigationAction); err != nil {
return diag.FromErr(err)
}

if err := d.Set("validation_override_mitigation_action", settings.OverrideMitigationAction); err != nil {
return diag.FromErr(err)
}

// Settings are configured at the zone level so using the zoneID as the ID
d.SetId(zoneID)
return nil
}

func resourceCloudflareAPIShieldSchemaValidationSettingsDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this a delete? We are not deleting anything? Or do you have to give a delete-function here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if a resource is removed from the terraform state, it deletes the resource - as we don't actually "delete" anything this just resets the state of the settings to default.

It could be argued there should be a DELETE endpoint on the API, however this implementation will achieve the same.

client := meta.(*cloudflare.API)
zoneID := d.Get(consts.ZoneIDSchemaKey).(string)

defaultSettings := cloudflareAPIShieldSchemaValidationSettingsDefault()

// There is no DELETE endpoint for schema validation settings,
// so terraform should reset the state to default settings
_, err := client.UpdateAPIShieldSchemaValidationSettings(
ctx,
cloudflare.ZoneIdentifier(zoneID),
cloudflare.UpdateAPIShieldSchemaValidationSettingsParams{
DefaultMitigationAction: &defaultSettings.DefaultMitigationAction,
OverrideMitigationAction: defaultSettings.OverrideMitigationAction,
},
)
if err != nil {
return diag.FromErr(fmt.Errorf("failed to delete API Shield Schema Validation Settings: %w", err))
}

return nil
}

func cloudflareAPIShieldSchemaValidationSettingsDefault() *cloudflare.APIShieldSchemaValidationSettings {
disableOverride := "disable_override"
return &cloudflare.APIShieldSchemaValidationSettings{
DefaultMitigationAction: "none",
OverrideMitigationAction: &disableOverride,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package sdkv2provider

import (
"context"
"fmt"
"os"
"testing"

"github.com/cloudflare/cloudflare-go"
"github.com/cloudflare/terraform-provider-cloudflare/internal/consts"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
)

func TestAccCloudflareAPIShieldSchemaValidationSettings_Create(t *testing.T) {
// Temporarily unset CLOUDFLARE_API_TOKEN if it is set as the API token
// endpoint does not yet support the API tokens without an explicit scope.
if os.Getenv("CLOUDFLARE_API_TOKEN") != "" {
t.Setenv("CLOUDFLARE_API_TOKEN", "")
}

rnd := generateRandomResourceName()
resourceID := "cloudflare_api_shield_schema_validation_settings." + rnd
zoneID := os.Getenv("CLOUDFLARE_ZONE_ID")

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: providerFactories,
CheckDestroy: testAccCheckAPIShieldSchemaValidationSettingsDelete,
Steps: []resource.TestStep{
{
Config: testAccCloudflareAPIShieldSchemaValidationSettingsDefaultMitigationSet(rnd, zoneID),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceID, consts.ZoneIDSchemaKey, zoneID),
resource.TestCheckResourceAttr(resourceID, "validation_default_mitigation_action", "log"),
// default
resource.TestCheckResourceAttr(resourceID, "validation_override_mitigation_action", ""),
),
},
{
Config: testAccCloudflareAPIShieldSchemaValidationSettingsAllMitigationsSet(rnd, zoneID),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceID, consts.ZoneIDSchemaKey, zoneID),
resource.TestCheckResourceAttr(resourceID, "validation_default_mitigation_action", "block"),
resource.TestCheckResourceAttr(resourceID, "validation_override_mitigation_action", "none"),
),
},
},
})
}

func testAccCheckAPIShieldSchemaValidationSettingsDelete(s *terraform.State) error {
client := testAccProvider.Meta().(*cloudflare.API)

for _, rs := range s.RootModule().Resources {
if rs.Type != "cloudflare_api_shield_schema_validation_settings" {
continue
}

result, err := client.GetAPIShieldSchemaValidationSettings(
context.Background(),
cloudflare.ZoneIdentifier(rs.Primary.Attributes[consts.ZoneIDSchemaKey]),
)
if err != nil {
return fmt.Errorf("encountered error getting schema validation settings: %w", err)
}

if result.DefaultMitigationAction != cloudflareAPIShieldSchemaValidationSettingsDefault().DefaultMitigationAction {
return fmt.Errorf("expected validation_default_mitigation_action to be 'none' but got: %s", result.DefaultMitigationAction)
}

if result.OverrideMitigationAction != nil {
return fmt.Errorf("expected validation_override_mitigation_action to be nil")
}
}

return nil
}

func testAccCloudflareAPIShieldSchemaValidationSettingsDefaultMitigationSet(resourceName, zone string) string {
return fmt.Sprintf(`
resource "cloudflare_api_shield_schema_validation_settings" "%[1]s" {
zone_id = "%[2]s"
validation_default_mitigation_action = "log"
}
`, resourceName, zone)
}

func testAccCloudflareAPIShieldSchemaValidationSettingsAllMitigationsSet(resourceName, zone string) string {
return fmt.Sprintf(`
resource "cloudflare_api_shield_schema_validation_settings" "%[1]s" {
zone_id = "%[2]s"
validation_default_mitigation_action = "block"
validation_override_mitigation_action = "none"
}
`, resourceName, zone)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package sdkv2provider

import (
"github.com/cloudflare/terraform-provider-cloudflare/internal/consts"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func resourceCloudflareAPIShieldSchemaValidationSettingsSchema() map[string]*schema.Schema {
return map[string]*schema.Schema{
consts.ZoneIDSchemaKey: {
Description: consts.ZoneIDSchemaDescription,
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"validation_default_mitigation_action": {
Description: "The default mitigation action used when there is no mitigation action defined on the operation",
Type: schema.TypeString,
Required: true,
},
"validation_override_mitigation_action": {
Description: "When set, this overrides both zone level and operation level mitigation actions",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add that this can only take values "none" and "disable_override" to kill SV 2.0?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather not encode this into here, the API rejects invalid values.

Type: schema.TypeString,
Optional: true,
},
}
}