{"id":92938,"date":"2021-12-06T17:00:10","date_gmt":"2021-12-06T17:00:10","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=92938"},"modified":"2021-12-07T23:13:15","modified_gmt":"2021-12-07T23:13:15","slug":"azure-sql-enforcing-sql-authentication-type","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/blogs\/azure-sql-enforcing-sql-authentication-type\/","title":{"rendered":"Azure SQL: Enforcing Azure AD Only Authentication"},"content":{"rendered":"<p>Some time ago I wrote <a href=\"https:\/\/www.red-gate.com\/simple-talk\/blogs\/azure-sql-tightening-the-security-using-integrated-authentication-only\/\">a blog<\/a> about the just released feature to allow only <strong>Azure Authentication<\/strong> in <strong>Azure SQL Databases.<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-92941\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/12\/Policy01.png\" alt=\"\" width=\"1135\" height=\"304\" \/><\/p>\n<p>On <a href=\"https:\/\/www.red-gate.com\/simple-talk\/blogs\/azure-sql-tightening-the-security-using-integrated-authentication-only\/\">that blog<\/a>, I explained not only about the feature, but how to use <strong>Azure Policies<\/strong>, a great feature for governance, to control which <strong>Azure SQL<\/strong> are correctly configured and which is not, even in a world-wide scenario.<\/p>\n<p>From that time to today, a lot of things happened. The feature was in preview. The structure of the <strong>ARM<\/strong> template for this feature changed, making the policies I create not work anymore. After a while, Microsoft reverted the changes or something similar and the policies started work again. Now I can publish this new blog post.<\/p>\n<p>The policy from the previous blog post can only to check if the <strong>Azure SQL<\/strong> is using Azure Authentication only or if it is accepting <strong>Azure SQL Authentication<\/strong> as well.<\/p>\n<p>This time, let&#8217;s analyse a policy not only to check, but to change this configuration.<\/p>\n<p>The policy is this one:<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff;overflow: auto;width: auto;border: solid gray;border-width: .1em .1em .1em .8em;padding: .2em .6em\">\n<pre style=\"margin: 0;line-height: 125%\" class=\"crayon:false\">{\r\n   <span style=\"color: #007700\">\"parameters\"<\/span>:{\r\n      \r\n   },\r\n   <span style=\"color: #007700\">\"policyRule\"<\/span>:{\r\n      <span style=\"color: #007700\">\"if\"<\/span>:{\r\n         <span style=\"color: #007700\">\"allOf\"<\/span>:[\r\n            {\r\n               <span style=\"color: #007700\">\"field\"<\/span>:<span style=\"background-color: #fff0f0\">\"type\"<\/span>,\r\n               <span style=\"color: #007700\">\"equals\"<\/span>:<span style=\"background-color: #fff0f0\">\"Microsoft.Sql\/servers\"<\/span>\r\n            }\r\n         ]\r\n      },\r\n      <span style=\"color: #007700\">\"then\"<\/span>:{\r\n         <span style=\"color: #007700\">\"effect\"<\/span>:<span style=\"background-color: #fff0f0\">\"deployIfNotExists\"<\/span>,\r\n         <span style=\"color: #007700\">\"details\"<\/span>:{\r\n            <span style=\"color: #007700\">\"type\"<\/span>:<span style=\"background-color: #fff0f0\">\"Microsoft.Sql\/servers\/azureADOnlyAuthentications\"<\/span>,\r\n            <span style=\"color: #007700\">\"roleDefinitionIds\"<\/span>:[\r\n               <span style=\"background-color: #fff0f0\">\"\/providers\/Microsoft.Authorization\/roleDefinitions\/056cd41c-7e88-42e1-933e-88ba6a50c9c3\"<\/span>,\r\n               <span style=\"background-color: #fff0f0\">\"\/providers\/Microsoft.Authorization\/roleDefinitions\/8e3af657-a8ff-443c-a75c-2fe8c4bcb635\"<\/span>\r\n            ],\r\n            <span style=\"color: #007700\">\"existenceCondition\"<\/span>:{\r\n               <span style=\"color: #007700\">\"allOf\"<\/span>:[\r\n                  {\r\n                     <span style=\"color: #007700\">\"field\"<\/span>:<span style=\"background-color: #fff0f0\">\"Microsoft.Sql\/servers\/azureADOnlyAuthentications\/azureADOnlyAuthentication\"<\/span>,\r\n                     <span style=\"color: #007700\">\"equals\"<\/span>:<span style=\"color: #008800;font-weight: bold\">true<\/span>\r\n                  }\r\n               ]\r\n            },\r\n            <span style=\"color: #007700\">\"deployment\"<\/span>:{\r\n               <span style=\"color: #007700\">\"properties\"<\/span>:{\r\n                  <span style=\"color: #007700\">\"mode\"<\/span>:<span style=\"background-color: #fff0f0\">\"incremental\"<\/span>,\r\n                  <span style=\"color: #007700\">\"name\"<\/span>:<span style=\"background-color: #fff0f0\">\"Default\"<\/span>,\r\n                  <span style=\"color: #007700\">\"template\"<\/span>:{\r\n                     <span style=\"color: #007700\">\"$schema\"<\/span>:<span style=\"background-color: #fff0f0\">\"https:\/\/schema.management.azure.com\/schemas\/2015-01-01\/deploymentTemplate.json#\"<\/span>,\r\n                     <span style=\"color: #007700\">\"contentVersion\"<\/span>:<span style=\"background-color: #fff0f0\">\"1.0.0.0\"<\/span>,\r\n                     <span style=\"color: #007700\">\"parameters\"<\/span>:{\r\n                        <span style=\"color: #007700\">\"fullServerName\"<\/span>:{\r\n                           <span style=\"color: #007700\">\"type\"<\/span>:<span style=\"background-color: #fff0f0\">\"string\"<\/span>\r\n                        }\r\n                     },\r\n                     <span style=\"color: #007700\">\"resources\"<\/span>:[\r\n                        {\r\n                           <span style=\"color: #007700\">\"name\"<\/span>:<span style=\"background-color: #fff0f0\">\"[concat(parameters('fullServerName'), '\/Default')]\"<\/span>,\r\n                           <span style=\"color: #007700\">\"apiVersion\"<\/span>:<span style=\"background-color: #fff0f0\">\"2021-02-01-preview\"<\/span>,\r\n                           <span style=\"color: #007700\">\"type\"<\/span>:<span style=\"background-color: #fff0f0\">\"Microsoft.Sql\/servers\/azureADOnlyAuthentications\"<\/span>,\r\n                           <span style=\"color: #007700\">\"properties\"<\/span>:{\r\n                              <span style=\"color: #007700\">\"azureADOnlyAuthentication\"<\/span>:<span style=\"color: #008800;font-weight: bold\">true<\/span>\r\n                           }\r\n                        }\r\n                     ]\r\n                  },\r\n                  <span style=\"color: #007700\">\"parameters\"<\/span>:{\r\n                     <span style=\"color: #007700\">\"fullServerName\"<\/span>:{\r\n                        <span style=\"color: #007700\">\"value\"<\/span>:<span style=\"background-color: #fff0f0\">\"[field('name')]\"<\/span>\r\n                     }\r\n                  }\r\n               }\r\n            }\r\n         }\r\n      }\r\n   }\r\n}\r\n<\/pre>\n<\/div>\n<p>There are some interesting points to analyse about this policy.<\/p>\n<h2>The Policy Effect: DeployIfNotExist<\/h2>\n<p>It&#8217;s using the effect called <strong>deployIfNotExist<\/strong>, it will generate a deployment in case the condition is not met<\/p>\n<p>There is an existence criteria in the effect and it needs to be met. In this policy most of the checks are in the effect, not in the main If of the policy. The main If is only checking for the type of the object. The additional conditionals are under <strong>existenceCondition<\/strong>, a property of this effect.<\/p>\n<h2>\nThe ExistenceCondition<\/h2>\n<p>The condition checks if\u00a0<strong>Azure SQL Server<\/strong>\u00a0accepts\u00a0<strong>Azure AD Authentication<\/strong>\u00a0only and if not, the effect executes a deployment.<\/p>\n<h2>Deployment<\/h2>\n<p>The <strong>deployment<\/strong> property,\u00a0 another property of the <strong>deployIfNotExist<\/strong> effect, contains an ARM template. The deployment is incremental, this means the policy effect will only deploy the features or properties in the template, nothing else.<\/p>\n<p>This policy is possible because the property to allow only <strong>Azure AD Authentication<\/strong> is in an isolated object, making it easy for a policy to deploy this object.<\/p>\n<p>The object needs to be related to the server, that&#8217;s why the deployment has a parameter called <strong>fullServerName<\/strong> and we use this parameter as the name of the deployed object.<\/p>\n<p>The parameter is filled with the expression <em>[field(&#8216;name&#8217;)]<\/em> . This expression retrieves the name of the object the policy is evaluating, in this case, the <strong>Azure SQL Server<\/strong>.<\/p>\n<h2>\nRole Definitions<\/h2>\n<p>The policy will execute the deployment of the template. Any change in Azure objects,\u00a0in our scenario, Azure SQL Servers, will trigger the policy check.<\/p>\n<p>It&#8217;s not so simple. This triggers many questions.<\/p>\n<ul>\n<li>Which identity will be used to make the deployment?<\/li>\n<li>What permissions this identity has?<\/li>\n<li>Will it be the same identity used everywhere?<\/li>\n<\/ul>\n<p>We create and save the policy in an Azure hierarchy and we can assign it at any level below this hierarchy. Only the policy assignment can trigger the policy execution, if we have no assignment, we have no execution.<\/p>\n<p>During the assignment, we create a link between the policy and one object, which can be a <strong>Resource Group<\/strong>, a <strong>Subscription<\/strong> or a <strong>Management Group<\/strong>. This assignment can, in some cases, also creates a managed identity. The created managed identity will need permission to execute the deployment required by the policy.<\/p>\n<p>The permissions and the management identity creation are related: The management identity will be created when the permissions needed by the managed identity are included in the policy.<\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-92942\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/12\/Policy02.png\" alt=\"\" width=\"930\" height=\"367\" \/><\/p>\n<p>The <strong>roleDefinitionIds<\/strong> property has the permissions for the managed identity on the level of the object assigned to the policy (<strong>Resource Group<\/strong>, <strong>Subscription<\/strong> or <strong>Management Group<\/strong>).<\/p>\n<h2>Remediation Task<\/h2>\n<p>You can force the policy check at any moment using powershell. However, the fix of the problem will only be executed in two situations: Either when the object is created or if we create a <strong>Remediation Task<\/strong>.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-92943\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/12\/Policy03.png\" alt=\"\" width=\"1238\" height=\"138\" \/><\/p>\n<p>Using the policy assignment we can create and execute a remediation task to fix the existing problems, executing the remediation already defined in the policy.<\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-92944\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/12\/Policy04.png\" alt=\"\" width=\"965\" height=\"533\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-92945\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/12\/Policy05.png\" alt=\"\" width=\"816\" height=\"199\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-92946\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/12\/Policy06.png\" alt=\"\" width=\"796\" height=\"179\" \/><\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-92947\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/12\/Policy07.png\" alt=\"\" width=\"1121\" height=\"291\" \/><\/p>\n<h2>Summary<\/h2>\n<p>The possibility to enable only <strong>Azure AD Authentication<\/strong> in <strong>Azure SQL Databases<\/strong> is already great. Adding to this\u00a0 the possibility to enforce this rule in many different levels using the policies is even better.<\/p>\n<p>This policy is not perfect. It will fail if the <strong>Azure SQL Server<\/strong> doesn&#8217;t have an administrator configured. But this blog gives you the overall idea about what&#8217;s possible to achieve.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Some time ago I wrote a blog about the just released feature to allow only Azure Authentication in Azure SQL Databases. &nbsp; On that blog, I explained not only about the feature, but how to use Azure Policies, a great feature for governance, to control which Azure SQL are correctly configured and which is not,&#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,145787,145786,136322],"coauthors":[6810],"class_list":["post-92938","post","type-post","status-publish","format-standard","hentry","category-blogs","tag-azure","tag-azure-ad-authentication","tag-azure-policy","tag-azure-sql"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/92938","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=92938"}],"version-history":[{"count":12,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/92938\/revisions"}],"predecessor-version":[{"id":93010,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/92938\/revisions\/93010"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=92938"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=92938"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=92938"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=92938"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}