Enable Managed Identity for Web App with Azure Policy

8 Min. Read

Today, a common theme in cloud environments is enforcing organizational standards and adopting cloud governance since day one. And this is very important since it will give you the ability to define policies, processes, and procedures. These policies then dictate what can be done and verify that what does exist is correct. A service from Microsoft called Azure Policy is a great way to make that happen and take corrective action.

This article will demonstrate how to enable managed identity for Web App and Function App with Azure Policy.

Introduction

Azure App Service enables you to build and host web apps, mobile back ends, and RESTful APIs in the programming language of your choice without managing infrastructure. It offers auto-scaling and high availability, supports both Windows and Linux, and enables automated deployments from GitHub, Azure DevOps, or any Git repo.

Azure Policy is a service in Azure that you use to create, assign, and manage policies. These policies enforce different rules and effects over your resources, so those resources stay compliant with your corporate standards and service level agreements. Azure Policy meets this need by continuously evaluating your resources for non-compliance with assigned policies.

You have a policy in your organization that dictates to enable managed identity on all new and existing App Services (web applications and functions) within your subscriptions for enhanced authentication security. As you know, managed identities eliminate the need for developers to have to manage credentials by providing an identity for the Azure resource in Azure AD and using it to obtain Azure Active Directory (Azure AD) tokens.

Managed identities on Azure are great. No need to store client secrets corresponding to a service principal. Instead, we let Azure worry about that. We can let compute resources (like App Services) authenticate against Azure AD to use other Azure resources securely.

There are two flavors of managed identity (user-assigned and system-assigned managed identity). The main difference is that system-assigned identity only lives with the lifetime of the associated resources. With the user assigned identity, the identity lives on regardless of the main resource gets deleted.

If we take a quick look at Azure Security Center as shown in the figure below, we do have already a built-in Policy definition which is based on the default Azure Security Benchmark (V2) that requires having Managed identity enabled for web app and function app to pass this security recommendation.

Managed identity should be used in your web app
Managed identity should be used in your web app

Based on this built-in policy, when you deploy a web app or function app, Azure Security Center will evaluate the configuration and recommends enabling managed identity (system-assigned or user-assigned) for enhanced authentication security to eliminate the need for app developers to have to manage credentials by providing an identity for the Azure resource in Azure AD and using it to obtain Azure Active Directory (Azure AD) tokens.

However, this policy does not auto-remediate the unhealthy resources, therefore, you should manually remediate them as described in the ‘Remediation steps‘, or you can trigger a logic app if you want. You can also exempt this recommendation if needed, but I don’t recommend doing so because it’s categorized as ‘Medium‘ severity.

Please note that it’s not enough to enable managed identity for your web/function apps and the developers did not change the authentication approach. Enabling managed identity is only one piece of the puzzle.

Once you have invested time and effort in remediating these resources to increase your Secure Score, you want to make sure that it will not decrease by a serious percentage, again. The problem is that the remediation is always done for existing resources, but NOT for new ones. You can think of remediating resources as a reactive versus a proactive approach.

As cybersecurity hygiene (practice), you need to have a solid Azure Governance to ensure that the new resources you deploy will have certain security standards, patterns, and configurations.

To ensure proper governance, we need to use Azure Policy. This will allow us to enable managed identity on newly deployed web app and function apps, as well as remediating existing resources at scale, so you can make sure your organization’s policy and security requirements are met.

Prerequisites

To follow this article, you need to have the following:

1) An Azure subscription. If you don’t have an Azure subscription, you can create a free one here.

2) At least one web app or function app is deployed in your subscription.

3) You need to have the appropriate permissions to create and manage Azure Policy definitions. The Azure RBAC built-in roles that you can use are Resource Policy Contributor or Security Admin.

4) Last but not least, you need to have the appropriate permissions to assign the Contributor role for the Managed Identity (Application ID) created during the assignment of the policy either on a management group or a subscription, so the policy with “DeployIfNotExists” can remediate and modify your Web App settings. Azure Policy creates a managed identity for each assignment but must have details about what roles to grant the managed identity.

If the managed identity is missing roles, an error is displayed during the assignment of the policy or an initiative. Please note that when creating an assignment through the Azure Portal, the role assignments are auto-granted. However, when using PowerShell, you must manually configure the managed identity. More information can be found here.

Assuming you have all the prerequisites in place, take now the following steps:

Enable Managed Identity Policy definition

A quick overview of Azure Policy effects. Each policy definition that you create in the Azure Policy has a single effect. That effect determines what happens when the policy rule is evaluated to match. The effects behave differently if they are for a new resource, an updated resource, or an existing resource.

