From 2852c72bceb329a1e842a6744293cc88742238df Mon Sep 17 00:00:00 2001 From: WS <20408400+WodansSon@users.noreply.github.com> Date: Tue, 11 May 2021 17:24:34 -0700 Subject: [PATCH] fixed #11623 * Support import for custom https configuration * Update import path * Update azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go * Add tests, a upgrade guide, and fix validation * Fix successfully... * terrafmt guide * remove frontendId as it's no longer needed * Update website/docs/guides/2.58.0-frontdoor-upgrade-guide.html.markdown Co-authored-by: kt * Update website/docs/guides/2.58.0-frontdoor-upgrade-guide.html.markdown Co-authored-by: kt * Update website/docs/guides/2.58.0-frontdoor-upgrade-guide.html.markdown Co-authored-by: kt * Update website/docs/guides/2.58.0-frontdoor-upgrade-guide.html.markdown Co-authored-by: kt * Update documentation Co-authored-by: kt --- .../services/frontdoor/customizediff.go | 63 ++- ...oor_custom_https_configuration_resource.go | 33 +- ...ustom_https_configuration_resource_test.go | 167 ++++++- ...58.0-frontdoor-upgrade-guide.html.markdown | 450 ++++++++++++++++++ website/docs/r/frontdoor.html.markdown | 4 +- ...r_custom_https_configuration.html.markdown | 12 +- 6 files changed, 691 insertions(+), 38 deletions(-) create mode 100644 website/docs/guides/2.58.0-frontdoor-upgrade-guide.html.markdown diff --git a/azurerm/internal/services/frontdoor/customizediff.go b/azurerm/internal/services/frontdoor/customizediff.go index 0d7c1be0adb5..4535ac1eff72 100644 --- a/azurerm/internal/services/frontdoor/customizediff.go +++ b/azurerm/internal/services/frontdoor/customizediff.go @@ -26,53 +26,78 @@ func customizeHttpsConfigurationCustomizeDiff(ctx context.Context, d *schema.Res } func customHttpsSettings(d *schema.ResourceDiff) error { - frontendId := d.Get("frontend_endpoint_id").(string) frontendEndpointCustomHttpsConfig := d.Get("custom_https_configuration").([]interface{}) customHttpsEnabled := d.Get("custom_https_provisioning_enabled").(bool) if len(frontendEndpointCustomHttpsConfig) > 0 { if !customHttpsEnabled { - return fmt.Errorf(`"frontend_endpoint":%q "custom_https_configuration" is invalid because "custom_https_provisioning_enabled" is set to "false". please remove the "custom_https_configuration" block from the configuration file`, frontendId) + return fmt.Errorf(`"custom_https_provisioning_enabled" is set to "false". please remove the "custom_https_configuration" block from the configuration file`) } // Verify frontend endpoints custom https configuration is valid if defined - if err := verifyCustomHttpsConfiguration(frontendEndpointCustomHttpsConfig, frontendId); err != nil { + if err := verifyCustomHttpsConfiguration(frontendEndpointCustomHttpsConfig); err != nil { return err } } else if customHttpsEnabled { - return fmt.Errorf(`"frontend_endpoint":%q "custom_https_configuration" is invalid because "custom_https_provisioning_enabled" is set to "true". please add a "custom_https_configuration" block to the configuration file`, frontendId) + return fmt.Errorf(`"custom_https_provisioning_enabled" is set to "true". please add a "custom_https_configuration" block to the configuration file`) } return nil } -func verifyCustomHttpsConfiguration(frontendEndpointCustomHttpsConfig []interface{}, frontendId string) error { +func verifyCustomHttpsConfiguration(frontendEndpointCustomHttpsConfig []interface{}) error { if len(frontendEndpointCustomHttpsConfig) > 0 { customHttpsConfiguration := frontendEndpointCustomHttpsConfig[0].(map[string]interface{}) - certificateSource := customHttpsConfiguration["certificate_source"] - if certificateSource == string(frontdoor.CertificateSourceAzureKeyVault) { - if !azureKeyVaultCertificateHasValues(customHttpsConfiguration, true) { - return fmt.Errorf(`"frontend_endpoint":%q "custom_https_configuration" is invalid, all of the following keys must have values in the "custom_https_configuration" block: "azure_key_vault_certificate_secret_name" and "azure_key_vault_certificate_vault_id"`, frontendId) + certificateSource := customHttpsConfiguration["certificate_source"].(string) + certificateVersion := customHttpsConfiguration["azure_key_vault_certificate_secret_version"].(string) + + if certificateSource == string(frontdoor.CertificateSourceFrontDoor) { + if azureKeyVaultCertificateHasValues(customHttpsConfiguration, true) { + return fmt.Errorf(`a Front Door managed "custom_https_configuration" block does not support the following keys. Please remove the following keys from your configuration file: "azure_key_vault_certificate_secret_name", "azure_key_vault_certificate_secret_version", and "azure_key_vault_certificate_vault_id"`) + } + } else { + // The latest secret version is no longer valid for key vaults + if strings.EqualFold(certificateVersion, "latest") { + return fmt.Errorf(`"azure_key_vault_certificate_secret_version" can not be set to "latest" please remove this attribute from the configuration file. Removing the value has the same functionality as setting it to "latest"`) + } + + if !azureKeyVaultCertificateHasValues(customHttpsConfiguration, false) { + if certificateVersion == "" { + // If using latest, empty string is now equivalent to using the keyword latest + return fmt.Errorf(`a "AzureKeyVault" managed "custom_https_configuration" block must have values in the following fileds: "azure_key_vault_certificate_secret_name" and "azure_key_vault_certificate_vault_id"`) + } else { + // If using a specific version of the secret + return fmt.Errorf(`a "AzureKeyVault" managed "custom_https_configuration" block must have values in the following fileds: "azure_key_vault_certificate_secret_name", "azure_key_vault_certificate_secret_version", and "azure_key_vault_certificate_vault_id"`) + } } - } else if azureKeyVaultCertificateHasValues(customHttpsConfiguration, false) { - return fmt.Errorf(`"frontend_endpoint":%q "custom_https_configuration" is invalid, all of the following keys must be removed from the "custom_https_configuration" block: "azure_key_vault_certificate_secret_name", "azure_key_vault_certificate_secret_version", and "azure_key_vault_certificate_vault_id"`, frontendId) } } return nil } -func azureKeyVaultCertificateHasValues(customHttpsConfiguration map[string]interface{}, matchAllKeys bool) bool { - certificateSecretName := customHttpsConfiguration["azure_key_vault_certificate_secret_name"] - certificateSecretVersion := customHttpsConfiguration["azure_key_vault_certificate_secret_version"] - certificateVaultId := customHttpsConfiguration["azure_key_vault_certificate_vault_id"] +func azureKeyVaultCertificateHasValues(customHttpsConfiguration map[string]interface{}, isFrontDoorManaged bool) bool { + certificateSecretName := customHttpsConfiguration["azure_key_vault_certificate_secret_name"].(string) + certificateSecretVersion := customHttpsConfiguration["azure_key_vault_certificate_secret_version"].(string) + certificateVaultId := customHttpsConfiguration["azure_key_vault_certificate_vault_id"].(string) - if matchAllKeys { - if strings.TrimSpace(certificateSecretName.(string)) != "" && strings.TrimSpace(certificateVaultId.(string)) != "" { + if isFrontDoorManaged { + // if any of these keys have values it is invalid + if strings.TrimSpace(certificateSecretName) != "" || strings.TrimSpace(certificateSecretVersion) != "" || strings.TrimSpace(certificateVaultId) != "" { return true } - } else if strings.TrimSpace(certificateSecretName.(string)) != "" || strings.TrimSpace(certificateSecretVersion.(string)) != "" || strings.TrimSpace(certificateVaultId.(string)) != "" { - return true + } else { + if certificateSecretVersion == "" { + // using latest ignore certificate secret version + if strings.TrimSpace(certificateSecretName) != "" && strings.TrimSpace(certificateVaultId) != "" { + return true + } + } else { + // not using latest make sure all keys have values + if strings.TrimSpace(certificateSecretName) != "" && strings.TrimSpace(certificateSecretVersion) != "" && strings.TrimSpace(certificateVaultId) != "" { + return true + } + } } return false diff --git a/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go b/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go index 0a51d39c588b..3f6c8fc1b80d 100644 --- a/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go +++ b/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource.go @@ -26,10 +26,33 @@ func resourceFrontDoorCustomHttpsConfiguration() *schema.Resource { Update: resourceFrontDoorCustomHttpsConfigurationCreateUpdate, Delete: resourceFrontDoorCustomHttpsConfigurationDelete, - Importer: pluginsdk.ImporterValidatingResourceId(func(id string) error { - _, err := parse.FrontendEndpointID(id) - return err - }), + Importer: &schema.ResourceImporter{ + State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + client := meta.(*clients.Client).Frontdoor.FrontDoorsFrontendClient + ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) + defer cancel() + + // validate that the passed ID is a valid custom HTTPS configuration ID + custom, err := parse.CustomHttpsConfigurationID(d.Id()) + if err != nil { + return []*schema.ResourceData{d}, fmt.Errorf("parsing Custom HTTPS Configuration ID %q for import: %v", d.Id(), err) + } + + // convert the passed custom HTTPS configuration ID to a frontend endpoint ID + frontend := parse.NewFrontendEndpointID(custom.SubscriptionId, custom.ResourceGroup, custom.FrontDoorName, custom.CustomHttpsConfigurationName) + + // validate that the frontend endpoint ID exists in the Frontdoor resource + if _, err = client.Get(ctx, custom.ResourceGroup, custom.FrontDoorName, custom.CustomHttpsConfigurationName); err != nil { + return []*schema.ResourceData{d}, fmt.Errorf("retrieving the Custom HTTPS Configuration(ID: %q) for the frontend endpoint (ID: %q): %s", custom.ID(), frontend.ID(), err) + } + + // set the new values for the custom HTTPS configuration resource + d.Set("id", custom.ID()) + d.Set("frontend_endpoint_id", frontend.ID()) + + return []*schema.ResourceData{d}, nil + }, + }, Timeouts: &schema.ResourceTimeout{ Create: schema.DefaultTimeout(6 * time.Hour), @@ -82,8 +105,6 @@ func resourceFrontDoorCustomHttpsConfigurationCreateUpdate(d *schema.ResourceDat customHttpsConfigurationId := parse.NewCustomHttpsConfigurationID(frontendEndpointId.SubscriptionId, frontendEndpointId.ResourceGroup, frontendEndpointId.FrontDoorName, frontendEndpointId.Name) - // TODO: Requires Import support - resp, err := client.Get(ctx, frontendEndpointId.ResourceGroup, frontendEndpointId.FrontDoorName, frontendEndpointId.Name) if err != nil { return fmt.Errorf("reading Endpoint %q (Front Door %q / Resource Group %q): %+v", frontendEndpointId.Name, frontendEndpointId.FrontDoorName, frontendEndpointId.ResourceGroup, err) diff --git a/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource_test.go b/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource_test.go index 3b6eb946e2f2..2c4b9f23d12e 100644 --- a/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource_test.go +++ b/azurerm/internal/services/frontdoor/frontdoor_custom_https_configuration_resource_test.go @@ -3,6 +3,7 @@ package frontdoor_test import ( "context" "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/helper/resource" @@ -22,7 +23,7 @@ func TestAccFrontDoorCustomHttpsConfiguration_CustomHttps(t *testing.T) { r := FrontDoorCustomHttpsConfigurationResource{} data.ResourceTest(t, r, []resource.TestStep{ { - Config: r.CustomHttpsEnabled(data), + Config: r.Enabled(data), Check: resource.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("custom_https_provisioning_enabled").HasValue("true"), @@ -30,7 +31,7 @@ func TestAccFrontDoorCustomHttpsConfiguration_CustomHttps(t *testing.T) { ), }, { - Config: r.CustomHttpsDisabled(data), + Config: r.Disabled(data), Check: resource.ComposeTestCheckFunc( check.That(data.ResourceName).ExistsInAzure(r), check.That(data.ResourceName).Key("custom_https_provisioning_enabled").HasValue("false"), @@ -39,6 +40,72 @@ func TestAccFrontDoorCustomHttpsConfiguration_CustomHttps(t *testing.T) { }) } +func TestAccFrontDoorCustomHttpsConfiguration_DisabledWithConfigurationBlock(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_frontdoor_custom_https_configuration", "test") + r := FrontDoorCustomHttpsConfigurationResource{} + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.DisabledWithConfigurationBlock(data), + ExpectError: regexp.MustCompile(`"custom_https_provisioning_enabled" is set to "false". please remove the "custom_https_configuration" block from the configuration file`), + }, + }) +} + +func TestAccFrontDoorCustomHttpsConfiguration_EnabledWithoutConfigurationBlock(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_frontdoor_custom_https_configuration", "test") + r := FrontDoorCustomHttpsConfigurationResource{} + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.EnabledWithoutConfigurationBlock(data), + ExpectError: regexp.MustCompile(`"custom_https_provisioning_enabled" is set to "true". please add a "custom_https_configuration" block to the configuration file`), + }, + }) +} + +func TestAccFrontDoorCustomHttpsConfiguration_EnabledFrontdoorExtraAttributes(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_frontdoor_custom_https_configuration", "test") + r := FrontDoorCustomHttpsConfigurationResource{} + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.EnabledFrontdoorExtraAttributes(data), + ExpectError: regexp.MustCompile(`a Front Door managed "custom_https_configuration" block does not support the following keys.`), + }, + }) +} + +func TestAccFrontDoorCustomHttpsConfiguration_EnabledKeyVaultLatest(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_frontdoor_custom_https_configuration", "test") + r := FrontDoorCustomHttpsConfigurationResource{} + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.EnabledKeyVaultLatest(data), + ExpectError: regexp.MustCompile(`"azure_key_vault_certificate_secret_version" can not be set to "latest" please remove this attribute from the configuration file.`), + }, + }) +} + +func TestAccFrontDoorCustomHttpsConfiguration_EnabledKeyVaultLatestMissingAttributes(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_frontdoor_custom_https_configuration", "test") + r := FrontDoorCustomHttpsConfigurationResource{} + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.EnabledKeyVaultLatestMissingAttributes(data), + ExpectError: regexp.MustCompile(`a "AzureKeyVault" managed "custom_https_configuration" block must have values in the following fileds: "azure_key_vault_certificate_secret_name" and "azure_key_vault_certificate_vault_id"`), + }, + }) +} + +func TestAccFrontDoorCustomHttpsConfiguration_EnabledKeyVaultMissingAttributes(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_frontdoor_custom_https_configuration", "test") + r := FrontDoorCustomHttpsConfigurationResource{} + data.ResourceTest(t, r, []resource.TestStep{ + { + Config: r.EnabledKeyVaultMissingAttributes(data), + ExpectError: regexp.MustCompile(`a "AzureKeyVault" managed "custom_https_configuration" block must have values in the following fileds: "azure_key_vault_certificate_secret_name", "azure_key_vault_certificate_secret_version", and "azure_key_vault_certificate_vault_id"`), + }, + }) +} + func (FrontDoorCustomHttpsConfigurationResource) Exists(ctx context.Context, clients *clients.Client, state *terraform.InstanceState) (*bool, error) { id, err := parse.CustomHttpsConfigurationIDInsensitively(state.ID) if err != nil { @@ -53,7 +120,7 @@ func (FrontDoorCustomHttpsConfigurationResource) Exists(ctx context.Context, cli return utils.Bool(resp.FrontendEndpointProperties != nil), nil } -func (r FrontDoorCustomHttpsConfigurationResource) CustomHttpsEnabled(data acceptance.TestData) string { +func (r FrontDoorCustomHttpsConfigurationResource) Enabled(data acceptance.TestData) string { return fmt.Sprintf(` %s @@ -68,7 +135,7 @@ resource "azurerm_frontdoor_custom_https_configuration" "test" { `, r.template(data)) } -func (r FrontDoorCustomHttpsConfigurationResource) CustomHttpsDisabled(data acceptance.TestData) string { +func (r FrontDoorCustomHttpsConfigurationResource) Disabled(data acceptance.TestData) string { return fmt.Sprintf(` %s @@ -79,6 +146,98 @@ resource "azurerm_frontdoor_custom_https_configuration" "test" { `, r.template(data)) } +func (r FrontDoorCustomHttpsConfigurationResource) DisabledWithConfigurationBlock(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_frontdoor_custom_https_configuration" "test" { + frontend_endpoint_id = azurerm_frontdoor.test.frontend_endpoints[local.endpoint_name] + custom_https_provisioning_enabled = false + + custom_https_configuration { + certificate_source = "FrontDoor" + } +} +`, r.template(data)) +} + +func (r FrontDoorCustomHttpsConfigurationResource) EnabledWithoutConfigurationBlock(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_frontdoor_custom_https_configuration" "test" { + frontend_endpoint_id = azurerm_frontdoor.test.frontend_endpoints[local.endpoint_name] + custom_https_provisioning_enabled = true +} +`, r.template(data)) +} + +func (r FrontDoorCustomHttpsConfigurationResource) EnabledFrontdoorExtraAttributes(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_frontdoor_custom_https_configuration" "test" { + frontend_endpoint_id = azurerm_frontdoor.test.frontend_endpoints[local.endpoint_name] + custom_https_provisioning_enabled = true + + custom_https_configuration { + certificate_source = "FrontDoor" + azure_key_vault_certificate_secret_name = "accTest" + } +} +`, r.template(data)) +} + +func (r FrontDoorCustomHttpsConfigurationResource) EnabledKeyVaultLatest(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_frontdoor_custom_https_configuration" "test" { + frontend_endpoint_id = azurerm_frontdoor.test.frontend_endpoints[local.endpoint_name] + custom_https_provisioning_enabled = true + + custom_https_configuration { + certificate_source = "AzureKeyVault" + azure_key_vault_certificate_secret_name = "accTest" + azure_key_vault_certificate_secret_version = "latest" + } +} +`, r.template(data)) +} + +func (r FrontDoorCustomHttpsConfigurationResource) EnabledKeyVaultLatestMissingAttributes(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_frontdoor_custom_https_configuration" "test" { + frontend_endpoint_id = azurerm_frontdoor.test.frontend_endpoints[local.endpoint_name] + custom_https_provisioning_enabled = true + + custom_https_configuration { + certificate_source = "AzureKeyVault" + azure_key_vault_certificate_secret_name = "accTest" + } +} +`, r.template(data)) +} + +func (r FrontDoorCustomHttpsConfigurationResource) EnabledKeyVaultMissingAttributes(data acceptance.TestData) string { + return fmt.Sprintf(` +%s + +resource "azurerm_frontdoor_custom_https_configuration" "test" { + frontend_endpoint_id = azurerm_frontdoor.test.frontend_endpoints[local.endpoint_name] + custom_https_provisioning_enabled = true + + custom_https_configuration { + certificate_source = "AzureKeyVault" + azure_key_vault_certificate_secret_name = "accTest" + azure_key_vault_certificate_secret_version = "accTest" + } +} +`, r.template(data)) +} + func (FrontDoorCustomHttpsConfigurationResource) template(data acceptance.TestData) string { return fmt.Sprintf(` provider "azurerm" { diff --git a/website/docs/guides/2.58.0-frontdoor-upgrade-guide.html.markdown b/website/docs/guides/2.58.0-frontdoor-upgrade-guide.html.markdown new file mode 100644 index 000000000000..56bbfc6e5c2a --- /dev/null +++ b/website/docs/guides/2.58.0-frontdoor-upgrade-guide.html.markdown @@ -0,0 +1,450 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: v2.58.0 Front Door Upgrade Guide" +description: |- + Azure Resource Manager: v2.58.0 Front Door Upgrade Guide + +--- + +# Overview of the Breaking Changes in the Azure Resource Manager: v2.58.0 release for Front Door + +## Resource Behavior Change + +With the release of the v2.58.0 provider, if you run the `apply` command against an existing Front Door resource it **will not** apply the detected changes. Instead it will persist the `explicit_resource_order` mapping structure to the state file. Once this operation has completed the resource will resume functioning normally. This change in behavior is due to the underlying service API now returning the JSON response's elements out of order from how it was sent to the resource by Terraform causing unexpected discrepancies in the `plan` after the resource has been provisioned. + +## Breaking Changes + +* `azurerm_frontdoor` - The `custom_https_provisioning_enabled` field and the `custom_https_configuration` block have been removed from the `azurerm_frontdoor` resource due to changes made by the service team. What this means is you have a `azurerm_frontdoor` configuration file with a `custom_https_configuration` block currently defined, once you upgrade to `v2.58.0` you will need to remove that code from the configuration file and define a separate `azurerm_frontdoor_custom_https_configuration` block in your configuration file for each frontend endpoint regardless if it had a `custom_https_configuration` block or not. If you do not remove these configuration file values after you upgrade you will receive a `An argument named "custom_https_provisioning_enabled" is not expected here.` or `An argument named "custom_https_configuration" is not expected here.` error. + +* `azurerm_frontdoor_custom_https_configuration` - The `resource_group_name` field has been removed from the `azurerm_frontdoor_custom_https_configuration` resource. If the `resource_group_name` field has been defined in your current `azurerm_frontdoor_custom_https_configuration` resource configuration file please remove it else you will receive a `An argument named "resource_group_name" is not expected here.` error. + +# How to Migrate Your Current Front Door Configuration to Azure Resource Manager: v2.58.0 + +For this upgrade guide we are going to assume that your configuration file looks something like the below example before you upgraded to `v2.58.0` of the Azure provider. For this upgrade guide we are also assuming that the Front Door resource already exists in Azure and that it is curretnly being managed by Terraform. + +**Example Configuration:** + +```hcl +provider "azurerm" { + features {} + version = "2.57.0" +} + +locals { + default_frontend_name = "default" + custom_frontend_name = "custom" +} + +resource "azurerm_resource_group" "example" { + name = "example-rg" + location = "westeurope" +} + +resource "azurerm_frontdoor" "example" { + name = "exampleFrontdoor" + resource_group_name = azurerm_resource_group.example.name + enforce_backend_pools_certificate_name_check = false + + frontend_endpoint { + name = "default" + host_name = "exampleFrontdoor.azurefd.net" + + custom_https_provisioning_enabled = false + } + + frontend_endpoint { + name = "custom" + host_name = "example-custom.contoso.com" + + custom_https_provisioning_enabled = true + + custom_https_configuration { + certificate_source = "FrontDoor" + } + } + + # Backend Pool 1 + backend_pool { + name = "example-AFD-pool-bing" + load_balancing_name = "example-AFD-bing-LB" + health_probe_name = "example-AFD-bing-HP" + + backend { + host_header = "bing.com" + address = "bing.com" + http_port = 80 + https_port = 443 + weight = 75 + enabled = true + } + } + + routing_rule { + name = "example-AFD-bing-RR" + accepted_protocols = ["Https"] + patterns_to_match = ["/*"] + frontend_endpoints = ["default"] + + forwarding_configuration { + forwarding_protocol = "MatchRequest" + backend_pool_name = "example-AFD-pool-bing" + cache_enabled = true + } + } + + routing_rule { + name = "example-AFD-bing-HTTPtoHTTPS" + accepted_protocols = ["Http"] + frontend_endpoints = ["default"] + patterns_to_match = ["/*"] + + redirect_configuration { + redirect_protocol = "HttpsOnly" + redirect_type = "Found" + custom_path = "/" + } + } + + backend_pool_load_balancing { + name = "example-AFD-bing-LB" + additional_latency_milliseconds = 0 + sample_size = 4 + successful_samples_required = 2 + } + + backend_pool_health_probe { + name = "example-AFD-bing-HP" + protocol = "Https" + } + + # Backend Pool 2 + backend_pool { + name = "example-AFD-pool-google" + load_balancing_name = "example-AFD-google-LB" + health_probe_name = "example-AFD-google-HP" + + backend { + host_header = "google.com" + address = "google.com" + http_port = 80 + https_port = 443 + weight = 75 + enabled = true + } + } + + routing_rule { + name = "example-AFD-google-RR" + accepted_protocols = ["Https"] + patterns_to_match = ["/*", "/poolGoogle/*"] + frontend_endpoints = ["custom"] + + forwarding_configuration { + forwarding_protocol = "MatchRequest" + backend_pool_name = "example-AFD-pool-google" + cache_enabled = true + } + } + + routing_rule { + name = "example-AFD-google-HTTPtoHTTPS" + accepted_protocols = ["Http"] + frontend_endpoints = ["custom"] + patterns_to_match = ["/*"] + + redirect_configuration { + redirect_protocol = "HttpsOnly" + redirect_type = "Found" + custom_path = "/" + } + } + + backend_pool_load_balancing { + name = "example-AFD-google-LB" + additional_latency_milliseconds = 0 + sample_size = 4 + successful_samples_required = 2 + } + + backend_pool_health_probe { + name = "example-AFD-google-HP" + protocol = "Https" + } +} +``` + +Firstly, you will need to upgrade your provider to `v2.58.0` or later in the way you normally would upgrade your provider, for more information about how to upgrade your provider please see the [product documentation](https://learn.hashicorp.com/tutorials/terraform/provider-versioning). For this upgrade guide I am going to force the upgrade via the configuration files `provider` block like this: + +```hcl +provider "azurerm" { + features {} + version = "2.58.0" +} +``` + +Once you have updated the `provider` block in your configuration file run the `terraform init` command and you should see the output: + +``` +Initializing the backend... + +Initializing provider plugins... +- Checking for available provider plugins... +- Downloading plugin for provider "azurerm" (hashicorp/azurerm) 2.58.0... + +Terraform has been successfully initialized! +``` + +At this point you now have the latest provider installed in your environment. Now you will need to update your configuration file and remove all of the unsupported attributes and code blocks from the existing configuration file mentioned above in the **Breaking Changes** section of this document. Once you have done that your configuration file should look something like this. + +**Example Configuration Post Upgrade to v2.58.0:** + +```hcl +provider "azurerm" { + features {} + version = "2.58.0" +} + +locals { + default_frontend_name = "default" + custom_frontend_name = "custom" +} + +resource "azurerm_resource_group" "example" { + name = "example-rg" + location = "westeurope" +} + +resource "azurerm_frontdoor" "example" { + name = "exampleFrontdoor" + resource_group_name = azurerm_resource_group.example.name + enforce_backend_pools_certificate_name_check = false + + frontend_endpoint { + name = "default" + host_name = "exampleFrontdoor.azurefd.net" + } + + frontend_endpoint { + name = "custom" + host_name = "example-custom.contoso.com" + } + + # Backend Pool 1 + backend_pool { + name = "example-AFD-pool-bing" + load_balancing_name = "example-AFD-bing-LB" + health_probe_name = "example-AFD-bing-HP" + + backend { + host_header = "bing.com" + address = "bing.com" + http_port = 80 + https_port = 443 + weight = 75 + enabled = true + } + } + + routing_rule { + name = "example-AFD-bing-RR" + accepted_protocols = ["Https"] + patterns_to_match = ["/*"] + frontend_endpoints = ["default"] + + forwarding_configuration { + forwarding_protocol = "MatchRequest" + backend_pool_name = "example-AFD-pool-bing" + cache_enabled = true + } + } + + routing_rule { + name = "example-AFD-bing-HTTPtoHTTPS" + accepted_protocols = ["Http"] + frontend_endpoints = ["default"] + patterns_to_match = ["/*"] + + redirect_configuration { + redirect_protocol = "HttpsOnly" + redirect_type = "Found" + custom_path = "/" + } + } + + backend_pool_load_balancing { + name = "example-AFD-bing-LB" + additional_latency_milliseconds = 0 + sample_size = 4 + successful_samples_required = 2 + } + + backend_pool_health_probe { + name = "example-AFD-bing-HP" + protocol = "Https" + } + + # Backend Pool 2 + backend_pool { + name = "example-AFD-pool-google" + load_balancing_name = "example-AFD-google-LB" + health_probe_name = "example-AFD-google-HP" + + backend { + host_header = "google.com" + address = "google.com" + http_port = 80 + https_port = 443 + weight = 75 + enabled = true + } + } + + routing_rule { + name = "example-AFD-google-RR" + accepted_protocols = ["Https"] + patterns_to_match = ["/*", "/poolGoogle/*"] + frontend_endpoints = ["custom"] + + forwarding_configuration { + forwarding_protocol = "MatchRequest" + backend_pool_name = "example-AFD-pool-google" + cache_enabled = true + } + } + + routing_rule { + name = "example-AFD-google-HTTPtoHTTPS" + accepted_protocols = ["Http"] + frontend_endpoints = ["custom"] + patterns_to_match = ["/*"] + + redirect_configuration { + redirect_protocol = "HttpsOnly" + redirect_type = "Found" + custom_path = "/" + } + } + + backend_pool_load_balancing { + name = "example-AFD-google-LB" + additional_latency_milliseconds = 0 + sample_size = 4 + successful_samples_required = 2 + } + + backend_pool_health_probe { + name = "example-AFD-google-HP" + protocol = "Https" + } +} +``` + +## What Was Removed: + +* `frontend_endpoint` block - in the `frontend_endpoint` block with the name `default` the `custom_https_provisioning_enabled` field. +* `frontend_endpoint` block - in the `frontend_endpoint` block with the name `custom` the `custom_https_provisioning_enabled` field and the `custom_https_configuration` code block. + +## What Was Updated: +* `provider` block - In the `provider` block the `version` field was updated to be `2.58.0` from `2.57.0`. + +Now you will need to run the `terraform apply -auto-approve` command to create the `explicit_resource_order` table in your state file. If done correctly you should see the output: + +``` +azurerm_resource_group.example: Refreshing state... [id=/subscriptions/XXXXXX/resourceGroups/example-rg] +azurerm_frontdoor.example: Refreshing state... [id=/subscriptions/XXXXXX/resourceGroups/example-rg/providers/Microsoft.Network/frontDoors/exampleFrontdoor] +azurerm_frontdoor.example: Modifying... [id=/subscriptions/XXXXXX/resourceGroups/example-rg/providers/Microsoft.Network/frontDoors/exampleFrontdoor] +azurerm_frontdoor.example: Modifications complete after 3s [id=/subscriptions/XXXXXX/resourceGroups/example-rg/providers/Microsoft.Network/frontDoors/exampleFrontdoor] + +Apply complete! Resources: 0 added, 1 changed, 0 destroyed. +``` + +!> **NOTE:** You can only do this step **ONCE** after the upgrade of the `provider`. If the `explicit_resource_order` table exists in the state file and you run the `apply` command again it will apply all of the detected configurataion file changes to the `azurerm_frontdoor` resource in Azure. If you feel you have done this step in error you will need to remove the `explicit_resource_order` table from your state file, however modifying the state file is not advised and is intended for advanced users, administrators, and IT Professionals only. + +## Import Your azurerm_frontdoor_custom_https_configuration Settings Into Your State File + +At this point, you have now successfully upgraded your provider and modified your configuration file to be **v2.58.0** compliant. You will need to import your frontend endpoint `custom_https_configuration` settings into a new `azurerm_frontdoor_custom_https_configuration` resource. This is done by modifying your configuration file with a new `azurerm_frontdoor_custom_https_configuration` resource stub for each of your frontend endpoints in your configuration file so they can be imported into the state file without causing an error during `apply`. To do this you will need to add the following `azurerm_frontdoor_custom_https_configuration` stubs to the end of your configuration file: + +```hcl +resource "azurerm_frontdoor_custom_https_configuration" "default" { +} + +resource "azurerm_frontdoor_custom_https_configuration" "custom" { +} +``` + +Once you have added these definitons to your configuration file you will run the following commands to import the new resources into your state file: + +``` +terraform import azurerm_frontdoor_custom_https_configuration.default /subscriptions/{subscription}/resourceGroups/{resorceGroup}/providers/Microsoft.Network/frontDoors/{frontDoor}/customHttpsConfiguration/default + +terraform import azurerm_frontdoor_custom_https_configuration.custom /subscriptions/{subscription}/resourceGroups/{resorceGroup}/providers/Microsoft.Network/frontDoors/{frontDoor}/customHttpsConfiguration/custom +``` + +The output from these command should look something like this: + +``` +> terraform import azurerm_frontdoor_custom_https_configuration.default /subscriptions/XXXXXX/resourceGroups/example-rg/providers/Microsoft.Network/frontDoors/exampleFrontdoor/customHttpsConfiguration/default +azurerm_frontdoor_custom_https_configuration.default: Importing from ID "/subscriptions/XXXXXX/resourceGroups/example-rg/providers/Microsoft.Network/frontDoors/exampleFrontdoor/customHttpsConfiguration/default"... +azurerm_frontdoor_custom_https_configuration.default: Import prepared! + Prepared azurerm_frontdoor_custom_https_configuration for import +azurerm_frontdoor_custom_https_configuration.default: Refreshing state... [id=/subscriptions/XXXXXX/resourceGroups/example-rg/providers/Microsoft.Network/frontDoors/exampleFrontdoor/customHttpsConfiguration/default] + +Import successful! + +The resources that were imported are shown above. These resources are now in +your Terraform state and will henceforth be managed by Terraform. +``` + +``` +> terraform import azurerm_frontdoor_custom_https_configuration.custom /subscriptions/XXXXXX/resourceGroups/example-rg/providers/Microsoft.Network/frontDoors/exampleFrontdoor/customHttpsConfiguration/custom +azurerm_frontdoor_custom_https_configuration.custom: Importing from ID "/subscriptions/XXXXXX/resourceGroups/example-rg/providers/Microsoft.Network/frontDoors/exampleFrontdoor/customHttpsConfiguration/custom"... +azurerm_frontdoor_custom_https_configuration.custom: Import prepared! + Prepared azurerm_frontdoor_custom_https_configuration for import +azurerm_frontdoor_custom_https_configuration.custom: Refreshing state... [id=/subscriptions/XXXXXX/resourceGroups/example-rg/providers/Microsoft.Network/frontDoors/exampleFrontdoor/customHttpsConfiguration/custom] + +Import successful! + +The resources that were imported are shown above. These resources are now in +your Terraform state and will henceforth be managed by Terraform. +``` + +Once the `azurerm_frontdoor_custom_https_configuration` stubs have been imported into your state file you will now need to update the stubs to have the correct values that live in Azure for your Front Door resource. So in this example we will be updating our `azurerm_frontdoor_custom_https_configuration` stubs to have these configurations settings: + +```hcl +resource "azurerm_frontdoor_custom_https_configuration" "default" { + frontend_endpoint_id = "${azurerm_frontdoor.example.id}/frontendEndpoints/${local.default_frontend_name}" + custom_https_provisioning_enabled = false +} + +resource "azurerm_frontdoor_custom_https_configuration" "custom" { + frontend_endpoint_id = "${azurerm_frontdoor.example.id}/frontendEndpoints/${local.custom_frontend_name}" + custom_https_provisioning_enabled = true + + custom_https_configuration { + certificate_source = "FrontDoor" + } +} +``` + +Now that you have updated the `azurerm_frontdoor_custom_https_configuration` resources with the correct values the last thing you need to do is run a `terrform plan` command and you will be back in the correct state where terraform can again manage your `azurerm_frontdoor` resource via Terraform. If all of the steps were followed correctly the output from the `plan` should look something like this. + +``` +> terraform plan + +Refreshing Terraform state in-memory prior to plan... +The refreshed state will be used to calculate this plan, but will not be +persisted to local or remote state storage. + +azurerm_resource_group.example: Refreshing state... [id=/subscriptions/XXXXXX/resourceGroups/example-rg] +azurerm_frontdoor.example: Refreshing state... [id=/subscriptions/XXXXXX/resourceGroups/example-rg/providers/Microsoft.Network/frontDoors/exampleFrontdoor] +azurerm_frontdoor_custom_https_configuration.default: Refreshing state... [id=/subscriptions/XXXXXX/resourceGroups/example-rg/providers/Microsoft.Network/frontDoors/exampleFrontdoor/customHttpsConfiguration/default] +azurerm_frontdoor_custom_https_configuration.custom: Refreshing state... [id=/subscriptions/XXXXXX/resourceGroups/example-rg/providers/Microsoft.Network/frontDoors/exampleFrontdoor/customHttpsConfiguration/custom] + +------------------------------------------------------------------------ + +No changes. Infrastructure is up-to-date. + +This means that Terraform did not detect any differences between your +configuration and real physical resources that exist. As a result, no +actions need to be performed. +``` diff --git a/website/docs/r/frontdoor.html.markdown b/website/docs/r/frontdoor.html.markdown index ba2cbbcbc67b..9f2c8f1fb313 100644 --- a/website/docs/r/frontdoor.html.markdown +++ b/website/docs/r/frontdoor.html.markdown @@ -19,9 +19,9 @@ Below are some of the key scenarios that Azure Front Door Service addresses: !> **Be Aware:** Azure is rolling out a breaking change on Friday 9th April which may cause issues with the CDN/FrontDoor resources. [More information is available in this Github issue](https://github.com/terraform-providers/terraform-provider-azurerm/issues/11231) - however unfortunately this may necessitate a breaking change to the CDN and FrontDoor resources, more information will be posted [in the Github issue](https://github.com/terraform-providers/terraform-provider-azurerm/issues/11231) as the necessary changes are identified. -!> **Breaking Provider Change:** The `custom_https_provisioning_enabled` field and the `custom_https_configuration` block have been removed from the `azurerm_frontdoor` resource in the v2.58.0 provider due to changes made by the service team. If you wish to enable the custom https configuration functionality within your `azurerm_frontdoor` resource moving forward you will need to define a separate `azurerm_frontdoor_custom_https_configuration` block in your configuration file. +!> **BREAKING CHANGE:** The `custom_https_provisioning_enabled` field and the `custom_https_configuration` block have been removed from the `azurerm_frontdoor` resource in the `v2.58.0` provider due to changes made by the service team. If you wish to enable the custom https configuration functionality within your `azurerm_frontdoor` resource moving forward you will need to define a separate `azurerm_frontdoor_custom_https_configuration` block in your configuration file. -!> **Breaking Behavior Change:** With the release of the v2.58.0 provider, if you run the `apply` command against an existing Front Door resource the changes will not be applied. This will only happen once with preexisting Front Door instances and will not affect newly provisioned Front Door resources. This change in behavior in Terraform is due to an issue where the underlying service teams API is now returning the response JSON out of order from the way it was sent to the resource provider by Terraform causing unexpected discrepancies in the `plan` after the resource has been provisioned. This will only happen one time, to avoid unwanted changes from being provisioned, once the `explicit_resource_order` mapping structure has been persisted to the state file the resource will resume functioning normally. +!> **BREAKING CHANGE:** With the release of the `v2.58.0` provider, if you run the `apply` command against an existing Front Door resource it **will not** apply the detected changes. Instead it will persist the `explicit_resource_order` mapping structure to the state file. Once this operation has completed the resource will resume functioning normally.This change in behavior in Terraform is due to an issue where the underlying service teams API is now returning the response JSON out of order from the way it was sent to the resource via Terraform causing unexpected discrepancies in the `plan` after the resource has been provisioned. If your pre-existing Front Door instance contains `custom_https_configuration` blocks there are additional steps that will need to be completed to succefully migrate your Front Door onto the `v2.58.0` provider which [can be found in this guide](../guides/2.58.0-frontdoor-upgrade-guide.html). ## Example Usage diff --git a/website/docs/r/frontdoor_custom_https_configuration.html.markdown b/website/docs/r/frontdoor_custom_https_configuration.html.markdown index 5d209a530ae8..b90b369005dc 100644 --- a/website/docs/r/frontdoor_custom_https_configuration.html.markdown +++ b/website/docs/r/frontdoor_custom_https_configuration.html.markdown @@ -10,15 +10,13 @@ description: |- Manages the Custom Https Configuration for an Azure Front Door Frontend Endpoint.. -~> **NOTE:** Custom https configurations for a Front Door Frontend Endpoint can be defined both within [the `azurerm_frontdoor` resource](frontdoor.html) via the `custom_https_configuration` block and by using a separate resource, as described in the following sections. - -> **NOTE:** Defining custom https configurations using a separate `azurerm_frontdoor_custom_https_configuration` resource allows for parallel creation/update. --> **NOTE:** UPCOMING BREAKING CHANGE: In order to address the ordering issue we have changed the design on how to retrieve existing sub resources such as frontend endpoints. Existing design will be deprecated and will result in an incorrect configuration. Please refer to the updated documentation below for more information. +!> **BREAKING CHANGE:** In order to address the ordering issue we have changed the design on how to retrieve existing sub resources such as frontend endpoints. Existing design will be deprecated and will result in an incorrect configuration. Please refer to the updated documentation below for more information. -!> **Be Aware:** Azure is rolling out a breaking change on Friday 9th April which may cause issues with the CDN/FrontDoor resources. [More information is available in this Github issue](https://github.com/terraform-providers/terraform-provider-azurerm/issues/11231) - however unfortunately this may necessitate a breaking change to the CDN and FrontDoor resources, more information will be posted [in the Github issue](https://github.com/terraform-providers/terraform-provider-azurerm/issues/11231) as the necessary changes are identified. +!> **BREAKING CHANGE:** The `resource_group_name` field has been removed as of the `v2.58.0` provider release. If the `resource_group_name` field has been defined in your current `azurerm_frontdoor_custom_https_configuration` resource configuration file please remove it else you will receive a `An argument named "resource_group_name" is not expected here.` error. If your pre-existing Front Door instance contained inline `custom_https_configuration` blocks there are additional steps that will need to be completed to succefully migrate your Front Door onto the `v2.58.0` provider which [can be found in this guide](../guides/2.58.0-frontdoor-upgrade-guide.html). -!> **Breaking Provider Change:** The `resource_group_name` field has been removed as of the v2.58.0 provider release. If the `resource_group_name` field has been defined in your current `azurerm_frontdoor_custom_https_configuration` resource configuration file please remove it else you will receive a `An argument named "resource_group_name" is not expected here.` error. +!> **Be Aware:** Azure is rolling out a breaking change on Friday 9th April which may cause issues with the CDN/FrontDoor resources. [More information is available in this Github issue](https://github.com/terraform-providers/terraform-provider-azurerm/issues/11231) - however unfortunately this may necessitate a breaking change to the CDN and FrontDoor resources, more information will be posted [in the Github issue](https://github.com/terraform-providers/terraform-provider-azurerm/issues/11231) as the necessary changes are identified. ```hcl resource "azurerm_resource_group" "example" { @@ -144,8 +142,8 @@ The `timeouts` block allows you to specify [timeouts](https://www.terraform.io/d ## Import -Front Door Custom Https Configurations can be imported using the `resource id` of the Frontend Endpoint, e.g. +Front Door Custom Https Configurations can be imported using the `resource id` of the Front Door Custom Https Configuration, e.g. ```shell -terraform import azurerm_frontdoor_custom_https_configuration.example_custom_https_1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Network/frontDoors/frontdoor1/frontendEndpoints/endpoint1 +terraform import azurerm_frontdoor_custom_https_configuration.example_custom_https_1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Network/frontDoors/frontdoor1/customHttpsConfiguration/endpoint1 ```