diff --git a/docs/resources/edge_services_route_stage.md b/docs/resources/edge_services_route_stage.md new file mode 100644 index 0000000000..5ec7ec1184 --- /dev/null +++ b/docs/resources/edge_services_route_stage.md @@ -0,0 +1,59 @@ +--- +subcategory: "Edge Services" +page_title: "Scaleway: scaleway_edge_services_route_stage" +--- + +# Resource: scaleway_edge_services_route_stage + +Creates and manages Scaleway Edge Services Route Stages. + +## Example Usage + +### Basic + +```terraform +resource "scaleway_edge_services_route_stage" "main" { + pipeline_id = scaleway_edge_services_pipeline.main.id + waf_stage_id = scaleway_edge_services_waf_stage.waf.id + + rule { + backend_stage_id = scaleway_edge_services_backend_stage.backend.id + rule_http_match { + method_filters = ["get", "post"] + path_filter { + path_filter_type = "regex" + value = ".*" + } + } + } +} +``` + +## Argument Reference + +- `pipeline_id` - (Required) The ID of the pipeline. +- `waf_stage_id` - (Optional) The ID of the WAF stage HTTP requests should be forwarded to when no rules are matched. +- `rule` - (Optional) The list of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`. + - `backend_stage_id` (Required) The ID of the backend stage that requests matching the rule should be forwarded to. + - `rule_http_match` (Optional) The rule condition to be matched. Requests matching the condition defined here will be directly forwarded to the backend specified by the `backend_stage_id` field. Requests that do not match will be checked by the next rule's condition. + - `method_filters` (Optional) HTTP methods to filter for. A request using any of these methods will be considered to match the rule. Possible values are `get`, `post`, `put`, `patch`, `delete`, `head`, `options`. All methods will match if none is provided. + - `path_filter` (Optional) HTTP URL path to filter for. A request whose path matches the given filter will be considered to match the rule. All paths will match if none is provided. + - `path_filter_type` (Required) The type of filter to match for the HTTP URL path. For now, all path filters must be written in regex and use the `regex` type. + - `value` (Required) The value to be matched for the HTTP URL path. +- `project_id` - (Defaults to [provider](../index.md#project_id) `project_id`) The ID of the project the route stage is associated with. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +- `id` - The ID of the route stage (UUID format). +- `created_at` - The date and time of the creation of the route stage. +- `updated_at` - The date and time of the last update of the route stage. + +## Import + +Route stages can be imported using the `{id}`, e.g. + +```bash +$ terraform import scaleway_edge_services_route_stage.basic 11111111-1111-1111-1111-111111111111 +``` diff --git a/docs/resources/edge_services_waf_stage.md b/docs/resources/edge_services_waf_stage.md new file mode 100644 index 0000000000..ce1d4881f5 --- /dev/null +++ b/docs/resources/edge_services_waf_stage.md @@ -0,0 +1,44 @@ +--- +subcategory: "Edge Services" +page_title: "Scaleway: scaleway_edge_services_waf_stage" +--- + +# Resource: scaleway_edge_services_waf_stage + +Creates and manages Scaleway Edge Services WAF Stages. + +## Example Usage + +### Basic + +```terraform +resource "scaleway_edge_services_waf_stage" "main" { + pipeline_id = scaleway_edge_services_pipeline.main.id + mode = "enable" + paranoia_level = 3 +} +``` + +## Argument Reference + +- `pipeline_id` - (Required) The ID of the pipeline. +- `paranoia_level` - (Required) The sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign. +- `backend_stage_id` - (Optional) The ID of the backend stage to forward requests to after the WAF stage. +- `mode` - (Optional) The mode defining WAF behavior (`disable`/`log_only`/`enable`). +- `project_id` - (Defaults to [provider](../index.md#project_id) `project_id`) The ID of the project the WAF stage is associated with. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +- `id` - The ID of the WAF stage (UUID format). +- `created_at` - The date and time of the creation of the WAF stage. +- `updated_at` - The date and time of the last update of the WAF stage. + +## Import + +WAF stages can be imported using the `{id}`, e.g. + +```bash +$ terraform import scaleway_edge_services_waf_stage.basic 11111111-1111-1111-1111-111111111111 +``` diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 2f949b2178..553cfd0695 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -148,7 +148,9 @@ func Provider(config *Config) plugin.ProviderFunc { "scaleway_edge_services_head_stage": edgeservices.ResourceHeadStage(), "scaleway_edge_services_pipeline": edgeservices.ResourcePipeline(), "scaleway_edge_services_plan": edgeservices.ResourcePlan(), + "scaleway_edge_services_route_stage": edgeservices.ResourceRouteStage(), "scaleway_edge_services_tls_stage": edgeservices.ResourceTLSStage(), + "scaleway_edge_services_waf_stage": edgeservices.ResourceWAFStage(), "scaleway_flexible_ip": flexibleip.ResourceIP(), "scaleway_flexible_ip_mac_address": flexibleip.ResourceMACAddress(), "scaleway_function": function.ResourceFunction(), diff --git a/internal/services/edgeservices/route_stage.go b/internal/services/edgeservices/route_stage.go new file mode 100644 index 0000000000..ad9b5d4d46 --- /dev/null +++ b/internal/services/edgeservices/route_stage.go @@ -0,0 +1,209 @@ +package edgeservices + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + edgeservices "github.com/scaleway/scaleway-sdk-go/api/edge_services/v1beta1" + "github.com/scaleway/scaleway-sdk-go/scw" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/types" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/verify" +) + +func ResourceRouteStage() *schema.Resource { + return &schema.Resource{ + CreateContext: ResourceRouteStageCreate, + ReadContext: ResourceRouteStageRead, + UpdateContext: ResourceRouteStageUpdate, + DeleteContext: ResourceRouteStageDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + SchemaVersion: 0, + Schema: map[string]*schema.Schema{ + "pipeline_id": { + Type: schema.TypeString, + Required: true, + Description: "The ID of the pipeline", + }, + "waf_stage_id": { + Type: schema.TypeString, + Optional: true, + Description: "The ID of the WAF stage HTTP requests should be forwarded to when no rules are matched", + }, + "rule": { + Type: schema.TypeList, + Optional: true, + Description: "List of rules to be checked against every HTTP request. The first matching rule will forward the request to its specified backend stage. If no rules are matched, the request is forwarded to the WAF stage defined by `waf_stage_id`", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "backend_stage_id": { + Type: schema.TypeString, + Required: true, + Description: "ID of the backend stage that requests matching the rule should be forwarded to", + }, + "rule_http_match": { + Type: schema.TypeList, + Optional: true, + Description: "Rule condition to be matched. Requests matching the condition defined here will be directly forwarded to the backend specified by the `backend_stage_id` field. Requests that do not match will be checked by the next rule's condition", + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "method_filters": { + Type: schema.TypeList, + Optional: true, + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateDiagFunc: verify.ValidateEnum[edgeservices.RuleHTTPMatchMethodFilter](), + }, + Description: "HTTP methods to filter for. A request using any of these methods will be considered to match the rule. Possible values are `get`, `post`, `put`, `patch`, `delete`, `head`, `options`. All methods will match if none is provided", + }, + "path_filter": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: "HTTP URL path to filter for. A request whose path matches the given filter will be considered to match the rule. All paths will match if none is provided", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "path_filter_type": { + Type: schema.TypeString, + Required: true, + ValidateDiagFunc: verify.ValidateEnum[edgeservices.RuleHTTPMatchPathFilterPathFilterType](), + Description: "The type of filter to match for the HTTP URL path. For now, all path filters must be written in regex and use the `regex` type", + }, + "value": { + Type: schema.TypeString, + Required: true, + Description: "The value to be matched for the HTTP URL path", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + Description: "The date and time of the creation of the route stage", + }, + "updated_at": { + Type: schema.TypeString, + Computed: true, + Description: "The date and time of the last update of the route stage", + }, + "project_id": account.ProjectIDSchema(), + }, + } +} + +func ResourceRouteStageCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + api := NewEdgeServicesAPI(m) + + routeStage, err := api.CreateRouteStage(&edgeservices.CreateRouteStageRequest{ + PipelineID: d.Get("pipeline_id").(string), + WafStageID: types.ExpandStringPtr(d.Get("waf_stage_id").(string)), + }, scw.WithContext(ctx)) + if err != nil { + return diag.FromErr(err) + } + + _, err = api.SetRouteRules(&edgeservices.SetRouteRulesRequest{ + RouteStageID: routeStage.ID, + RouteRules: expandRouteRules(d.Get("rule")), + }, scw.WithContext(ctx)) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(routeStage.ID) + + return ResourceRouteStageRead(ctx, d, m) +} + +func ResourceRouteStageRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + api := NewEdgeServicesAPI(m) + + routeStage, err := api.GetRouteStage(&edgeservices.GetRouteStageRequest{ + RouteStageID: d.Id(), + }, scw.WithContext(ctx)) + if err != nil { + if httperrors.Is404(err) { + d.SetId("") + + return nil + } + + return diag.FromErr(err) + } + + _ = d.Set("pipeline_id", routeStage.PipelineID) + _ = d.Set("waf_stage_id", types.FlattenStringPtr(routeStage.WafStageID)) + _ = d.Set("created_at", types.FlattenTime(routeStage.CreatedAt)) + _ = d.Set("updated_at", types.FlattenTime(routeStage.UpdatedAt)) + + routeRules, err := api.ListRouteRules(&edgeservices.ListRouteRulesRequest{ + RouteStageID: routeStage.ID, + }, scw.WithContext(ctx)) + if err != nil { + return diag.FromErr(err) + } + + _ = d.Set("rule", flattenRouteRules(routeRules.RouteRules)) + + return nil +} + +func ResourceRouteStageUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + api := NewEdgeServicesAPI(m) + + hasChanged := false + + updateRequest := &edgeservices.UpdateRouteStageRequest{ + RouteStageID: d.Id(), + } + + if d.HasChange("waf_stage_id") { + updateRequest.WafStageID = types.ExpandStringPtr(d.Get("waf_stage_id").(string)) + hasChanged = true + } + + if hasChanged { + _, err := api.UpdateRouteStage(updateRequest, scw.WithContext(ctx)) + if err != nil { + return diag.FromErr(err) + } + } + + if d.HasChange("rule") { + _, err := api.SetRouteRules(&edgeservices.SetRouteRulesRequest{ + RouteStageID: d.Id(), + RouteRules: expandRouteRules(d.Get("rule")), + }, scw.WithContext(ctx)) + if err != nil { + return diag.FromErr(err) + } + } + + return ResourceRouteStageRead(ctx, d, m) +} + +func ResourceRouteStageDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + api := NewEdgeServicesAPI(m) + + err := api.DeleteRouteStage(&edgeservices.DeleteRouteStageRequest{ + RouteStageID: d.Id(), + }, scw.WithContext(ctx)) + if err != nil && !httperrors.Is404(err) { + return diag.FromErr(err) + } + + return nil +} diff --git a/internal/services/edgeservices/route_stage_test.go b/internal/services/edgeservices/route_stage_test.go new file mode 100644 index 0000000000..20cbd5637a --- /dev/null +++ b/internal/services/edgeservices/route_stage_test.go @@ -0,0 +1,84 @@ +package edgeservices_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/acctest" + edgeservicestestfuncs "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/edgeservices/testfuncs" +) + +func TestAccEdgeServicesRoute_Basic(t *testing.T) { + tt := acctest.NewTestTools(t) + defer tt.Cleanup() + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProviderFactories: tt.ProviderFactories, + CheckDestroy: edgeservicestestfuncs.CheckEdgeServicesRouteDestroy(tt), + Steps: []resource.TestStep{ + { + Config: ` + resource "scaleway_edge_services_pipeline" "main" { + name = "my-edge-services-pipeline" + description = "pipeline description" + } + + resource "scaleway_edge_services_waf_stage" "waf" { + pipeline_id = scaleway_edge_services_pipeline.main.id + mode = "enable" + paranoia_level = 3 + } + + resource "scaleway_object_bucket" "main" { + name = "test-acc-scaleway-object-bucket-basic-route" + tags = { + foo = "bar" + } + } + + resource "scaleway_edge_services_backend_stage" "backend" { + pipeline_id = scaleway_edge_services_pipeline.main.id + s3_backend_config { + bucket_name = scaleway_object_bucket.main.name + bucket_region = "fr-par" + } + } + + resource "scaleway_edge_services_route_stage" "main" { + pipeline_id = scaleway_edge_services_pipeline.main.id + waf_stage_id = scaleway_edge_services_waf_stage.waf.id + + rule { + backend_stage_id = scaleway_edge_services_backend_stage.backend.id + rule_http_match { + method_filters = ["get", "post"] + path_filter { + path_filter_type = "regex" + value = ".*" + } + } + } + } + `, + Check: resource.ComposeTestCheckFunc( + edgeservicestestfuncs.CheckEdgeServicesRouteExists(tt, "scaleway_edge_services_route_stage.main"), + resource.TestCheckResourceAttrPair( + "scaleway_edge_services_backend_stage.backend", "id", + "scaleway_edge_services_route_stage.main", "rule.0.backend_stage_id"), + resource.TestCheckResourceAttrPair( + "scaleway_edge_services_waf_stage.waf", "id", + "scaleway_edge_services_route_stage.main", "waf_stage_id"), + resource.TestCheckResourceAttrPair( + "scaleway_edge_services_waf_stage.waf", "id", + "scaleway_edge_services_route_stage.main", "waf_stage_id"), + resource.TestCheckResourceAttr("scaleway_edge_services_route_stage.main", "rule.0.rule_http_match.0.method_filters.0", "get"), + resource.TestCheckResourceAttr("scaleway_edge_services_route_stage.main", "rule.0.rule_http_match.0.method_filters.1", "post"), + resource.TestCheckResourceAttr("scaleway_edge_services_route_stage.main", "rule.0.rule_http_match.0.path_filter.0.path_filter_type", "regex"), + resource.TestCheckResourceAttr("scaleway_edge_services_route_stage.main", "rule.0.rule_http_match.0.path_filter.0.value", ".*"), + resource.TestCheckResourceAttrSet("scaleway_edge_services_route_stage.main", "created_at"), + resource.TestCheckResourceAttrSet("scaleway_edge_services_route_stage.main", "updated_at"), + ), + }, + }, + }) +} diff --git a/internal/services/edgeservices/testdata/edge-services-route-basic.cassette.yaml b/internal/services/edgeservices/testdata/edge-services-route-basic.cassette.yaml new file mode 100644 index 0000000000..0b03a58760 --- /dev/null +++ b/internal/services/edgeservices/testdata/edge-services-route-basic.cassette.yaml @@ -0,0 +1,2021 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 125 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: '{"project_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","name":"my-edge-services-pipeline","description":"pipeline description"}' + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/pipelines + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 349 + uncompressed: false + body: '{"created_at":"2025-03-26T10:26:32.641789624Z","description":"pipeline description","errors":[],"id":"5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340","name":"my-edge-services-pipeline","organization_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","project_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","status":"pending","updated_at":"2025-03-26T10:26:32.641789624Z"}' + headers: + Content-Length: + - "349" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:32 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 65983927-27c4-49c4-837c-b5d1a0a7e395 + status: 200 OK + code: 200 + duration: 1.709746089s + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/pipelines/5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 343 + uncompressed: false + body: '{"created_at":"2025-03-26T10:26:32.641789Z","description":"pipeline description","errors":[],"id":"5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340","name":"my-edge-services-pipeline","organization_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","project_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","status":"pending","updated_at":"2025-03-26T10:26:32.641789Z"}' + headers: + Content-Length: + - "343" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:32 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - be95ba71-5b18-48e4-9a5c-a1fee332bea6 + status: 200 OK + code: 200 + duration: 178.286099ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 36 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: '{"mode":"enable","paranoia_level":3}' + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/pipelines/5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340/waf-stages + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 225 + uncompressed: false + body: '{"created_at":"2025-03-26T10:26:33.093099552Z","id":"1337b601-899a-4f7c-a978-fb2d86abcad0","mode":"enable","paranoia_level":3,"pipeline_id":"5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340","updated_at":"2025-03-26T10:26:33.093099552Z"}' + headers: + Content-Length: + - "225" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:33 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 80ab46ee-81f4-4b47-97ce-0ac172d32977 + status: 200 OK + code: 200 + duration: 902.859746ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/waf-stages/1337b601-899a-4f7c-a978-fb2d86abcad0 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 219 + uncompressed: false + body: '{"created_at":"2025-03-26T10:26:33.093099Z","id":"1337b601-899a-4f7c-a978-fb2d86abcad0","mode":"enable","paranoia_level":3,"pipeline_id":"5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340","updated_at":"2025-03-26T10:26:33.093099Z"}' + headers: + Content-Length: + - "219" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:34 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - cc6de602-d794-4750-9776-3b83e790e98e + status: 200 OK + code: 200 + duration: 137.710075ms + - id: 4 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - 337c0cc5-40fc-4de7-8c6b-6e1e4c87a923 + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,e + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102630Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/ + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Content-Length: + - "0" + Date: + - Wed, 26 Mar 2025 10:26:37 GMT + Location: + - /test-acc-scaleway-object-bucket-basic-route + X-Amz-Id-2: + - txgbdd433410deb45d7bd74-0067e3d65d + X-Amz-Request-Id: + - txgbdd433410deb45d7bd74-0067e3d65d + status: 200 OK + code: 200 + duration: 7.713638261s + - id: 5 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 127 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: foobar + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - ff4c563f-3793-43b3-a5dd-8b177be46f76 + Amz-Sdk-Request: + - attempt=1; max=3 + Content-Type: + - application/xml + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,Z,e + X-Amz-Checksum-Crc32: + - Y9NeVA== + X-Amz-Content-Sha256: + - d68cba1a39d89eb72e49b2e5b04058846b60e88e6e32eae42901c4f57a4727a8 + X-Amz-Date: + - 20250326T102638Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/?tagging= + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Content-Length: + - "0" + Date: + - Wed, 26 Mar 2025 10:26:38 GMT + X-Amz-Id-2: + - txg82092825e34647ad8eb4-0067e3d65e + X-Amz-Request-Id: + - txg82092825e34647ad8eb4-0067e3d65e + status: 200 OK + code: 200 + duration: 344.95915ms + - id: 6 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - df69f0bf-a092-4597-b7d0-932302203b66 + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,Z,e + X-Amz-Acl: + - private + X-Amz-Checksum-Crc32: + - AAAAAA== + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102639Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/?acl= + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Content-Length: + - "0" + Date: + - Wed, 26 Mar 2025 10:26:39 GMT + X-Amz-Id-2: + - txgc2aa5bad1a5a4161a6ac-0067e3d65f + X-Amz-Request-Id: + - txgc2aa5bad1a5a4161a6ac-0067e3d65f + status: 200 OK + code: 200 + duration: 234.81805ms + - id: 7 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 127 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: foobar + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - 1fbc2cf6-3256-4590-9267-abf342f02847 + Amz-Sdk-Request: + - attempt=1; max=3 + Content-Type: + - application/xml + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,Z,e + X-Amz-Checksum-Crc32: + - Y9NeVA== + X-Amz-Content-Sha256: + - d68cba1a39d89eb72e49b2e5b04058846b60e88e6e32eae42901c4f57a4727a8 + X-Amz-Date: + - 20250326T102639Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/?tagging= + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Content-Length: + - "0" + Date: + - Wed, 26 Mar 2025 10:26:39 GMT + X-Amz-Id-2: + - txgf9a326beb9734c8590e5-0067e3d65f + X-Amz-Request-Id: + - txgf9a326beb9734c8590e5-0067e3d65f + status: 200 OK + code: 200 + duration: 346.95297ms + - id: 8 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - 022af387-d802-4835-923d-a4378b9c12cd + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,e + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102639Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/?acl= + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 698 + uncompressed: false + body: |- + + 564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5:564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5:564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5:564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5:564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5FULL_CONTROL + headers: + Content-Length: + - "698" + Content-Type: + - text/xml; charset=utf-8 + Date: + - Wed, 26 Mar 2025 10:26:39 GMT + X-Amz-Id-2: + - txgbf34ffdb0901470b8de2-0067e3d65f + X-Amz-Request-Id: + - txgbf34ffdb0901470b8de2-0067e3d65f + status: 200 OK + code: 200 + duration: 177.419187ms + - id: 9 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - 2e0c20c9-a15d-46c0-bcde-a53dedce47ef + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,e + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102639Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/?object-lock= + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 312 + uncompressed: false + body: ObjectLockConfigurationNotFoundErrorObject Lock configuration does not exist for this buckettxg7019bae900ab4502a12c-0067e3d65ftxg7019bae900ab4502a12c-0067e3d65f/test-acc-scaleway-object-bucket-basic-route + headers: + Content-Length: + - "312" + Content-Type: + - application/xml + Date: + - Wed, 26 Mar 2025 10:26:39 GMT + X-Amz-Id-2: + - txg7019bae900ab4502a12c-0067e3d65f + X-Amz-Request-Id: + - txg7019bae900ab4502a12c-0067e3d65f + status: 404 Not Found + code: 404 + duration: 179.726098ms + - id: 10 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - 4a3e2345-9e03-47c2-8fca-740d024f3ead + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,e + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102639Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/ + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 269 + uncompressed: false + body: |- + + test-acc-scaleway-object-bucket-basic-route1000false + headers: + Content-Length: + - "269" + Content-Type: + - application/xml + Date: + - Wed, 26 Mar 2025 10:26:40 GMT + X-Amz-Id-2: + - txg2d58e115f8044eaf964b-0067e3d660 + X-Amz-Request-Id: + - txg2d58e115f8044eaf964b-0067e3d660 + status: 200 OK + code: 200 + duration: 356.572076ms + - id: 11 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - 45d14352-d41d-496e-8eeb-278892ebe2bb + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,e + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102640Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/?tagging= + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 118 + uncompressed: false + body: |- + + foobar + headers: + Content-Length: + - "118" + Content-Type: + - text/xml; charset=utf-8 + Date: + - Wed, 26 Mar 2025 10:26:40 GMT + X-Amz-Id-2: + - txg8ea3d165469d4e5a8f97-0067e3d660 + X-Amz-Request-Id: + - txg8ea3d165469d4e5a8f97-0067e3d660 + status: 200 OK + code: 200 + duration: 322.841541ms + - id: 12 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - 2870511d-a5c8-47ed-b857-4bca6dace105 + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,e + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102640Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/?cors= + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 280 + uncompressed: false + body: NoSuchCORSConfigurationThe CORS configuration does not existtxgda2fc86be5694b848e63-0067e3d660txgda2fc86be5694b848e63-0067e3d660/test-acc-scaleway-object-bucket-basic-route + headers: + Content-Length: + - "280" + Content-Type: + - application/xml + Date: + - Wed, 26 Mar 2025 10:26:40 GMT + X-Amz-Id-2: + - txgda2fc86be5694b848e63-0067e3d660 + X-Amz-Request-Id: + - txgda2fc86be5694b848e63-0067e3d660 + status: 404 Not Found + code: 404 + duration: 585.657933ms + - id: 13 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - 5b310860-6ec6-4906-89f2-bcc250eabda5 + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,e + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102641Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/?versioning= + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 155 + uncompressed: false + body: |- + + + headers: + Content-Length: + - "155" + Content-Type: + - text/xml; charset=utf-8 + Date: + - Wed, 26 Mar 2025 10:26:41 GMT + X-Amz-Id-2: + - txgf15a29dec62f46a2ad65-0067e3d661 + X-Amz-Request-Id: + - txgf15a29dec62f46a2ad65-0067e3d661 + status: 200 OK + code: 200 + duration: 155.299622ms + - id: 14 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - 967afd9b-6ae0-4caa-bc16-ba05bb66ce6e + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,e + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102641Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/?lifecycle= + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 358 + uncompressed: false + body: NoSuchLifecycleConfigurationThe lifecycle configuration does not existtxg998a1ca30b74474aac2d-0067e3d661txg998a1ca30b74474aac2d-0067e3d661/test-acc-scaleway-object-bucket-basic-routetest-acc-scaleway-object-bucket-basic-route + headers: + Content-Length: + - "358" + Content-Type: + - application/xml + Date: + - Wed, 26 Mar 2025 10:26:41 GMT + X-Amz-Id-2: + - txg998a1ca30b74474aac2d-0067e3d661 + X-Amz-Request-Id: + - txg998a1ca30b74474aac2d-0067e3d661 + status: 404 Not Found + code: 404 + duration: 160.05499ms + - id: 15 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 121 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: '{"scaleway_s3":{"bucket_name":"test-acc-scaleway-object-bucket-basic-route","bucket_region":"fr-par","is_website":false}}' + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/pipelines/5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340/backend-stages + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 310 + uncompressed: false + body: '{"created_at":"2025-03-26T10:26:42.338796872Z","id":"c16ad531-08d9-4455-b882-180c7ba9aabf","pipeline_id":"5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340","scaleway_s3":{"bucket_name":"test-acc-scaleway-object-bucket-basic-route","bucket_region":"fr-par","is_website":false},"updated_at":"2025-03-26T10:26:42.338796872Z"}' + headers: + Content-Length: + - "310" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:42 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 8beb7a7f-44f4-4c4a-a444-a9b8165dd08d + status: 200 OK + code: 200 + duration: 666.223709ms + - id: 16 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/backend-stages/c16ad531-08d9-4455-b882-180c7ba9aabf + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 304 + uncompressed: false + body: '{"created_at":"2025-03-26T10:26:42.338796Z","id":"c16ad531-08d9-4455-b882-180c7ba9aabf","pipeline_id":"5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340","scaleway_s3":{"bucket_name":"test-acc-scaleway-object-bucket-basic-route","bucket_region":"fr-par","is_website":false},"updated_at":"2025-03-26T10:26:42.338796Z"}' + headers: + Content-Length: + - "304" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:42 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - c8013ba7-0059-4859-b18e-e4252281483d + status: 200 OK + code: 200 + duration: 112.667088ms + - id: 17 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 55 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: '{"waf_stage_id":"1337b601-899a-4f7c-a978-fb2d86abcad0"}' + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/pipelines/5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340/route-stages + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 244 + uncompressed: false + body: '{"created_at":"2025-03-26T10:26:42.612173654Z","id":"f157ee76-3c98-4fb1-a230-b6fd6c03d55d","pipeline_id":"5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340","updated_at":"2025-03-26T10:26:42.612173654Z","waf_stage_id":"1337b601-899a-4f7c-a978-fb2d86abcad0"}' + headers: + Content-Length: + - "244" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:42 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - a8942a20-c916-4122-b598-4b8f2aea18df + status: 200 OK + code: 200 + duration: 123.093566ms + - id: 18 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 185 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: '{"route_rules":[{"rule_http_match":{"method_filters":["get","post"],"path_filter":{"path_filter_type":"regex","value":".*"}},"backend_stage_id":"c16ad531-08d9-4455-b882-180c7ba9aabf"}]}' + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/route-stages/f157ee76-3c98-4fb1-a230-b6fd6c03d55d/route-rules + method: PUT + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 218 + uncompressed: false + body: '{"route_rules":[{"backend_stage_id":"c16ad531-08d9-4455-b882-180c7ba9aabf","position":1,"route_stage_id":"","rule_http_match":{"method_filters":["get","post"],"path_filter":{"path_filter_type":"regex","value":".*"}}}]}' + headers: + Content-Length: + - "218" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:43 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 0a08964e-5940-4621-bb5a-1782910314d9 + status: 200 OK + code: 200 + duration: 489.556707ms + - id: 19 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/route-stages/f157ee76-3c98-4fb1-a230-b6fd6c03d55d + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 238 + uncompressed: false + body: '{"created_at":"2025-03-26T10:26:42.612173Z","id":"f157ee76-3c98-4fb1-a230-b6fd6c03d55d","pipeline_id":"5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340","updated_at":"2025-03-26T10:26:43.090704Z","waf_stage_id":"1337b601-899a-4f7c-a978-fb2d86abcad0"}' + headers: + Content-Length: + - "238" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:43 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 9959d5f8-6fc5-4c1a-9487-aa17e3227d6f + status: 200 OK + code: 200 + duration: 125.251315ms + - id: 20 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/route-stages/f157ee76-3c98-4fb1-a230-b6fd6c03d55d/route-rules + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 218 + uncompressed: false + body: '{"route_rules":[{"backend_stage_id":"c16ad531-08d9-4455-b882-180c7ba9aabf","position":1,"route_stage_id":"","rule_http_match":{"method_filters":["get","post"],"path_filter":{"path_filter_type":"regex","value":".*"}}}]}' + headers: + Content-Length: + - "218" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:43 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - f666769a-bb51-4313-af0e-f44ab91bfe0f + status: 200 OK + code: 200 + duration: 124.192963ms + - id: 21 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/route-stages/f157ee76-3c98-4fb1-a230-b6fd6c03d55d + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 238 + uncompressed: false + body: '{"created_at":"2025-03-26T10:26:42.612173Z","id":"f157ee76-3c98-4fb1-a230-b6fd6c03d55d","pipeline_id":"5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340","updated_at":"2025-03-26T10:26:43.090704Z","waf_stage_id":"1337b601-899a-4f7c-a978-fb2d86abcad0"}' + headers: + Content-Length: + - "238" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:43 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 9c5e0e51-99fb-455a-8efe-b77198fdd869 + status: 200 OK + code: 200 + duration: 100.245871ms + - id: 22 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - 333ecf71-fd85-4026-800e-83fec56b14ad + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,e + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102643Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/?acl= + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 698 + uncompressed: false + body: |- + + 564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5:564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5:564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5:564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5:564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5FULL_CONTROL + headers: + Content-Length: + - "698" + Content-Type: + - text/xml; charset=utf-8 + Date: + - Wed, 26 Mar 2025 10:26:44 GMT + X-Amz-Id-2: + - txgf24bacdfa7eb455fa025-0067e3d664 + X-Amz-Request-Id: + - txgf24bacdfa7eb455fa025-0067e3d664 + status: 200 OK + code: 200 + duration: 109.779741ms + - id: 23 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/pipelines/5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 343 + uncompressed: false + body: '{"created_at":"2025-03-26T10:26:32.641789Z","description":"pipeline description","errors":[],"id":"5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340","name":"my-edge-services-pipeline","organization_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","project_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","status":"pending","updated_at":"2025-03-26T10:26:32.641789Z"}' + headers: + Content-Length: + - "343" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:44 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - ecf97d80-c5fd-48f0-9138-d4def6eed496 + status: 200 OK + code: 200 + duration: 140.124395ms + - id: 24 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/waf-stages/1337b601-899a-4f7c-a978-fb2d86abcad0 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 219 + uncompressed: false + body: '{"created_at":"2025-03-26T10:26:33.093099Z","id":"1337b601-899a-4f7c-a978-fb2d86abcad0","mode":"enable","paranoia_level":3,"pipeline_id":"5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340","updated_at":"2025-03-26T10:26:33.093099Z"}' + headers: + Content-Length: + - "219" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:44 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 3872e956-cddd-4fa6-82d0-a4ca258f0885 + status: 200 OK + code: 200 + duration: 101.816961ms + - id: 25 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - 21703b0e-f425-4e56-a0ec-47f9916f1189 + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,e + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102644Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/?object-lock= + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 312 + uncompressed: false + body: ObjectLockConfigurationNotFoundErrorObject Lock configuration does not exist for this buckettxg24d6993d145e49518100-0067e3d664txg24d6993d145e49518100-0067e3d664/test-acc-scaleway-object-bucket-basic-route + headers: + Content-Length: + - "312" + Content-Type: + - application/xml + Date: + - Wed, 26 Mar 2025 10:26:44 GMT + X-Amz-Id-2: + - txg24d6993d145e49518100-0067e3d664 + X-Amz-Request-Id: + - txg24d6993d145e49518100-0067e3d664 + status: 404 Not Found + code: 404 + duration: 257.014099ms + - id: 26 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - d7bead97-2e31-45b9-bd06-9e20d71dc308 + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,e + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102644Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/ + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 269 + uncompressed: false + body: |- + + test-acc-scaleway-object-bucket-basic-route1000false + headers: + Content-Length: + - "269" + Content-Type: + - application/xml + Date: + - Wed, 26 Mar 2025 10:26:44 GMT + X-Amz-Id-2: + - txg5c35c42f64a34d53913a-0067e3d664 + X-Amz-Request-Id: + - txg5c35c42f64a34d53913a-0067e3d664 + status: 200 OK + code: 200 + duration: 256.442796ms + - id: 27 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - f574e166-8e44-4393-8984-e0b7cb3eeb32 + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,e + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102644Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/?tagging= + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 118 + uncompressed: false + body: |- + + foobar + headers: + Content-Length: + - "118" + Content-Type: + - text/xml; charset=utf-8 + Date: + - Wed, 26 Mar 2025 10:26:44 GMT + X-Amz-Id-2: + - txg51cc88c2443f4f0296ee-0067e3d664 + X-Amz-Request-Id: + - txg51cc88c2443f4f0296ee-0067e3d664 + status: 200 OK + code: 200 + duration: 252.154536ms + - id: 28 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - 2c859ba4-aa1a-46b1-84d6-b0b6128fb278 + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,e + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102644Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/?cors= + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 280 + uncompressed: false + body: NoSuchCORSConfigurationThe CORS configuration does not existtxg47bb6ac61285422989b4-0067e3d665txg47bb6ac61285422989b4-0067e3d665/test-acc-scaleway-object-bucket-basic-route + headers: + Content-Length: + - "280" + Content-Type: + - application/xml + Date: + - Wed, 26 Mar 2025 10:26:45 GMT + X-Amz-Id-2: + - txg47bb6ac61285422989b4-0067e3d665 + X-Amz-Request-Id: + - txg47bb6ac61285422989b4-0067e3d665 + status: 404 Not Found + code: 404 + duration: 155.143749ms + - id: 29 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - 8781eacf-6211-4638-906a-a5139a8643e6 + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,e + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102644Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/?versioning= + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 155 + uncompressed: false + body: |- + + + headers: + Content-Length: + - "155" + Content-Type: + - text/xml; charset=utf-8 + Date: + - Wed, 26 Mar 2025 10:26:45 GMT + X-Amz-Id-2: + - txgbd8c176fbd3b4fd78bdc-0067e3d665 + X-Amz-Request-Id: + - txgbd8c176fbd3b4fd78bdc-0067e3d665 + status: 200 OK + code: 200 + duration: 158.25079ms + - id: 30 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - 5022a12f-463c-4af7-88c8-26d26510c1cd + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,e + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102645Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/?lifecycle= + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 358 + uncompressed: false + body: NoSuchLifecycleConfigurationThe lifecycle configuration does not existtxge8654d4fc6cb4f008e73-0067e3d665txge8654d4fc6cb4f008e73-0067e3d665/test-acc-scaleway-object-bucket-basic-routetest-acc-scaleway-object-bucket-basic-route + headers: + Content-Length: + - "358" + Content-Type: + - application/xml + Date: + - Wed, 26 Mar 2025 10:26:45 GMT + X-Amz-Id-2: + - txge8654d4fc6cb4f008e73-0067e3d665 + X-Amz-Request-Id: + - txge8654d4fc6cb4f008e73-0067e3d665 + status: 404 Not Found + code: 404 + duration: 64.379067ms + - id: 31 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/backend-stages/c16ad531-08d9-4455-b882-180c7ba9aabf + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 304 + uncompressed: false + body: '{"created_at":"2025-03-26T10:26:42.338796Z","id":"c16ad531-08d9-4455-b882-180c7ba9aabf","pipeline_id":"5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340","scaleway_s3":{"bucket_name":"test-acc-scaleway-object-bucket-basic-route","bucket_region":"fr-par","is_website":false},"updated_at":"2025-03-26T10:26:42.338796Z"}' + headers: + Content-Length: + - "304" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:45 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 5c9a62e1-6921-4ff9-96fc-57b10377dad5 + status: 200 OK + code: 200 + duration: 120.350936ms + - id: 32 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/route-stages/f157ee76-3c98-4fb1-a230-b6fd6c03d55d + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 238 + uncompressed: false + body: '{"created_at":"2025-03-26T10:26:42.612173Z","id":"f157ee76-3c98-4fb1-a230-b6fd6c03d55d","pipeline_id":"5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340","updated_at":"2025-03-26T10:26:43.090704Z","waf_stage_id":"1337b601-899a-4f7c-a978-fb2d86abcad0"}' + headers: + Content-Length: + - "238" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:45 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 38130e7e-6a92-44bd-bf78-558660b68602 + status: 200 OK + code: 200 + duration: 115.037768ms + - id: 33 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/route-stages/f157ee76-3c98-4fb1-a230-b6fd6c03d55d/route-rules + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 218 + uncompressed: false + body: '{"route_rules":[{"backend_stage_id":"c16ad531-08d9-4455-b882-180c7ba9aabf","position":1,"route_stage_id":"","rule_http_match":{"method_filters":["get","post"],"path_filter":{"path_filter_type":"regex","value":".*"}}}]}' + headers: + Content-Length: + - "218" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:45 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 3426db30-1856-4b34-b49e-9830d54eec84 + status: 200 OK + code: 200 + duration: 116.505491ms + - id: 34 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/route-stages/f157ee76-3c98-4fb1-a230-b6fd6c03d55d + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:46 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - b3b23c2e-45a1-4198-85a1-fbbf4835b4d5 + status: 204 No Content + code: 204 + duration: 126.247206ms + - id: 35 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/backend-stages/c16ad531-08d9-4455-b882-180c7ba9aabf + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:46 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 18b383d9-33e0-4a8e-b28b-ea03efd02204 + status: 204 No Content + code: 204 + duration: 134.623108ms + - id: 36 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/waf-stages/1337b601-899a-4f7c-a978-fb2d86abcad0 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:46 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - a72e5120-4f42-4bc0-bcc5-638e34cc4416 + status: 204 No Content + code: 204 + duration: 142.302505ms + - id: 37 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/pipelines/5ca2ea3f-ddfc-4b11-bcd7-410c98ddf340 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:46 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 7ca9488e-45c2-4e2f-870a-65068d3186a8 + status: 204 No Content + code: 204 + duration: 225.888664ms + - id: 38 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + Accept-Encoding: + - identity + Amz-Sdk-Invocation-Id: + - 1135788e-fcfa-41c8-a77f-b3f3cb1e68ca + Amz-Sdk-Request: + - attempt=1; max=3 + User-Agent: + - aws-sdk-go-v2/1.36.3 ua/2.1 os/macos lang/go#1.24.0 md/GOOS#darwin md/GOARCH#amd64 api/s3#1.78.0 m/E,e + X-Amz-Content-Sha256: + - e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + X-Amz-Date: + - 20250326T102646Z + url: https://test-acc-scaleway-object-bucket-basic-route.s3.fr-par.scw.cloud/ + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Date: + - Wed, 26 Mar 2025 10:26:46 GMT + X-Amz-Id-2: + - txg5ecbc9d424aa47d49be2-0067e3d666 + X-Amz-Request-Id: + - txg5ecbc9d424aa47d49be2-0067e3d666 + status: 204 No Content + code: 204 + duration: 343.828563ms + - id: 39 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/route-stages/f157ee76-3c98-4fb1-a230-b6fd6c03d55d + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 31 + uncompressed: false + body: '{"message":"Permission denied"}' + headers: + Content-Length: + - "31" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 10:26:47 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge03) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - f4761b6f-0c24-4926-8c7e-a4447f46b127 + status: 403 Forbidden + code: 403 + duration: 101.588438ms diff --git a/internal/services/edgeservices/testdata/edge-services-waf-basic.cassette.yaml b/internal/services/edgeservices/testdata/edge-services-waf-basic.cassette.yaml new file mode 100644 index 0000000000..804e74495f --- /dev/null +++ b/internal/services/edgeservices/testdata/edge-services-waf-basic.cassette.yaml @@ -0,0 +1,493 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 125 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: '{"project_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","name":"my-edge_services-pipeline","description":"pipeline description"}' + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/pipelines + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 349 + uncompressed: false + body: '{"created_at":"2025-03-26T08:52:23.524205643Z","description":"pipeline description","errors":[],"id":"eec1bc8b-416d-427d-852e-02a6b2ff4b06","name":"my-edge_services-pipeline","organization_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","project_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","status":"pending","updated_at":"2025-03-26T08:52:23.524205643Z"}' + headers: + Content-Length: + - "349" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 08:52:23 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 10a62a0e-8267-464c-a206-95d72a31cc79 + status: 200 OK + code: 200 + duration: 464.502491ms + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/pipelines/eec1bc8b-416d-427d-852e-02a6b2ff4b06 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 343 + uncompressed: false + body: '{"created_at":"2025-03-26T08:52:23.524205Z","description":"pipeline description","errors":[],"id":"eec1bc8b-416d-427d-852e-02a6b2ff4b06","name":"my-edge_services-pipeline","organization_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","project_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","status":"pending","updated_at":"2025-03-26T08:52:23.524205Z"}' + headers: + Content-Length: + - "343" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 08:52:23 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - fa38c9f6-339f-44b5-b8ea-baad5eb52018 + status: 200 OK + code: 200 + duration: 100.644088ms + - id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 36 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: '{"mode":"enable","paranoia_level":3}' + form: {} + headers: + Content-Type: + - application/json + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/pipelines/eec1bc8b-416d-427d-852e-02a6b2ff4b06/waf-stages + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 225 + uncompressed: false + body: '{"created_at":"2025-03-26T08:52:23.799835302Z","id":"b761f774-40dc-4a86-90b9-a92bcebb6851","mode":"enable","paranoia_level":3,"pipeline_id":"eec1bc8b-416d-427d-852e-02a6b2ff4b06","updated_at":"2025-03-26T08:52:23.799835302Z"}' + headers: + Content-Length: + - "225" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 08:52:23 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - fb70f2d2-ec22-4686-b5d7-4fb453335961 + status: 200 OK + code: 200 + duration: 97.565765ms + - id: 3 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/waf-stages/b761f774-40dc-4a86-90b9-a92bcebb6851 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 219 + uncompressed: false + body: '{"created_at":"2025-03-26T08:52:23.799835Z","id":"b761f774-40dc-4a86-90b9-a92bcebb6851","mode":"enable","paranoia_level":3,"pipeline_id":"eec1bc8b-416d-427d-852e-02a6b2ff4b06","updated_at":"2025-03-26T08:52:23.799835Z"}' + headers: + Content-Length: + - "219" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 08:52:23 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 1f898be4-4538-496b-8b9e-614893f120b9 + status: 200 OK + code: 200 + duration: 115.526841ms + - id: 4 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/waf-stages/b761f774-40dc-4a86-90b9-a92bcebb6851 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 219 + uncompressed: false + body: '{"created_at":"2025-03-26T08:52:23.799835Z","id":"b761f774-40dc-4a86-90b9-a92bcebb6851","mode":"enable","paranoia_level":3,"pipeline_id":"eec1bc8b-416d-427d-852e-02a6b2ff4b06","updated_at":"2025-03-26T08:52:23.799835Z"}' + headers: + Content-Length: + - "219" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 08:52:24 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - a7a9afa8-5cfc-45b3-9589-b46853f30802 + status: 200 OK + code: 200 + duration: 114.349521ms + - id: 5 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/pipelines/eec1bc8b-416d-427d-852e-02a6b2ff4b06 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 343 + uncompressed: false + body: '{"created_at":"2025-03-26T08:52:23.524205Z","description":"pipeline description","errors":[],"id":"eec1bc8b-416d-427d-852e-02a6b2ff4b06","name":"my-edge_services-pipeline","organization_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","project_id":"564aa517-68b0-4fd7-8c8c-d21c4bcdcbd5","status":"pending","updated_at":"2025-03-26T08:52:23.524205Z"}' + headers: + Content-Length: + - "343" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 08:52:24 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 3f899161-847c-4ab9-bd20-73b620eaaeab + status: 200 OK + code: 200 + duration: 99.420742ms + - id: 6 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/waf-stages/b761f774-40dc-4a86-90b9-a92bcebb6851 + method: GET + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 219 + uncompressed: false + body: '{"created_at":"2025-03-26T08:52:23.799835Z","id":"b761f774-40dc-4a86-90b9-a92bcebb6851","mode":"enable","paranoia_level":3,"pipeline_id":"eec1bc8b-416d-427d-852e-02a6b2ff4b06","updated_at":"2025-03-26T08:52:23.799835Z"}' + headers: + Content-Length: + - "219" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 08:52:24 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - c5175da0-dd7e-4ebc-91a9-00594103e16e + status: 200 OK + code: 200 + duration: 93.14413ms + - id: 7 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/waf-stages/b761f774-40dc-4a86-90b9-a92bcebb6851 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 08:52:25 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - c5b159eb-86ac-46c4-9146-90458fdb4c27 + status: 204 No Content + code: 204 + duration: 128.220881ms + - id: 8 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/pipelines/eec1bc8b-416d-427d-852e-02a6b2ff4b06 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 0 + uncompressed: false + body: "" + headers: + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 08:52:25 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 50b765ee-7556-485e-a2a1-07318a0cb47e + status: 204 No Content + code: 204 + duration: 207.432364ms + - id: 9 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 0 + transfer_encoding: [] + trailer: {} + host: api.scaleway.com + remote_addr: "" + request_uri: "" + body: "" + form: {} + headers: + User-Agent: + - scaleway-sdk-go/v1.0.0-beta.7+dev (go1.24.0; darwin; amd64) terraform-provider/develop terraform/terraform-tests + url: https://api.scaleway.com/edge-services/v1beta1/waf-stages/b761f774-40dc-4a86-90b9-a92bcebb6851 + method: DELETE + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + transfer_encoding: [] + trailer: {} + content_length: 31 + uncompressed: false + body: '{"message":"Permission denied"}' + headers: + Content-Length: + - "31" + Content-Security-Policy: + - default-src 'none'; frame-ancestors 'none' + Content-Type: + - application/json + Date: + - Wed, 26 Mar 2025 08:52:25 GMT + Server: + - Scaleway API Gateway (fr-par-3;edge01) + Strict-Transport-Security: + - max-age=63072000 + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + X-Request-Id: + - 7b8c0c88-168d-4c4a-984c-f50e3e1973d6 + status: 403 Forbidden + code: 403 + duration: 106.825439ms diff --git a/internal/services/edgeservices/testfuncs/checks.go b/internal/services/edgeservices/testfuncs/checks.go index 523db98d01..c6e0570690 100644 --- a/internal/services/edgeservices/testfuncs/checks.go +++ b/internal/services/edgeservices/testfuncs/checks.go @@ -151,6 +151,62 @@ func CheckEdgeServicesCacheDestroy(tt *acctest.TestTools) resource.TestCheckFunc } } +func CheckEdgeServicesWAFDestroy(tt *acctest.TestTools) resource.TestCheckFunc { + return func(state *terraform.State) error { + for _, rs := range state.RootModule().Resources { + if rs.Type != "scaleway_edge_services_waf_stage" { + continue + } + + edgeAPI := edgeservices.NewEdgeServicesAPI(tt.Meta) + + err := edgeAPI.DeleteWafStage(&edge.DeleteWafStageRequest{ + WafStageID: rs.Primary.ID, + }) + + // If no error resource still exist + if err == nil { + return fmt.Errorf("WAF stage (%s) still exists", rs.Primary.ID) + } + + // Unexpected api error we return it + if !httperrors.Is404(err) && !httperrors.Is403(err) { + return err + } + } + + return nil + } +} + +func CheckEdgeServicesRouteDestroy(tt *acctest.TestTools) resource.TestCheckFunc { + return func(state *terraform.State) error { + for _, rs := range state.RootModule().Resources { + if rs.Type != "scaleway_edge_services_route_stage" { + continue + } + + edgeAPI := edgeservices.NewEdgeServicesAPI(tt.Meta) + + err := edgeAPI.DeleteRouteStage(&edge.DeleteRouteStageRequest{ + RouteStageID: rs.Primary.ID, + }) + + // If no error resource still exist + if err == nil { + return fmt.Errorf("route stage (%s) still exists", rs.Primary.ID) + } + + // Unexpected api error we return it + if !httperrors.Is404(err) && !httperrors.Is403(err) { + return err + } + } + + return nil + } +} + func CheckEdgeServicesPipelineExists(tt *acctest.TestTools, n string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -250,3 +306,43 @@ func CheckEdgeServicesTLSExists(tt *acctest.TestTools, n string) resource.TestCh return nil } } + +func CheckEdgeServicesWAFExists(tt *acctest.TestTools, n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("resource not found: %s", n) + } + + edgeAPI := edgeservices.NewEdgeServicesAPI(tt.Meta) + + _, err := edgeAPI.GetWafStage(&edge.GetWafStageRequest{ + WafStageID: rs.Primary.ID, + }) + if err != nil { + return err + } + + return nil + } +} + +func CheckEdgeServicesRouteExists(tt *acctest.TestTools, n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("resource not found: %s", n) + } + + edgeAPI := edgeservices.NewEdgeServicesAPI(tt.Meta) + + _, err := edgeAPI.GetRouteStage(&edge.GetRouteStageRequest{ + RouteStageID: rs.Primary.ID, + }) + if err != nil { + return err + } + + return nil + } +} diff --git a/internal/services/edgeservices/testfuncs/sweep.go b/internal/services/edgeservices/testfuncs/sweep.go index 96ee927909..1b850dd37c 100644 --- a/internal/services/edgeservices/testfuncs/sweep.go +++ b/internal/services/edgeservices/testfuncs/sweep.go @@ -35,6 +35,14 @@ func AddTestSweepers() { Name: "scaleway_edge_services_plan", F: testSweepPlan, }) + resource.AddTestSweepers("scaleway_edge_services_waf_stage", &resource.Sweeper{ + Name: "scaleway_edge_services_waf_stage", + F: testSweepWAF, + }) + resource.AddTestSweepers("scaleway_edge_services_route_stage", &resource.Sweeper{ + Name: "scaleway_edge_services_route_stage", + F: testSweepRoute, + }) } func testSweepPipeline(_ string) error { @@ -168,3 +176,47 @@ func testSweepPlan(_ string) error { return nil }) } + +func testSweepWAF(_ string) error { + return acctest.Sweep(func(scwClient *scw.Client) error { + edgeAPI := edgeservices.NewEdgeServicesAPI(scwClient) + + listWAF, err := edgeAPI.ListWafStages(&edge.ListWafStagesRequest{}) + if err != nil { + return fmt.Errorf("failed to list WAF stage: %w", err) + } + + for _, stage := range listWAF.Stages { + err = edgeAPI.DeleteWafStage(&edge.DeleteWafStageRequest{ + WafStageID: stage.ID, + }) + if err != nil { + return fmt.Errorf("failed to delete WAF stage: %w", err) + } + } + + return nil + }) +} + +func testSweepRoute(_ string) error { + return acctest.Sweep(func(scwClient *scw.Client) error { + edgeAPI := edgeservices.NewEdgeServicesAPI(scwClient) + + listRoutes, err := edgeAPI.ListRouteStages(&edge.ListRouteStagesRequest{}) + if err != nil { + return fmt.Errorf("failed to list route stage: %w", err) + } + + for _, stage := range listRoutes.Stages { + err = edgeAPI.DeleteRouteStage(&edge.DeleteRouteStageRequest{ + RouteStageID: stage.ID, + }) + if err != nil { + return fmt.Errorf("failed to delete route stage: %w", err) + } + } + + return nil + }) +} diff --git a/internal/services/edgeservices/types.go b/internal/services/edgeservices/types.go index 86d6f2de6c..4ff7ba2ce5 100644 --- a/internal/services/edgeservices/types.go +++ b/internal/services/edgeservices/types.go @@ -140,3 +140,122 @@ func wrapSecretsInConfig(secrets []*edge_services.TLSSecret) *edge_services.TLSS TLSSecrets: secrets, } } + +func expandRouteRules(raw interface{}) []*edge_services.SetRouteRulesRequestRouteRule { + if raw == nil { + return nil + } + + rulesList := raw.([]interface{}) + result := make([]*edge_services.SetRouteRulesRequestRouteRule, 0, len(rulesList)) + + for _, rawRule := range rulesList { + ruleMap := rawRule.(map[string]interface{}) + rule := &edge_services.SetRouteRulesRequestRouteRule{ + BackendStageID: types.ExpandStringPtr(ruleMap["backend_stage_id"].(string)), + } + + if rawHTTPMatch, ok := ruleMap["rule_http_match"]; ok && rawHTTPMatch != nil { + if expandedHTTP := expandRuleHTTPMatch(rawHTTPMatch); expandedHTTP != nil { + rule.RuleHTTPMatch = expandedHTTP + } + } + + result = append(result, rule) + } + + return result +} + +func expandRuleHTTPMatch(raw interface{}) *edge_services.RuleHTTPMatch { + list, ok := raw.([]interface{}) + if !ok || len(list) < 1 { + return nil + } + + ruleMap := list[0].(map[string]interface{}) + result := &edge_services.RuleHTTPMatch{} + + if v, exists := ruleMap["method_filters"]; exists && v != nil { + filters := v.([]interface{}) + result.MethodFilters = make([]edge_services.RuleHTTPMatchMethodFilter, len(filters)) + + for i, item := range filters { + result.MethodFilters[i] = edge_services.RuleHTTPMatchMethodFilter(item.(string)) + } + } + + if rawPF, exists := ruleMap["path_filter"]; exists && rawPF != nil { + result.PathFilter = expandRuleHTTPMatchPathFilter(rawPF) + } + + return result +} + +func expandRuleHTTPMatchPathFilter(raw interface{}) *edge_services.RuleHTTPMatchPathFilter { + list, ok := raw.([]interface{}) + if !ok || len(list) < 1 { + return nil + } + + mapPF := list[0].(map[string]interface{}) + + return &edge_services.RuleHTTPMatchPathFilter{ + PathFilterType: edge_services.RuleHTTPMatchPathFilterPathFilterType(mapPF["path_filter_type"].(string)), + Value: mapPF["value"].(string), + } +} + +func flattenRouteRules(rules []*edge_services.RouteRule) []interface{} { + if rules == nil { + return nil + } + + result := make([]interface{}, 0, len(rules)) + + for _, rule := range rules { + m := map[string]interface{}{ + "backend_stage_id": types.FlattenStringPtr(rule.BackendStageID), + "rule_http_match": flattenRuleHTTPMatch(rule.RuleHTTPMatch), + } + result = append(result, m) + } + + return result +} + +func flattenRuleHTTPMatch(match *edge_services.RuleHTTPMatch) []interface{} { + if match == nil { + return nil + } + + m := map[string]interface{}{} + + if len(match.MethodFilters) > 0 { + filters := make([]interface{}, len(match.MethodFilters)) + for i, v := range match.MethodFilters { + filters[i] = string(v) + } + + m["method_filters"] = filters + } else { + m["method_filters"] = []interface{}{} + } + + m["path_filter"] = flattenRuleHTTPMatchPathFilter(match.PathFilter) + + return []interface{}{m} +} + +func flattenRuleHTTPMatchPathFilter(pathFilter *edge_services.RuleHTTPMatchPathFilter) []interface{} { + if pathFilter == nil { + return nil + } + + m := map[string]interface{}{ + "path_filter_type": pathFilter.PathFilterType.String(), + "value": pathFilter.Value, + } + + return []interface{}{m} +} diff --git a/internal/services/edgeservices/waf_stage.go b/internal/services/edgeservices/waf_stage.go new file mode 100644 index 0000000000..7af4b0ebce --- /dev/null +++ b/internal/services/edgeservices/waf_stage.go @@ -0,0 +1,152 @@ +package edgeservices + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + edgeservices "github.com/scaleway/scaleway-sdk-go/api/edge_services/v1beta1" + "github.com/scaleway/scaleway-sdk-go/scw" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/httperrors" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/account" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/types" +) + +func ResourceWAFStage() *schema.Resource { + return &schema.Resource{ + CreateContext: ResourceWAFStageCreate, + ReadContext: ResourceWAFStageRead, + UpdateContext: ResourceWAFStageUpdate, + DeleteContext: ResourceWAFStageDelete, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + SchemaVersion: 0, + Schema: map[string]*schema.Schema{ + "pipeline_id": { + Type: schema.TypeString, + Required: true, + Description: "The ID of the pipeline", + }, + "backend_stage_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "The ID of the backend stage to forward requests to after the WAF stage", + }, + "paranoia_level": { + Type: schema.TypeInt, + Required: true, + Description: "The sensitivity level (`1`,`2`,`3`,`4`) to use when classifying requests as malicious. With a high level, requests are more likely to be classed as malicious, and false positives are expected. With a lower level, requests are more likely to be classed as benign", + }, + "mode": { + Type: schema.TypeString, + Optional: true, + Computed: true, + Description: "Mode defining WAF behavior (`disable`/`log_only`/`enable`)", + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + Description: "The date and time of the creation of the WAF stage", + }, + "updated_at": { + Type: schema.TypeString, + Computed: true, + Description: "The date and time of the last update of the WAF stage", + }, + "project_id": account.ProjectIDSchema(), + }, + } +} + +func ResourceWAFStageCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + api := NewEdgeServicesAPI(m) + + wafStage, err := api.CreateWafStage(&edgeservices.CreateWafStageRequest{ + PipelineID: d.Get("pipeline_id").(string), + BackendStageID: types.ExpandStringPtr(d.Get("backend_stage_id").(string)), + ParanoiaLevel: uint32(d.Get("paranoia_level").(int)), + Mode: edgeservices.WafStageMode(d.Get("mode").(string)), + }, scw.WithContext(ctx)) + if err != nil { + return diag.FromErr(err) + } + + d.SetId(wafStage.ID) + + return ResourceWAFStageRead(ctx, d, m) +} + +func ResourceWAFStageRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + api := NewEdgeServicesAPI(m) + + wafStage, err := api.GetWafStage(&edgeservices.GetWafStageRequest{ + WafStageID: d.Id(), + }, scw.WithContext(ctx)) + if err != nil { + if httperrors.Is404(err) { + d.SetId("") + + return nil + } + + return diag.FromErr(err) + } + + _ = d.Set("pipeline_id", wafStage.PipelineID) + _ = d.Set("backend_stage_id", types.FlattenStringPtr(wafStage.BackendStageID)) + _ = d.Set("paranoia_level", int(wafStage.ParanoiaLevel)) + _ = d.Set("mode", wafStage.Mode.String()) + _ = d.Set("created_at", types.FlattenTime(wafStage.CreatedAt)) + _ = d.Set("updated_at", types.FlattenTime(wafStage.UpdatedAt)) + + return nil +} + +func ResourceWAFStageUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + api := NewEdgeServicesAPI(m) + + hasChanged := false + + updateRequest := &edgeservices.UpdateWafStageRequest{ + WafStageID: d.Id(), + } + + if d.HasChange("mode") { + updateRequest.Mode = edgeservices.WafStageMode(d.Get("mode").(string)) + hasChanged = true + } + + if d.HasChange("paranoia_level") { + updateRequest.ParanoiaLevel = types.ExpandUint32Ptr(d.Get("paranoia_level")) + hasChanged = true + } + + if d.HasChange("backend_stage_id") { + updateRequest.BackendStageID = types.ExpandStringPtr(d.Get("backend_stage_id").(string)) + hasChanged = true + } + + if hasChanged { + _, err := api.UpdateWafStage(updateRequest, scw.WithContext(ctx)) + if err != nil { + return diag.FromErr(err) + } + } + + return ResourceWAFStageRead(ctx, d, m) +} + +func ResourceWAFStageDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + api := NewEdgeServicesAPI(m) + + err := api.DeleteWafStage(&edgeservices.DeleteWafStageRequest{ + WafStageID: d.Id(), + }, scw.WithContext(ctx)) + if err != nil && !httperrors.Is404(err) { + return diag.FromErr(err) + } + + return nil +} diff --git a/internal/services/edgeservices/waf_stage_test.go b/internal/services/edgeservices/waf_stage_test.go new file mode 100644 index 0000000000..ae2417f8e6 --- /dev/null +++ b/internal/services/edgeservices/waf_stage_test.go @@ -0,0 +1,45 @@ +package edgeservices_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/scaleway/terraform-provider-scaleway/v2/internal/acctest" + edgeservicestestfuncs "github.com/scaleway/terraform-provider-scaleway/v2/internal/services/edgeservices/testfuncs" +) + +func TestAccEdgeServicesWAF_Basic(t *testing.T) { + tt := acctest.NewTestTools(t) + defer tt.Cleanup() + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ProviderFactories: tt.ProviderFactories, + CheckDestroy: edgeservicestestfuncs.CheckEdgeServicesWAFDestroy(tt), + Steps: []resource.TestStep{ + { + Config: ` + resource "scaleway_edge_services_pipeline" "main" { + name = "my-edge_services-pipeline" + description = "pipeline description" + } + + resource "scaleway_edge_services_waf_stage" "main" { + pipeline_id = scaleway_edge_services_pipeline.main.id + mode = "enable" + paranoia_level = 3 + } + `, + Check: resource.ComposeTestCheckFunc( + edgeservicestestfuncs.CheckEdgeServicesWAFExists(tt, "scaleway_edge_services_waf_stage.main"), + resource.TestCheckResourceAttrPair( + "scaleway_edge_services_pipeline.main", "id", + "scaleway_edge_services_waf_stage.main", "pipeline_id"), + resource.TestCheckResourceAttr("scaleway_edge_services_waf_stage.main", "mode", "enable"), + resource.TestCheckResourceAttr("scaleway_edge_services_waf_stage.main", "paranoia_level", "3"), + resource.TestCheckResourceAttrSet("scaleway_edge_services_waf_stage.main", "created_at"), + resource.TestCheckResourceAttrSet("scaleway_edge_services_waf_stage.main", "updated_at"), + ), + }, + }, + }) +} diff --git a/internal/types/number.go b/internal/types/number.go index 0b68174db0..5be0b8eaf8 100644 --- a/internal/types/number.go +++ b/internal/types/number.go @@ -33,3 +33,11 @@ func ExpandUint32Ptr(data interface{}) *uint32 { return scw.Uint32Ptr(uint32(data.(int))) } + +func ExpandUint64Ptr(data interface{}) *uint64 { + if data == nil || data == "" { + return nil + } + + return scw.Uint64Ptr(uint64(data.(int))) +}