diff --git a/azurerm/internal/services/network/application_gateway_resource.go b/azurerm/internal/services/network/application_gateway_resource.go index a2558f9cd5bb..c9471651f13a 100644 --- a/azurerm/internal/services/network/application_gateway_resource.go +++ b/azurerm/internal/services/network/application_gateway_resource.go @@ -3243,6 +3243,7 @@ func expandApplicationGatewaySslCertificates(d *schema.ResourceData) (*[]network data := v["data"].(string) password := v["password"].(string) kvsid := v["key_vault_secret_id"].(string) + cert := v["public_cert_data"].(string) output := network.ApplicationGatewaySslCertificate{ Name: utils.String(name), @@ -3263,6 +3264,8 @@ func expandApplicationGatewaySslCertificates(d *schema.ResourceData) (*[]network } output.ApplicationGatewaySslCertificatePropertiesFormat.KeyVaultSecretID = utils.String(kvsid) + } else if cert != "" { + output.ApplicationGatewaySslCertificatePropertiesFormat.PublicCertData = utils.String(cert) } else { return nil, fmt.Errorf("either `key_vault_secret_id` or `data` must be specified for the `ssl_certificate` block %q", name) } diff --git a/azurerm/internal/services/network/tests/application_gateway_resource_test.go b/azurerm/internal/services/network/tests/application_gateway_resource_test.go index 1599c3405447..8fb0c340d571 100644 --- a/azurerm/internal/services/network/tests/application_gateway_resource_test.go +++ b/azurerm/internal/services/network/tests/application_gateway_resource_test.go @@ -1,10 +1,15 @@ package tests import ( + "encoding/base64" "fmt" + "io/ioutil" + "log" "regexp" "testing" + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2020-05-01/network" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/terraform" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/acceptance" @@ -662,6 +667,33 @@ func TestAccAzureRMApplicationGateway_sslCertificate_EmptyPassword(t *testing.T) }) } +func TestAccAzureRMApplicationGateway_manualSslCertificateChangeIgnoreChanges(t *testing.T) { + data := acceptance.BuildTestData(t, "azurerm_application_gateway", "test") + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.PreCheck(t) }, + Providers: acceptance.SupportedProviders, + CheckDestroy: testCheckAzureRMApplicationGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApplicationGateway_manualSslCertificateChangeIgnoreChangesConfig(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationGatewayExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "ssl_certificate.0.name", "acctestcertificate1"), + testCheckAzureRMApplicationGatewayChangeCert(data.ResourceName, "acctestcertificate2"), + ), + }, + { + Config: testAccAzureRMApplicationGateway_manualSslCertificateChangeIgnoreChangesUpdatedConfig(data), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationGatewayExists(data.ResourceName), + resource.TestCheckResourceAttr(data.ResourceName, "ssl_certificate.0.name", "acctestcertificate2"), + ), + }, + }, + }) +} + func TestAccAzureRMApplicationGateway_sslCertificate(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_application_gateway", "test") @@ -4011,6 +4043,225 @@ resource "azurerm_application_gateway" "test" { `, template, data.RandomInteger) } +func testCheckAzureRMApplicationGatewayChangeCert(resourceName, certName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + client := acceptance.AzureProvider.Meta().(*clients.Client).Network.ApplicationGatewaysClient + ctx := acceptance.AzureProvider.Meta().(*clients.Client).StopContext + + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + gatewayName := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + agw, err := client.Get(ctx, resourceGroup, gatewayName) + if err != nil { + return fmt.Errorf("Bad: Get on ApplicationGatewaysClient: %+v", err) + } + + certPfx, err := ioutil.ReadFile("testdata/application_gateway_test.pfx") + if err != nil { + log.Fatal(err) + } + certB64 := base64.StdEncoding.EncodeToString(certPfx) + + newSslCertificates := make([]network.ApplicationGatewaySslCertificate, 1) + newSslCertificates[0] = network.ApplicationGatewaySslCertificate{ + Name: utils.String(certName), + Etag: utils.String("*"), + + ApplicationGatewaySslCertificatePropertiesFormat: &network.ApplicationGatewaySslCertificatePropertiesFormat{ + Data: utils.String(certB64), + Password: utils.String("terraform"), + }, + } + + agw.SslCertificates = &newSslCertificates + + future, err := client.CreateOrUpdate(ctx, resourceGroup, gatewayName, agw) + if err != nil { + return fmt.Errorf("Bad: updating AGW: %+v", err) + } + + if err := future.WaitForCompletionRef(ctx, client.Client); err != nil { + return fmt.Errorf("Bad: waiting for update of AGW: %+v", err) + } + + return nil + } +} + +func testAccAzureRMApplicationGateway_manualSslCertificateChangeIgnoreChangesConfig(data acceptance.TestData) string { + template := testAccAzureRMApplicationGateway_template(data) + return fmt.Sprintf(` +%s + +# since these variables are re-used - a locals block makes this more maintainable +locals { + backend_address_pool_name = "${azurerm_virtual_network.test.name}-beap" + frontend_port_name = "${azurerm_virtual_network.test.name}-feport" + frontend_ip_configuration_name = "${azurerm_virtual_network.test.name}-feip" + http_setting_name = "${azurerm_virtual_network.test.name}-be-htst" + listener_name = "${azurerm_virtual_network.test.name}-httplstn" + request_routing_rule_name = "${azurerm_virtual_network.test.name}-rqrt" + ssl_certificate_name = "acctestcertificate1" +} + +resource "azurerm_application_gateway" "test" { + name = "acctesttag" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + + sku { + name = "Standard_Small" + tier = "Standard" + capacity = 2 + } + + gateway_ip_configuration { + name = "my-gateway-ip-configuration" + subnet_id = azurerm_subnet.test.id + } + + frontend_port { + name = local.frontend_port_name + port = 80 + } + + frontend_ip_configuration { + name = local.frontend_ip_configuration_name + public_ip_address_id = azurerm_public_ip.test.id + } + + backend_address_pool { + name = local.backend_address_pool_name + } + + backend_http_settings { + name = local.http_setting_name + cookie_based_affinity = "Disabled" + port = 80 + protocol = "Http" + request_timeout = 1 + } + + http_listener { + name = local.listener_name + frontend_ip_configuration_name = local.frontend_ip_configuration_name + frontend_port_name = local.frontend_port_name + protocol = "Http" + } + + request_routing_rule { + name = local.request_routing_rule_name + rule_type = "Basic" + http_listener_name = local.listener_name + backend_address_pool_name = local.backend_address_pool_name + backend_http_settings_name = local.http_setting_name + } + + ssl_certificate { + name = local.ssl_certificate_name + data = filebase64("testdata/application_gateway_test.pfx") + password = "terraform" + } + + lifecycle { + ignore_changes = [ + ssl_certificate, + ] + } +} +`, template) +} + +func testAccAzureRMApplicationGateway_manualSslCertificateChangeIgnoreChangesUpdatedConfig(data acceptance.TestData) string { + template := testAccAzureRMApplicationGateway_template(data) + return fmt.Sprintf(` +%s + +# since these variables are re-used - a locals block makes this more maintainable +locals { + backend_address_pool_name = "${azurerm_virtual_network.test.name}-beap" + frontend_port_name = "${azurerm_virtual_network.test.name}-feport" + frontend_ip_configuration_name = "${azurerm_virtual_network.test.name}-feip" + http_setting_name = "${azurerm_virtual_network.test.name}-be-htst" + listener_name = "${azurerm_virtual_network.test.name}-httplstn" + request_routing_rule_name = "${azurerm_virtual_network.test.name}-rqrt" + ssl_certificate_name = "acctestcertificate3" +} + +resource "azurerm_application_gateway" "test" { + name = "acctesttag" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + + sku { + name = "Standard_Small" + tier = "Standard" + capacity = 2 + } + + gateway_ip_configuration { + name = "my-gateway-ip-configuration" + subnet_id = azurerm_subnet.test.id + } + + frontend_port { + name = local.frontend_port_name + port = 80 + } + + frontend_ip_configuration { + name = local.frontend_ip_configuration_name + public_ip_address_id = azurerm_public_ip.test.id + } + + backend_address_pool { + name = local.backend_address_pool_name + } + + backend_http_settings { + name = local.http_setting_name + cookie_based_affinity = "Disabled" + port = 80 + protocol = "Http" + request_timeout = 1 + } + + http_listener { + name = local.listener_name + frontend_ip_configuration_name = local.frontend_ip_configuration_name + frontend_port_name = local.frontend_port_name + protocol = "Http" + } + + request_routing_rule { + name = local.request_routing_rule_name + rule_type = "Basic" + http_listener_name = local.listener_name + backend_address_pool_name = local.backend_address_pool_name + backend_http_settings_name = local.http_setting_name + } + + ssl_certificate { + name = local.ssl_certificate_name + data = filebase64("testdata/application_gateway_test.pfx") + password = "terraform" + } + + lifecycle { + ignore_changes = [ + ssl_certificate, + ] + } +} +`, template) +} + func testAccAzureRMApplicationGateway_webApplicationFirewall(data acceptance.TestData) string { template := testAccAzureRMApplicationGateway_template(data) return fmt.Sprintf(`