diff --git a/GNUmakefile b/GNUmakefile index c9eacb4511da..090f821c3f04 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -12,7 +12,7 @@ test: fmtcheck xargs -t -n4 go test $(TESTARGS) -timeout=30s -parallel=4 testacc: fmtcheck - TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m + TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 180m vet: @echo "go vet ." diff --git a/azurerm/config.go b/azurerm/config.go index fb0e93c55e3d..d8ad4eb8a0a2 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -70,7 +70,7 @@ type ArmClient struct { automationCredentialClient automation.CredentialClient automationScheduleClient automation.ScheduleClient - appGatewayClient network.ApplicationGatewaysClient + applicationGatewayClient network.ApplicationGatewaysClient ifaceClient network.InterfacesClient expressRouteCircuitClient network.ExpressRouteCircuitsClient loadBalancerClient network.LoadBalancersClient @@ -325,7 +325,7 @@ func (c *Config) getArmClient() (*ArmClient, error) { setUserAgent(&agc.Client) agc.Authorizer = auth agc.Sender = sender - client.appGatewayClient = agc + client.applicationGatewayClient = agc crc := containerregistry.NewRegistriesClientWithBaseURI(endpoint, c.SubscriptionID) setUserAgent(&crc.Client) diff --git a/azurerm/import_arm_application_gateway_test.go b/azurerm/import_arm_application_gateway_test.go new file mode 100644 index 000000000000..e418bbc03534 --- /dev/null +++ b/azurerm/import_arm_application_gateway_test.go @@ -0,0 +1,31 @@ +package azurerm + +import ( + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAzureRMApplicationGateway_importBasic(t *testing.T) { + resourceName := "azurerm_application_gateway.test" + + ri := acctest.RandInt() + config := testAccAzureRMApplicationGateway_basic(ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApplicationGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: config, + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} diff --git a/azurerm/provider.go b/azurerm/provider.go index ec5776437fcf..cda04bd7fc21 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -80,6 +80,7 @@ func Provider() terraform.ResourceProvider { }, ResourcesMap: map[string]*schema.Resource{ + "azurerm_application_gateway": resourceArmApplicationGateway(), "azurerm_application_insights": resourceArmApplicationInsights(), "azurerm_app_service": resourceArmAppService(), "azurerm_app_service_plan": resourceArmAppServicePlan(), diff --git a/azurerm/resource_arm_application_gateway.go b/azurerm/resource_arm_application_gateway.go new file mode 100644 index 000000000000..8fe50505d610 --- /dev/null +++ b/azurerm/resource_arm_application_gateway.go @@ -0,0 +1,1739 @@ +package azurerm + +import ( + "bytes" + "fmt" + "log" + // "time" + + "github.com/Azure/azure-sdk-for-go/arm/network" + "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform/helper/hashcode" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmApplicationGateway() *schema.Resource { + return &schema.Resource{ + Create: resourceArmApplicationGatewayCreate, + Read: resourceArmApplicationGatewayRead, + Update: resourceArmApplicationGatewayCreate, + Delete: resourceArmApplicationGatewayDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + StateFunc: azureRMNormalizeLocation, + }, + + "resource_group_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "sku": { + Type: schema.TypeSet, + Required: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, + ValidateFunc: validation.StringInSlice([]string{ + string(network.StandardSmall), + string(network.StandardMedium), + string(network.StandardLarge), + string(network.WAFLarge), + string(network.WAFMedium), + }, true), + }, + + "tier": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, + ValidateFunc: validation.StringInSlice([]string{ + string(network.Standard), + string(network.WAF), + }, true), + }, + + "capacity": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(1, 10), + }, + }, + }, + }, + + "disabled_ssl_protocols": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, + ValidateFunc: validation.StringInSlice([]string{ + string(network.TLSv10), + string(network.TLSv11), + string(network.TLSv12), + }, true), + }, + }, + + "waf_configuration": { + Type: schema.TypeSet, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + }, + + "firewall_mode": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, + ValidateFunc: validation.StringInSlice([]string{ + string(network.Detection), + string(network.Prevention), + }, true), + }, + + "rule_set_type": { + Type: schema.TypeString, + Optional: true, + Default: "OWASP", + }, + + "rule_set_version": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, + ValidateFunc: validation.StringInSlice([]string{"2.2.9", "3.0"}, true), + }, + }, + }, + }, + + "gateway_ip_configuration": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "subnet_id": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + }, + + "frontend_port": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "port": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + + "frontend_ip_configuration": { + Type: schema.TypeList, + Required: true, + MinItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "subnet_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + + "private_ip_address": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + + "public_ip_address_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + + "private_ip_address_allocation": { + Type: schema.TypeString, + Optional: true, + Computed: true, + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, + ValidateFunc: validation.StringInSlice([]string{ + string(network.Dynamic), + string(network.Static), + }, true), + }, + }, + }, + }, + + "backend_address_pool": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "ip_address_list": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "fqdn_list": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + + "backend_http_settings": { + Type: schema.TypeList, + Required: true, + MinItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "port": { + Type: schema.TypeInt, + Required: true, + }, + + "protocol": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, + ValidateFunc: validation.StringInSlice([]string{ + string(network.HTTP), + string(network.HTTPS), + }, true), + }, + + "cookie_based_affinity": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, + ValidateFunc: validation.StringInSlice([]string{ + string(network.Enabled), + string(network.Disabled), + }, true), + }, + + "request_timeout": { + Type: schema.TypeInt, + Optional: true, + }, + + "authentication_certificate": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + + "id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + + "probe_name": { + Type: schema.TypeString, + Optional: true, + }, + + "probe_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + + "http_listener": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "frontend_ip_configuration_name": { + Type: schema.TypeString, + Required: true, + }, + + "frontend_ip_configuration_id": { + Type: schema.TypeString, + Computed: true, + }, + + "frontend_port_name": { + Type: schema.TypeString, + Required: true, + }, + + "frontend_port_id": { + Type: schema.TypeString, + Computed: true, + }, + + "protocol": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, + ValidateFunc: validation.StringInSlice([]string{ + string(network.HTTP), + string(network.HTTPS), + }, true), + }, + + "host_name": { + Type: schema.TypeString, + Optional: true, + }, + + "ssl_certificate_name": { + Type: schema.TypeString, + Optional: true, + }, + + "ssl_certificate_id": { + Type: schema.TypeString, + Computed: true, + }, + + "require_sni": { + Type: schema.TypeBool, + Optional: true, + }, + }, + }, + }, + + "probe": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "protocol": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, + ValidateFunc: validation.StringInSlice([]string{ + string(network.HTTP), + string(network.HTTPS), + }, true), + }, + + "path": { + Type: schema.TypeString, + Required: true, + }, + + "host": { + Type: schema.TypeString, + Required: true, + }, + + "interval": { + Type: schema.TypeInt, + Required: true, + }, + + "timeout": { + Type: schema.TypeInt, + Required: true, + }, + + "unhealthy_threshold": { + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + + "request_routing_rule": { + Type: schema.TypeList, + Required: true, + MinItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "rule_type": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: ignoreCaseDiffSuppressFunc, + ValidateFunc: validation.StringInSlice([]string{ + string(network.Basic), + string(network.PathBasedRouting), + }, true), + }, + + "http_listener_name": { + Type: schema.TypeString, + Required: true, + }, + + "http_listener_id": { + Type: schema.TypeString, + Computed: true, + }, + + "backend_address_pool_name": { + Type: schema.TypeString, + Optional: true, + }, + + "backend_address_pool_id": { + Type: schema.TypeString, + Computed: true, + }, + + "backend_http_settings_name": { + Type: schema.TypeString, + Optional: true, + }, + + "backend_http_settings_id": { + Type: schema.TypeString, + Computed: true, + }, + + "url_path_map_name": { + Type: schema.TypeString, + Optional: true, + }, + + "url_path_map_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + + "url_path_map": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "default_backend_address_pool_name": { + Type: schema.TypeString, + Required: true, + }, + + "default_backend_address_pool_id": { + Type: schema.TypeString, + Computed: true, + }, + + "default_backend_http_settings_name": { + Type: schema.TypeString, + Required: true, + }, + + "default_backend_http_settings_id": { + Type: schema.TypeString, + Computed: true, + }, + + "path_rule": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "paths": { + Type: schema.TypeList, + Required: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "backend_address_pool_name": { + Type: schema.TypeString, + Required: true, + }, + + "backend_address_pool_id": { + Type: schema.TypeString, + Computed: true, + }, + + "backend_http_settings_name": { + Type: schema.TypeString, + Required: true, + }, + + "backend_http_settings_id": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + }, + }, + + "authentication_certificate": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "data": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + }, + }, + }, + + "ssl_certificate": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + + "name": { + Type: schema.TypeString, + Required: true, + }, + + "data": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + + "password": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + + "public_cert_data": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + + "tags": tagsSchema(), + }, + } +} + +func resourceArmApplicationGatewayCreate(d *schema.ResourceData, meta interface{}) error { + armClient := meta.(*ArmClient) + client := armClient.applicationGatewayClient + + log.Printf("[INFO] preparing arguments for AzureRM ApplicationGateway creation.") + + name := d.Get("name").(string) + location := d.Get("location").(string) + resGroup := d.Get("resource_group_name").(string) + tags := d.Get("tags").(map[string]interface{}) + + // Gateway ID is needed to link sub-resources together in expand functions + gatewayID := fmt.Sprintf( + "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/applicationGateways/%s", + armClient.subscriptionId, resGroup, name) + + properties := network.ApplicationGatewayPropertiesFormat{} + properties.Sku = expandApplicationGatewaySku(d) + properties.SslPolicy = expandApplicationGatewaySslPolicy(d) + properties.GatewayIPConfigurations = expandApplicationGatewayIPConfigurations(d) + properties.FrontendPorts = expandApplicationGatewayFrontendPorts(d) + properties.FrontendIPConfigurations = expandApplicationGatewayFrontendIPConfigurations(d) + properties.BackendAddressPools = expandApplicationGatewayBackendAddressPools(d) + properties.BackendHTTPSettingsCollection = expandApplicationGatewayBackendHTTPSettings(d, gatewayID) + properties.HTTPListeners = expandApplicationGatewayHTTPListeners(d, gatewayID) + properties.Probes = expandApplicationGatewayProbes(d) + properties.RequestRoutingRules = expandApplicationGatewayRequestRoutingRules(d, gatewayID) + properties.URLPathMaps = expandApplicationGatewayURLPathMaps(d, gatewayID) + properties.AuthenticationCertificates = expandApplicationGatewayAuthenticationCertificates(d) + properties.SslCertificates = expandApplicationGatewaySslCertificates(d) + + if _, ok := d.GetOk("waf_configuration"); ok { + properties.WebApplicationFirewallConfiguration = expandApplicationGatewayWafConfig(d) + } + + gateway := network.ApplicationGateway{ + Name: utils.String(name), + Location: utils.String(location), + Tags: expandTags(tags), + ApplicationGatewayPropertiesFormat: &properties, + } + + _, errChan := client.CreateOrUpdate(resGroup, name, gateway, make(chan struct{})) + err := <-errChan + if err != nil { + return errwrap.Wrapf("Error Creating/Updating ApplicationGateway {{err}}", err) + } + + read, err := client.Get(resGroup, name) + if err != nil { + return errwrap.Wrapf("Error Getting ApplicationGateway {{err}}", err) + } + if read.ID == nil { + return fmt.Errorf("Cannot read ApplicationGateway %s (resource group %s) ID", name, resGroup) + } + + d.SetId(*read.ID) + + return resourceArmApplicationGatewayRead(d, meta) +} + +func resourceArmApplicationGatewayRead(d *schema.ResourceData, meta interface{}) error { + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return errwrap.Wrapf("Error parsing ApplicationGateway ID {{err}}", err) + } + + applicationGateway, exists, err := retrieveApplicationGatewayById(d.Id(), meta) + if err != nil { + return errwrap.Wrapf("Error Getting ApplicationGateway By ID {{err}}", err) + } + if !exists { + d.SetId("") + log.Printf("[INFO] ApplicationGateway %q not found. Removing from state", d.Get("name").(string)) + return nil + } + + d.Set("name", applicationGateway.Name) + d.Set("resource_group_name", id.ResourceGroup) + d.Set("location", applicationGateway.Location) + d.Set("sku", schema.NewSet(hashApplicationGatewaySku, flattenApplicationGatewaySku(applicationGateway.ApplicationGatewayPropertiesFormat.Sku))) + d.Set("disabled_ssl_protocols", flattenApplicationGatewaySslPolicy(applicationGateway.ApplicationGatewayPropertiesFormat.SslPolicy)) + d.Set("gateway_ip_configuration", flattenApplicationGatewayIPConfigurations(applicationGateway.ApplicationGatewayPropertiesFormat.GatewayIPConfigurations)) + d.Set("frontend_port", flattenApplicationGatewayFrontendPorts(applicationGateway.ApplicationGatewayPropertiesFormat.FrontendPorts)) + d.Set("frontend_ip_configuration", flattenApplicationGatewayFrontendIPConfigurations(applicationGateway.ApplicationGatewayPropertiesFormat.FrontendIPConfigurations)) + d.Set("backend_address_pool", flattenApplicationGatewayBackendAddressPools(applicationGateway.ApplicationGatewayPropertiesFormat.BackendAddressPools)) + + v1, err1 := flattenApplicationGatewayBackendHTTPSettings(applicationGateway.ApplicationGatewayPropertiesFormat.BackendHTTPSettingsCollection) + if err1 != nil { + return fmt.Errorf("error flattening BackendHTTPSettings: %+v", err1) + } + d.Set("backend_http_settings", v1) + + v2, err2 := flattenApplicationGatewayHTTPListeners(applicationGateway.ApplicationGatewayPropertiesFormat.HTTPListeners) + if err2 != nil { + return fmt.Errorf("error flattening HTTPListeners: %+v", err2) + } + d.Set("http_listener", v2) + + d.Set("probe", flattenApplicationGatewayProbes(applicationGateway.ApplicationGatewayPropertiesFormat.Probes)) + + v3, err3 := flattenApplicationGatewayRequestRoutingRules(applicationGateway.ApplicationGatewayPropertiesFormat.RequestRoutingRules) + if err3 != nil { + return fmt.Errorf("error flattening RequestRoutingRules: %+v", err3) + } + d.Set("request_routing_rule", v3) + + v4, err4 := flattenApplicationGatewayURLPathMaps(applicationGateway.ApplicationGatewayPropertiesFormat.URLPathMaps) + if err4 != nil { + return fmt.Errorf("error flattening URLPathMaps: %+v", err4) + } + d.Set("url_path_map", v4) + + d.Set("authentication_certificate", schema.NewSet(hashApplicationGatewayAuthenticationCertificates, flattenApplicationGatewayAuthenticationCertificates(applicationGateway.ApplicationGatewayPropertiesFormat.AuthenticationCertificates))) + d.Set("ssl_certificate", schema.NewSet(hashApplicationGatewaySslCertificates, flattenApplicationGatewaySslCertificates(applicationGateway.ApplicationGatewayPropertiesFormat.SslCertificates))) + + if applicationGateway.ApplicationGatewayPropertiesFormat.WebApplicationFirewallConfiguration != nil { + d.Set("waf_configuration", schema.NewSet(hashApplicationGatewayWafConfig, + flattenApplicationGatewayWafConfig(applicationGateway.ApplicationGatewayPropertiesFormat.WebApplicationFirewallConfiguration))) + } + + flattenAndSetTags(d, applicationGateway.Tags) + + return nil +} + +func resourceArmApplicationGatewayDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).applicationGatewayClient + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return errwrap.Wrapf("Error Parsing Azure Resource ID {{err}}", err) + } + resGroup := id.ResourceGroup + name := id.Path["applicationGateways"] + + _, errChan := client.Delete(resGroup, name, make(chan struct{})) + err = <-errChan + if err != nil { + return errwrap.Wrapf("Error Deleting ApplicationGateway {{err}}", err) + } + + d.SetId("") + return nil +} + +func ApplicationGatewayResGroupAndNameFromID(ApplicationGatewayID string) (string, string, error) { + id, err := parseAzureResourceID(ApplicationGatewayID) + if err != nil { + return "", "", err + } + name := id.Path["applicationGateways"] + resGroup := id.ResourceGroup + + return resGroup, name, nil +} + +func retrieveApplicationGatewayById(ApplicationGatewayID string, meta interface{}) (*network.ApplicationGateway, bool, error) { + client := meta.(*ArmClient).applicationGatewayClient + + resGroup, name, err := ApplicationGatewayResGroupAndNameFromID(ApplicationGatewayID) + if err != nil { + return nil, false, errwrap.Wrapf("Error Getting ApplicationGateway Name and Group: {{err}}", err) + } + + resp, err := client.Get(resGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil, false, nil + } + return nil, false, fmt.Errorf("Error making Read request on Azure ApplicationGateway %s: %+v", name, err) + } + + return &resp, true, nil +} + +func ApplicationGatewayStateRefreshFunc(client *ArmClient, resourceGroupName string, name string) resource.StateRefreshFunc { + return func() (interface{}, string, error) { + res, err := client.applicationGatewayClient.Get(resourceGroupName, name) + if err != nil { + return nil, "", fmt.Errorf( + "Error issuing read request in ApplicationGatewayStateRefreshFunc to Azure ARM for ApplicationGateway '%s' (RG: '%s'): %+v", + name, resourceGroupName, err) + } + + return res, *res.ApplicationGatewayPropertiesFormat.ProvisioningState, nil + } +} + +func expandApplicationGatewaySku(d *schema.ResourceData) *network.ApplicationGatewaySku { + skuSet := d.Get("sku").(*schema.Set).List() + sku := skuSet[0].(map[string]interface{}) + + name := sku["name"].(string) + tier := sku["tier"].(string) + capacity := int32(sku["capacity"].(int)) + + return &network.ApplicationGatewaySku{ + Name: network.ApplicationGatewaySkuName(name), + Tier: network.ApplicationGatewayTier(tier), + Capacity: &capacity, + } +} + +func expandApplicationGatewayWafConfig(d *schema.ResourceData) *network.ApplicationGatewayWebApplicationFirewallConfiguration { + wafSet := d.Get("waf_configuration").(*schema.Set).List() + waf := wafSet[0].(map[string]interface{}) + + enabled := waf["enabled"].(bool) + mode := waf["firewall_mode"].(string) + rulesettype := waf["rule_set_type"].(string) + rulesetversion := waf["rule_set_version"].(string) + + return &network.ApplicationGatewayWebApplicationFirewallConfiguration{ + Enabled: &enabled, + FirewallMode: network.ApplicationGatewayFirewallMode(mode), + RuleSetType: &rulesettype, + RuleSetVersion: &rulesetversion, + } +} + +func expandApplicationGatewaySslPolicy(d *schema.ResourceData) *network.ApplicationGatewaySslPolicy { + disabledProtoList := d.Get("disabled_ssl_protocols").([]interface{}) + disabled := []network.ApplicationGatewaySslProtocol{} + + for _, proto := range disabledProtoList { + disabled = append(disabled, network.ApplicationGatewaySslProtocol(proto.(string))) + } + + return &network.ApplicationGatewaySslPolicy{ + DisabledSslProtocols: &disabled, + } +} + +func expandApplicationGatewayIPConfigurations(d *schema.ResourceData) *[]network.ApplicationGatewayIPConfiguration { + configs := d.Get("gateway_ip_configuration").([]interface{}) + ipConfigurations := make([]network.ApplicationGatewayIPConfiguration, 0, len(configs)) + + for _, configRaw := range configs { + data := configRaw.(map[string]interface{}) + + name := data["name"].(string) + subnetID := data["subnet_id"].(string) + + ipConfig := network.ApplicationGatewayIPConfiguration{ + Name: &name, + ApplicationGatewayIPConfigurationPropertiesFormat: &network.ApplicationGatewayIPConfigurationPropertiesFormat{ + Subnet: &network.SubResource{ + ID: &subnetID, + }, + }, + } + ipConfigurations = append(ipConfigurations, ipConfig) + } + + return &ipConfigurations +} + +func expandApplicationGatewayFrontendPorts(d *schema.ResourceData) *[]network.ApplicationGatewayFrontendPort { + configs := d.Get("frontend_port").([]interface{}) + frontendPorts := make([]network.ApplicationGatewayFrontendPort, 0, len(configs)) + + for _, configRaw := range configs { + data := configRaw.(map[string]interface{}) + + name := data["name"].(string) + port := int32(data["port"].(int)) + + portConfig := network.ApplicationGatewayFrontendPort{ + Name: &name, + ApplicationGatewayFrontendPortPropertiesFormat: &network.ApplicationGatewayFrontendPortPropertiesFormat{ + Port: &port, + }, + } + frontendPorts = append(frontendPorts, portConfig) + } + + return &frontendPorts +} + +func expandApplicationGatewayFrontendIPConfigurations(d *schema.ResourceData) *[]network.ApplicationGatewayFrontendIPConfiguration { + configs := d.Get("frontend_ip_configuration").([]interface{}) + frontEndConfigs := make([]network.ApplicationGatewayFrontendIPConfiguration, 0, len(configs)) + + for _, configRaw := range configs { + data := configRaw.(map[string]interface{}) + + properties := network.ApplicationGatewayFrontendIPConfigurationPropertiesFormat{} + + if v := data["subnet_id"].(string); v != "" { + properties.Subnet = &network.SubResource{ + ID: &v, + } + } + + if v := data["private_ip_address_allocation"].(string); v != "" { + properties.PrivateIPAllocationMethod = network.IPAllocationMethod(v) + } + + if v := data["private_ip_address"].(string); v != "" { + properties.PrivateIPAddress = &v + } + + if v := data["public_ip_address_id"].(string); v != "" { + properties.PublicIPAddress = &network.SubResource{ + ID: &v, + } + } + + name := data["name"].(string) + frontEndConfig := network.ApplicationGatewayFrontendIPConfiguration{ + Name: &name, + ApplicationGatewayFrontendIPConfigurationPropertiesFormat: &properties, + } + + frontEndConfigs = append(frontEndConfigs, frontEndConfig) + } + + return &frontEndConfigs +} + +func expandApplicationGatewayBackendAddressPools(d *schema.ResourceData) *[]network.ApplicationGatewayBackendAddressPool { + configs := d.Get("backend_address_pool").([]interface{}) + backendPools := make([]network.ApplicationGatewayBackendAddressPool, 0, len(configs)) + + for _, configRaw := range configs { + data := configRaw.(map[string]interface{}) + + backendAddresses := []network.ApplicationGatewayBackendAddress{} + + for _, rawIP := range data["ip_address_list"].([]interface{}) { + ip := rawIP.(string) + backendAddresses = append(backendAddresses, network.ApplicationGatewayBackendAddress{IPAddress: &ip}) + } + + for _, rawFQDN := range data["fqdn_list"].([]interface{}) { + fqdn := rawFQDN.(string) + backendAddresses = append(backendAddresses, network.ApplicationGatewayBackendAddress{Fqdn: &fqdn}) + } + + name := data["name"].(string) + pool := network.ApplicationGatewayBackendAddressPool{ + Name: &name, + ApplicationGatewayBackendAddressPoolPropertiesFormat: &network.ApplicationGatewayBackendAddressPoolPropertiesFormat{ + BackendAddresses: &backendAddresses, + }, + } + + backendPools = append(backendPools, pool) + } + + return &backendPools +} + +func expandApplicationGatewayBackendHTTPSettings(d *schema.ResourceData, gatewayID string) *[]network.ApplicationGatewayBackendHTTPSettings { + configs := d.Get("backend_http_settings").([]interface{}) + backendSettings := make([]network.ApplicationGatewayBackendHTTPSettings, 0, len(configs)) + + for _, configRaw := range configs { + data := configRaw.(map[string]interface{}) + + name := data["name"].(string) + port := int32(data["port"].(int)) + protocol := data["protocol"].(string) + cookieBasedAffinity := data["cookie_based_affinity"].(string) + requestTimeout := int32(data["request_timeout"].(int)) + + setting := network.ApplicationGatewayBackendHTTPSettings{ + Name: &name, + ApplicationGatewayBackendHTTPSettingsPropertiesFormat: &network.ApplicationGatewayBackendHTTPSettingsPropertiesFormat{ + Port: &port, + Protocol: network.ApplicationGatewayProtocol(protocol), + CookieBasedAffinity: network.ApplicationGatewayCookieBasedAffinity(cookieBasedAffinity), + RequestTimeout: &requestTimeout, + }, + } + + if data["authentication_certificate"] != nil { + authCerts := data["authentication_certificate"].([]interface{}) + authCertSubResources := make([]network.SubResource, 0, len(authCerts)) + + for _, rawAuthCert := range authCerts { + authCert := rawAuthCert.(map[string]interface{}) + authCertID := fmt.Sprintf("%s/authenticationCertificates/%s", gatewayID, authCert["name"]) + authCertSubResource := network.SubResource{ + ID: &authCertID, + } + + authCertSubResources = append(authCertSubResources, authCertSubResource) + } + + setting.ApplicationGatewayBackendHTTPSettingsPropertiesFormat.AuthenticationCertificates = &authCertSubResources + } + + probeName := data["probe_name"].(string) + if probeName != "" { + probeID := fmt.Sprintf("%s/probes/%s", gatewayID, probeName) + setting.ApplicationGatewayBackendHTTPSettingsPropertiesFormat.Probe = &network.SubResource{ + ID: &probeID, + } + } + + backendSettings = append(backendSettings, setting) + } + + return &backendSettings +} + +func expandApplicationGatewayHTTPListeners(d *schema.ResourceData, gatewayID string) *[]network.ApplicationGatewayHTTPListener { + configs := d.Get("http_listener").([]interface{}) + httpListeners := make([]network.ApplicationGatewayHTTPListener, 0, len(configs)) + + for _, configRaw := range configs { + data := configRaw.(map[string]interface{}) + + name := data["name"].(string) + frontendIPConfigName := data["frontend_ip_configuration_name"].(string) + frontendIPConfigID := fmt.Sprintf("%s/frontendIPConfigurations/%s", gatewayID, frontendIPConfigName) + frontendPortName := data["frontend_port_name"].(string) + frontendPortID := fmt.Sprintf("%s/frontendPorts/%s", gatewayID, frontendPortName) + protocol := data["protocol"].(string) + + listener := network.ApplicationGatewayHTTPListener{ + Name: &name, + ApplicationGatewayHTTPListenerPropertiesFormat: &network.ApplicationGatewayHTTPListenerPropertiesFormat{ + FrontendIPConfiguration: &network.SubResource{ + ID: &frontendIPConfigID, + }, + FrontendPort: &network.SubResource{ + ID: &frontendPortID, + }, + Protocol: network.ApplicationGatewayProtocol(protocol), + }, + } + + if host := data["host_name"].(string); host != "" { + listener.ApplicationGatewayHTTPListenerPropertiesFormat.HostName = &host + } + + if sslCertName := data["ssl_certificate_name"].(string); sslCertName != "" { + certID := fmt.Sprintf("%s/sslCertificates/%s", gatewayID, sslCertName) + listener.ApplicationGatewayHTTPListenerPropertiesFormat.SslCertificate = &network.SubResource{ + ID: &certID, + } + } + + if requireSNI, ok := data["require_sni"].(bool); ok { + listener.ApplicationGatewayHTTPListenerPropertiesFormat.RequireServerNameIndication = &requireSNI + } + + httpListeners = append(httpListeners, listener) + } + + return &httpListeners +} + +func expandApplicationGatewayProbes(d *schema.ResourceData) *[]network.ApplicationGatewayProbe { + configs := d.Get("probe").([]interface{}) + backendSettings := make([]network.ApplicationGatewayProbe, 0, len(configs)) + + for _, configRaw := range configs { + data := configRaw.(map[string]interface{}) + + name := data["name"].(string) + protocol := data["protocol"].(string) + probePath := data["path"].(string) + host := data["host"].(string) + interval := int32(data["interval"].(int)) + timeout := int32(data["timeout"].(int)) + unhealthyThreshold := int32(data["unhealthy_threshold"].(int)) + + setting := network.ApplicationGatewayProbe{ + Name: &name, + ApplicationGatewayProbePropertiesFormat: &network.ApplicationGatewayProbePropertiesFormat{ + Protocol: network.ApplicationGatewayProtocol(protocol), + Path: &probePath, + Host: &host, + Interval: &interval, + Timeout: &timeout, + UnhealthyThreshold: &unhealthyThreshold, + }, + } + + backendSettings = append(backendSettings, setting) + } + + return &backendSettings +} + +func expandApplicationGatewayRequestRoutingRules(d *schema.ResourceData, gatewayID string) *[]network.ApplicationGatewayRequestRoutingRule { + configs := d.Get("request_routing_rule").([]interface{}) + rules := make([]network.ApplicationGatewayRequestRoutingRule, 0, len(configs)) + + for _, configRaw := range configs { + data := configRaw.(map[string]interface{}) + + name := data["name"].(string) + ruleType := data["rule_type"].(string) + httpListenerName := data["http_listener_name"].(string) + httpListenerID := fmt.Sprintf("%s/httpListeners/%s", gatewayID, httpListenerName) + + rule := network.ApplicationGatewayRequestRoutingRule{ + Name: &name, + ApplicationGatewayRequestRoutingRulePropertiesFormat: &network.ApplicationGatewayRequestRoutingRulePropertiesFormat{ + RuleType: network.ApplicationGatewayRequestRoutingRuleType(ruleType), + HTTPListener: &network.SubResource{ + ID: &httpListenerID, + }, + }, + } + + if backendAddressPoolName := data["backend_address_pool_name"].(string); backendAddressPoolName != "" { + backendAddressPoolID := fmt.Sprintf("%s/backendAddressPools/%s", gatewayID, backendAddressPoolName) + rule.ApplicationGatewayRequestRoutingRulePropertiesFormat.BackendAddressPool = &network.SubResource{ + ID: &backendAddressPoolID, + } + } + + if backendHTTPSettingsName := data["backend_http_settings_name"].(string); backendHTTPSettingsName != "" { + backendHTTPSettingsID := fmt.Sprintf("%s/backendHttpSettingsCollection/%s", gatewayID, backendHTTPSettingsName) + rule.ApplicationGatewayRequestRoutingRulePropertiesFormat.BackendHTTPSettings = &network.SubResource{ + ID: &backendHTTPSettingsID, + } + } + + if urlPathMapName := data["url_path_map_name"].(string); urlPathMapName != "" { + urlPathMapID := fmt.Sprintf("%s/urlPathMaps/%s", gatewayID, urlPathMapName) + rule.ApplicationGatewayRequestRoutingRulePropertiesFormat.URLPathMap = &network.SubResource{ + ID: &urlPathMapID, + } + } + + rules = append(rules, rule) + } + + return &rules +} + +func expandApplicationGatewayURLPathMaps(d *schema.ResourceData, gatewayID string) *[]network.ApplicationGatewayURLPathMap { + configs := d.Get("url_path_map").([]interface{}) + pathMaps := make([]network.ApplicationGatewayURLPathMap, 0, len(configs)) + + for _, configRaw := range configs { + data := configRaw.(map[string]interface{}) + + name := data["name"].(string) + defaultBackendAddressPoolName := data["default_backend_address_pool_name"].(string) + defaultBackendAddressPoolID := fmt.Sprintf("%s/backendAddressPools/%s", gatewayID, defaultBackendAddressPoolName) + defaultBackendHTTPSettingsName := data["default_backend_http_settings_name"].(string) + defaultBackendHTTPSettingsID := fmt.Sprintf("%s/backendHttpSettingsCollection/%s", gatewayID, defaultBackendHTTPSettingsName) + + pathRules := []network.ApplicationGatewayPathRule{} + for _, ruleConfig := range data["path_rule"].([]interface{}) { + ruleConfigMap := ruleConfig.(map[string]interface{}) + + ruleName := ruleConfigMap["name"].(string) + + rulePaths := []string{} + for _, rulePath := range ruleConfigMap["paths"].([]interface{}) { + rulePaths = append(rulePaths, rulePath.(string)) + } + + rule := network.ApplicationGatewayPathRule{ + Name: &ruleName, + ApplicationGatewayPathRulePropertiesFormat: &network.ApplicationGatewayPathRulePropertiesFormat{ + Paths: &rulePaths, + }, + } + + if backendAddressPoolName := ruleConfigMap["backend_address_pool_name"].(string); backendAddressPoolName != "" { + backendAddressPoolID := fmt.Sprintf("%s/backendAddressPools/%s", gatewayID, backendAddressPoolName) + rule.ApplicationGatewayPathRulePropertiesFormat.BackendAddressPool = &network.SubResource{ + ID: &backendAddressPoolID, + } + } + + if backendHTTPSettingsName := ruleConfigMap["backend_http_settings_name"].(string); backendHTTPSettingsName != "" { + backendHTTPSettingsID := fmt.Sprintf("%s/backendHttpSettingsCollection/%s", gatewayID, backendHTTPSettingsName) + rule.ApplicationGatewayPathRulePropertiesFormat.BackendHTTPSettings = &network.SubResource{ + ID: &backendHTTPSettingsID, + } + } + + pathRules = append(pathRules, rule) + } + + pathMap := network.ApplicationGatewayURLPathMap{ + Name: &name, + ApplicationGatewayURLPathMapPropertiesFormat: &network.ApplicationGatewayURLPathMapPropertiesFormat{ + DefaultBackendAddressPool: &network.SubResource{ + ID: &defaultBackendAddressPoolID, + }, + DefaultBackendHTTPSettings: &network.SubResource{ + ID: &defaultBackendHTTPSettingsID, + }, + PathRules: &pathRules, + }, + } + + pathMaps = append(pathMaps, pathMap) + } + + return &pathMaps +} + +func expandApplicationGatewayAuthenticationCertificates(d *schema.ResourceData) *[]network.ApplicationGatewayAuthenticationCertificate { + configs := d.Get("authentication_certificate").([]interface{}) + authCerts := make([]network.ApplicationGatewayAuthenticationCertificate, 0, len(configs)) + + for _, configRaw := range configs { + raw := configRaw.(map[string]interface{}) + + name := raw["name"].(string) + data := raw["data"].(string) + + // data must be base64 encoded + data = base64Encode(data) + + cert := network.ApplicationGatewayAuthenticationCertificate{ + Name: &name, + ApplicationGatewayAuthenticationCertificatePropertiesFormat: &network.ApplicationGatewayAuthenticationCertificatePropertiesFormat{ + Data: &data, + }, + } + + authCerts = append(authCerts, cert) + } + + return &authCerts +} + +func expandApplicationGatewaySslCertificates(d *schema.ResourceData) *[]network.ApplicationGatewaySslCertificate { + configs := d.Get("ssl_certificate").([]interface{}) + sslCerts := make([]network.ApplicationGatewaySslCertificate, 0, len(configs)) + + for _, configRaw := range configs { + raw := configRaw.(map[string]interface{}) + + name := raw["name"].(string) + data := raw["data"].(string) + password := raw["password"].(string) + + // data must be base64 encoded + data = base64Encode(data) + + cert := network.ApplicationGatewaySslCertificate{ + Name: &name, + ApplicationGatewaySslCertificatePropertiesFormat: &network.ApplicationGatewaySslCertificatePropertiesFormat{ + Data: &data, + Password: &password, + }, + } + + sslCerts = append(sslCerts, cert) + } + + return &sslCerts +} + +func flattenApplicationGatewaySku(sku *network.ApplicationGatewaySku) []interface{} { + result := make(map[string]interface{}) + + result["name"] = string(sku.Name) + result["tier"] = string(sku.Tier) + result["capacity"] = int(*sku.Capacity) + + return []interface{}{result} +} + +func flattenApplicationGatewayWafConfig(waf *network.ApplicationGatewayWebApplicationFirewallConfiguration) []interface{} { + result := make(map[string]interface{}) + + result["enabled"] = *waf.Enabled + result["firewall_mode"] = string(waf.FirewallMode) + result["rule_set_type"] = waf.RuleSetType + result["rule_set_version"] = waf.RuleSetVersion + + return []interface{}{result} +} + +func flattenApplicationGatewaySslPolicy(policy *network.ApplicationGatewaySslPolicy) []interface{} { + result := make([]interface{}, 0, len(*policy.DisabledSslProtocols)) + + for _, proto := range *policy.DisabledSslProtocols { + result = append(result, string(proto)) + } + + return result +} + +func flattenApplicationGatewayIPConfigurations(ipConfigs *[]network.ApplicationGatewayIPConfiguration) []interface{} { + result := make([]interface{}, 0, len(*ipConfigs)) + + for _, config := range *ipConfigs { + ipConfig := map[string]interface{}{ + "id": *config.ID, + "name": *config.Name, + "subnet_id": *config.ApplicationGatewayIPConfigurationPropertiesFormat.Subnet.ID, + } + + result = append(result, ipConfig) + } + + return result +} + +func flattenApplicationGatewayFrontendPorts(portConfigs *[]network.ApplicationGatewayFrontendPort) []interface{} { + result := make([]interface{}, 0, len(*portConfigs)) + + for _, config := range *portConfigs { + port := map[string]interface{}{ + "id": *config.ID, + "name": *config.Name, + "port": int(*config.ApplicationGatewayFrontendPortPropertiesFormat.Port), + } + + result = append(result, port) + } + + return result +} + +func flattenApplicationGatewayFrontendIPConfigurations(ipConfigs *[]network.ApplicationGatewayFrontendIPConfiguration) []interface{} { + result := make([]interface{}, 0, len(*ipConfigs)) + for _, config := range *ipConfigs { + ipConfig := make(map[string]interface{}) + ipConfig["id"] = *config.ID + ipConfig["name"] = *config.Name + + if config.ApplicationGatewayFrontendIPConfigurationPropertiesFormat.PrivateIPAllocationMethod != "" { + ipConfig["private_ip_address_allocation"] = config.ApplicationGatewayFrontendIPConfigurationPropertiesFormat.PrivateIPAllocationMethod + } + + if config.ApplicationGatewayFrontendIPConfigurationPropertiesFormat.Subnet != nil { + ipConfig["subnet_id"] = *config.ApplicationGatewayFrontendIPConfigurationPropertiesFormat.Subnet.ID + } + + if config.ApplicationGatewayFrontendIPConfigurationPropertiesFormat.PrivateIPAddress != nil { + ipConfig["private_ip_address"] = *config.ApplicationGatewayFrontendIPConfigurationPropertiesFormat.PrivateIPAddress + } + + if config.ApplicationGatewayFrontendIPConfigurationPropertiesFormat.PublicIPAddress != nil { + ipConfig["public_ip_address_id"] = *config.ApplicationGatewayFrontendIPConfigurationPropertiesFormat.PublicIPAddress.ID + } + + result = append(result, ipConfig) + } + return result +} + +func flattenApplicationGatewayBackendAddressPools(poolConfigs *[]network.ApplicationGatewayBackendAddressPool) []interface{} { + result := make([]interface{}, 0, len(*poolConfigs)) + + for _, config := range *poolConfigs { + ipAddressList := []interface{}{} + fqdnList := []interface{}{} + for _, address := range *config.ApplicationGatewayBackendAddressPoolPropertiesFormat.BackendAddresses { + if address.IPAddress != nil { + ipAddressList = append(ipAddressList, *address.IPAddress) + } else if address.Fqdn != nil { + fqdnList = append(fqdnList, *address.Fqdn) + } + } + + pool := map[string]interface{}{ + "id": *config.ID, + "name": *config.Name, + "ip_address_list": ipAddressList, + "fqdn_list": fqdnList, + } + + result = append(result, pool) + } + + return result +} + +func flattenApplicationGatewayBackendHTTPSettings(backendSettings *[]network.ApplicationGatewayBackendHTTPSettings) ([]interface{}, error) { + result := make([]interface{}, 0, len(*backendSettings)) + + for _, config := range *backendSettings { + settings := map[string]interface{}{ + "id": *config.ID, + "name": *config.Name, + "port": int(*config.ApplicationGatewayBackendHTTPSettingsPropertiesFormat.Port), + "protocol": string(config.ApplicationGatewayBackendHTTPSettingsPropertiesFormat.Protocol), + "cookie_based_affinity": string(config.ApplicationGatewayBackendHTTPSettingsPropertiesFormat.CookieBasedAffinity), + "request_timeout": int(*config.ApplicationGatewayBackendHTTPSettingsPropertiesFormat.RequestTimeout), + } + + if config.ApplicationGatewayBackendHTTPSettingsPropertiesFormat.AuthenticationCertificates != nil { + authCerts := make([]interface{}, 0, len(*config.ApplicationGatewayBackendHTTPSettingsPropertiesFormat.AuthenticationCertificates)) + + for _, config := range *config.ApplicationGatewayBackendHTTPSettingsPropertiesFormat.AuthenticationCertificates { + id, err := parseAzureResourceID(*config.ID) + if err != nil { + return result, err + } + + authCert := map[string]interface{}{ + "name": id.Path["name"], + "id": *config.ID, + } + + authCerts = append(authCerts, authCert) + } + + settings["authentication_certificate"] = authCerts + } + + if config.ApplicationGatewayBackendHTTPSettingsPropertiesFormat.Probe != nil { + id, err := parseAzureResourceID(*config.ApplicationGatewayBackendHTTPSettingsPropertiesFormat.Probe.ID) + if err != nil { + return result, err + } + + settings["probe_name"] = id.Path["name"] + settings["probe_id"] = *config.ApplicationGatewayBackendHTTPSettingsPropertiesFormat.Probe.ID + } + + result = append(result, settings) + } + + return result, nil +} + +func flattenApplicationGatewayHTTPListeners(httpListeners *[]network.ApplicationGatewayHTTPListener) ([]interface{}, error) { + result := make([]interface{}, 0, len(*httpListeners)) + + for _, config := range *httpListeners { + id, err := parseAzureResourceID(*config.ID) + if err != nil { + return result, err + } + + listener := map[string]interface{}{ + "id": *config.ID, + "name": *config.Name, + "frontend_ip_configuration_id": *config.ApplicationGatewayHTTPListenerPropertiesFormat.FrontendIPConfiguration.ID, + "frontend_ip_configuration_name": id.Path["frontendIPName"], + "frontend_port_name": id.Path["frontEndPortName"], + "frontend_port_id": *config.ApplicationGatewayHTTPListenerPropertiesFormat.FrontendPort.ID, + "protocol": string(config.ApplicationGatewayHTTPListenerPropertiesFormat.Protocol), + } + + if config.ApplicationGatewayHTTPListenerPropertiesFormat.HostName != nil { + listener["host_name"] = *config.ApplicationGatewayHTTPListenerPropertiesFormat.HostName + } + + if config.ApplicationGatewayHTTPListenerPropertiesFormat.SslCertificate != nil { + id, err := parseAzureResourceID(*config.ApplicationGatewayHTTPListenerPropertiesFormat.SslCertificate.ID) + if err != nil { + return result, err + } + + listener["ssl_certificate_name"] = id.Path["sslCertFriendlyName"] + listener["ssl_certificate_id"] = *config.ApplicationGatewayHTTPListenerPropertiesFormat.SslCertificate.ID + } + + if config.ApplicationGatewayHTTPListenerPropertiesFormat.RequireServerNameIndication != nil { + listener["require_sni"] = *config.ApplicationGatewayHTTPListenerPropertiesFormat.RequireServerNameIndication + } + + result = append(result, listener) + } + + return result, nil +} + +func flattenApplicationGatewayProbes(probes *[]network.ApplicationGatewayProbe) []interface{} { + result := make([]interface{}, 0, len(*probes)) + + for _, config := range *probes { + settings := map[string]interface{}{ + "id": *config.ID, + "name": *config.Name, + "protocol": string(config.ApplicationGatewayProbePropertiesFormat.Protocol), + "path": *config.ApplicationGatewayProbePropertiesFormat.Path, + "host": *config.ApplicationGatewayProbePropertiesFormat.Host, + "interval": int(*config.ApplicationGatewayProbePropertiesFormat.Interval), + "timeout": int(*config.ApplicationGatewayProbePropertiesFormat.Timeout), + "unhealthy_threshold": int(*config.ApplicationGatewayProbePropertiesFormat.UnhealthyThreshold), + } + + result = append(result, settings) + } + + return result +} + +func flattenApplicationGatewayRequestRoutingRules(rules *[]network.ApplicationGatewayRequestRoutingRule) ([]interface{}, error) { + result := make([]interface{}, 0, len(*rules)) + + for _, config := range *rules { + id, err := parseAzureResourceID(*config.ID) + if err != nil { + return result, err + } + + listener := map[string]interface{}{ + "id": *config.ID, + "name": *config.Name, + "rule_type": string(config.ApplicationGatewayRequestRoutingRulePropertiesFormat.RuleType), + "http_listener_id": *config.ApplicationGatewayRequestRoutingRulePropertiesFormat.HTTPListener.ID, + "http_listener_name": id.Path["listenerName"], + } + + if config.ApplicationGatewayRequestRoutingRulePropertiesFormat.BackendAddressPool != nil { + listener["backend_address_pool_name"] = id.Path["backendPoolName"] + listener["backend_address_pool_id"] = *config.ApplicationGatewayRequestRoutingRulePropertiesFormat.BackendAddressPool.ID + } + + if config.ApplicationGatewayRequestRoutingRulePropertiesFormat.BackendHTTPSettings != nil { + listener["backend_http_settings_name"] = id.Path["backendHttpSettingsName"] + listener["backend_http_settings_id"] = *config.ApplicationGatewayRequestRoutingRulePropertiesFormat.BackendHTTPSettings.ID + } + + if config.ApplicationGatewayRequestRoutingRulePropertiesFormat.URLPathMap != nil { + listener["url_path_map_name"] = id.Path["urlPathMap"] + listener["url_path_map_id"] = *config.ApplicationGatewayRequestRoutingRulePropertiesFormat.URLPathMap.ID + } + + result = append(result, listener) + } + + return result, nil +} + +func flattenApplicationGatewayURLPathMaps(pathMaps *[]network.ApplicationGatewayURLPathMap) ([]interface{}, error) { + result := make([]interface{}, 0, len(*pathMaps)) + + for _, config := range *pathMaps { + id, err := parseAzureResourceID(*config.ID) + if err != nil { + return result, err + } + + pathMap := map[string]interface{}{ + "id": *config.ID, + "name": *config.Name, + } + + if config.ApplicationGatewayURLPathMapPropertiesFormat.DefaultBackendAddressPool != nil { + pathMap["default_backend_address_pool_name"] = id.Path["poolName"] + pathMap["default_backend_address_pool_id"] = *config.ApplicationGatewayURLPathMapPropertiesFormat.DefaultBackendAddressPool.ID + } + + if config.ApplicationGatewayURLPathMapPropertiesFormat.DefaultBackendHTTPSettings != nil { + pathMap["default_backend_http_settings_name"] = id.Path["settingsName"] + pathMap["default_backend_http_settings_id"] = *config.ApplicationGatewayURLPathMapPropertiesFormat.DefaultBackendHTTPSettings.ID + } + + pathRules := make([]interface{}, 0, len(*config.ApplicationGatewayURLPathMapPropertiesFormat.PathRules)) + for _, pathRuleConfig := range *config.ApplicationGatewayURLPathMapPropertiesFormat.PathRules { + id, err := parseAzureResourceID(*pathRuleConfig.ID) + if err != nil { + return result, err + } + + rule := map[string]interface{}{ + "id": *pathRuleConfig.ID, + "name": *pathRuleConfig.Name, + } + + if pathRuleConfig.ApplicationGatewayPathRulePropertiesFormat.BackendAddressPool != nil { + rule["backend_address_pool_name"] = id.Path["poolName2"] + rule["backend_address_pool_id"] = *pathRuleConfig.ApplicationGatewayPathRulePropertiesFormat.BackendAddressPool.ID + } + + if pathRuleConfig.ApplicationGatewayPathRulePropertiesFormat.BackendHTTPSettings != nil { + rule["backend_http_settings_name"] = id.Path["settingsName2"] + rule["backend_http_settings_id"] = *pathRuleConfig.ApplicationGatewayPathRulePropertiesFormat.BackendHTTPSettings.ID + } + + paths := make([]interface{}, 0, len(*pathRuleConfig.ApplicationGatewayPathRulePropertiesFormat.Paths)) + for _, rulePath := range *pathRuleConfig.ApplicationGatewayPathRulePropertiesFormat.Paths { + paths = append(paths, rulePath) + } + rule["paths"] = paths + + pathRules = append(pathRules, rule) + } + pathMap["path_rule"] = pathRules + + result = append(result, pathMap) + } + + return result, nil +} + +func flattenApplicationGatewayAuthenticationCertificates(certs *[]network.ApplicationGatewayAuthenticationCertificate) []interface{} { + result := make([]interface{}, 0, len(*certs)) + + for _, config := range *certs { + certConfig := map[string]interface{}{ + "id": *config.ID, + "name": *config.Name, + } + + result = append(result, certConfig) + } + + return result +} + +func flattenApplicationGatewaySslCertificates(certs *[]network.ApplicationGatewaySslCertificate) []interface{} { + result := make([]interface{}, 0, len(*certs)) + + for _, config := range *certs { + certConfig := map[string]interface{}{ + "id": *config.ID, + "name": *config.Name, + "public_cert_data": *config.ApplicationGatewaySslCertificatePropertiesFormat.PublicCertData, + } + + result = append(result, certConfig) + } + + return result +} + +func hashApplicationGatewaySku(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["tier"].(string))) + buf.WriteString(fmt.Sprintf("%d-", m["capacity"].(int))) + + return hashcode.String(buf.String()) +} + +func hashApplicationGatewayWafConfig(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%t-", m["enabled"].(bool))) + buf.WriteString(fmt.Sprintf("%s-", m["firewall_mode"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["rule_set_type"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["rule_set_version"].(string))) + + return hashcode.String(buf.String()) +} + +func hashApplicationGatewayAuthenticationCertificates(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) + + return hashcode.String(buf.String()) +} + +func hashApplicationGatewaySslCertificates(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) + buf.WriteString(fmt.Sprintf("%s-", m["public_cert_data"].(string))) + + return hashcode.String(buf.String()) +} diff --git a/azurerm/resource_arm_application_gateway_test.cer b/azurerm/resource_arm_application_gateway_test.cer new file mode 100644 index 000000000000..577947b220d7 --- /dev/null +++ b/azurerm/resource_arm_application_gateway_test.cer @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDbzCCAlegAwIBAgIJAIzjRD36sIbbMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNV +BAYTAlVTMRMwEQYDVQQIDApTb21lLVN0YXRlMRIwEAYDVQQKDAl0ZXJyYWZvcm0x +FTATBgNVBAMMDHRlcnJhZm9ybS5pbzAgFw0xNzA0MjEyMDA1MjdaGA8yMTE3MDMy +ODIwMDUyN1owTTELMAkGA1UEBhMCVVMxEzARBgNVBAgMClNvbWUtU3RhdGUxEjAQ +BgNVBAoMCXRlcnJhZm9ybTEVMBMGA1UEAwwMdGVycmFmb3JtLmlvMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3L9L5szT4+FLykTFNyyPjy/k3BQTYAfR +QzP2dhnsuUKm3cdPC0NyZ+wEXIUGhoDO2YG6EYChOl8fsDqDOjloSUGKqYw++nlp +HIuUgJx8IxxG2XkALCjFU7EmF+w7kn76d0ezpEIYxnLP+KG2DVornoEt1aLhv1ML +mpgEZZPhDbMSLhSYWeTVRMayXLwqtfgnDumQSB+8d/1JuJqrSI4pD12JozVThzb6 +hsjfb6RMX4epPmrGn0PbTPEEA6awmsxBCXB0s13nNQt/O0hLM2agwvAyozilQV+s +616Ckgk6DJoUkqZhDy7vPYMIRSr98fBws6zkrV6tTLjmD8xAvobePQIDAQABo1Aw +TjAdBgNVHQ4EFgQUXIqO421zMMmbcRRX9wctZFCQuPIwHwYDVR0jBBgwFoAUXIqO +421zMMmbcRRX9wctZFCQuPIwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC +AQEAr82NeT3BYJOKLlUL6Om5LjUF66ewcJjG9ltdvyQwVneMcq7t5UAPxgChzqNR +Vk4da8PzkXpjBJyWezHupdJNX3XqeUk2kSxqQ6/gmhqvfI3y7djrwoO6jvMEY26W +qtkTNORWDP3THJJVimC3zV+KMU5UBVrEzhOVhHSU709lBP75o0BBn3xGsPqSq9k8 +IotIFfyAc6a+XP3+ZMpvh7wqAUml7vWa5wlcXExCx39h1balfDSLGNC4swWPCp9A +MnQR0p+vMay9hNP1Eh+9QYUai14d5KS3cFV+KxE1cJR5HD/iLltnnOEbpMsB0eVO +ZWkFvE7Y5lW0oVSAfin5TwTJMQ== +-----END CERTIFICATE----- \ No newline at end of file diff --git a/azurerm/resource_arm_application_gateway_test.go b/azurerm/resource_arm_application_gateway_test.go new file mode 100644 index 000000000000..f8ec0711385f --- /dev/null +++ b/azurerm/resource_arm_application_gateway_test.go @@ -0,0 +1,1239 @@ +package azurerm + +import ( + "fmt" + "net/http" + "os" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAzureRMApplicationGateway_basic_base(t *testing.T) { + ri := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApplicationGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApplicationGateway_basic(ri), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationGatewayExists("azurerm_application_gateway.test"), + testCheckAzureRMApplicationGatewaySslCertificateAssigned("azurerm_application_gateway.test", "ssl-1"), + ), + }, + }, + }) +} + +func TestAccAzureRMApplicationGateway_basic_changeSslCert(t *testing.T) { + ri := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApplicationGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApplicationGateway_basic(ri), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationGatewayExists("azurerm_application_gateway.test"), + testCheckAzureRMApplicationGatewaySslCertificateAssigned("azurerm_application_gateway.test", "ssl-1"), + ), + Destroy: false, + }, + { + Config: testAccAzureRMApplicationGateway_basic_changeSslCert(ri), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationGatewayExists("azurerm_application_gateway.test"), + testCheckAzureRMApplicationGatewaySslCertificateAssigned("azurerm_application_gateway.test", "ssl-2"), + ), + }, + }, + }) +} + +func TestAccAzureRMApplicationGateway_basic_authCert(t *testing.T) { + ri := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApplicationGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApplicationGateway_basic_authCert(ri), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationGatewayExists("azurerm_application_gateway.test"), + testCheckAzureRMApplicationGatewaySslCertificateAssigned("azurerm_application_gateway.test", "ssl-1"), + testCheckAzureRMApplicationGatewayAuthenticationCertificateAssigned("azurerm_application_gateway.test", "auth-1"), + ), + }, + }, + }) +} + +func TestAccAzureRMApplicationGateway_basic_changeAuthCert(t *testing.T) { + ri := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApplicationGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApplicationGateway_basic_authCert(ri), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationGatewayExists("azurerm_application_gateway.test"), + testCheckAzureRMApplicationGatewaySslCertificateAssigned("azurerm_application_gateway.test", "ssl-1"), + testCheckAzureRMApplicationGatewayAuthenticationCertificateAssigned("azurerm_application_gateway.test", "auth-1"), + ), + Destroy: false, + }, + { + Config: testAccAzureRMApplicationGateway_basic_changeAuthCert(ri), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationGatewayExists("azurerm_application_gateway.test"), + testCheckAzureRMApplicationGatewaySslCertificateAssigned("azurerm_application_gateway.test", "ssl-1"), + testCheckAzureRMApplicationGatewayAuthenticationCertificateAssigned("azurerm_application_gateway.test", "auth-2"), + ), + }, + }, + }) +} + +func TestAccAzureRMApplicationGateway_waf(t *testing.T) { + ri := acctest.RandInt() + + subscriptionID := os.Getenv("ARM_SUBSCRIPTION_ID") + gwID := fmt.Sprintf( + "/subscriptions/%s/resourceGroups/acctestrg-%d/providers/Microsoft.Network/applicationGateways/acctestgw-%d", + subscriptionID, ri, ri) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApplicationGatewayDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApplicationGateway_waf(ri), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationGatewayExists("azurerm_application_gateway.test"), + testCheckAzureRMApplicationGatewaySslCertificateAssigned("azurerm_application_gateway.test", "ssl-1"), + resource.TestCheckResourceAttr("azurerm_application_gateway.test", "id", gwID), + ), + }, + }, + }) +} + +func testCheckAzureRMApplicationGatewayExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + ApplicationGatewayName := rs.Primary.Attributes["name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for App Gateway: %s", ApplicationGatewayName) + } + + conn := testAccProvider.Meta().(*ArmClient).applicationGatewayClient + + resp, err := conn.Get(resourceGroup, ApplicationGatewayName) + if err != nil { + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("Bad: App Gateway %q (resource group: %q) does not exist", ApplicationGatewayName, resourceGroup) + } + + return fmt.Errorf("Bad: Get on ApplicationGatewayClient: %+v", err) + } + + return nil + } +} + +func testCheckAzureRMApplicationGatewaySslCertificateAssigned(name string, certName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + ApplicationGatewayName := rs.Primary.Attributes["name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for App Gateway: %s", ApplicationGatewayName) + } + + conn := testAccProvider.Meta().(*ArmClient).applicationGatewayClient + + resp, err := conn.Get(resourceGroup, ApplicationGatewayName) + if err != nil { + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("Bad: App Gateway %q (resource group: %q) does not exist", ApplicationGatewayName, resourceGroup) + } + + return fmt.Errorf("Bad: Get on ApplicationGatewayClient: %+v", err) + } + + var certId *string + + for _, cert := range *resp.SslCertificates { + if *cert.Name == certName { + certId = cert.ID + } + } + + if certId == nil { + return fmt.Errorf("Bad: SSL certificate not found: %s", certName) + } + + for _, listener := range *resp.HTTPListeners { + if listener.SslCertificate != nil && *listener.SslCertificate.ID == *certId { + return nil + } + } + + return fmt.Errorf("Bad: SSL certificate not assigned to a listener: %s", certName) + } +} + +func testCheckAzureRMApplicationGatewayAuthenticationCertificateAssigned(name string, certName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + ApplicationGatewayName := rs.Primary.Attributes["name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for App Gateway: %s", ApplicationGatewayName) + } + + conn := testAccProvider.Meta().(*ArmClient).applicationGatewayClient + + resp, err := conn.Get(resourceGroup, ApplicationGatewayName) + if err != nil { + if resp.StatusCode == http.StatusNotFound { + return fmt.Errorf("Bad: App Gateway %q (resource group: %q) does not exist", ApplicationGatewayName, resourceGroup) + } + + return fmt.Errorf("Bad: Get on ApplicationGatewayClient: %+v", err) + } + + var certId *string + + for _, cert := range *resp.AuthenticationCertificates { + if *cert.Name == certName { + certId = cert.ID + } + } + + if certId == nil { + return fmt.Errorf("Bad: Authentication certificate not found: %s", certName) + } + + for _, backendHttpSettings := range *resp.BackendHTTPSettingsCollection { + if backendHttpSettings.AuthenticationCertificates != nil { + for _, authCert := range *backendHttpSettings.AuthenticationCertificates { + if *authCert.ID == *certId { + return nil + } + } + } + } + + return fmt.Errorf("Bad: Authentication certificate not assigned: %s", certName) + } +} + +func testCheckAzureRMApplicationGatewayDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).applicationGatewayClient + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_application_gateway" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + resp, err := conn.Get(resourceGroup, name) + + if err != nil { + return nil + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("App Gateway still exists:\n%#v", resp.ApplicationGatewayPropertiesFormat) + } + } + + return nil +} + +func testAccAzureRMApplicationGateway_basic(rInt int) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestrg-%d" + location = "West US 2" +} + +resource "azurerm_virtual_network" "test" { + name = "acctest-vnet-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + address_space = ["10.254.0.0/16"] + location = "${azurerm_resource_group.test.location}" +} + +resource "azurerm_subnet" "test" { + name = "subnet" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.254.0.0/24" +} + +resource "azurerm_public_ip" "test" { + name = "acctest-pubip-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + public_ip_address_allocation = "dynamic" +} + +resource "azurerm_application_gateway" "test" { + name = "acctestgw-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + sku { + name = "Standard_Medium" + tier = "Standard" + capacity = 1 + } + + disabled_ssl_protocols = [ + "TLSv1_0", + ] + + gateway_ip_configuration { + # id = computed + name = "gw-ip-config1" + subnet_id = "${azurerm_subnet.test.id}" + } + + frontend_ip_configuration { + # id = computed + name = "ip-config-public" + public_ip_address_id = "${azurerm_public_ip.test.id}" + } + + frontend_ip_configuration { + # id = computed + name = "ip-config-private" + subnet_id = "${azurerm_subnet.test.id}" + + # private_ip_address = computed + private_ip_address_allocation = "Dynamic" + } + + frontend_port { + # id = computed + name = "port-8080" + port = 8080 + } + + backend_address_pool { + # id = computed + name = "pool-1" + + fqdn_list = [ + "terraform.io", + ] + } + + backend_http_settings { + # id = computed + name = "backend-http-1" + port = 8010 + protocol = "Https" + cookie_based_affinity = "Enabled" + request_timeout = 30 + + # probe_id = computed + probe_name = "probe-1" + } + + http_listener { + # id = computed + name = "listener-1" + + # frontend_ip_configuration_id = computed + frontend_ip_configuration_name = "ip-config-public" + + # frontend_ip_port_id = computed + frontend_port_name = "port-8080" + protocol = "Http" + } + + http_listener { + name = "listener-2" + frontend_ip_configuration_name = "ip-config-public" + frontend_port_name = "port-8080" + protocol = "Https" + + # ssl_certificate_id = computed + ssl_certificate_name = "ssl-1" + host_name = "terraform.io" + require_sni = true + } + + probe { + # id = computed + name = "probe-1" + protocol = "Https" + path = "/test" + host = "azure.com" + timeout = 120 + interval = 300 + unhealthy_threshold = 8 + } + + url_path_map { + # id = computed + name = "path-map-1" + default_backend_address_pool_name = "pool-1" + default_backend_http_settings_name = "backend-http-1" + + path_rule { + # id = computed + name = "path-rule-1" + backend_address_pool_name = "pool-1" + backend_http_settings_name = "backend-http-1" + + paths = [ + "/test", + ] + } + } + + request_routing_rule { + # id = computed + name = "rule-basic-1" + rule_type = "Basic" + + # http_listener_id = computed + http_listener_name = "listener-1" + + # backend_address_pool_id = computed + backend_address_pool_name = "pool-1" + + # backend_http_settings_id = computed + backend_http_settings_name = "backend-http-1" + } + + request_routing_rule { + # id = computed + name = "rule-path-1" + rule_type = "PathBasedRouting" + url_path_map_name = "path-map-1" + + # http_listener_id = computed + http_listener_name = "listener-2" + } + + ssl_certificate { + # id = computed + name = "ssl-1" + data = "${file("resource_arm_application_gateway_test.pfx")}" + password = "terraform" + } + + tags { + environment = "tf01" + } +} +`, rInt, rInt, rInt, rInt) +} + +func testAccAzureRMApplicationGateway_basic_changeSslCert(rInt int) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestrg-%d" + location = "West US 2" +} + +resource "azurerm_virtual_network" "test" { + name = "acctest-vnet-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + address_space = ["10.254.0.0/16"] + location = "${azurerm_resource_group.test.location}" +} + +resource "azurerm_subnet" "test" { + name = "subnet" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.254.0.0/24" +} + +resource "azurerm_public_ip" "test" { + name = "acctest-pubip-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + public_ip_address_allocation = "dynamic" +} + +resource "azurerm_application_gateway" "test" { + name = "acctestgw-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + sku { + name = "Standard_Medium" + tier = "Standard" + capacity = 1 + } + + disabled_ssl_protocols = [ + "TLSv1_0", + ] + + gateway_ip_configuration { + # id = computed + name = "gw-ip-config1" + subnet_id = "${azurerm_subnet.test.id}" + } + + frontend_ip_configuration { + # id = computed + name = "ip-config-public" + public_ip_address_id = "${azurerm_public_ip.test.id}" + } + + frontend_ip_configuration { + # id = computed + name = "ip-config-private" + subnet_id = "${azurerm_subnet.test.id}" + + # private_ip_address = computed + private_ip_address_allocation = "Dynamic" + } + + frontend_port { + # id = computed + name = "port-8080" + port = 8080 + } + + backend_address_pool { + # id = computed + name = "pool-1" + + fqdn_list = [ + "terraform.io", + ] + } + + backend_http_settings { + # id = computed + name = "backend-http-1" + port = 8010 + protocol = "Https" + cookie_based_affinity = "Enabled" + request_timeout = 30 + + # probe_id = computed + probe_name = "probe-1" + } + + http_listener { + # id = computed + name = "listener-1" + + # frontend_ip_configuration_id = computed + frontend_ip_configuration_name = "ip-config-public" + + # frontend_ip_port_id = computed + frontend_port_name = "port-8080" + protocol = "Http" + } + + http_listener { + name = "listener-2" + frontend_ip_configuration_name = "ip-config-public" + frontend_port_name = "port-8080" + protocol = "Https" + + # ssl_certificate_id = computed + ssl_certificate_name = "ssl-2" + host_name = "terraform.io" + require_sni = true + } + + probe { + # id = computed + name = "probe-1" + protocol = "Https" + path = "/test" + host = "azure.com" + timeout = 120 + interval = 300 + unhealthy_threshold = 8 + } + + url_path_map { + # id = computed + name = "path-map-1" + default_backend_address_pool_name = "pool-1" + default_backend_http_settings_name = "backend-http-1" + + path_rule { + # id = computed + name = "path-rule-1" + backend_address_pool_name = "pool-1" + backend_http_settings_name = "backend-http-1" + + paths = [ + "/test", + ] + } + } + + request_routing_rule { + # id = computed + name = "rule-basic-1" + rule_type = "Basic" + + # http_listener_id = computed + http_listener_name = "listener-1" + + # backend_address_pool_id = computed + backend_address_pool_name = "pool-1" + + # backend_http_settings_id = computed + backend_http_settings_name = "backend-http-1" + } + + request_routing_rule { + # id = computed + name = "rule-path-1" + rule_type = "PathBasedRouting" + url_path_map_name = "path-map-1" + + # http_listener_id = computed + http_listener_name = "listener-2" + } + + ssl_certificate { + # id = computed + name = "ssl-2" + data = "${file("resource_arm_application_gateway_test.pfx")}" + password = "terraform" + } + + tags { + environment = "tf01" + } +} +`, rInt, rInt, rInt, rInt) +} + +func testAccAzureRMApplicationGateway_basic_authCert(rInt int) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestrg-%d" + location = "West US 2" +} + +resource "azurerm_virtual_network" "test" { + name = "acctest-vnet-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + address_space = ["10.254.0.0/16"] + location = "${azurerm_resource_group.test.location}" +} + +resource "azurerm_subnet" "test" { + name = "subnet" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.254.0.0/24" +} + +resource "azurerm_public_ip" "test" { + name = "acctest-pubip-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + public_ip_address_allocation = "dynamic" +} + +resource "azurerm_application_gateway" "test" { + name = "acctestgw-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + sku { + name = "Standard_Medium" + tier = "Standard" + capacity = 1 + } + + disabled_ssl_protocols = [ + "TLSv1_0", + ] + + gateway_ip_configuration { + # id = computed + name = "gw-ip-config1" + subnet_id = "${azurerm_subnet.test.id}" + } + + frontend_ip_configuration { + # id = computed + name = "ip-config-public" + public_ip_address_id = "${azurerm_public_ip.test.id}" + } + + frontend_ip_configuration { + # id = computed + name = "ip-config-private" + subnet_id = "${azurerm_subnet.test.id}" + + # private_ip_address = computed + private_ip_address_allocation = "Dynamic" + } + + frontend_port { + # id = computed + name = "port-8080" + port = 8080 + } + + backend_address_pool { + # id = computed + name = "pool-1" + + fqdn_list = [ + "terraform.io", + ] + } + + backend_http_settings { + # id = computed + name = "backend-http-1" + port = 8010 + protocol = "Http" + cookie_based_affinity = "Enabled" + request_timeout = 30 + } + + backend_http_settings { + # id = computed + name = "backend-http-2" + port = 8011 + protocol = "Https" + cookie_based_affinity = "Enabled" + request_timeout = 30 + + authentication_certificate { + name = "auth-1" + } + + # probe_id = computed + probe_name = "probe-1" + } + + http_listener { + # id = computed + name = "listener-1" + + # frontend_ip_configuration_id = computed + frontend_ip_configuration_name = "ip-config-public" + + # frontend_ip_port_id = computed + frontend_port_name = "port-8080" + protocol = "Http" + } + + http_listener { + name = "listener-2" + frontend_ip_configuration_name = "ip-config-public" + frontend_port_name = "port-8080" + protocol = "Https" + + # ssl_certificate_id = computed + ssl_certificate_name = "ssl-1" + host_name = "terraform.io" + require_sni = true + } + + probe { + # id = computed + name = "probe-1" + protocol = "Https" + path = "/test" + host = "azure.com" + timeout = 120 + interval = 300 + unhealthy_threshold = 8 + } + + url_path_map { + # id = computed + name = "path-map-1" + default_backend_address_pool_name = "pool-1" + default_backend_http_settings_name = "backend-http-1" + + path_rule { + # id = computed + name = "path-rule-1" + backend_address_pool_name = "pool-1" + backend_http_settings_name = "backend-http-1" + + paths = [ + "/test", + ] + } + } + + request_routing_rule { + # id = computed + name = "rule-basic-1" + rule_type = "Basic" + + # http_listener_id = computed + http_listener_name = "listener-1" + + # backend_address_pool_id = computed + backend_address_pool_name = "pool-1" + + # backend_http_settings_id = computed + backend_http_settings_name = "backend-http-1" + } + + request_routing_rule { + # id = computed + name = "rule-path-1" + rule_type = "PathBasedRouting" + url_path_map_name = "path-map-1" + + # http_listener_id = computed + http_listener_name = "listener-2" + } + + authentication_certificate { + name = "auth-1" + data = "${file("resource_arm_application_gateway_test.cer")}" + } + + ssl_certificate { + # id = computed + name = "ssl-1" + data = "${file("resource_arm_application_gateway_test.pfx")}" + password = "terraform" + } + + tags { + environment = "tf01" + } +} +`, rInt, rInt, rInt, rInt) +} + +func testAccAzureRMApplicationGateway_basic_changeAuthCert(rInt int) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestrg-%d" + location = "West US 2" +} + +resource "azurerm_virtual_network" "test" { + name = "acctest-vnet-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + address_space = ["10.254.0.0/16"] + location = "${azurerm_resource_group.test.location}" +} + +resource "azurerm_subnet" "test" { + name = "subnet" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.254.0.0/24" +} + +resource "azurerm_public_ip" "test" { + name = "acctest-pubip-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + public_ip_address_allocation = "dynamic" +} + +resource "azurerm_application_gateway" "test" { + name = "acctestgw-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + sku { + name = "Standard_Medium" + tier = "Standard" + capacity = 1 + } + + disabled_ssl_protocols = [ + "TLSv1_0", + ] + + gateway_ip_configuration { + # id = computed + name = "gw-ip-config1" + subnet_id = "${azurerm_subnet.test.id}" + } + + frontend_ip_configuration { + # id = computed + name = "ip-config-public" + public_ip_address_id = "${azurerm_public_ip.test.id}" + } + + frontend_ip_configuration { + # id = computed + name = "ip-config-private" + subnet_id = "${azurerm_subnet.test.id}" + + # private_ip_address = computed + private_ip_address_allocation = "Dynamic" + } + + frontend_port { + # id = computed + name = "port-8080" + port = 8080 + } + + backend_address_pool { + # id = computed + name = "pool-1" + + fqdn_list = [ + "terraform.io", + ] + } + + backend_http_settings { + # id = computed + name = "backend-http-1" + port = 8010 + protocol = "Http" + cookie_based_affinity = "Enabled" + request_timeout = 30 + } + + backend_http_settings { + # id = computed + name = "backend-http-2" + port = 8011 + protocol = "Https" + cookie_based_affinity = "Enabled" + request_timeout = 30 + + authentication_certificate { + name = "auth-2" + } + + # probe_id = computed + probe_name = "probe-1" + } + + http_listener { + # id = computed + name = "listener-1" + + # frontend_ip_configuration_id = computed + frontend_ip_configuration_name = "ip-config-public" + + # frontend_ip_port_id = computed + frontend_port_name = "port-8080" + protocol = "Http" + } + + http_listener { + name = "listener-2" + frontend_ip_configuration_name = "ip-config-public" + frontend_port_name = "port-8080" + protocol = "Https" + + # ssl_certificate_id = computed + ssl_certificate_name = "ssl-1" + host_name = "terraform.io" + require_sni = true + } + + probe { + # id = computed + name = "probe-1" + protocol = "Https" + path = "/test" + host = "azure.com" + timeout = 120 + interval = 300 + unhealthy_threshold = 8 + } + + url_path_map { + # id = computed + name = "path-map-1" + default_backend_address_pool_name = "pool-1" + default_backend_http_settings_name = "backend-http-1" + + path_rule { + # id = computed + name = "path-rule-1" + backend_address_pool_name = "pool-1" + backend_http_settings_name = "backend-http-1" + + paths = [ + "/test", + ] + } + } + + request_routing_rule { + # id = computed + name = "rule-basic-1" + rule_type = "Basic" + + # http_listener_id = computed + http_listener_name = "listener-1" + + # backend_address_pool_id = computed + backend_address_pool_name = "pool-1" + + # backend_http_settings_id = computed + backend_http_settings_name = "backend-http-1" + } + + request_routing_rule { + # id = computed + name = "rule-path-1" + rule_type = "PathBasedRouting" + url_path_map_name = "path-map-1" + + # http_listener_id = computed + http_listener_name = "listener-2" + } + + authentication_certificate { + name = "auth-2" + data = "${file("resource_arm_application_gateway_test.cer")}" + } + + ssl_certificate { + # id = computed + name = "ssl-1" + data = "${file("resource_arm_application_gateway_test.pfx")}" + password = "terraform" + } + + tags { + environment = "tf01" + } +} +`, rInt, rInt, rInt, rInt) +} + +func testAccAzureRMApplicationGateway_waf(rInt int) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestrg-%d" + location = "West US 2" +} + +resource "azurerm_virtual_network" "test" { + name = "acctest-vnet-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + address_space = ["10.254.0.0/16"] + location = "${azurerm_resource_group.test.location}" +} + +resource "azurerm_subnet" "test" { + name = "subnet" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.254.0.0/24" +} + +resource "azurerm_public_ip" "test" { + name = "acctest-pubip-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + public_ip_address_allocation = "dynamic" +} + +resource "azurerm_application_gateway" "test" { + name = "acctestgw-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + sku { + name = "WAF_Medium" + tier = "WAF" + capacity = 1 + } + + disabled_ssl_protocols = [ + "TLSv1_0", + ] + + waf_configuration { + enabled = "true" + firewall_mode = "Detection" + rule_set_type = "OWASP" + rule_set_version = "3.0" + } + + gateway_ip_configuration { + # id = computed + name = "gw-ip-config1" + subnet_id = "${azurerm_subnet.test.id}" + } + + frontend_ip_configuration { + # id = computed + name = "ip-config-public" + public_ip_address_id = "${azurerm_public_ip.test.id}" + } + + frontend_ip_configuration { + # id = computed + name = "ip-config-private" + subnet_id = "${azurerm_subnet.test.id}" + + # private_ip_address = computed + private_ip_address_allocation = "Dynamic" + } + + frontend_port { + # id = computed + name = "port-8080" + port = 8080 + } + + backend_address_pool { + # id = computed + name = "pool-1" + + fqdn_list = [ + "terraform.io", + ] + } + + backend_http_settings { + # id = computed + name = "backend-http-1" + port = 8010 + protocol = "Https" + cookie_based_affinity = "Enabled" + request_timeout = 30 + + # probe_id = computed + probe_name = "probe-1" + } + + http_listener { + # id = computed + name = "listener-1" + + # frontend_ip_configuration_id = computed + frontend_ip_configuration_name = "ip-config-public" + + # frontend_ip_port_id = computed + frontend_port_name = "port-8080" + protocol = "Http" + } + + http_listener { + name = "listener-2" + frontend_ip_configuration_name = "ip-config-public" + frontend_port_name = "port-8080" + protocol = "Https" + + # ssl_certificate_id = computed + ssl_certificate_name = "ssl-1" + host_name = "terraform.io" + require_sni = true + } + + probe { + # id = computed + name = "probe-1" + protocol = "Https" + path = "/test" + host = "azure.com" + timeout = 120 + interval = 300 + unhealthy_threshold = 8 + } + + url_path_map { + # id = computed + name = "path-map-1" + default_backend_address_pool_name = "pool-1" + default_backend_http_settings_name = "backend-http-1" + + path_rule { + # id = computed + name = "path-rule-1" + backend_address_pool_name = "pool-1" + backend_http_settings_name = "backend-http-1" + + paths = [ + "/test", + ] + } + } + + request_routing_rule { + # id = computed + name = "rule-basic-1" + rule_type = "Basic" + + # http_listener_id = computed + http_listener_name = "listener-1" + + # backend_address_pool_id = computed + backend_address_pool_name = "pool-1" + + # backend_http_settings_id = computed + backend_http_settings_name = "backend-http-1" + } + + request_routing_rule { + # id = computed + name = "rule-path-1" + rule_type = "PathBasedRouting" + url_path_map_name = "path-map-1" + + # http_listener_id = computed + http_listener_name = "listener-2" + } + + ssl_certificate { + # id = computed + name = "ssl-1" + data = "${file("resource_arm_application_gateway_test.pfx")}" + password = "terraform" + } + + tags { + environment = "tf01" + } +} +`, rInt, rInt, rInt, rInt) +} diff --git a/azurerm/resource_arm_application_gateway_test.pfx b/azurerm/resource_arm_application_gateway_test.pfx new file mode 100644 index 000000000000..691fa08577cf Binary files /dev/null and b/azurerm/resource_arm_application_gateway_test.pfx differ diff --git a/website/azurerm.erb b/website/azurerm.erb index f0f06e3f973b..21e8c4d05c91 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -368,6 +368,11 @@ Network Resources