In this example, we need to set and enable managed identity for all Azure App Services and on the existing web apps in our environment. For this to work, we need to use the “DeployIfNotExists” policy. To understand how the Azure Policy effect works with the “DeployIfNotExists” policy definition, please check the official documentation from Microsoft here.

Open the Azure Portal, click “All services” and then search for “Policy” and then click on “Definitions” → “+ Policy definition”.

For the “Definition location“, select the location by clicking the ellipsis [] and select either a management group or a subscription.

In the “Name“ field, give a descriptive name for the policy definition such as – “Enable Managed identity (system-assigned) for Azure Web App” and add a Description.

In the “Category” section, select the appropriate category for this policy. In this example, we will choose “App Service” as shown in the figure below.

New Policy Definition
New Policy Definition

For the “POLICY RULE“, paste the following policy definition in JSON format and then click “Save“.

For the “Role definitions“, make sure that the Contributor is selected. The contributor role is required to set and enable managed identity on the resources.

Here is the Policy definition in JSON format:

{
  "mode": "All",
  "policyRule": {
    "if": {
      "allOf": [
        {
          "field": "type",
          "equals": "Microsoft.Web/sites"
        },
        {
          "field": "kind",
          "like": "app*"
        }
      ]
    },
    "then": {
      "effect": "[parameters('effect')]",
      "details": {
        "type": "Microsoft.Web/sites/config",
        "name": "web",
        "existenceCondition": {
          "field": "Microsoft.Web/sites/config/managedServiceIdentityId",
          "exists": "true"
        },
        "roleDefinitionIds": [
          "/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c"
        ],
        "deployment": {
          "properties": {
            "mode": "incremental",
            "parameters": {
              "webAppName": {
                "value": "[field('name')]"
              },
              "location": {
                "value": "[field('location')]"
              }
            },
            "template": {
              "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
              "contentVersion": "1.0.0.0",
              "parameters": {
                "webAppName": {
                  "type": "string"
                },
                "location": {
                  "type": "string"
                }
              },
              "variables": {
                "hostingPlanName": "[replace(parameters('webAppName'),'wa-', 'sp-')]"
              },
              "resources": [
                {
                  "type": "Microsoft.Web/sites",
                  "apiVersion": "2021-01-15",
                  "name": "[parameters('webAppName')]",
                  "location": "[parameters('location')]",
                  "identity": {
                    "type": "SystemAssigned"
                  },
                  "properties": {
                    "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]"
                  }
                }
              ]
            }
          }
        }
      }
    }
  },
  "parameters": {
    "effect": {
      "type": "String",
      "metadata": {
        "displayName": "Effect",
        "description": "Enable or disable the execution of the policy"
      },
      "allowedValues": [
        "DeployIfNotExists",
        "Disabled"
      ],
      "defaultValue": "DeployIfNotExists"
    }
  }
}

In this custom policy, I am looking for all kinds of web app “app*“, and then I am checking if the “managedServiceIdentityId” exists.

If you want to include both web app and function apps, then you can remove the following policy rule:

{ "field": "kind", "like": "app*" }

The ExistenceCondition option in the template above is super useful for the Azure web app that has already Managed Service Identity enabled. If this condition is true, the policy definition will skip the deployment defined in the “DeployIfNotExists” section.

In this example, I am enabling “SystemAssigned” identity, if you want to enable “UserAssigned identity instead, then you need to update the resources definition to the following.

You need to replace <RESOURCEID> with the resource ID of the desired identity. Please note that creating an app with a user-assigned identity requires that you create the identity first, and then add its resource identifier to your app configuration.

"identity": {
    "type": "UserAssigned",
    "userAssignedIdentities": {
        "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('identityName'))]": {}
    }
}

As part of this policy template, take also a note of the following variables ‘hostingPlanName’. To update the identity of an existing web app or function app, you need to specify the properties for the server farm id of the App Service Plan. As you know, every web app and function app are attached to an app service plan.

"variables": { "hostingPlanName": "[replace(parameters('webAppName'),'wa-', 'sp-')]" }

If you don’t specify the server farm id under the properties definition, you will the following error message: “The parameter properties has an invalid value.”

"properties": { "serverFarmId": "[resourceId('Microsoft.Web/serverfarms', variables('hostingPlanName'))]" }

In this example, I am using the following naming convention standard in my deployment:

  • My Web App name starts with ‘wa-‘ followed by the web app name.
  • My App Service Plan name starts with ‘sp-‘ followed by the same web app name.

Please make sure to update the variables section to match your environment and naming convention.

To learn more about the ExistenceCondition option for the “DeployIfNotExists” properties, please check the official documentation here.

