{"id":60837,"date":"2021-01-28T09:00:38","date_gmt":"2021-01-28T17:00:38","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/devops\/?p=60837"},"modified":"2021-01-25T13:06:53","modified_gmt":"2021-01-25T21:06:53","slug":"demystifying-service-principals-managed-identities","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/devops\/demystifying-service-principals-managed-identities\/","title":{"rendered":"Demystifying Service Principals &#8211; Managed Identities"},"content":{"rendered":"<p>Hey friends,<\/p>\n<p>In this article, I want to clarify one of the more confusing concepts in Azure and more specifically around the Azure Identity objects known as <strong><a href=\"https:\/\/docs.microsoft.com\/azure\/active-directory\/develop\/app-objects-and-service-principals\/?WT.mc_id=devops-10986-petender\">Service Principals<\/a><\/strong> and <strong><a href=\"https:\/\/docs.microsoft.com\/azure\/active-directory\/managed-identities-azure-resources\/overview\/?WT.mc_id=devops-10986-petender\">Managed Identities<\/a><\/strong>.<\/p>\n<p>Before zooming in on these, let&#8217;s take a step back and look at the different Azure Identity Objects we have available in <strong><a href=\"https:\/\/azure.microsoft.com\/services\/active-directory\/?WT.mc_id=devops-10986-petender\">Azure Active Directory<\/a><\/strong> today.<\/p>\n<h2>Azure AD Identity<\/h2>\n<p>Azure AD is the trusted Identity Object store, in which you can create different Identity Object types. The most common ones are <strong>Users and Groups<\/strong>, but you can also have <strong>Applications<\/strong> in there, also known as <strong>Enterprise Apps<\/strong>.<\/p>\n<p>An example for each could be:<\/p>\n<ul>\n<li><strong>Users<\/strong>: you create a user object in Azure AD, and from there allow the user to authenticate to the Azure Portal, to start using Office 365,\u2026<\/li>\n<li><strong>Groups<\/strong>: you define a security group in Azure AD, which can be used to specify permissions to SharePoint sites for example<\/li>\n<li><strong>Enterprise Apps<\/strong>: using <em>OpenIDConnect<\/em> and <em>OAuth<\/em>, you allow a cloud-based application to trust your Azure AD for user authentication; the trusting app is known as an enterprise app object in Azure AD. <\/li>\n<\/ul>\n<h2>Service Principal<\/h2>\n<p>Most relevant to Service Principal, is the Enterprise apps; according to the formal definition, <em>a service principal is \u201c\u2026An application whose tokens can be used to authenticate and grant access to specific Azure resources from a user-app, service or automation tool, when an organization is using Azure Active Directory\u2026\u201d<\/em><\/p>\n<p>In essence, by using a Service Principal, you avoid creating <strong>\u201cfake users\u201d<\/strong> (we would call them service account in on-premises Active Directory&#8230;) in Azure AD to manage authentication when you need to access Azure Resources.<\/p>\n<p>The Service Principals&#8217; access can be <strong>restricted<\/strong> by assigning <strong><a href=\"https:\/\/docs.microsoft.com\/azure\/role-based-access-control\/overview\/?WT.mc_id=devops-10986-petender\">Azure RBAC roles<\/a><\/strong> so that they can access the specific set of resources only. There is <strong>one major exception<\/strong> to this RBAC rule, and that is <strong><a href=\"https:\/\/azure.microsoft.com\/services\/key-vault\/?WT.mc_id=devops-10986-petender\">Azure Key Vault<\/a><\/strong>, which can be extended by using Key Vault Access Policies to define permissions, instead of Azure RBAC roles. (to be 100% correct on this statement, there is actually a preview available since mid Oct 2020, allowing RBAC KeyVault access as well &#8211; check <a href=\"https:\/\/docs.microsoft.com\/azure\/key-vault\/general\/rbac-guide\/?WT.mc_id=devops-10986-petender\">this article<\/a> for more details).<\/p>\n<p>Typical use cases where you would rely on a Service Principal is for example when running <a href=\"http:\/\/www.terraform.io\/?WT.mc_id=devops-10986-petender\">Terraform<\/a> IAC (Infrastructure as Code) deployments, or when using <a href=\"http:\/\/dev.azure.com\/?WT.mc_id=devops-10986-petender\">Azure DevOps<\/a> for example, where you define a Service Connection from DevOps Pipelines to Azure; or basically any other 3rd party application requiring an authentication token to connect to Azure resources.<\/p>\n<p>An Azure Service Principal can be created using &#8220;any&#8221; traditional way like the Azure Portal, Azure PowerShell, Rest API or Azure CLI. Let me show you the command syntax out of Azure CLI to achieve this:<\/p>\n<pre><code>az ad sp create-for-rbac --name \"pdtdevblogsp\"\n<\/code><\/pre>\n<p>resulting in this outcome:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2021\/01\/2021-01-12-01.jpg\" alt=\"az ad sp result\" \/><\/p>\n<p>Copy this information aside; in the example of an <strong>Azure DevOps Service Connection<\/strong>, this information would be used as follows:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2021\/01\/2021-01-12-02.jpg\" alt=\"ado service connection\" \/><\/p>\n<p>where you just need to copy the correct information in the corresponding parameter fields:<\/p>\n<ul>\n<li>Subscription Id = can be found from the Azure CLI under &#8220;\/subscriptions\/xxxxxx-xxxx-xxxx&#8221; format<\/li>\n<li>Subscription Name = can be found from your Azure Portal \/ Subscriptions; make sure you use the exact name as is listed<\/li>\n<li>Service Principal Id = appId from the Azure CLI output<\/li>\n<li>Service Principal Key = password from the Azure CLI output<\/li>\n<li>Tenant ID = tenant from the Azure CLI output<\/li>\n<\/ul>\n<p>And using a Terraform deployment template file (or terraform.tfvars variable file) as an example, would use this information like this:<\/p>\n<pre><code>Terraform subscription service principal vars\n\n  subscription_id = \"0a407898-c077-442d-xxxx-xxxxxxxxxxxx\"\n  client_id       = \"3723bfcc-f0ba-4bba-xxxx-xxxxxxxxxxxx\"\n  client_secret   = \"b9eab5cb-c1b0-46e6-xxxx-xxxxxxxxxxxx\"\n  tenant_id       = \"70681eb4-8dbc-4dc2-xxxx-xxxxxxxxxxxx\"\n<\/code><\/pre>\n<p><strong>NOTE: The best recommendation I can give, is to store the Service Principal credentials in a safe way, like using Azure Key Vault, instead of a clear-text Notepad document or Terraform.tf file<\/strong><\/p>\n<p>And in a somehow similar way, you would use the same concept from about any other third party solution, keeping in mind that the technical parameter field names might differ a bit from what the Azure CLI command provides as output.<\/p>\n<p>While this seems all fair from a security perspective, since we are not literally using the Azure administrative accounts (former service account concepts, remember&#8230;) anymore, there are also a few challenges involved in using SPs:<\/p>\n<ul>\n<li>First, Someone needs to create the Service Principal objects, which could be a security risk<\/li>\n<li>Client ID and Secret are exposed \/ known to the creator of the Service Principal<\/li>\n<li>Client ID and Secret are exposed \/ known to the consumer of the Service Principal<\/li>\n<li>Object validity is 1 or 2 years; I\u2019ve been in situations where I deployed an App, which after one year stopped working (losing the token, which means no more authentication possibilities)<\/li>\n<\/ul>\n<p>Where Service Principals are important and very useful from a security perspective, I also pointed out some challenges. The fact that there is administrative overhead (and potential security risk) involved is probably the biggest one.<\/p>\n<p>That\u2019s where Managed Identities come in.<\/p>\n<h2>Managed Identities<\/h2>\n<p>Managed Identities are in essence 100% identical in functionality and use case than Service Principals. In fact, they are actually Service Principals.<\/p>\n<p>What makes them different though, is: &#8211; They are always linked to an Azure Resource, not to an application or 3rd party connector &#8211; They are automatically created for you, including the credentials; big benefit here is that <strong>no one knows the credentials<\/strong><\/p>\n<p>Managed Identities exist in 2 formats: &#8211; <strong>System assigned<\/strong>; in this scenario, the identity is linked to a single Azure Resource, eg a Virtual Machine, a Logic App, a Storage Account, Web App, Function,\u2026 so almost anything. Next, they also \u201clive\u201d with the Azure Resource, which means they get deleted when the Azure Resource gets deleted. &#8211; <strong>User Assigned<\/strong> Managed Identity, which means that you first have to create it as a stand-alone Azure resource by itself, after which it can be linked to multiple Azure Resources. An example here could be out of an integration with Key Vault, where different Workload services belonging to the same application stack, need to read out information from Key Vault. In this case, one could create a \u201cread KV\u201d Managed Identity, and link it to the web app, storage account, function, logic app,\u2026 all belonging to the same application architecture.<\/p>\n<p>Let&#8217;s walk through a quick demo scenario for both, using a Virtual Machine as Azure Resource:<\/p>\n<ul>\n<li>From the Azure Portal, select the Virtual Machine; under settings, find <strong>Identity<\/strong><\/li>\n<li>Set Status as <strong>On<\/strong>, and save the changes<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2021\/01\/2021-01-12-03.jpg\" alt=\"System Assigned\" \/><\/p>\n<p>Switching to Azure Key Vault \/ Access Policies, we can now define this <strong>System Assigned Managed Identity<\/strong> having <em>get<\/em> and <em>list<\/em> permissions (or any other) for keys, secrets or certificates. For example reading out an Azure Storage Account Access key or similar.<\/p>\n<p>Notice how Azure Key Vault is expecting a <strong>Service Principal<\/strong> object here (where in reality we are using a Managed Identity).<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2021\/01\/2021-01-12-04.jpg\" alt=\"Access Policy\" \/><\/p>\n<p>Similarly, let&#8217;s remove the System Assigned MI of the VM and use a User Assigned one in the next example (an Azure Resource can only be linked to one or the other, not both&#8230;):<\/p>\n<ul>\n<li>From the Azure Virtual Machine blade, navigate to <strong>Identity<\/strong> and switch the &#8220;Status&#8221; toggle button to <strong>Off<\/strong>. <\/li>\n<li>This will prompt for your confirmation when saving the settings <\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2021\/01\/2021-01-12-05.jpg\" alt=\"Confirmation\" \/><\/p>\n<p>As you notice, the Managed Identity object gets immediately removed from Azure AD. Yes, security is key here&#8230;<\/p>\n<ul>\n<li>Wait for the deregistration of the object.<\/li>\n<\/ul>\n<p>Remember that a <strong>User Assigned<\/strong> Managed Identity is a stand-alone Azure Resource, which needs to be created first, after which you can assign it to another Azure Resource (our VM in this scenario).<\/p>\n<ul>\n<li>From the Azure Portal, Create new Resource, and search for &#8220;User Assigned Managed Identity&#8221;<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2021\/01\/2021-01-12-06.jpg\" alt=\"User Assigned\" \/><\/p>\n<ul>\n<li>click <strong>Create<\/strong>.<\/li>\n<li>Specify the Resource Group, Azure Region and Name for this resource.<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2021\/01\/2021-01-12-07.jpg\" alt=\"User Assigned\" \/><\/p>\n<ul>\n<li>Confirm by clicking create and Wait for the resource creation to complete successfully.<\/li>\n<li>Once created, switch back to the Azure Virtual Machine, select <strong>Identity<\/strong> and select <strong>User Assigned<\/strong><\/li>\n<li>Notice the Managed Identity you just created.<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2021\/01\/2021-01-12-08.jpg\" alt=\"User Assigned\" \/><\/p>\n<ul>\n<li>\n<p>Select it and add it as a Virtual Machine User Assigned object.<\/p>\n<\/li>\n<li>\n<p>Select another Azure Resource in your subscription, for example an Azure Web App, Logic App,&#8230; and once more select <strong>Identity<\/strong> from the settings. Below screenshot shows what it looks like for an Azure Web App Resource:<\/p>\n<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2021\/01\/2021-01-12-09.jpg\" alt=\"User Assigned\" \/><\/p>\n<p>To complete the sample scenario, let&#8217;s go back to Azure Key Vault, and specify another Access Policy for this User Assigned Managed Identity:<\/p>\n<ul>\n<li>Select your Azure Key Vault resource, followed by selecting <strong>Access Policy<\/strong> from the settings.<\/li>\n<li>Specify the Key and\/or Secret Permissions (for example get, list)<\/li>\n<li>Click &#8220;Select Principal&#8221; and search for the <em>User Assigned Managed Identity<\/em> you created earlier<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2021\/01\/2021-01-12-10.jpg\" alt=\"User Assigned\" \/><\/p>\n<p>After saving the changes, the result is that now both the Azure Virtual Machine as well as the Web App &#8211; having the User Assigned Managed Identity assigned to them &#8211; can read our keys and secrets from Azure Key Vault.<\/p>\n<h2>Summary<\/h2>\n<p>In this post, I wanted to clarify the use case, difference and similarities between Service Principals and Managed Identities. A Service Principal could be looked at as similar to a <strong>service account-alike<\/strong> in a more traditional on-premises application or service scenario. Managed Identities are used for &#8220;linking&#8221; a Service Principal security object to an Azure Resource like a Virtual Machine, Web App, Logic App or similar. For a <strong>1:1 relation<\/strong> between both, you would use a <strong>System Assigned<\/strong>, where for a <strong>1:multi relation<\/strong>, you would use a <strong>User Assigned Managed Identity<\/strong>.<\/p>\n<ul>\n<li>Create your <a href=\"https:\/\/azure.microsoft.com\/free\/?WT.mc_id=devops-10986-petender\">Azure Trial subscription<\/a><\/li>\n<li>Additional reading material on <a href=\"https:\/\/docs.microsoft.com\/azure\/active-directory\/develop\/app-objects-and-service-principals\/?WT.mc_id=devops-10986-petender\">Service Principals<\/a><\/li>\n<li>Additional reading material on <a href=\"https:\/\/docs.microsoft.com\/azure\/active-directory\/managed-identities-azure-resources\/overview\/?WT.mc_id=devops-10986-petender\">Managed Identities<\/a> <\/li>\n<\/ul>\n<p>As always, holler when having any questions petender@microsoft.com or @pdtit on Twitter<\/p>\n<p>\/Peter<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This article will describe the use case and core differences between Service Principal and Managed Identities, using Key Vault and other Azure services as an example<\/p>\n","protected":false},"author":45107,"featured_media":60852,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[224,251],"tags":[],"class_list":["post-60837","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure","category-security"],"acf":[],"blog_post_summary":"<p>This article will describe the use case and core differences between Service Principal and Managed Identities, using Key Vault and other Azure services as an example<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/60837","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/users\/45107"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/comments?post=60837"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/60837\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media\/60852"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media?parent=60837"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/categories?post=60837"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/tags?post=60837"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}