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.59k stars 4.63k forks source link

Support for ingress CORS setting in azurerm_container_app #21073

Open daseth opened 1 year ago

daseth commented 1 year ago

Is there an existing issue for this?

Community Note

Description

Terraform provider should allow setting the CORS policy in the ingress properties of the Contaienr App, as per this documentation: https://learn.microsoft.com/en-us/azure/templates/microsoft.app/containerapps?pivots=deployment-language-arm-template#corspolicy-1

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

azurerm_3.48.0

Potential Terraform Configuration

A cors block under ingress block that supports the following:

Name                    Description           Value
allowCredentials    allow credential or not    bool
allowedHeaders          allowed HTTP headers       string[]
allowedMethods          allowed HTTP methods       string[]
allowedOrigins          allowed origins            string[] (required)
exposeHeaders           expose HTTP headers    string[]
maxAge                  max time client can cache the result    int

References

https://learn.microsoft.com/en-us/azure/templates/microsoft.app/containerapps?pivots=deployment-language-arm-template#corspolicy-1

fbridger commented 9 months ago

Is there any existing workaround to be able to configure CORS for a container app?

snilk commented 9 months ago

@fbridger As a workaround, you could use azapi_update_resource together with azurerm_container_app. Important note: you need to duplicate all secrets if you have them in azurerm_container_app

 resource "azapi_update_resource" "set_cors" {
  type        = "Microsoft.App/containerApps@2023-05-01"
  resource_id = azurerm_container_app.containerApp.id

  body = jsonencode({
    properties = {
      configuration = {
       # Duplicate all secrets here
        secrets = [
          for secretKey, secretValue in local.containerSecrets: {
            name  = secretKey
            value = secretValue
          }
        ]
        ingress = {
          corsPolicy = {
            allowedOrigins = ["*"]
            allowedMethods = ["*"]
            allowedHeaders = ["*"]
          }
        }
      }
    }
  })
} 
fbridger commented 9 months ago

Thanks @snilk! I was able to use your suggestion. Thanks for your help!

sk-concerto commented 6 months ago

The workaround provided by @snilk didn't work for me.

The container app environment variables kept getting overwritten. I tried duplicating them too like the secrets, but that didn't work either.

We could really do with a proper CORS block like the suggested change.

fbridger commented 6 months ago

@sk-concerto I would suggest you to review your Terraform code as there is probably something wrong.

Using the code suggested by @snilk I was able to set the CORS perfectly (remember to include the secrets).


locals {
  container_app_secrets = [
    {
      name        = "username"
      keyVaultUrl = "${azurerm_key_vault.main.vault_uri}secrets/${azurerm_key_vault_secret.username.name}"
      identity    = azurerm_user_assigned_identity.container_app.id
    }
  ]
}

resource "azapi_update_resource" "container_app" {
  type        = "Microsoft.App/containerApps@2023-05-01"
  resource_id = azurerm_container_app.container_app.id

  body = jsonencode({
    properties = {
      configuration = {
        # Duplicate all secrets here (Using local variable to avoid duplicating secrets)
        secrets = local.container_app_secrets 
        ingress = {
          corsPolicy = {
            allowedOrigins = [var.CORS_ALLOWED_ORIGIN, "https://${azurerm_storage_account.main.primary_web_host}", "https://${azurerm_cdn_frontdoor_endpoint.frontend.host_name}"]
            allowedMethods = ["*"]
            allowedHeaders = ["*"]
          }
        }
      }
    }
  })
}
sk-concerto commented 6 months ago

The azapi_update_resource call updates the CORS policy correctly. However the next deployment of the app via Azure DevOps clears the environment variables. If I remove the azapi_update_resource call, everything works as expected.

Sample code:

locals {
  secrets = {
      my-secret = var.my_secret_value
  }
  env_vars = [
    {
      name  = "ASPNETCORE_ENVIRONMENT",
      value = var.env_group_fullname
    },
    {
      name  = "AppSecretsKeyVaultName",
      value = var.app_secrets_key_vault_name
    }
  ]
}

module "ca_myapp" {
  source                       = "../../../.modules/azure/container-app"
  resource_group_name          = var.resource_group_name
  region                       = var.region
  env_name                     = var.env_name
  workload_name                = "myapp"
  container_app_environment_id = module.cae.id
  user_assigned_identity_id    = var.user_assigned_identity_id
  container_name               = "myapp"
  container_image              = "cruksapps.azurecr.io/mycompany/myapp:latest"
  container_cpu                = 0.25
  container_memory             = "0.5Gi"
  ingress_port                 = 8080
  startup_probe_path           = "/healthz/readiness"
  readiness_probe_path         = "/healthz/readiness"
  liveness_probe_path          = "/healthz/liveness"
  secrets                      = local.secrets
  env_vars                     = local.env_vars
}

resource "azapi_update_resource" "set_containerapp_cors" {
  type        = "Microsoft.App/containerApps@2023-05-01"
  resource_id = module.ca_myapp.id
  body = jsonencode({
    properties = {
      configuration = {
        secrets = [
          for secretName, secertValue in local.secrets : {
            name  = secretName
            value = secertValue
          }
        ]
        ingress = {
          corsPolicy = {
            allowedOrigins = ["*"]
            allowedMethods = ["*"]
            allowedHeaders = ["*"]
          }
        }
      }
    }
  })
}

If I include the environment variables in the azapi_update_resource (see below) it still has the same problem:

resource "azapi_update_resource" "set_containerapp_cors" {
  type        = "Microsoft.App/containerApps@2023-05-01"
  resource_id = module.ca_myapp.id
  body = jsonencode({
    properties = {
      configuration = {
        secrets = [
          for secretName, secertValue in local.secrets : {
            name  = secretName
            value = secertValue
          }
        ]
        env_vars = [
          for environmentVarName, environmentVarValue in local.env_vars : {
            name  = environmentVarName
            value = environmentVarValue
          }
        ]
        ingress = {
          corsPolicy = {
            allowedOrigins = ["*"]
            allowedMethods = ["*"]
            allowedHeaders = ["*"]
          }
        }
      }
    }
  })
}
AndHain commented 1 day ago

I cannot recommend the approach using the azapi_update_resource to set the CORS configuration. The reason is that the given CAPP configuration will be overridden. It's to cumbersome and error prone to duplicate the configuration for a container app.

Instead, I suggest a solution like the following:

resource "azapi_resource_action" "cors" {
  type        = "Microsoft.App/containerApps@2023-05-01"
  resource_id = <container_app_id>
  method = "PATCH"

  body = jsonencode({
    properties = {
      configuration = {
        ingress = {
          corsPolicy = {
            allowedOrigins = ["*"]
            allowedMethods  = ["*"]
            allowedHeaders = ["*"]
          }
        }
      }
    }
  })
}

This will update the container app configuration with the specified parts only.

Nevertheless, it would be great to have an updated provider to address CORS settings on theazurerm_container_app resource.