<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>David Barbarin &#187; Azure Monitor</title>
	<atom:link href="https://blog.developpez.com/mikedavem/ptag/azure-monitor/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/mikedavem</link>
	<description>MVP DataPlatform - MCM SQL Server</description>
	<lastBuildDate>Thu, 09 Sep 2021 21:19:50 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>Azure monitor as observability platform for Azure SQL Databases and more</title>
		<link>https://blog.developpez.com/mikedavem/p13205/sql-azure/azure-monitor-as-observability-platform-for-azure-sql-databases</link>
		<comments>https://blog.developpez.com/mikedavem/p13205/sql-azure/azure-monitor-as-observability-platform-for-azure-sql-databases#comments</comments>
		<pubDate>Mon, 08 Feb 2021 16:57:26 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[DevOps]]></category>
		<category><![CDATA[SQL Azure]]></category>
		<category><![CDATA[Azure Monitor]]></category>
		<category><![CDATA[Azure SQL Analytics]]></category>
		<category><![CDATA[Azure SQL Database]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[Log Analytics]]></category>
		<category><![CDATA[observability]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1762</guid>
		<description><![CDATA[In a previous blog post, I wrote about reasons we moved our monitoring of on-prem SQL Server instances on Prometheus and Grafana. But what about Cloud and database services? We have different options and obviously in my company we thought &#8230; <a href="https://blog.developpez.com/mikedavem/p13205/sql-azure/azure-monitor-as-observability-platform-for-azure-sql-databases">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>In a previous <a href="https://blog.developpez.com/mikedavem/p13203/sql-server-2014/why-we-moved-sql-server-monitoring-on-prometheus-and-grafana" rel="noopener" target="_blank">blog post</a>, I wrote about reasons we moved our monitoring of on-prem SQL Server instances on Prometheus and Grafana. But what about Cloud and database services? </p>
<p><span id="more-1762"></span></p>
<p>We have different options and obviously in my company we thought first moving our Azure SQL Database workload telemetry on on-prem central monitoring infrastructure as well. But not to mention the main blocker which is the serverless compute tier because Telegraf Server agent would imply initiating a connection that could prevent auto-pausing the database or at least it would made monitoring more complex because it would supposed to have a predictable workload all the time. </p>
<p>The second option was to rely on Azure monitor which is a common platform for combining several logging, monitoring and dashboard solutions across a wide set of Azure resources. It is scalable platform, fully managed and provides a powerful query language and native features like alerts, if logs or metrics match specific conditions. Another important point is there is no vendor lock-in, with this solution, as we can always fallback to our self-hosted Prometheus and Grafana instances if neither computer tier doesn’t fit nor in case Azure Monitor might not be an option anymore! </p>
<p>Firstly, to achieve a good observability with Azure SQL Database we need to put both diagnostic telemetry and SQL Server audits events in a common Log Analytics workspace. A quick illustration below: </p>
<p><a href="http://blog.developpez.com/mikedavem/files/2021/02/173-0-Azure-SQL-DB-Monitor-architecture.jpg"><img src="http://blog.developpez.com/mikedavem/files/2021/02/173-0-Azure-SQL-DB-Monitor-architecture-1024x387.jpg" alt="173 - 0 - Azure SQL DB Monitor architecture" width="584" height="221" class="alignnone size-large wp-image-1763" /></a></p>
<p>Diagnostic settings are configured per database and including basic metrics (CPU, IO, Memory etc …) and also different SQL Server internal metrics as deadlock, blocked processes or query store information about query execution statistic and waits etc&#8230; For more details please refer to the Microsoft <a href="https://docs.microsoft.com/en-us/azure/azure-sql/database/metrics-diagnostic-telemetry-logging-streaming-export-configure?tabs=azure-portal" rel="noopener" target="_blank">BOL</a>.</p>
<p>SQL Azure DB auditing is both server-level or database-level configuration setting. In our context, we defined a template of events at the server level which is then applied to all databases within the logical server. By default, 3 events are automatically audited:<br />
&#8211;	BATCH_COMPLETED_GROUP<br />
&#8211;	SUCCESSFUL_DATABASE_AUTHENTICATION_GROUP<br />
&#8211;	FAILED_DATABASE_AUTHENTICATION_GROUP</p>
<p>The first one of the list is probably to be discussed according to the environment because of its impact but in our context that&rsquo;s ok because we faced a data warehouse workload. However we added other ones to meet our security requirements:<br />
&#8211;	PERMISSION_CHANGE_GROUP<br />
&#8211;	DATABASE_PRINCIPAL_CHANGE_GROUP<br />
&#8211;	DATABASE_ROLE_MEMBER_CHANGE_GROUP<br />
&#8211;	USER_CHANGE_PASSWORD_GROUP</p>
<p>But if you take care about Log Analytics as target for SQL audits, you will notice it is still a feature in preview as shown below:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2021/02/173-4-Audit-target.jpg"><img src="http://blog.developpez.com/mikedavem/files/2021/02/173-4-Audit-target.jpg" alt="173 - 4 - Audit target" width="484" height="153" class="alignnone size-full wp-image-1765" /></a></p>
<p>To be clear, usually we don’t consider using Azure preview features in production especially when they remain in this state for a long time but in this specific context we got interested by observability capabilities of the platform. From one hand, we get very useful performance insights through SQL Analytics dashboards (again in preview) and from the other hand we can easily query logs and traces through Log Analytics for correlation with other metrics. Obviously, we hope Microsoft moving a step further and providing this feature in GA in the near feature. </p>
<p>Let’s talk briefly of SQL Analytics first. It is an advanced and free cloud monitoring solution for Azure SQL database monitoring performance and it relies mainly on your Azure Diagnostic metrics and Azure Monitor views to present data in a structured way through performance dashboard.</p>
<p>Here an example of built-in dashboards we are using to track activity and high CPU / IO bound queries against our data warehouse.</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2021/02/173-1-SQL-Analytics-general-dashboard-e1612797920282.jpg"><img src="http://blog.developpez.com/mikedavem/files/2021/02/173-1-SQL-Analytics-general-dashboard-1024x410.jpg" alt="173 - 1 - SQL Analytics general dashboard" width="584" height="234" class="alignnone size-large wp-image-1768" /></a></p>
<p>You can use drill-down capabilities to different contextual dashboards to get insights of resource intensive queries. For example, we identified some LOG IO intensive queries against a clustered columnstore index and after some refactoring of UPDATE statement to DELETE + INSERT we reduced drastically LOG IO waits.</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2021/02/173-2-SQL-Analytics-IO-e1612797960660.jpg"><img src="http://blog.developpez.com/mikedavem/files/2021/02/173-2-SQL-Analytics-IO-1024x316.jpg" alt="173 - 2 - SQL Analytics IO" width="584" height="180" class="alignnone size-large wp-image-1767" /></a></p>
<p>In addition, Azure monitor helped us in an another scenario where we tried to figure out recent workload patterns and to know if the current compute tier still fits with it. As said previously, we are relying on Serverless compute tier to handle the data warehouse-oriented workload with both auto-scaling and auto-pausing capabilities. At the first glance, we might expect a typical nightly workload as illustrated to Microsoft <a href="https://docs.microsoft.com/en-us/azure/azure-sql/database/serverless-tier-overview#:~:text=Serverless%20is%20a%20compute%20tier,of%20compute%20used%20per%20second." rel="noopener" target="_blank">BOL</a> and a cost optimized to this workload:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2021/02/173-6-Serverless-pattern.jpg"><img src="http://blog.developpez.com/mikedavem/files/2021/02/173-6-Serverless-pattern.jpg" alt="173 - 6 - Serverless pattern" width="516" height="316" class="alignnone size-full wp-image-1769" /></a></p>
<p><em>Images from Microsoft BOL</em></p>
<p>It could have been true when the activity started on Azure, but the game has changed with new incoming projects over the time. Starting with the general performance dashboard, the workload seems to follow the right pattern for Serverless compute tier, but we noticed billing keep going during unexpected timeframe as shown below. Let’s precise that I put deliberately only a sample of two days, but this pattern is a good representation of the general workload in our context. </p>
<p><a href="http://blog.developpez.com/mikedavem/files/2021/02/173-3-General-performance-dashboard.jpg"><img src="http://blog.developpez.com/mikedavem/files/2021/02/173-3-General-performance-dashboard-1024x556.jpg" alt="173 - 3 - General performance dashboard" width="584" height="317" class="alignnone size-large wp-image-1771" /></a></p>
<p>Indeed, workload should be mostly nightly-oriented with sporadic activity during the day but quick correlation with other basic metrics like CPU or Memory percentage usage confirmed a persistent activity all day. We have CPU spikes and probably small batches that keep minimum memory around at other moments. </p>
<p>As per the <a href="https://docs.microsoft.com/en-us/azure/azure-sql/database/serverless-tier-overview#:~:text=Serverless%20is%20a%20compute%20tier,of%20compute%20used%20per%20second." rel="noopener" target="_blank">Microsoft documentation</a>, the minimum auto-pausing  delay value is 1h and requires an inactive database (number of sessions = 0 and CPU = 0 for user workload) during this timeframe. Basic metrics didn’t provide any further insights about connections, applications or users that could generate such &laquo;&nbsp;noisy&nbsp;&raquo; activity, so we had to go another way by looking at the SQL Audit logs stored in Azure Monitor Logs. Data can be read through KQL which stands for Kusto Query Language (and not Kibana Query Language <img src="https://blog.developpez.com/mikedavem/wp-includes/images/smilies/icon_smile.gif" alt=":-)" class="wp-smiley" /> ). It’s the language used to query the Azure log databases: Azure Monitor Logs, Azure Monitor Application Insights and others and it is pretty similar to SQL language in the construct. </p>
<p>Here the first query I used to correlate number of events with metrics and that could prevent auto-pausing to kick in for the concerned database including RPC COMPLETED, BATCH COMPLETED, DATABASE AUTHENTICATION SUCCEEDED or DATABASE AUTHENTICATION FAILED</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">AzureDiagnostics<br />
| where Category == 'SQLSecurityAuditEvents' and (action_name_s in ('RPC COMPLETED','BATCH COMPLETED') or action_name_s contains &quot;DATABASE AUTHENTICATION&quot;) &nbsp;and LogicalServerName_s == 'xxxx' and database_name_s == xxxx<br />
| summarize count() by bin(event_time_t, 1h),action_name_s<br />
| render columnchart</div></div>
<p>Results are aggregated and bucketized per hour on generated time event with bin() function. Finally, for a quick and easy read, I choosed a simple and unformatted column chart render. Here the outcome:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2021/02/173-7-Audit-per-hour-per-event-e1612798279257.jpg"><img src="http://blog.developpez.com/mikedavem/files/2021/02/173-7-Audit-per-hour-per-event-1024x459.jpg" alt="173 - 7 - Audit per hour per event" width="584" height="262" class="alignnone size-large wp-image-1772" /></a></p>
<p>As you probably noticed, daily activity is pretty small compared to nightly one and seems to confirm SQL batches and remote procedure calls. From this unclear picture, we can confirm anyway the daily workload is enough to keep the billing going because there is no per hour timeframe where there is no activity. </p>
<p>Let’s write another KQL query to draw a clearer picture of which applications ran during the a daily timeframe 07:00 – 20:00:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">let start=datetime(&quot;2021-01-26&quot;);<br />
let end=datetime(&quot;2021-01-29&quot;);<br />
let dailystart=7;<br />
let dailyend=20;<br />
let timegrain=1d;<br />
AzureDiagnostics<br />
| project &nbsp;action_name_s, event_time_t, application_name_s, server_principal_name_s, Category, LogicalServerName_s, database_name_s<br />
| where Category == 'SQLSecurityAuditEvents' and (action_name_s in ('RPC COMPLETED','BATCH COMPLETED') or action_name_s contains &quot;DATABASE AUTHENTICATION&quot;) &nbsp;<br />
| where LogicalServerName_s == 'xxxx' and database_name_s == 'xxxx' <br />
| where event_time_t &amp;gt; start and event_time_t &amp;lt; end<br />
| where datetime_part(&amp;quot;Hour&amp;quot;,event_time_t) between (dailystart .. dailyend)<br />
| summarize count() by bin(event_time_t, 1h), application_name_s<br />
| render columnchart with (xtitle = &amp;#039;Date&amp;#039;, ytitle = &amp;#039;Nb events&amp;#039;, title = &amp;#039;Prod SQL Workload pattern&amp;#039;)</div></div>
<p>And here the new outcome:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2021/02/173-8-Audit-per-hour-per-application.jpg"><img src="http://blog.developpez.com/mikedavem/files/2021/02/173-8-Audit-per-hour-per-application-1024x380.jpg" alt="173 - 8 - Audit per hour per application" width="584" height="217" class="alignnone size-large wp-image-1774" /></a></p>
<p>The new chart reveals some activities from SQL Server Management Studio but most part concerns applications with .Net SQL Data Provider. For a better clarity, we need more information related about applications and, in my context, I managed to address the point by reducing the search scope with the service principal name that issued the related audit event. It results to this new outcome that is pretty similar to previous one:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2021/02/173-9-Audit-per-hour-per-sp.jpg"><img src="http://blog.developpez.com/mikedavem/files/2021/02/173-9-Audit-per-hour-per-sp-1024x362.jpg" alt="173 - 9 - Audit per hour per sp" width="584" height="206" class="alignnone size-large wp-image-1775" /></a></p>
<p>Good job so far. For a sake of clarity, the service principal obfuscated above is used by our Reporting Server infrastructure and reports to get data from this data warehouse.  By going this way to investigate daily activity at different moments on the concerned Azure SQL database, we came to the conclusion that using Serverless computer tier didn’t make sense anymore and we need to upgrade likely to another computer tier.</p>
<p><strong>Additional thoughts</strong></p>
<p>Azure monitor is definitely a must to have if you are running resources on Azure and if you don’t own a platform for observability (metrics, logs and traces). Otherwise, it can be even beneficial for freeing up your on-prem monitoring infrastructure resources if scalability is a concern. Furthermore, there is no vendor-locking and you can decide to stream Azure monitor data outside in another place but at the cost of additional network transfer fees according to the target scenario. For example, Azure monitor can be used directly as datasource with Grafana. Azure SQL telemetry can be collected with Telegraf agent whereas audit logs can be recorded in another logging system like Kibana. In this blog post, we just surfaced the Azure monitor capabilities but, as demonstrated above, performing deep analysis correlations from different sources in a very few steps is a good point of this platform.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Monitoring Azure SQL Databases with Azure Monitor and Automation</title>
		<link>https://blog.developpez.com/mikedavem/p13198/sql-server-2012/monitoring-azure-sql-databases-with-azure-monitor-and-automation</link>
		<comments>https://blog.developpez.com/mikedavem/p13198/sql-server-2012/monitoring-azure-sql-databases-with-azure-monitor-and-automation#comments</comments>
		<pubDate>Sun, 23 Aug 2020 15:32:07 +0000</pubDate>
		<dc:creator><![CDATA[mikedavem]]></dc:creator>
				<category><![CDATA[SQL Azure]]></category>
		<category><![CDATA[SQL Server 2012]]></category>
		<category><![CDATA[Azure]]></category>
		<category><![CDATA[Azure Alerts]]></category>
		<category><![CDATA[Azure Monitor]]></category>
		<category><![CDATA[Azure SQL Database]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[monitoring]]></category>
		<category><![CDATA[SQL Server]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/mikedavem/?p=1653</guid>
		<description><![CDATA[Supervising Cloud Infrastructure is an important aspect of Cloud administration and Azure SQL Databases are no exception. This is something we are continuously improving at my company. On-prem, DBAs often rely on well-established products but with Cloud-based architectures, often implemented &#8230; <a href="https://blog.developpez.com/mikedavem/p13198/sql-server-2012/monitoring-azure-sql-databases-with-azure-monitor-and-automation">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Supervising Cloud Infrastructure is an important aspect of Cloud administration and Azure SQL Databases are no exception. This is something we are continuously improving at my company. </p>
<p>On-prem, DBAs often rely on well-established products but with Cloud-based architectures, often implemented through DevOps projects and developers, monitoring should be been redefined and include some new topics as:</p>
<p><span id="more-1653"></span></p>
<p>1)	Cloud service usage and fees observability<br />
2)	Metrics and events detection that could affect bottom line<br />
3)	Implementing a single platform to report all data that comes from different sources<br />
4)	Trigger rules with data if workload reaches over or drops below certain levels or when an event is enough relevant to not meet the configuration standard and implies unwanted extra billing or when it compromises the company security rules.<br />
5)	Monitoring of the user experience</p>
<p>A key benefit often discussed about Cloud computing, and mainly driven by DevOps, is how it enables agility. One of the meaning of term agility is tied to the rapid provisioning of computer resources (in seconds or minutes) and this shortening provisioning path enables work to start quickly. You may be tempted to grant some provisioning permissions to DEV teams and from my opinion this is not a bad thing, but it may come with some drawbacks if not under control by Ops team including database area. Indeed, for example I have in mind some real cases including architecture configuration drift, security breaches created by unwanted item changes, or idle orphan resources for which you keep being charged. All of these scenarios may lead either to security issues or extra billing and I believe it is important to get clear visibility of such events. </p>
<p>In my company, Azure built-in capabilities with Azure Monitor architecture are our first target (at least in a first stage) and seem to address the aforementioned topics. To set the context, we already relied on Azure Monitor infrastructure for different things including Query Performance Insight, SQL Audit analysis through Log Analytics and Azure alerts for some performance metrics. Therefore, it was the obvious way to go further by adding activity log events to the story. </p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/08/165-1-Azure-Monitor.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/08/165-1-Azure-Monitor.jpg" alt="165 - 1 - Azure Monitor" width="843" height="474" class="alignnone size-full wp-image-1655" /></a></p>
<p>In this blog post, let’s focus on the items 2) 4). I would like to share some experimentations and thoughts about them. As a reminder, items 2) 4) are about catching relevant events to help identifying configuration and security drifts and performing actions accordingly. In addition, as many event-based architectures, additional events may appear or evolve over the time and we started thinking about the concept with the following basic diagram …</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/08/165-2-Workflow-chart-e1598182358607.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/08/165-2-Workflow-chart-e1598182358607.jpg" alt="165 - 2 - Workflow chart" width="800" height="533" class="alignnone size-full wp-image-1657" /></a></p>
<p>… that led to the creation of the two following workflows:<br />
&#8211;	Workflow 1: To get notified immediately for critical events that may compromise security or lead immediately to important extra billing<br />
&#8211;	Workflow 2: To get a report of other misconfigured items (including critical ones) on schedule basis but don’t require quick responsiveness of Ops team.</p>
<p>Concerning the first workflow, using <a href="https://docs.microsoft.com/en-us/azure/azure-monitor/platform/activity-log-alerts" rel="noopener" target="_blank">alerts on activity logs</a>, action groups and webhooks as input of an Azure automation runbook appeared to be a good solution. On another side, the second one only requires running an Azure automation workbook on schedule basis. In fact, this is the same runbook but with different input parameters according to the targeted environment (e.g. PROD / ACC / INT). In addition, the runbook should be able to identity unmanaged events and notified Ops team who will decide either to skip it or to integrate it to runbook processing.</p>
<p>Azure alerts which can be divided in different categories including metric, log alerts and activity log alerts. The last one drew our attention because it allows getting notified for operation of specific resources by email or by generating JSON schema reusable from Azure Automation runbook. Focusing on the latter, we had come up (I believe) with what we thought was a reasonable solution. </p>
<p>Here the high-level picture of the architecture we have implemented:</p>
<p><a href="http://blog.developpez.com/mikedavem/files/2020/08/165-3-Architecture-e1598182462929.jpg"><img src="http://blog.developpez.com/mikedavem/files/2020/08/165-3-Architecture-e1598182462929.jpg" alt="165 - 3 - Architecture" width="800" height="347" class="alignnone size-full wp-image-1659" /></a></p>
<p>1-	During the creation of an Azure SQL Server or a database, corresponding alerts are added with Administrative category with a specific scope. Let&rsquo;s precise that concerned operations must be registered with Azure Resource Manager in order to be used in Activity Log and fortunately they are all including in the <a href="https://docs.microsoft.com/en-us/azure/role-based-access-control/resource-provider-operations" rel="noopener" target="_blank">Microsoft.Sql</a> resource provider in this case.<br />
2-	When an event occurs on the targeted environment, an alert is triggered as well as the concerned runbook.<br />
3-	The execution of the same runbook but with different input parameters is scheduled on weekly basis to a general configuration report of our Azure SQL environments.<br />
4-	According the event, Ops team gets notified and acts (either to update misconfigured item, or to delete the unauthorized item, or to update runbook code on Git Repo to handle the new event and so on …)</p>
<p>The skeleton of the Azure automation runbook is pretty similar to the following one:</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:650px;height:450px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">[OutputType(&quot;PSAzureOperationResponse&quot;)]<br />
param<br />
(<br />
&nbsp; &nbsp; [Parameter (Mandatory=$false)]<br />
&nbsp; &nbsp; [object] $WebhookData<br />
&nbsp; &nbsp; ,<br />
&nbsp; &nbsp; [parameter(Mandatory=$False)]<br />
&nbsp; &nbsp; [ValidateSet(&quot;PROD&quot;,&quot;ACC&quot;,&quot;INT&quot;)]<br />
&nbsp; &nbsp; [String]$EnvTarget<br />
&nbsp; &nbsp; ,<br />
&nbsp; &nbsp; [parameter(Mandatory=$False)]<br />
&nbsp; &nbsp; [Boolean]$DebugMode = $False<br />
)<br />
<br />
<br />
<br />
<br />
If ($WebhookData)<br />
{<br />
<br />
&nbsp; &nbsp; # Logic to allow for testing in test pane<br />
&nbsp; &nbsp; If (-Not $WebhookData.RequestBody){<br />
&nbsp; &nbsp; &nbsp; &nbsp; $WebhookData = (ConvertFrom-Json -InputObject $WebhookData)<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; $WebhookBody = (ConvertFrom-Json -InputObject $WebhookData.RequestBody)<br />
<br />
&nbsp; &nbsp; $schemaId = $WebhookBody.schemaId<br />
<br />
&nbsp; &nbsp; If ($schemaId -eq &quot;azureMonitorCommonAlertSchema&quot;) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; # This is the common Metric Alert schema (released March 2019)<br />
&nbsp; &nbsp; &nbsp; &nbsp; $Essentials = [object] ($WebhookBody.data).essentials<br />
&nbsp; &nbsp; &nbsp; &nbsp; # Get the first target only as this script doesn't handle multiple<br />
&nbsp; &nbsp; &nbsp; &nbsp; $status = $Essentials.monitorCondition<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; # Focus only on succeeded or Fired Events<br />
&nbsp; &nbsp; &nbsp; &nbsp; If ($status -eq &quot;Succeeded&quot; -Or $Status -eq &quot;Fired&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Extract info from webook <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $alertTargetIdArray = (($Essentials.alertTargetIds)[0]).Split(&quot;/&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $SubId = ($alertTargetIdArray)[2]<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $ResourceGroupName = ($alertTargetIdArray)[4]<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $ResourceType = ($alertTargetIdArray)[6] + &quot;/&quot; + ($alertTargetIdArray)[7]<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Determine code path depending on the resourceType<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if ($ResourceType -eq &quot;microsoft.sql/servers&quot;)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # DEBUG<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;This is a SQL Server Resource.&quot;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $firedDate = $Essentials.firedDateTime<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $AlertContext = [object] ($WebhookBody.data).alertContext<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $channel = $AlertContext.channels<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $EventSource = $AlertContext.eventSource<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $Level = $AlertContext.level<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $Operation = $AlertContext.operationName<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $Properties = [object] ($WebhookBody.data).alertContext.properties<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $EventName = $Properties.eventName<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $EventStatus = $Properties.status<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $Description = $Properties.description_scrubbed<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $Caller = $Properties.caller<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $IPAddress = $Properties.ipAddress<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $ResourceName = ($alertTargetIdArray)[8]<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $DatabaseName = ($alertTargetIdArray)[10]<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $Operation_detail = $Operation.Split('/')<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Check firewall rules<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; If ($EventName -eq 'OverwriteFirewallRules'){<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;Firewall Overwrite is detected ...&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Code to handle firewall update event<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Update DB =&amp;gt; No need to be monitored in real time<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Elseif ($EventName -eq 'UpdateDatabase') {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Code to handle Database config update event or skip <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Create DB<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Elseif ($EventName -eq 'CreateDatabase' -Or `<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $Operation -eq 'Microsoft.Sql/servers/databases/write'){<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;Azure Database creation has been detected ...&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Code to handle Database creation event or skip <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Delete DB<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Elseif ($EventName -eq 'DeleteDatabase' -Or `<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $Operation -eq 'Microsoft.Sql/servers/databases/delete') {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;Azure Database has been deleted ...&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Code to handle Database deletion event or skip <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Elseif ($Operation -eq 'Microsoft.Sql/servers/databases/transparentDataEncryption/write') {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;Azure Database Encryption update has been detected ...&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Code to handle Database encryption update event or skip <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Elseif ($Operation -eq 'Microsoft.Sql/servers/databases/auditingSettings/write') {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;Azure Database Audit update has been detected ...&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Code to handle Database audit update event or skip <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Elseif ($Operation -eq 'Microsoft.Sql/servers/databases/securityAlertPolicies/write' -or $Operation -eq 'Microsoft.Sql/servers/databases/vulnerabilityAssessments/write') {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;Azure ADS update has been detected ...&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Code to handle ADS update event or skip <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ElseIf ($Operation -eq 'Microsoft.Sql/servers/databases/backupShortTermRetentionPolicies/write'){<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;Azure Retention Backup has been modified ...&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # Code to handle Database retention backup update event or skip <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # ... other ones <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Else {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Output &quot;Event not managed yet &nbsp; &nbsp;&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # ResourceType not supported<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Error &quot;$ResourceType is not a supported resource type for this runbook.&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; Else {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; # The alert status was not 'Activated' or 'Fired' so no action taken<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Write-Verbose (&quot;No action taken. Alert status: &quot; + $status) -Verbose<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; Else{<br />
&nbsp; &nbsp; &nbsp; &nbsp;# SchemaID doesn't correspond to azureMonitorCommonAlertSchema =&amp;gt;&amp;gt; Skip<br />
&nbsp; &nbsp; &nbsp; &nbsp;Write-Host &quot;Skip ...&quot; <br />
&nbsp; &nbsp; }<br />
}<br />
Else {<br />
&nbsp; &nbsp; Write-Output &quot;No Webhook detected ... switch to normal mode ...&quot;<br />
<br />
&nbsp; &nbsp; If ([String]::IsNullOrEmpty($EnvTarget)){<br />
&nbsp; &nbsp; &nbsp; &nbsp; Write-Error '$EnvTarget is mandatory in normal mode'<br />
&nbsp; &nbsp; }<br />
<br />
&nbsp; &nbsp; #########################################################<br />
&nbsp; &nbsp; # Code for a complete check of Azure SQL DB environment #<br />
&nbsp; &nbsp; #########################################################<br />
}</div></div>
<p>Some comments about the PowerShell script:</p>
<p>1)	Input parameters should include either the Webhook data or specific parameter values for a complete Azure SQL DB check.<br />
2)	The first section should include your own functions to respond to different events. In our context, currently we drew on <a href="https://github.com/sqlcollaborative/dbachecks" rel="noopener" target="_blank">DBAChecks</a> thinking to develop a derived model but why not using directly DBAChecks in a near future?<br />
3)	When an event is triggered, a JSON schema is generated and provides insight. The point here is you must navigate through different properties according to the operation type (cf. <a href="https://docs.microsoft.com/en-us/azure/azure-monitor/platform/activity-log-schema" rel="noopener" target="_blank">BOL</a>).<br />
4)	The increase of events to manage could be a potential issue making the runbook fat especially if we keep both the core functions and event processing. To mitigate this topic, we are thinking to move functions into modules in Azure automation (next step).</p>
<p><strong>Bottom line</strong></p>
<p>Thanks to Azure built-in capabilities we improved our visibility of events that occur on the Azure SQL environment (both expected and unexcepted) and we’re now able to act accordingly. But I should tell you that going this way is not a free lunch and we achieved a reasonable solution after some programming and testing efforts. If you can invest time, it is probably the kind of solution you can add to your study.</p>
<p>See you</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
