From c2fcbebff4e5fbcf7f01c67e68f42e241a6aa860 Mon Sep 17 00:00:00 2001 From: Maxime Guerreiro Date: Thu, 21 Dec 2023 23:17:36 +0100 Subject: [PATCH 1/2] Update VCR for Turnstile Widgets This includes more widgets, including more 'exotic' configs - and adds new response fields introduced over time. --- .../app/cf-terraforming/cmd/generate_test.go | 1 + .../cloudflare_turnstile_widget.yaml | 2 +- ...loudflare_turnstile_widget_no_domains.yaml | 22 +++++++++++++++++++ .../cloudflare_turnstile_widget/test.tf | 6 ++--- .../provider.tf | 7 ++++++ .../test.tf | 6 +++++ 6 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 testdata/cloudflare/cloudflare_turnstile_widget_no_domains.yaml create mode 100644 testdata/terraform/cloudflare_turnstile_widget_no_domains/provider.tf create mode 100644 testdata/terraform/cloudflare_turnstile_widget_no_domains/test.tf diff --git a/internal/app/cf-terraforming/cmd/generate_test.go b/internal/app/cf-terraforming/cmd/generate_test.go index 3d7d8f46e..8aa4fb778 100644 --- a/internal/app/cf-terraforming/cmd/generate_test.go +++ b/internal/app/cf-terraforming/cmd/generate_test.go @@ -140,6 +140,7 @@ func TestResourceGeneration(t *testing.T) { "cloudflare spectrum application": {identiferType: "zone", resourceType: "cloudflare_spectrum_application", testdataFilename: "cloudflare_spectrum_application"}, "cloudflare tunnel": {identiferType: "account", resourceType: "cloudflare_tunnel", testdataFilename: "cloudflare_tunnel"}, "cloudflare turnstile_widget": {identiferType: "account", resourceType: "cloudflare_turnstile_widget", testdataFilename: "cloudflare_turnstile_widget"}, + "cloudflare turnstile_widget_no_domains": {identiferType: "account", resourceType: "cloudflare_turnstile_widget", testdataFilename: "cloudflare_turnstile_widget_no_domains"}, "cloudflare url normalization settings": {identiferType: "zone", resourceType: "cloudflare_url_normalization_settings", testdataFilename: "cloudflare_url_normalization_settings"}, "cloudflare user agent blocking rule": {identiferType: "zone", resourceType: "cloudflare_user_agent_blocking_rule", testdataFilename: "cloudflare_user_agent_blocking_rule"}, "cloudflare waiting room": {identiferType: "zone", resourceType: "cloudflare_waiting_room", testdataFilename: "cloudflare_waiting_room"}, diff --git a/testdata/cloudflare/cloudflare_turnstile_widget.yaml b/testdata/cloudflare/cloudflare_turnstile_widget.yaml index 78d66fe4b..ce6feca9c 100644 --- a/testdata/cloudflare/cloudflare_turnstile_widget.yaml +++ b/testdata/cloudflare/cloudflare_turnstile_widget.yaml @@ -11,7 +11,7 @@ interactions: method: GET response: body: | - {"result":[{"sitekey":"0x4AAAAAAAEg5sP3rwf91fe8","modified_on":"2023-05-08T11:49:41.862676Z","created_on":"2023-05-08T11:49:41.862676Z","mode":"managed","domains":["example.com"],"name":"test site","bot_fight_mode":false,"region":"world","offlabel":false}],"success":true,"errors":[],"messages":[],"result_info":{"page":1,"per_page":25,"count":3,"total_count":3,"total_pages":1}} + {"result":[{"sitekey":"0xAAAAAAAAAAAAAAAAAAAAABC","modified_on":"2023-12-20T13:39:04.94052Z","created_on":"2022-05-18T14:21:50.966586Z","mode":"non-interactive","domains":["example.com","example.net"],"name":"example sitekey","bot_fight_mode":false,"region":"world","offlabel":false,"clearance_level":"no_clearance"}],"success":true,"errors":[],"messages":[],"result_info":{"page":1,"per_page":25,"count":1,"total_count":1,"total_pages":1}} headers: Content-Type: - application/json diff --git a/testdata/cloudflare/cloudflare_turnstile_widget_no_domains.yaml b/testdata/cloudflare/cloudflare_turnstile_widget_no_domains.yaml new file mode 100644 index 000000000..9f4c6ad3c --- /dev/null +++ b/testdata/cloudflare/cloudflare_turnstile_widget_no_domains.yaml @@ -0,0 +1,22 @@ +--- +version: 1 +interactions: +- request: + body: "" + form: {} + headers: + Content-Type: + - application/json + url: https://api.cloudflare.com/client/v4/accounts/f037e56e89293a057740de681ac9abbe/challenges/widgets?page=1&per_page=25 + method: GET + response: + body: | + {"result":[{"sitekey":"0xAAAAAAAAAAAAAAAAAAAAABC","modified_on":"2023-12-20T13:39:04.94052Z","created_on":"2022-05-18T14:21:50.966586Z","mode":"non-interactive","domains":[],"name":"example sitekey with no domains","bot_fight_mode":false,"region":"world","offlabel":false,"clearance_level":"no_clearance"}],"success":true,"errors":[],"messages":[],"result_info":{"page":1,"per_page":25,"count":1,"total_count":1,"total_pages":1}} + headers: + Content-Type: + - application/json + Vary: + - Accept-Encoding + status: 200 OK + code: 200 + duration: "" diff --git a/testdata/terraform/cloudflare_turnstile_widget/test.tf b/testdata/terraform/cloudflare_turnstile_widget/test.tf index 0c4eddee2..0d6af7107 100644 --- a/testdata/terraform/cloudflare_turnstile_widget/test.tf +++ b/testdata/terraform/cloudflare_turnstile_widget/test.tf @@ -1,7 +1,7 @@ resource "cloudflare_turnstile_widget" "terraform_managed_resource" { account_id = "f037e56e89293a057740de681ac9abbe" - domains = ["example.com"] - mode = "managed" - name = "test site" + domains = ["example.com", "example.net"] + mode = "non-interactive" + name = "example sitekey" region = "world" } diff --git a/testdata/terraform/cloudflare_turnstile_widget_no_domains/provider.tf b/testdata/terraform/cloudflare_turnstile_widget_no_domains/provider.tf new file mode 100644 index 000000000..6d4066837 --- /dev/null +++ b/testdata/terraform/cloudflare_turnstile_widget_no_domains/provider.tf @@ -0,0 +1,7 @@ +terraform { + required_providers { + cloudflare = { + source = "cloudflare/cloudflare" + } + } +} diff --git a/testdata/terraform/cloudflare_turnstile_widget_no_domains/test.tf b/testdata/terraform/cloudflare_turnstile_widget_no_domains/test.tf new file mode 100644 index 000000000..df2e7e2c9 --- /dev/null +++ b/testdata/terraform/cloudflare_turnstile_widget_no_domains/test.tf @@ -0,0 +1,6 @@ +resource "cloudflare_turnstile_widget" "terraform_managed_resource" { + account_id = "f037e56e89293a057740de681ac9abbe" + mode = "non-interactive" + name = "example sitekey with no domains" + region = "world" +} From f787ca46877100fb53528600bf94d78ee1cc5812 Mon Sep 17 00:00:00 2001 From: Maxime Guerreiro Date: Thu, 21 Dec 2023 22:43:54 +0100 Subject: [PATCH 2/2] Always emit Turnstile domains, even when empty When Turnstile is configured with an empty list of domains, no validation is performed by Cloudflare - the widget can be used anywhere. The website owner is responsible for validating the challenge was solved on the "right" website. This feature is gated behind an entitlement, and `domains = []` is used to enable this. This is *not* a default value for domains, it must be picked explicitly. Fixes #655. --- internal/app/cf-terraforming/cmd/generate.go | 6 +++ .../app/cf-terraforming/cmd/generate_test.go | 48 +++++++++---------- internal/app/cf-terraforming/cmd/util.go | 2 + .../test.tf | 1 + 4 files changed, 33 insertions(+), 24 deletions(-) diff --git a/internal/app/cf-terraforming/cmd/generate.go b/internal/app/cf-terraforming/cmd/generate.go index c759e7a8a..735e37a7c 100644 --- a/internal/app/cf-terraforming/cmd/generate.go +++ b/internal/app/cf-terraforming/cmd/generate.go @@ -931,6 +931,12 @@ func generateResources() func(cmd *cobra.Command, args []string) { for i := 0; i < resourceCount; i++ { jsonStructData[i].(map[string]interface{})["id"] = jsonStructData[i].(map[string]interface{})["sitekey"] + + // We always want to emit a list of domains, even if it is empty. + // The empty list is used to enable the "Allow on any hostname" feature, it is *not* a default value. + if jsonStructData[i].(map[string]interface{})["domains"] == nil { + jsonStructData[i].(map[string]interface{})["domains"] = []string{} + } } case "cloudflare_url_normalization_settings": jsonPayload, err := api.URLNormalizationSettings(context.Background(), &cloudflare.ResourceContainer{Identifier: zoneID, Level: cloudflare.ZoneRouteLevel}) diff --git a/internal/app/cf-terraforming/cmd/generate_test.go b/internal/app/cf-terraforming/cmd/generate_test.go index 8aa4fb778..7f3a82620 100644 --- a/internal/app/cf-terraforming/cmd/generate_test.go +++ b/internal/app/cf-terraforming/cmd/generate_test.go @@ -89,29 +89,29 @@ func TestResourceGeneration(t *testing.T) { resourceType string testdataFilename string }{ - "cloudflare access application simple (account)": {identiferType: "account", resourceType: "cloudflare_access_application", testdataFilename: "cloudflare_access_application_simple_account"}, - "cloudflare access application with CORS (account)": {identiferType: "account", resourceType: "cloudflare_access_application", testdataFilename: "cloudflare_access_application_with_cors_account"}, - "cloudflare access IdP OAuth (account)": {identiferType: "account", resourceType: "cloudflare_access_identity_provider", testdataFilename: "cloudflare_access_identity_provider_oauth_account"}, - "cloudflare access IdP OAuth (zone)": {identiferType: "zone", resourceType: "cloudflare_access_identity_provider", testdataFilename: "cloudflare_access_identity_provider_oauth_zone"}, - "cloudflare access IdP OTP (account)": {identiferType: "account", resourceType: "cloudflare_access_identity_provider", testdataFilename: "cloudflare_access_identity_provider_otp_account"}, - "cloudflare access IdP OTP (zone)": {identiferType: "zone", resourceType: "cloudflare_access_identity_provider", testdataFilename: "cloudflare_access_identity_provider_otp_zone"}, - "cloudflare access rule (account)": {identiferType: "account", resourceType: "cloudflare_access_rule", testdataFilename: "cloudflare_access_rule_account"}, - "cloudflare access rule (zone)": {identiferType: "zone", resourceType: "cloudflare_access_rule", testdataFilename: "cloudflare_access_rule_zone"}, - "cloudflare account member": {identiferType: "account", resourceType: "cloudflare_account_member", testdataFilename: "cloudflare_account_member"}, - "cloudflare api shield": {identiferType: "zone", resourceType: "cloudflare_api_shield", testdataFilename: "cloudflare_api_shield"}, - "cloudflare argo": {identiferType: "zone", resourceType: "cloudflare_argo", testdataFilename: "cloudflare_argo"}, - "cloudflare bot management": {identiferType: "zone", resourceType: "cloudflare_bot_management", testdataFilename: "cloudflare_bot_management"}, - "cloudflare BYO IP prefix": {identiferType: "account", resourceType: "cloudflare_byo_ip_prefix", testdataFilename: "cloudflare_byo_ip_prefix"}, - "cloudflare certificate pack": {identiferType: "zone", resourceType: "cloudflare_certificate_pack", testdataFilename: "cloudflare_certificate_pack_acm"}, - "cloudflare custom hostname fallback origin": {identiferType: "zone", resourceType: "cloudflare_custom_hostname_fallback_origin", testdataFilename: "cloudflare_custom_hostname_fallback_origin"}, - "cloudflare custom hostname": {identiferType: "zone", resourceType: "cloudflare_custom_hostname", testdataFilename: "cloudflare_custom_hostname"}, - "cloudflare custom pages (account)": {identiferType: "account", resourceType: "cloudflare_custom_pages", testdataFilename: "cloudflare_custom_pages_account"}, - "cloudflare custom pages (zone)": {identiferType: "zone", resourceType: "cloudflare_custom_pages", testdataFilename: "cloudflare_custom_pages_zone"}, - "cloudflare filter": {identiferType: "zone", resourceType: "cloudflare_filter", testdataFilename: "cloudflare_filter"}, - "cloudflare firewall rule": {identiferType: "zone", resourceType: "cloudflare_firewall_rule", testdataFilename: "cloudflare_firewall_rule"}, - "cloudflare health check": {identiferType: "zone", resourceType: "cloudflare_healthcheck", testdataFilename: "cloudflare_healthcheck"}, - "cloudflare load balancer monitor": {identiferType: "account", resourceType: "cloudflare_load_balancer_monitor", testdataFilename: "cloudflare_load_balancer_monitor"}, - "cloudflare load balancer pool": {identiferType: "account", resourceType: "cloudflare_load_balancer_pool", testdataFilename: "cloudflare_load_balancer_pool"}, + "cloudflare access application simple (account)": {identiferType: "account", resourceType: "cloudflare_access_application", testdataFilename: "cloudflare_access_application_simple_account"}, + "cloudflare access application with CORS (account)": {identiferType: "account", resourceType: "cloudflare_access_application", testdataFilename: "cloudflare_access_application_with_cors_account"}, + "cloudflare access IdP OAuth (account)": {identiferType: "account", resourceType: "cloudflare_access_identity_provider", testdataFilename: "cloudflare_access_identity_provider_oauth_account"}, + "cloudflare access IdP OAuth (zone)": {identiferType: "zone", resourceType: "cloudflare_access_identity_provider", testdataFilename: "cloudflare_access_identity_provider_oauth_zone"}, + "cloudflare access IdP OTP (account)": {identiferType: "account", resourceType: "cloudflare_access_identity_provider", testdataFilename: "cloudflare_access_identity_provider_otp_account"}, + "cloudflare access IdP OTP (zone)": {identiferType: "zone", resourceType: "cloudflare_access_identity_provider", testdataFilename: "cloudflare_access_identity_provider_otp_zone"}, + "cloudflare access rule (account)": {identiferType: "account", resourceType: "cloudflare_access_rule", testdataFilename: "cloudflare_access_rule_account"}, + "cloudflare access rule (zone)": {identiferType: "zone", resourceType: "cloudflare_access_rule", testdataFilename: "cloudflare_access_rule_zone"}, + "cloudflare account member": {identiferType: "account", resourceType: "cloudflare_account_member", testdataFilename: "cloudflare_account_member"}, + "cloudflare api shield": {identiferType: "zone", resourceType: "cloudflare_api_shield", testdataFilename: "cloudflare_api_shield"}, + "cloudflare argo": {identiferType: "zone", resourceType: "cloudflare_argo", testdataFilename: "cloudflare_argo"}, + "cloudflare bot management": {identiferType: "zone", resourceType: "cloudflare_bot_management", testdataFilename: "cloudflare_bot_management"}, + "cloudflare BYO IP prefix": {identiferType: "account", resourceType: "cloudflare_byo_ip_prefix", testdataFilename: "cloudflare_byo_ip_prefix"}, + "cloudflare certificate pack": {identiferType: "zone", resourceType: "cloudflare_certificate_pack", testdataFilename: "cloudflare_certificate_pack_acm"}, + "cloudflare custom hostname fallback origin": {identiferType: "zone", resourceType: "cloudflare_custom_hostname_fallback_origin", testdataFilename: "cloudflare_custom_hostname_fallback_origin"}, + "cloudflare custom hostname": {identiferType: "zone", resourceType: "cloudflare_custom_hostname", testdataFilename: "cloudflare_custom_hostname"}, + "cloudflare custom pages (account)": {identiferType: "account", resourceType: "cloudflare_custom_pages", testdataFilename: "cloudflare_custom_pages_account"}, + "cloudflare custom pages (zone)": {identiferType: "zone", resourceType: "cloudflare_custom_pages", testdataFilename: "cloudflare_custom_pages_zone"}, + "cloudflare filter": {identiferType: "zone", resourceType: "cloudflare_filter", testdataFilename: "cloudflare_filter"}, + "cloudflare firewall rule": {identiferType: "zone", resourceType: "cloudflare_firewall_rule", testdataFilename: "cloudflare_firewall_rule"}, + "cloudflare health check": {identiferType: "zone", resourceType: "cloudflare_healthcheck", testdataFilename: "cloudflare_healthcheck"}, + "cloudflare load balancer monitor": {identiferType: "account", resourceType: "cloudflare_load_balancer_monitor", testdataFilename: "cloudflare_load_balancer_monitor"}, + "cloudflare load balancer pool": {identiferType: "account", resourceType: "cloudflare_load_balancer_pool", testdataFilename: "cloudflare_load_balancer_pool"}, // "cloudflare load balancer": {identiferType: "zone", resourceType: "cloudflare_load_balancer", testdataFilename: "cloudflare_load_balancer"}, "cloudflare logpush jobs with filter": {identiferType: "zone", resourceType: "cloudflare_logpush_job", testdataFilename: "cloudflare_logpush_job_with_filter"}, "cloudflare logpush jobs": {identiferType: "zone", resourceType: "cloudflare_logpush_job", testdataFilename: "cloudflare_logpush_job"}, @@ -140,7 +140,7 @@ func TestResourceGeneration(t *testing.T) { "cloudflare spectrum application": {identiferType: "zone", resourceType: "cloudflare_spectrum_application", testdataFilename: "cloudflare_spectrum_application"}, "cloudflare tunnel": {identiferType: "account", resourceType: "cloudflare_tunnel", testdataFilename: "cloudflare_tunnel"}, "cloudflare turnstile_widget": {identiferType: "account", resourceType: "cloudflare_turnstile_widget", testdataFilename: "cloudflare_turnstile_widget"}, - "cloudflare turnstile_widget_no_domains": {identiferType: "account", resourceType: "cloudflare_turnstile_widget", testdataFilename: "cloudflare_turnstile_widget_no_domains"}, + "cloudflare turnstile_widget_no_domains": {identiferType: "account", resourceType: "cloudflare_turnstile_widget", testdataFilename: "cloudflare_turnstile_widget_no_domains"}, "cloudflare url normalization settings": {identiferType: "zone", resourceType: "cloudflare_url_normalization_settings", testdataFilename: "cloudflare_url_normalization_settings"}, "cloudflare user agent blocking rule": {identiferType: "zone", resourceType: "cloudflare_user_agent_blocking_rule", testdataFilename: "cloudflare_user_agent_blocking_rule"}, "cloudflare waiting room": {identiferType: "zone", resourceType: "cloudflare_waiting_room", testdataFilename: "cloudflare_waiting_room"}, diff --git a/internal/app/cf-terraforming/cmd/util.go b/internal/app/cf-terraforming/cmd/util.go index 273debc4d..d4199e134 100644 --- a/internal/app/cf-terraforming/cmd/util.go +++ b/internal/app/cf-terraforming/cmd/util.go @@ -293,6 +293,8 @@ func writeAttrLine(key string, value interface{}, parentName string, body *hclwr vals = append(vals, cty.StringVal(item)) } body.SetAttributeValue(key, cty.ListVal(vals)) + } else { + body.SetAttributeValue(key, cty.ListValEmpty(cty.String)) } case string: if parentName == "query" && key == "value" && value == "" { diff --git a/testdata/terraform/cloudflare_turnstile_widget_no_domains/test.tf b/testdata/terraform/cloudflare_turnstile_widget_no_domains/test.tf index df2e7e2c9..58cfe1410 100644 --- a/testdata/terraform/cloudflare_turnstile_widget_no_domains/test.tf +++ b/testdata/terraform/cloudflare_turnstile_widget_no_domains/test.tf @@ -1,5 +1,6 @@ resource "cloudflare_turnstile_widget" "terraform_managed_resource" { account_id = "f037e56e89293a057740de681ac9abbe" + domains = [] mode = "non-interactive" name = "example sitekey with no domains" region = "world"