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.62k forks source link

Support for user-assigned identity for function app AzureWebJobsStorage #24730

Open guidojw opened 8 months ago

guidojw commented 8 months ago

Is there an existing issue for this?

Community Note

Description

I want to be able to specify a user-assigned identity to be used for AzureWebJobsStorage. Currently with the storage_uses_managed_identity argument, only using the system-assigned identity is supported.

Look at the references for more information on how Azure supports this, it is a bit specific and requires some testing to find out how it exactly works. According to the first reference, both AzureWebJobsStorage__clientId and AzureWebJobsStorage__managedIdentityResourceId can be set, but the bottom note on the second reference seems to imply specifically clientID (probably AzureWebJobsStorage__clientId) needs to be set.

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

azurerm_windows_web_app, azurerm_windows_web_app_slot, azurerm_linux_web_app, azurerm_linux_web_app_slot, azurerm_windows_function_app, azurerm_windows_function_app_slot, azurerm_linux_function_app, azurerm_linux_function_app_slot

Potential Terraform Configuration

resource "azurerm_linux_function_app" "function_app" {
  ...
  storage_uses_managed_identity = true
  storage_identity_id = azurerm_user_assigned_identity.user_assigned_identity.id # similar to key_vault_reference_identity_id
}

References

https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference#common-properties-for-identity-based-connections https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference#configure-an-identity-based-connection (bottom note of paragraph) https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/linux_function_app#storage_uses_managed_identity

guidojw commented 8 months ago

(and AzureWebJobsDashboard, don't know how that is currently resolved but azurerm sets it too)

oscarhermoso commented 8 months ago

I've been running into the same issue as you @guidojw over the last three days.

When you function app is using a managed identity, you want AzureWebJobsDashboard__accountName, AzureWebJobsStorage__accountName, instead of AzureWebJobsDashboard, AzureWebJobsStorage.

These should be populated by terraform already (as long as your terraform provider is up to date, this feature was added recently). However, it only seems to happen if the function app successfully authenticates to the storage account.

You will need to grant permissions to the managed identity:

https://techcommunity.microsoft.com/t5/apps-on-azure-blog/use-managed-identity-instead-of-azurewebjobsstorage-to-connect-a/ba-p/3657606

You also need app settings AzureWebJobsStorage__clientId = "<your-managed-identity-client-id>" and AzureWebJobsStorage__credential = "managedidentity", and these are not populated by terraform.

Config that (probably) works:

data "azuread_service_principal" "managed_id" {
  display_name = var.managed_id_name

  # Managed id with Storage Account Contributor, Storage Queue Data Contributor, and Storage Blob Data Owner roles
  # ( see https://techcommunity.microsoft.com/t5/apps-on-azure-blog/use-managed-identity-instead-of-azurewebjobsstorage-to-connect-a/ba-p/3657606 )
}

resource "azurerm_linux_function_app" "function_app" {
  resource_group_name             = var.resource_group_name
  location                        = var.location
  name                            = var.function_app_name
  tags                            = var.tags
  service_plan_id                 = var.app_service_plan_id
  storage_account_name            = var.storage_account_name
  storage_uses_managed_identity   = true

  app_settings = {
    "AzureWebJobsStorage__clientId" : data.azuread_service_principal.managed_id.client_id
    "AzureWebJobsStorage__credential" : "managedidentity"
  }

  identity {
    type         = "UserAssigned"
    identity_ids = [var.managed_identity_resource_id]
  }

  site_config {
    # ...
  }
}
guidojw commented 8 months ago

I've been running into the same issue as you @guidojw over the last three days.

When you function app is using a managed identity, you want AzureWebJobsDashboard__accountName, AzureWebJobsStorage__accountName, instead of AzureWebJobsDashboard, AzureWebJobsStorage.

These should be populated by terraform already, but it only seems to happen if the function app successfully authenticates to the storage account,

You also need AzureWebJobsStorage__clientId = "<your-managed-identity-client-id>" and AzureWebJobsStorage__credential = "managedidentity", and these are not populated by terraform.

This doco page might help:

https://techcommunity.microsoft.com/t5/apps-on-azure-blog/use-managed-identity-instead-of-azurewebjobsstorage-to-connect-a/ba-p/3657606

Config that (probably) works:

data "azuread_service_principal" "managed_id" {
  display_name = var.managed_id_name

  # Managed id with Storage Account Contributor, Storage Queue Data , and Storage Blob Data Owner roles
  # ( see https://techcommunity.microsoft.com/t5/apps-on-azure-blog/use-managed-identity-instead-of-azurewebjobsstorage-to-connect-a/ba-p/3657606 )
}

resource "azurerm_linux_function_app" "function_app" {
  resource_group_name             = var.resource_group_name
  location                        = var.location
  name                            = var.function_app_name
  tags                            = var.tags
  service_plan_id                 = var.app_service_plan_id
  storage_account_name            = var.storage_account_name
  storage_uses_managed_identity   = true

  app_settings = {
    "AzureWebJobsStorage__clientId" : data.azuread_service_principal.managed_id.client_id
    "AzureWebJobsStorage__credential" : "managedidentity"
  }

  identity {
    type         = "UserAssigned"
    identity_ids = [var.managed_identity_resource_id]
  }

  site_config {
    # ...
  }
}

I will try that out, thanks! It would probably be desired for azurerm to support it with custom properties how also storage_uses_managed_identity populates the regarding app settings, but this looks like a good temporary fix.

oscarhermoso commented 8 months ago

I will try that out, thanks! It would probably be desired for azurerm to support it with custom properties how also storage_uses_managed_identity populates the regarding app settings, but this looks like a good temporary fix.

Yep definitely agree, needs a long term solution. It has been extremely painful to troubleshoot as the error messages are not at all informative.

xiaxyi commented 8 months ago

Thanks @guidojw for raising this issue, let me check the feature and update the thread about the next step, whether we'll support it or not.

guidojw commented 8 months ago

I've been running into the same issue as you @guidojw over the last three days.

When you function app is using a managed identity, you want AzureWebJobsDashboard__accountName, AzureWebJobsStorage__accountName, instead of AzureWebJobsDashboard, AzureWebJobsStorage.

These should be populated by terraform already (as long as your terraform provider is up to date, this feature was added recently). However, it only seems to happen if the function app successfully authenticates to the storage account.

You will need to grant permissions to the managed identity:

techcommunity.microsoft.com/t5/apps-on-azure-blog/use-managed-identity-instead-of-azurewebjobsstorage-to-connect-a/ba-p/3657606

You also need app settings AzureWebJobsStorage__clientId = "<your-managed-identity-client-id>" and AzureWebJobsStorage__credential = "managedidentity", and these are not populated by terraform.

Config that (probably) works:

data "azuread_service_principal" "managed_id" {
  display_name = var.managed_id_name

  # Managed id with Storage Account Contributor, Storage Queue Data Contributor, and Storage Blob Data Owner roles
  # ( see https://techcommunity.microsoft.com/t5/apps-on-azure-blog/use-managed-identity-instead-of-azurewebjobsstorage-to-connect-a/ba-p/3657606 )
}

resource "azurerm_linux_function_app" "function_app" {
  resource_group_name             = var.resource_group_name
  location                        = var.location
  name                            = var.function_app_name
  tags                            = var.tags
  service_plan_id                 = var.app_service_plan_id
  storage_account_name            = var.storage_account_name
  storage_uses_managed_identity   = true

  app_settings = {
    "AzureWebJobsStorage__clientId" : data.azuread_service_principal.managed_id.client_id
    "AzureWebJobsStorage__credential" : "managedidentity"
  }

  identity {
    type         = "UserAssigned"
    identity_ids = [var.managed_identity_resource_id]
  }

  site_config {
    # ...
  }
}

I tested this with both app settings for AzureWebJobsStorage and AzureWebJobsDashboard, works like charm! Proposed solution would still be more elegant though :)

