{"id":89732,"date":"2021-02-01T17:00:00","date_gmt":"2021-02-01T17:00:00","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=89732"},"modified":"2021-02-01T21:03:19","modified_gmt":"2021-02-01T21:03:19","slug":"azure-sql-and-managed-identity","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/blogs\/azure-sql-and-managed-identity\/","title":{"rendered":"Azure SQL and Managed Identity"},"content":{"rendered":"<p><strong>Azure SQL<\/strong> has a close relationship with <strong>Azure Storage<\/strong>. Features like Polybase, backups, extended events and more make use of Azure Storage.<\/p>\n<p>On Azure SQL Database, probably the most common use is <strong>Extended Events<\/strong>. When we create a file target, we need to point to the Azure Storage URL where the file will be stored.<\/p>\n<h2>Using Keys<\/h2>\n<p>In order to access Azure Storage, we need to control the authentication. The most common way is to use credentials, creating a credential with the storage <strong>SAS<\/strong> key<\/p>\n<p>. <img loading=\"lazy\" decoding=\"async\" width=\"1208\" height=\"712\" class=\"wp-image-89733\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/01\/graphical-user-interface-text-application-email.png\" alt=\"Graphical user interface, text, application, email\n\nDescription automatically generated\" \/><\/p>\n<p>Once we generate the <strong>SAS<\/strong> key, we create the credential object inside our database. For this we have Database Scoped a new feature introduced exactly for these situations, allowing us to create the credential inside the database, instead of at server level.<\/p>\n<p>The statement to create the credential would be like this:<\/p>\n<div style=\"padding-left: 30px\"><span style=\"font-family: Courier New;font-size: 10pt\"> <span style=\"color: blue\">CREATE<\/span>\u00a0<span style=\"color: blue\">DATABASE<\/span>\u00a0<span style=\"color: maroon\">scoped<\/span>\u00a0<span style=\"color: maroon\">credential<\/span> <br \/>\n<span style=\"color: maroon\">[https:\/\/dummystorageaccount.blob.core.windows.net\/extendedevents]<\/span>\u00a0<span style=\"color: blue\">WITH<\/span>\u00a0<span style=\"color: blue\">IDENTITY<\/span> <br \/>\n<span style=\"color: silver\">=<\/span><span style=\"color: red\">&#8216;SHARED\u00a0ACCESS\u00a0SIGNATURE&#8217;<\/span><span style=\"color: silver\">,<\/span>\u00a0<span style=\"color: maroon\">secret<\/span>\u00a0<span style=\"color: silver\">=<\/span> <br \/>\n<span style=\"color: red\">&#8216;sv=2019-12-12&amp;ss=b&amp;srt=sco&amp;sp=rwdlacx&amp;se=2021-12-30T20:03:34Z&amp;st=2021-01-22T12:03:34Z&amp;spr=https&amp;sig=kMj8oq7bKderywanUcYN9vE3ebx0GxOaj3N7NU%2BMdgE%3D&#8217;<\/span>\u00a0 <\/span><\/div>\n<p>The Identity value is fixed, to identify the kind of key we are using, a <strong>SAS<\/strong> key. The name needs to be the URL to the container, but not always, it depends on what feature will be using this credential.<\/p>\n<p>Some more recent features are prepared to use credentials, receiving the name of the credential as a parameter. In these cases, the credential can have whatever name we would like.<\/p>\n<p>However, older features, such as <strong>Extended Events<\/strong>, are not prepared to be linked to a credential. This is solved by ensuring the credential name has the same name of the path used by the feature. In this way, SQL Server identifies which credential should be used for that access.<\/p>\n<h2>Avoiding Keys<\/h2>\n<p>This method ends up spreading <strong>SAS<\/strong> keys all around. We can&#8217;t really tell this is unsafe, since the credentials are kept encrypted using the <a href=\"https:\/\/docs.microsoft.com\/en-us\/sql\/relational-databases\/security\/encryption\/encryption-hierarchy?view=sql-server-ver15\">SQL Server encryption system<\/a>, but it would be better if we could make the authentication without directly using a key or password.<\/p>\n<p>That&#8217;s what we can achieve using <strong>Managed Identities<\/strong>. Each service on Azure can have its own identity registered with Azure Active Directory. Once the identity is stablished, we can use Role Based security (<strong>RBAC<\/strong>) to set permissions for the service, avoiding the use of passwords or keys.<\/p>\n<p>Azure SQL Database doesn&#8217;t have a control on the UI to set the managed identity, but we can easily do it using PowerShell in the cloud shell on the portal.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"1266\" height=\"359\" class=\"wp-image-89734\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/01\/graphical-user-interface-text-application-descr-4.png\" alt=\"Graphical user interface, text, application\n\nDescription automatically generated\" \/><\/p>\n<p>The statement to set the managed identity is like this:<\/p>\n<p><span style=\"color: #000000\"><\/p>\n<pre class=\"tsqlcode\" style=\"font-size: small;color: black;font-family: Consolas,\">Set-AzSqlServer -ResourceGroupName &lt;&lt;resourcegroup&gt;&gt; -ServerName &lt;&lt;sqlservername&gt;&gt; -AssignIdentity\r\n<\/pre>\n<p><\/span><\/p>\n<h2>Setting Identity Permissions<\/h2>\n<p>Once we execute this statement, the server gets an identity, and we can use this identity to control the access to the Azure Storage. The next step is to give permission to this identity.<\/p>\n<p>When dealing with <strong>RBAC<\/strong> permissions it&#8217;s important to mind there are two kinds of permissions: Object permissions, for managing the object, and data permission, to access the data within the object. In this case, we need the data permissions, so SQL Server will be able to write the extended events file to the blob storage. We can set the <strong>Managed Identity<\/strong> with the permission <strong>Storage Blob Data Contributor<\/strong>, which is different than <strong>Storage Blob Contributor<\/strong>.<\/p>\n<p>On the storage account, we access the tab <strong>Access Control (IAM)<\/strong> and click the <strong>Add<\/strong> button. A new window will open, where we configure the identity and permission. The permission is set on <strong>Role<\/strong> dropdown, we just choose it. We type on the <strong>Select<\/strong> text box to filter the identities. The <strong>Manage Identity<\/strong> will have the same name as the SQL Server we created. Once found, we select it and complete the creation of the role assignment.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"510\" height=\"385\" class=\"wp-image-89735\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/01\/graphical-user-interface-text-application-descr-5.png\" alt=\"Graphical user interface, text, application\n\nDescription automatically generated\" \/><\/p>\n<p>Next step is creating a credential in the database to use the managed identity. This time we don\u2019t have a secret for the credential, we only define the type of Identity we will use:<\/p>\n<div style=\"padding-left: 30px\"><span style=\"font-family: Courier New;font-size: 10pt\"> <span style=\"color: blue\">CREATE<\/span>\u00a0<span style=\"color: blue\">DATABASE<\/span>\u00a0<span style=\"color: maroon\">scoped<\/span>\u00a0<span style=\"color: maroon\">credential<\/span> <br \/>\n<span style=\"color: maroon\">[https:\/\/dummystorageaccount.blob.core.windows.net\/extendedevents]<\/span>\u00a0<span style=\"color: blue\">WITH<\/span>\u00a0<span style=\"color: blue\">IDENTITY<\/span> <br \/>\n<span style=\"color: silver\">=<\/span>\u00a0<span style=\"color: red\">&#8216;Managed\u00a0Identity&#8217;<\/span><span style=\"color: silver\">;<\/span>\u00a0 <\/span><\/div>\n<h2>Creating the XE Session<\/h2>\n<p>This is only an example of an Extended Events session pointing to the blob storage. It will use the credential to authenticate and, in our example, will be using the SQL Server Managed Identity.<\/p>\n<div style=\"padding-left: 30px\"><span style=\"font-family: Courier New;font-size: 10pt\"> CREATE\u00a0<span style=\"color: maroon\">EVENT<\/span>\u00a0<span style=\"color: maroon\">SESSION<\/span>\u00a0<span style=\"color: maroon\">[queries]<\/span>\u00a0<span style=\"color: blue\">ON<\/span>\u00a0<span style=\"color: blue\">DATABASE<\/span> <br \/>\n<span style=\"color: blue\">ADD<\/span>\u00a0<span style=\"color: maroon\">EVENT<\/span>\u00a0<span style=\"color: maroon\">sqlserver<\/span><span style=\"color: silver\">.<\/span><span style=\"color: maroon\">sql_statement_completed<\/span><span style=\"color: maroon\">(<\/span> <br \/>\n<span style=\"color: maroon\">ACTION<\/span><span style=\"color: maroon\">(<\/span><span style=\"color: maroon\">sqlserver<\/span><span style=\"color: silver\">.<\/span><span style=\"color: maroon\">client_app_name<\/span><span style=\"color: silver\">,<\/span><span style=\"color: maroon\">sqlserver<\/span><span style=\"color: silver\">.<\/span><span style=\"color: maroon\">client_hostname<\/span><span style=\"color: silver\">,<\/span><span style=\"color: maroon\">sqlserver<\/span><span style=\"color: silver\">.<\/span><span style=\"color: maroon\">context_info<\/span><span style=\"color: silver\">,<\/span><span style=\"color: maroon\">sqlserver<\/span><span style=\"color: silver\">.<\/span><span style=\"color: maroon\">database_id<\/span><span style=\"color: silver\">,<\/span><span style=\"color: maroon\">sqlserver<\/span><span style=\"color: silver\">.<\/span><span style=\"color: maroon\">database_name<\/span><span style=\"color: silver\">,<\/span><span style=\"color: maroon\">sqlserver<\/span><span style=\"color: silver\">.<\/span><span style=\"color: maroon\">username<\/span><span style=\"color: maroon\">)<\/span><span style=\"color: maroon\">)<\/span><span style=\"color: silver\">,<\/span> <br \/>\n<span style=\"color: blue\">ADD<\/span>\u00a0<span style=\"color: maroon\">EVENT<\/span>\u00a0<span style=\"color: maroon\">sqlserver<\/span><span style=\"color: silver\">.<\/span><span style=\"color: maroon\">sql_statement_starting<\/span><span style=\"color: maroon\">(<\/span><span style=\"color: blue\">SET<\/span>\u00a0<span style=\"color: maroon\">collect_statement<\/span><span style=\"color: silver\">=<\/span><span style=\"color: maroon\">(<\/span><span style=\"color: black\">1<\/span><span style=\"color: maroon\">)<\/span> <br \/>\n<span style=\"color: maroon\">ACTION<\/span><span style=\"color: maroon\">(<\/span><span style=\"color: maroon\">sqlserver<\/span><span style=\"color: silver\">.<\/span><span style=\"color: maroon\">client_app_name<\/span><span style=\"color: silver\">,<\/span><span style=\"color: maroon\">sqlserver<\/span><span style=\"color: silver\">.<\/span><span style=\"color: maroon\">client_hostname<\/span><span style=\"color: silver\">,<\/span><span style=\"color: maroon\">sqlserver<\/span><span style=\"color: silver\">.<\/span><span style=\"color: maroon\">database_id<\/span><span style=\"color: silver\">,<\/span><span style=\"color: maroon\">sqlserver<\/span><span style=\"color: silver\">.<\/span><span style=\"color: maroon\">database_name<\/span><span style=\"color: silver\">,<\/span><span style=\"color: maroon\">sqlserver<\/span><span style=\"color: silver\">.<\/span><span style=\"color: maroon\">username<\/span><span style=\"color: maroon\">)<\/span><span style=\"color: maroon\">)<\/span> <br \/>\n<span style=\"color: blue\">ADD<\/span>\u00a0<span style=\"color: maroon\">TARGET<\/span>\u00a0<span style=\"color: maroon\">package0<\/span><span style=\"color: silver\">.<\/span><span style=\"color: maroon\">event_file<\/span><span style=\"color: maroon\">(<\/span><span style=\"color: blue\">SET<\/span>\u00a0<span style=\"color: maroon\">filename<\/span><span style=\"color: silver\">=<\/span><span style=\"color: red\">N&#8217;https:\/\/dummystorageaccount.blob.core.windows.net\/extendedevents\/queries\/&#8217;<\/span><span style=\"color: maroon\">)<\/span> <br \/>\n<span style=\"color: blue\">WITH<\/span>\u00a0<span style=\"color: maroon\">(<\/span><span style=\"color: maroon\">STARTUP_STATE<\/span><span style=\"color: silver\">=<\/span><span style=\"color: blue\">ON<\/span><span style=\"color: maroon\">)<\/span><span style=\"color: maroon\">GO<\/span> <\/span><\/div>\n<h2>Conclusion<\/h2>\n<p>Managed Identities can make our cloud environment safer, removing keys and passwords from our control.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Azure SQL has a close relationship with Azure Storage. Features like Polybase, backups, extended events and more make use of Azure Storage. On Azure SQL Database, probably the most common use is Extended Events. When we create a file target, we need to point to the Azure Storage URL where the file will be stored&#8230;.&hellip;<\/p>\n","protected":false},"author":50808,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[5364,136322,136323,136324,4162],"coauthors":[6810],"class_list":["post-89732","post","type-post","status-publish","format-standard","hentry","category-blogs","tag-azure","tag-azure-sql","tag-credential","tag-managed-identity","tag-microsoft"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/89732","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/50808"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=89732"}],"version-history":[{"count":4,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/89732\/revisions"}],"predecessor-version":[{"id":89740,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/89732\/revisions\/89740"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=89732"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=89732"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=89732"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=89732"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}