{"id":73,"date":"2022-12-23T14:49:54","date_gmt":"2022-12-23T14:49:54","guid":{"rendered":"https:\/\/mortenknudsen.net\/?p=73"},"modified":"2023-04-10T11:35:25","modified_gmt":"2023-04-10T10:35:25","slug":"data-transformation-in-azure-loganalytics","status":"publish","type":"post","link":"https:\/\/mortenknudsen.net\/?p=73","title":{"rendered":"How to do data transformation with Azure LogAnalytics &#8211; to enrich information, optimize cost, remove sensitive data?"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">One of the cool features in Azure LogAnalytics is the capability to do <strong>data-transformation before the data enters your LogAnalytics workspaces<\/strong>. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you want to see my latest blog-series of articles about &#8216;mastering Azure logging&#8217;, please <a href=\"https:\/\/mortenknudsen.net\/?p=1687\" target=\"_blank\" rel=\"noreferrer noopener\">check the overview here<\/a> <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you want to see my latest tutorial on setting up data transformation, <a href=\"https:\/\/mortenknudsen.net\/?p=1440\" target=\"_blank\" rel=\"noreferrer noopener\">please check it out here<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I use this feature to normalize data and enrich data for Microsoft Sentinel environments and optimize costs by removing &#8220;noise&#8221; in logs. I have also used it to temporary stop millions of unnecessary log events caused by application errors or misconfigurations. Then I could investigate and fix the root cause of the issue.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To summarize, this feature can help your with:<\/p>\n\n\n\n<figure class=\"wp-block-table has-small-font-size\"><table><tbody><tr><td><strong>Category<\/strong><\/td><td><strong>Details<\/strong><\/td><\/tr><tr><td>Remove sensitive data<\/td><td>You may have a data source that sends information you don&#8217;t want stored for privacy or compliancy reasons.<br><br><strong>Filter sensitive information.<\/strong>&nbsp;Filter out entire rows or just particular columns that contain sensitive information.<br><br><strong>Obfuscate sensitive information<\/strong>. For example, you might replace digits with a common character in an IP address or telephone number.<\/td><\/tr><tr><td>Enrich data with additional or calculated information<\/td><td>Use a transformation to add information to data that provides business context or simplifies querying the data later.<br><br><strong>Add a column with additional information.<\/strong>&nbsp;For example, you might add a column identifying whether an IP address in another column is internal or external.<br><br><strong>Add business specific information.<\/strong>&nbsp;For example, you might add a column indicating a company division based on location information in other columns.<\/td><\/tr><tr><td>Reduce data costs<\/td><td>Since you&#8217;re charged ingestion cost for any data sent to a Log Analytics workspace, you want to filter out any data that you don&#8217;t require to reduce your costs.<br><br><strong>Remove entire rows.<\/strong>&nbsp;For example, you might have a diagnostic setting to collect resource logs from a particular resource but not require all of the log entries that it generates. Create a transformation that filters out records that match a certain criteria.<br><br><strong>Remove a column from each row.<\/strong>&nbsp;For example, your data may include columns with data that&#8217;s redundant or has minimal value. Create a transformation that filters out columns that aren&#8217;t required.<br><br><strong>Parse important data from a column.<\/strong>&nbsp;You may have a table with valuable data buried in a particular column. Use a transformation to parse the valuable data into a new column and remove the original. &nbsp; Examples of where data-transformation is useful: We want to remove specific security-events from a server, which are making lots of \u201dnoise\u201d in our logs due to a misconfiguration or error and it is impossible to fix itWe want to remove security events, which we might show with a high amount, but we want to filter it out like kerberos computer-logon traffic.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<figure class=\"wp-block-table has-medium-font-size\"><table class=\"has-luminous-vivid-orange-to-vivid-red-gradient-background has-background\"><tbody><tr><td><strong>Disclaimer about security &amp; data-transformation<\/strong> <br>From a security hunting perspective, it is important to note, that you should be very careful with this, as you might remove data which will make security hunting harder \u2013 or even impossible if vital data is removed or table structure is altered. <br><br>Please do proper testing and be aware of the consequences.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Supported ways of doing data-transformation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Currently, there are support for doing data-transformation using 4 methods:<\/p>\n\n\n\n<ol class=\"wp-block-list\" type=\"1\">\n<li>XPath filtering using Azure Monitor Agent<\/li>\n\n\n\n<li>Azure Monitor Agent (AMA) using TransformKql in Data Collection Rule (DCR)<\/li>\n\n\n\n<li>Custom application sending data using logs ingestion API via DCR<\/li>\n\n\n\n<li>Workspace transformation DCR<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">This blog will go deep-dive on method 2; \u2019Azure Monitor Agent (AMA) using TransformKql in Data Collection Rule (DCR)\u2019. I will make another post on method 4 soon.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Before going into configurering data-transformation, I want to touch on the \u201dold\u201d method using XPath (XML Path Language).<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-large-font-size\"><strong>Transformation using XPath<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Since AMA was launched in June 2021, it has supported doing transformation with XPath. This methods works fine and has helped my customers to save money.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Microsoft asked me to provide a statement about this in the officiel go-live announcement, when Azure Monitor Agent went GA in June 2021 (<a href=\"https:\/\/techcommunity.microsoft.com\/t5\/azure-observability-blog\/a-powerful-agent-for-azure-monitor-and-a-simpler-world-of-data\/ba-p\/2443285\">https:\/\/techcommunity.microsoft.com\/t5\/azure-observability-blog\/a-powerful-agent-for-azure-monitor-and-a-simpler-world-of-data\/ba-p\/2443285<\/a>).<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">Here is an example of using XPath where I am collecting all security events, excluding any computer-related security-events like Computer Kerberos logon-traffic<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\"Security!*&#91;System&#91;(band(Keywords,13510798882111488))]] and *&#91;(EventData&#91;Data&#91;@Name='TargetUserName'] != 'EXCHANGE01$']) and (EventData&#91;Data&#91;@Name='TargetUserName'] != 'EXCHANGE02$']) and (EventData&#91;Data&#91;@Name='TargetUserName'] != 'EXCHANGE03$']) and (EventData&#91;Data&#91;@Name='TargetUserName'] != 'EXCHANGE04$']) and (EventData&#91;Data&#91;@Name='TargetUserName'] != 'EXCHANGE05$']) ]\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">AMA is still supporting XPath, but I recommend to use data transformation using DCR-rules, as it solves some of the limitations in the XPath implementation in AMA. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">XPath is a standard, currently at 3.1 (2017), but Microsoft chose to implement XPath v1 in AMA from 1999. V1 doesn\u2019t support filtering with <strong>like<\/strong> or <strong>contains<\/strong>. Therefore it is hard to scale using xpath v1, if you need advanced features. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the sample above, I had to explicitly define the server-names where I wanted to remove computer-related security events.<\/p>\n\n\n\n<h2 class=\"wp-block-heading has-large-font-size\">How does transformation work using AMA &amp; DCR ?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The main difference between XPath and data-transformation using DCR is where it runs, as XPath filtering is done on the endpoint, whereas data-transformation using a DCR runs in the Azure backend in a dedicated pipeline per DCR &#8211; being applied on each row of data coming in &#8211; before data is sent into Loganalytics.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"999\" height=\"385\" src=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/transformation-azure-monitor-agent.png\" alt=\"\" class=\"wp-image-74\" srcset=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/transformation-azure-monitor-agent.png 999w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/transformation-azure-monitor-agent-300x116.png 300w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/transformation-azure-monitor-agent-768x296.png 768w\" sizes=\"auto, (max-width: 999px) 100vw, 999px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Before going into the details on how to create a data-transformation in data collection rules, we will recap the principles about Data Collection Rules (DCRs) and data transformations.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><em>Any resource using AMA is always collecting the union of all DCRs.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>This way multiple teams \/ roles can enable what they need, without impacting other teams. If Microsoft switched the behavior, one team could disable other collection by accident.<\/em><em>&nbsp;<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Therefore a transformation will only impact that particular workspace where the transformation applies.<\/em><\/p>\n<cite>If you &#8211; by mistake &#8211; have 2 DCRs for SecurityEvent collection and use one of them for transformation, then you will end up having double of the events (except for the filtered away events). <\/cite><\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">As mentioned earlier, AMA will union all DCRs, so it is important, that you have a good overview of the current associated DCRs associated with the endpoints. Which data is being collected into which tables ? <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Implementation of Data Collection using Data Collection Rules (DCRs)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This blog will not go into details on how to configure a data collection rule, but for reading purpose I will touch on this high-level.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Normally, I\u2019m configuring a set of default DCRs that are being applied to all servers, both native Azure VMs and Azure Arc-enabled servers \u2013 for example:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Collection of VMInsights (using Dependency Agent with AMA-support)<\/li>\n\n\n\n<li>Collection of System and Application event log<\/li>\n\n\n\n<li>Collection of Security event log<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"451\" height=\"121\" src=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/dcr.jpg\" alt=\"\" class=\"wp-image-75\" srcset=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/dcr.jpg 451w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/dcr-300x80.jpg 300w\" sizes=\"auto, (max-width: 451px) 100vw, 451px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Targeting your DCRs<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After defining the DCRs, you need to associate the DCRs to your resources. This can be done in multiple ways:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Azure Policy and Tags \u2013 for example defining a tag. <\/li>\n\n\n\n<li>Scripts \u2013 for example using Powershell \u2019New-AzDataCollectionRuleAssociation\u2019<\/li>\n\n\n\n<li>Terraform<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Pick your choice depending on how you want to do this \ud83d\ude0a<\/p>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>How to transform your data using TransformKql in a DCR using AMA<\/strong><\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The process to create a separate DCR with data transformation is done in 7 steps:<\/p>\n\n\n\n<ol class=\"wp-block-list\" type=\"1\">\n<li>Kusto command must be defined<\/li>\n\n\n\n<li>Deploy a new DCR using Azure Monitor &#8211; or via Sentinel AMA-connector if transformation is for SecurityEvents<\/li>\n\n\n\n<li>Adding the TransformKql to the DCR<\/li>\n\n\n\n<li>Updating\/uploading the modified DCR<\/li>\n\n\n\n<li>Verification of changes in DCR<\/li>\n\n\n\n<li>Assign the DCR to the machine(s) where the transformation must happend<\/li>\n\n\n\n<li>Wait for the DCR and transformation pipeline to kick in<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Step 1: Kusto command must be defined<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Typically, I start by defining the Kusto command to show all data; except the data we want to filter away.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Below are 4 samples<\/p>\n\n\n\n<figure class=\"wp-block-table has-small-font-size\"><table><tbody><tr><td>SecurityEvent | where EventID != 5145<\/td><td>Here I want to see all Security event except for EventID = 5145<\/td><\/tr><tr><td>SecurityEvent | where (EventID != 8002) and (EventID != 5058) and (EventID != 4662)<\/td><td>Here I want to see all Security events except for EventID = 8002,5058,4662<\/td><\/tr><tr><td>Event | where ( (EventID != 10016 and EventLog == &#8220;Application&#8221;)&nbsp; )<\/td><td>Here I want to see all Event system and application events, except for application events with eventid 10016<\/td><\/tr><tr><td>CommonSecurityLog | where (DeviceVendor !contains &#8220;sonicwall&#8221;) or ((DeviceVendor contains &#8220;sonicwall&#8221;) and (Activity contains &#8220;connection opened&#8221; or Activity contains &#8220;connection closed&#8221;) and (Protocol != &#8220;udp\/dns&#8221;))<\/td><td>Here I want to see all CEF\/syslog where devicevendor is different from sonicwall like Cisco and all sonicwall events, except if protocol is udp\/dns<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Note:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Since the transformation is applied to each record individually, it can&#8217;t use any KQL operators that act on multiple records. Only operators that take a single row as input and return no more than one row are supported. For example,&nbsp;<a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/data-explorer\/kusto\/query\/summarizeoperator\">summarize<\/a>&nbsp;isn&#8217;t supported since it summarizes multiple records. See&nbsp;<a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/azure-monitor\/essentials\/data-collection-transformations-structure#supported-kql-features\">Supported KQL features<\/a>&nbsp;for a complete list of supported features.<\/li>\n\n\n\n<li>You cannot use cross-workspace references<\/li>\n\n\n\n<li>See this link for more information (<a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/azure-monitor\/essentials\/data-collection-transformations-structure\">https:\/\/learn.microsoft.com\/en-us\/azure\/azure-monitor\/essentials\/data-collection-transformations-structure<\/a>)<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">When the Kusto command is working as expected, then copy the Kusto query into Notepad and change the tablename to source \u2013 below I changed <strong>SecurityEvent<\/strong> with <strong>source<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-table has-small-font-size\"><table><tbody><tr><td>source | where EventID != 5145<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Lastly we need to change the Kusto query, so it will be applied as one line with escape characters<\/p>\n\n\n\n<figure class=\"wp-block-table has-small-font-size\"><table><tbody><tr><td>&nbsp; source\\n| where EventID != 5145 &nbsp;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Tip<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In case you are working with advanced queries, I take my Kusto query and paste it in an online converter, which will create everything with escape characters. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Personally, I use the online website <a href=\"https:\/\/jsonformatter.org\/json-escape\">https:\/\/jsonformatter.org\/json-escape<\/a><\/p>\n\n\n\n<figure class=\"wp-block-table has-small-font-size\"><table><tbody><tr><td><strong>Transformation query (Kusto)<\/strong><\/td><td><strong>Transformation query for transformKql<\/strong><\/td><\/tr><tr><td>source | where (Account != &#8220;WINSFTP\\\\autotest&#8221;) and (EventID != 4688 and EventID != 8002 and EventID != 4625) and (Account != &#8220;WORKGROUP\\\\WINSFTP$&#8221;)<\/td><td>source\\r\\n| where (Account != \\&#8221;CVT-WINSFTP\\\\\\\\cvtautotest\\&#8221;) and (EventID != 4688 and EventID != 8002 and EventID != 4625) and (Account != \\&#8221;WORKGROUP\\\\\\\\CVT-WINSFTP$\\&#8221;)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Step 2: Deploy a new DCR<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Configure a standard DCR rule and choose to collect what you want like all security events or all system and application events.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Make a note of the ResourceId of the DCR rule. You will use the ResourceId in step 3<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"2099\" height=\"348\" src=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/resid.jpg\" alt=\"\" class=\"wp-image-78\" srcset=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/resid.jpg 2099w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/resid-300x50.jpg 300w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/resid-1024x170.jpg 1024w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/resid-768x127.jpg 768w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/resid-1536x255.jpg 1536w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/resid-2048x340.jpg 2048w\" sizes=\"auto, (max-width: 2099px) 100vw, 2099px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"162\" src=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/resourceid-1024x162.jpg\" alt=\"\" class=\"wp-image-77\" srcset=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/resourceid-1024x162.jpg 1024w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/resourceid-300x48.jpg 300w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/resourceid-768x122.jpg 768w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/resourceid.jpg 1425w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Step 3: Adding the TransformKql to the DCR<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I use a Powershell script to retrieve the DCR into a flat JSON-file; use Notepad++ to edit the file and add the needed transformation \u2013 and then upload the modified DCR again. Below I have created a sample folder C:\\TMP where the file will be stored<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The script can be found here on <a href=\"https:\/\/github.com\/KnudsenMorten\/Azure_LogAnalytics_Data_Transformation.git\" data-type=\"URL\" data-id=\"https:\/\/github.com\/KnudsenMorten\/Azure_LogAnalytics_Data_Transformation.git\" target=\"_blank\" rel=\"noreferrer noopener\">my github<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Start by setting the variables $ResourceId and $FilePath<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">ResourceId was noted in the previous step 2<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">FilePath can be any path \u2013 it is only a temporary file used for this change \u2013 example<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>####################################################\n# VARIABLES\n####################################################\n\n# here you put the ResourceID of the Data Collection Rules (a sample is provided below)\n$ResourceId = \"\/subscriptions\/xxxxxx\/resourceGroups\/rg-logworkspaces\/providers\/microsoft.insights\/dataCollectionRules\/dcr-ingest-exclude-security-eventid\"\n    \n# here you put a path and file name where you want to store the temporary file-extract from DCR (a sample is provided below)\n$FilePath   = \"c:\\tmp\\dcr-ingest-exclude-security-eventid.txt\"\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Connect to Azure<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>####################################################\n# CONNECT TO AZURE\n####################################################\n\nConnect-AzAccount<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Run the export DCR <\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>$DCR = Invoke-AzRestMethod -Path (\"$ResourceId\"+\"?api-version=2021-09-01-preview\") -Method GET\n\n$DCR.Content | ConvertFrom-Json | ConvertTo-Json -Depth 20 | Out-File -FilePath $FilePath<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now you have a JSON file in c:\\tmp folder<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Modify file and add TransformKql<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Open the file using Notepad++ and add the line transformKql command that you created in step 1<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code><strong>\"transformKql\":&nbsp; \"source\\n| where (EventID != 5145)\"<\/strong><\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"222\" src=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/transformkql-1024x222.jpg\" alt=\"\" class=\"wp-image-80\" srcset=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/transformkql-1024x222.jpg 1024w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/transformkql-300x65.jpg 300w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/transformkql-768x166.jpg 768w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/transformkql.jpg 1204w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">NOTE: Remember to add the , (comma) on the line before so you are not breaking the JSON structure.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Step 4: Update the DCR (Uploading the changed DCR from the file)<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now we want to run the last part of the powershell script, which will update the DCR taking the entire content of the local file and making a REST api call using a specific api version (2021-09-01-preview). TransformKql requires a specific api-version (2021-09-01-preview), so we need to communicate with that particular api-set using REST api.<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>####################################################\n# UPLOAD FILE \/ UPDATE DCR WITH TRANSFORM\n####################################################\n\n$DCRContent = Get-Content $FilePath -Raw \n\nInvoke-AzRestMethod -Path (\"$ResourceId\"+\"?api-version=2021-09-01-preview\") -Method PUT -Payload $DCRContent<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You should be getting a StatusCode 200 with the PUT commmand, indicating everything it updated correctly<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"75\" src=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/ok-1024x75.jpg\" alt=\"\" class=\"wp-image-81\" srcset=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/ok-1024x75.jpg 1024w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/ok-300x22.jpg 300w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/ok-768x56.jpg 768w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/ok-1536x113.jpg 1536w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/ok.jpg 1759w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">If there is is an error in the file structure, you will get an error 400<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"88\" src=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/error-1024x88.jpg\" alt=\"\" class=\"wp-image-82\" srcset=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/error-1024x88.jpg 1024w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/error-300x26.jpg 300w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/error-768x66.jpg 768w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/error-1536x131.jpg 1536w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/error.jpg 1778w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Step 5: Verification of changes in DCR<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If you go and check the GUI for the changes, please remember to choose the correct API in the drop-down menu. Otherwise you wont be able to see the changes. You will now see the transformKql.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"199\" src=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/api-1024x199.jpg\" alt=\"\" class=\"wp-image-83\" srcset=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/api-1024x199.jpg 1024w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/api-300x58.jpg 300w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/api-768x149.jpg 768w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/api.jpg 1402w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can also extract the changes running the first lines again to extract into the local file using the GET command<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>####################################################\n# EXPORT EXISTING DCR TO FILE\n####################################################\n\n$DCR = Invoke-AzRestMethod -Path (\"$ResourceId\"+\"?api-version=2021-09-01-preview\") -Method GET\n\n$DCR.Content | ConvertFrom-Json | ConvertTo-Json -Depth 20 | Out-File -FilePath $FilePath<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Step 6: Associate the DCR rule to the machine(s)<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now you have to associate the DCR rule to the machine(s) where you want the transformation to happend.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Step 7: Wait for the DCR and transformation pipeline to kick in<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now we have to wait for pipeline transformation to happend. Normally it wil start within 5-10 minutes, but I have seen changes taking 30 min.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>Troubleshooting<\/strong><\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">If you want to verify, that the local Azure Monitor Agent has received the DCR rule, this can be done using the local AMA files. AMA will check every 5 min for new DCR changes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Verification using local AMA config files<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Open your DCR rule in JSON view and note the <strong>ImmuntableId<\/strong> of your DCR rule<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"272\" src=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/immun-1024x272.jpg\" alt=\"\" class=\"wp-image-84\" srcset=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/immun-1024x272.jpg 1024w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/immun-300x80.jpg 300w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/immun-768x204.jpg 768w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/immun.jpg 1166w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Open the file <strong>C:\\WindowsAzure\\Resources\\AMADataStore.DC1\\mcs\\mcsconfig.latest.xml<\/strong> (or <strong>mcsconfig.latest.json<\/strong>). <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Search for the <strong>ImmuntableId<\/strong>. You should now see that it is using the new DCR rule. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If AMA is not receiving the DCR rule, please verify that you have linked the DCR rule to the server. Otherwise continue to the AMA troubleshooting below.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h1 class=\"wp-block-heading\"><strong>Azure Monitor Agent troubleshooting<\/strong><\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Azure Monitor Agent has a troubleshooting Powershell-script, which might be able to help you.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Run the following Powershell script:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>C:\\Packages\\Plugins\\Microsoft.Azure.Monitor.AzureMonitorWindowsAgent\\&lt;latest version on your computer&gt;\\CollectAMALogs.ps1<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">It will generate a zip-file on your desktop with all the log-files.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Open the file <strong>maeventtable.csv<\/strong> in Excel and filter<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Stream = MonAgentManager.exe<\/li>\n\n\n\n<li>File = refreshconfigurations.cpp<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">You should now be able to see the DCR changes<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/logfile2-1024x86.jpg\" alt=\"\" class=\"wp-image-86\" width=\"740\" height=\"62\" srcset=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/logfile2-1024x86.jpg 1024w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/logfile2-300x25.jpg 300w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/logfile2-768x64.jpg 768w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/logfile2-1536x129.jpg 1536w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/logfile2-2048x171.jpg 2048w\" sizes=\"auto, (max-width: 740px) 100vw, 740px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"440\" height=\"147\" src=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/logfile.jpg\" alt=\"\" class=\"wp-image-87\" srcset=\"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/logfile.jpg 440w, https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/logfile-300x100.jpg 300w\" sizes=\"auto, (max-width: 440px) 100vw, 440px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>More resources<\/strong> about data transformation<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/azure-monitor\/essentials\/data-collection-transformations\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/learn.microsoft.com\/en-us\/azure\/azure-monitor\/essentials\/data-collection-transformations<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/azure-monitor\/essentials\/data-collection-rule-structure\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/learn.microsoft.com\/en-us\/azure\/azure-monitor\/essentials\/data-collection-rule-structure<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">More samples on transformation of custom logs<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/github.com\/MicrosoftDocs\/azure-docs\/blob\/main\/articles\/azure-monitor\/agents\/data-collection-text-log.md\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/MicrosoftDocs\/azure-docs\/blob\/main\/articles\/azure-monitor\/agents\/data-collection-text-log.md<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/MicrosoftDocs\/azure-docs\/blob\/main\/articles\/azure-monitor\/agents\/data-collection-text-log.md\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/github.com\/MicrosoftDocs\/azure-docs\/blob\/main\/articles\/azure-monitor\/agents\/data-collection-text-log.md<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the cool features in Azure LogAnalytics is the capability to do data-transformation before the data enters your LogAnalytics &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"How to do data transformation with Azure LogAnalytics &#8211; to enrich information, optimize cost, remove sensitive data?\" class=\"read-more button\" href=\"https:\/\/mortenknudsen.net\/?p=73#more-73\" aria-label=\"Read more about How to do data transformation with Azure LogAnalytics &#8211; to enrich information, optimize cost, remove sensitive data?\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":143,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"ngg_post_thumbnail":0,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[55,54,57,58],"tags":[23,20,18,13,19,96,6,21,22,25,5,9,26,15,24,7,27],"class_list":["post-73","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure","category-azure-loganalytics","category-azure-security","category-sentinel","tag-ama","tag-automation","tag-azure","tag-azure-loganalytics","tag-azure-monitor-agent","tag-azuremonitoragent","tag-cost-optimization","tag-data-collection-rules","tag-dcr","tag-enrich-information","tag-loganalytics","tag-logging","tag-remove-noise","tag-securityevent","tag-sentinel","tag-transformation","tag-unneccessary-logs","infinite-scroll-item","resize-featured-image"],"featured_image_src":"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/53A1655_fritlagt.png","author_info":{"display_name":"Morten Knudsen","author_link":"https:\/\/mortenknudsen.net\/?author=1"},"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack_featured_media_url":"https:\/\/mortenknudsen.net\/wp-content\/uploads\/2022\/12\/53A1655_fritlagt.png","_links":{"self":[{"href":"https:\/\/mortenknudsen.net\/index.php?rest_route=\/wp\/v2\/posts\/73","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mortenknudsen.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mortenknudsen.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mortenknudsen.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mortenknudsen.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=73"}],"version-history":[{"count":36,"href":"https:\/\/mortenknudsen.net\/index.php?rest_route=\/wp\/v2\/posts\/73\/revisions"}],"predecessor-version":[{"id":2262,"href":"https:\/\/mortenknudsen.net\/index.php?rest_route=\/wp\/v2\/posts\/73\/revisions\/2262"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/mortenknudsen.net\/index.php?rest_route=\/wp\/v2\/media\/143"}],"wp:attachment":[{"href":"https:\/\/mortenknudsen.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=73"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mortenknudsen.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=73"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mortenknudsen.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=73"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}