drdamour commented 8 months ago

@guidojw in the portal's function overview blade do you get a warning like

image

following what you've done here...but can't seem to make that go away

guidojw commented 7 months ago

@guidojw in the portal's function overview blade do you get a warning like

image

following what you've done here...but can't seem to make that go away

No warning for me. Did you pass the user assigned identity in the identity block correctly, set storage_uses_managed_identity to true and pass the two extra app_settings?

drdamour commented 7 months ago

@guidojw in the portal's function overview blade do you get a warning like image following what you've done here...but can't seem to make that go away

No warning for me. Did you pass the user assigned identity in the identity block correctly, set storage_uses_managed_identity to true and pass the two extra app_settings?

Yup, r u on consumption or elastic plan?

guidojw commented 7 months ago

@guidojw in the portal's function overview blade do you get a warning like

image

following what you've done here...but can't seem to make that go away

No warning for me. Did you pass the user assigned identity in the identity block correctly, set storage_uses_managed_identity to true and pass the two extra app_settings?

Yup, r u on consumption or elastic plan?

I'm on an app service plan with sku B1

drdamour commented 7 months ago

@guidojw in the portal's function overview blade do you get a warning like

image

following what you've done here...but can't seem to make that go away

No warning for me. Did you pass the user assigned identity in the identity block correctly, set storage_uses_managed_identity to true and pass the two extra app_settings?

Yup, r u on consumption or elastic plan?

I'm on an app service plan with sku B1

ah...scaling doesnt come into play there so that explains it.thx!