Assign Custom Policy definition

To assign the custom policy definition, take the following steps:

If you want to automate the deployment and assignment of Azure Policies via Azure DevOps instead of using the Azure Portal, then please check the following step-by-step guide.

Open the Azure Portal, click “All services” and then search for “Policy” and then click on “Assignments”. An assignment is a policy that has been assigned to take place within a specific scope.

Select “Assign policy” from the top of the “Policy | Assignments” page.

On the “Assign Policy” page, select the Scope by clicking the ellipsis [] and select either a management group or subscription. You can optionally select a resource group if you want. A scope determines what resources or grouping of resources the policy assignment gets enforced on. Then click Select at the bottom of the Scope page.

Select the Policy definition ellipsis [] to open the list of available definitions. Choose the custom policy that we created in the previous step. The Policy enforcement is Enabled by default. Click Next to continue.

On the Parameters page, specify the parameters for this policy assignment (DeployIfNotExists or Disabled). The default value is set to “DeployIfNotExists“, you can disable the effect of this policy later on by setting the effect to “Disabled“. Click Next to continue.

Assign Policy - DeployIfNotExists
Assign Policy – DeployIfNotExists

In the Remediation page, by default “Create a Managed Identity” is selected for you because existing resources can be updated via a remediation task after the policy is assigned only. Choose the default location for the “Managed Identity“, this is required because policies with the “deployIfNotExists” and “Modify” effect types need the ability to modify resources and edit the configuration on existing resources respectively. To do this, a managed identity will be created automatically for each policy assignment. This identity will also be given the “Contributor” permissions on the scope that you have selected. Click Next to continue.

On the Non-compliance messages page, set the desired message (e.g. Managed identity should be enabled for enhanced authentication security). Then click the “Review + create” button.

Finally, click “Create” to create the assignment.

Verify managed identity enabled on web app

To verify that the custom policy is deployed successfully, you need to wait for at least 30 minutes after a resource has been created or updated. The policy won’t be triggered immediately, this is by design. To trigger the policy compliance scan manually (immediately), open the cloud shell and run the following command:

$job = Start-AzPolicyComplianceScan -AsJob
$job | ft -AutoSize

The scan job will run in the background as shown in the figure below.

Trigger Azure Policy Compliance Evaluation Manually
Trigger Azure Policy Compliance Evaluation Manually

If you want to check Azure Policy compliance status and remediate non-compliant resources via Azure DevOps Pipelines, then please check the following step-by-step guide.

Behind the scene, Azure Policy will create a Remediation task as shown in the figure below. To remediate existing resources, select the desired policy and then click on the “Remediate” button.

Policy Remediation - Enable Managed Identity for Web App
Policy Remediation – Enable Managed Identity for Web App

Please note that during an evaluation cycle, the policy definition with a “DeployIfNotExists” effect that matches resources is marked as non-compliant only, but no action is taken on that resource. For this reason, the remediation task was created when you assign the policy definition as described in the previous section.

Open the Azure Portal, click “All services” and then search for “Policy” and then click on “Remediation”. In the Policy | Remediation page, select the Remediation tasks tab, and check the status of the auto-remediation task. It’s completed successfully without any error as shown in the figure below.

Azure Policy - Remediation tasks
Azure Policy – Remediation tasks

If we look at the Web App resource under Settings | Identity, we can see that the “System assigned” status is set to On.

Azure Web App - System assigned identity
Azure Web App – System assigned identity

That’s it there you have it!

Summary

In this article, we showed you how to enable and enforce managed identities on all web apps with Azure Policy, so you can make sure your organization’s policy and security requirements are met.

Azure Policies are becoming increasingly popular, as they provide a wide range of management capabilities over Azure resources. Not only do they allow us to enforce policy rules to control Azure resources, but they can also enable us to automatically evaluate compliance and remediate non-compliant resources.

To learn more about auditing publicly accessible Azure App Services with Azure Policy, please check the following step-by-step guide.

To learn more about auditing subnets that do not have Network Security Group (NSG) associated, please check the following step-by-step guide.

__
Thank you for reading my blog.

If you have any questions or feedback, please leave a comment.

-Charbel Nemnom-

Related Posts

Previous

Change Performance Tiers of Azure Managed Disk

Enable Purge Protection for Azure Key Vault with Azure Policy

Next

Let me know what you think, or ask a question...

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Subscribe to Stay in Touch

Never miss out on your favorite posts and our latest announcements!

The content of this website is copyrighted from being plagiarized!

You can copy from the 'Code Blocks' in 'Black' by selecting the Code.

Please send your feedback to the author using this form for any 'Code' you like.

Thank you for visiting!