From f787ca46877100fb53528600bf94d78ee1cc5812 Mon Sep 17 00:00:00 2001 From: Maxime Guerreiro Date: Thu, 21 Dec 2023 22:43:54 +0100 Subject: [PATCH] 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"