hashicorp / terraform-provider-azurerm

Terraform provider for Azure Resource Manager
https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs
Mozilla Public License 2.0
4.52k stars 4.6k forks source link

Add #18448

Closed luissalgadofreire closed 1 year ago

luissalgadofreire commented 1 year ago

Is there an existing issue for this?

Community Note

Description

Azure Application Gateway has a section in the portal under Backend Settings > Backend authentication certificate with the following description:

"For end-to-end SSL encryption, the backends must be in the allowlist of the application gateway. Upload the public certificate of the backend servers to this Backend setting".

Under that, there is an option called Use for App service.

If we check it, Azure Application Gateway will copy the target Azure App Service or Azure Container App's public certificate. That is in alternative to forcing us to create a new certificate and add the private key to the backend service, and the public certificate to Azure Application Gateway.

That option, however, is not available in the Terraform resource.

It would be great to have it.

New or Affected Resource(s)/Data Source(s)

azurerm_application_gateway

Potential Terraform Configuration

resource "azurerm_application_gateway" "agw" {
  name                = local.agw_name
  resource_group_name = local.resource_group_name
  location            = local.location

  sku {
    name     = "Standard_Small"
    tier     = "Standard"
    capacity = 1
  }

  ssl_policy {
    policy_type = "Custom"
    cipher_suites = [
      "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
      "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
    ]
    min_protocol_version = "TLSv1_2"
  }

  enable_http2 = false
  gateway_ip_configuration {
    name      = "agwfrontend-subnet"
    subnet_id = data.azurerm_subnet.frontend.id
  }

  frontend_port {
    name = "agw-frontend-port"
    port = 443
  }

  frontend_ip_configuration {
    name                 = lower("agw-frontend-ip")
    public_ip_address_id = data.azurerm_public_ip.spokein.id
  }

  ssl_certificate {
    name                = local.frontend_secret_name
    data                = local.frontend_cert
  }

  http_listener {
    name                           = lower("agw-https-listener-${local.acae_key}")
    frontend_ip_configuration_name = lower("agw-frontend-ip")
    frontend_port_name             = lower("agw-frontend-port")
    protocol                       = "Https"
    host_name                      = local.host_name
    ssl_certificate_name           = local.frontend_secret_name
    require_sni                    = true
  }
  // endregion

  request_routing_rule {
    name                       = lower("agw-routing-rule-${local.acae_key}")
    rule_type                  = "Basic"
    http_listener_name         = lower("agw-https-listener-${local.acae_key}")
    backend_address_pool_name  = lower("agw-backend-address-pool-${local.acae_key}")
    backend_http_settings_name = lower("agw-backend-http-settings-${local.acae_key}")
  }

  backend_address_pool {
    name = lower("agw-backend-address-pool-${local.acae_key}")
    fqdns = [
      lower(local.ingress_fqdn)
    ]
  }

  backend_http_settings {
    name                                   = lower("agw-backend-http-settings-${local.acae_key}")
    port                                   = 443
    protocol                               = "Https"
    cookie_based_affinity                  = "Disabled"
    pick_host_name_from_backend_address    = true
    pick_public_certificate_from_backend = true  <===== this would be the new option
    request_timeout                        = 20
    probe_name                             = lower("agw-probe-${local.acae_key}")
  }

  dynamic "probe" {
    name                                      = lower("agw-probe-${local.acae_key}")
    path                                      = "/"
    protocol                                  = "Https"
    interval                                  = 30
    timeout                                   = 30
    unhealthy_threshold                       = 3
    pick_host_name_from_backend_http_settings = true
    minimum_servers                           = 0
  }
}

References

Check: https://github.com/microsoft/azure-container-apps/issues/322

luissalgadofreire commented 1 year ago

For the benefit of those who might come across this issue.

It turns out Azure Application Gateway assumes Use for App Service is default.

If you do not provide a backend certificate - either Authentication Certificate for V1 or Trusted Root Certificate for V2 - then Azure Application Gateway will set the Use for App Service to true.

Therefore, the config would be something like the below.

Notice that no authentication_certificate or trusted_root_certificate variables are set or referenced anywhere:

resource "azurerm_application_gateway" "agw" {
  name                = local.agw_name
  resource_group_name = local.resource_group_name
  location            = local.location

  sku {
    name     = "Standard_Small"
    tier     = "Standard"
    capacity = 1
  }

  ssl_policy {
    policy_type = "Custom"
    cipher_suites = [
      "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
      "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
    ]
    min_protocol_version = "TLSv1_2"
  }

  enable_http2 = false
  gateway_ip_configuration {
    name      = "agwfrontend-subnet"
    subnet_id = data.azurerm_subnet.frontend.id
  }

  frontend_port {
    name = "agw-frontend-port"
    port = 443
  }

  frontend_ip_configuration {
    name                 = lower("agw-frontend-ip")
    public_ip_address_id = data.azurerm_public_ip.spokein.id
  }

  ssl_certificate {
    name                = local.frontend_secret_name
    data                = local.frontend_cert
  }

  http_listener {
    name                           = lower("agw-https-listener-${local.acae_key}")
    frontend_ip_configuration_name = lower("agw-frontend-ip")
    frontend_port_name             = lower("agw-frontend-port")
    protocol                       = "Https"
    host_name                      = local.host_name
    ssl_certificate_name           = local.frontend_secret_name
    require_sni                    = true
  }
  // endregion

  request_routing_rule {
    name                       = lower("agw-routing-rule-${local.acae_key}")
    rule_type                  = "Basic"
    http_listener_name         = lower("agw-https-listener-${local.acae_key}")
    backend_address_pool_name  = lower("agw-backend-address-pool-${local.acae_key}")
    backend_http_settings_name = lower("agw-backend-http-settings-${local.acae_key}")
  }

  backend_address_pool {
    name = lower("agw-backend-address-pool-${local.acae_key}")
    fqdns = [
      lower(local.ingress_fqdn)
    ]
  }

  backend_http_settings {
    name                                   = lower("agw-backend-http-settings-${local.acae_key}")
    port                                   = 443
    protocol                               = "Https"
    cookie_based_affinity                  = "Disabled"
    pick_host_name_from_backend_address    = true
    request_timeout                        = 20
    probe_name                             = lower("agw-probe-${local.acae_key}")
  }

  dynamic "probe" {
    name                                      = lower("agw-probe-${local.acae_key}")
    path                                      = "/"
    protocol                                  = "Https"
    interval                                  = 30
    timeout                                   = 30
    unhealthy_threshold                       = 3
    pick_host_name_from_backend_http_settings = true
    minimum_servers                           = 0
  }
}
github-actions[bot] commented 1 year ago

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.