%3CLINGO-SUB%20id%3D%22lingo-sub-1712564%22%20slang%3D%22en-US%22%3EEnriching%20Windows%20Security%20Events%20with%20Parameterized%20Function%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1712564%22%20slang%3D%22en-US%22%3E%3CH3%20id%3D%22toc-hId-1255359119%22%20id%3D%22toc-hId-1255359151%22%20id%3D%22toc-hId-1255359151%22%20id%3D%22toc-hId-1255359151%22%20id%3D%22toc-hId-1255359151%22%20id%3D%22toc-hId-1255359151%22%20id%3D%22toc-hId-1255359151%22%20id%3D%22toc-hId-1255359151%22%3E%26nbsp%3B%3C%2FH3%3E%0A%3CH3%20id%3D%22toc-hId--552095344%22%20id%3D%22toc-hId--552095312%22%20id%3D%22toc-hId--552095312%22%20id%3D%22toc-hId--552095312%22%20id%3D%22toc-hId--552095312%22%20id%3D%22toc-hId--552095312%22%20id%3D%22toc-hId--552095312%22%20id%3D%22toc-hId--552095312%22%3E%3CFONT%20size%3D%225%22%3E%3CSTRONG%3E%3CU%3EOverview%3C%2FU%3E%3C%2FSTRONG%3E%3C%2FFONT%3E%3C%2FH3%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EMonitoring%20Windows%20Security%20Auditing%20logs%20is%20essential%20in%20helping%20SOC%20analysts%20to%20keep%20track%20of%20any%20unplanned%20changes%20in%20a%20computer's%20system%20audit%20policy%20settings.%20If%20there%20is%20an%20indication%20of%20a%20suspicious%20anomalous%20activity%2C%20an%20investigation%20needs%20to%20be%20performed%20as%20soon%20as%20possible.%20Hence%2C%20the%20ability%20to%20analyze%20collected%20Windows%20Security%20Auditing%20logs%20efficiently%20in%20Azure%20Sentinel%20is%20crucial.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EWindows%20Security%20Events%20can%20be%20collected%20in%20Azure%20Sentinel%20with%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fsentinel%2Fconnect-windows-security-events%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3ESecurity%20Events%20Connector%3C%2FA%3E%20or%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fsecurity-center%2Fsecurity-center-enable-data-collection%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3EData%20Collection%3C%2FA%3E%20in%20Azure%20Security%20Center%20Standard%20Tier%20(If%20both%20Azure%20Sentinel%20and%20Azure%20Security%20Center%20are%20running%20in%20the%20same%20workspace).%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EIn%20this%20blog%20post%2C%20you%20will%20learn%20how%20to%20use%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Frest%2Fapi%2Floganalytics%2Fsavedsearches%2Fcreateorupdate%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3EParameterized%20Function%3C%2FA%3E%20to%20perform%20data%20enrichment%20and%20simplify%20your%20KQL%20query.%20We%20will%20use%20Windows%20Security%20Audit%20Policy%20Change%20events%20as%20our%20use%20case%20for%20data%20enrichment.%20You%20can%20refer%20to%20a%20list%20of%20%3CSPAN%3EAudit%20Policy%20Change%20%3C%2FSPAN%3EEvent%20IDs%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fwindows%2Fsecurity%2Fthreat-protection%2Fauditing%2Faudit-audit-policy-change%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Ehere%3C%2FA%3E%20if%20you%20are%20unfamiliar%20with%20these%20events.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EFirst%2C%20let%20me%20give%20you%20an%20overview%20of%20the%20use%20case%20that%20I%20am%20about%20to%20walkthrough%3A%20let%E2%80%99s%20take%20Event%20ID%204719%20(%E2%80%9CSystem%20audit%20policy%20was%20changed%E2%80%9D)%20as%20an%20example.%20The%20following%20event%204719%20is%20logged%20when%20the%20audit%20policy%20was%20changed.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-center%22%20image-alt%3D%22event.png%22%20style%3D%22width%3A%20400px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222056i25CDA4C8457B4768%2Fimage-size%2Fmedium%3Fv%3D1.0%26amp%3Bpx%3D400%22%20title%3D%22event.png%22%20alt%3D%22event.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EBelow%20is%20how%20the%20event%20data%20would%20look%20when%20you%20query%20for%20this%20event%20in%20your%20Sentinel%20workspace.%20As%20you%20can%20see%2C%20the%20%3CSTRONG%3ECategory%3C%2FSTRONG%3E%2C%20%3CSTRONG%3ESubcategory%3C%2FSTRONG%3E%20and%20%3CSTRONG%3EAuditPolicyChanges%3C%2FSTRONG%3E%20fields%20are%20captured%20in%20their%20IDs%20by%20design%20instead%20of%20the%20text%20values.%20This%20might%20be%20a%20challenge%20when%20you%20need%20to%20understand%20more%20about%20the%20event%20or%20perform%20a%20filter%20based%20the%20string%20value%20such%20as%20%E2%80%9CObject%20Access%E2%80%9D.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-center%22%20image-alt%3D%22QueryResultbyDesign.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222058i56D39B140A7B2B7D%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20title%3D%22QueryResultbyDesign.png%22%20alt%3D%22QueryResultbyDesign.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%26nbsp%3B%3C%2FP%3E%0A%3CP%3EIn%20the%20following%20sections%20of%20this%20blog%2C%20you%20will%20learn%3A%3C%2FP%3E%0A%3CUL%3E%0A%3CLI%3EWhat%20is%20a%20%3CSTRONG%3EParameterized%20Function%3C%2FSTRONG%3E%3F%3C%2FLI%3E%0A%3CLI%3EHow%20to%20enrich%20%3CSTRONG%3ECategory%3C%2FSTRONG%3E%2C%20%3CSTRONG%3ESubcategory%3C%2FSTRONG%3E%20and%20%3CSTRONG%3EChanges%20%3C%2FSTRONG%3Efields%20with%20parameterized%20function%20when%20analyzing%20Windows%20Security%20Audit%20Policy%20Change%20events%20in%20Azure%20Sentinel.%3C%2FLI%3E%0A%3C%2FUL%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH4%20id%3D%22toc-hId-138466130%22%20id%3D%22toc-hId-138466162%22%20id%3D%22toc-hId-138466162%22%20id%3D%22toc-hId-138466162%22%20id%3D%22toc-hId-138466162%22%20id%3D%22toc-hId-138466162%22%20id%3D%22toc-hId-138466162%22%20id%3D%22toc-hId-138466162%22%3E%3CFONT%20size%3D%225%22%3E%3CSTRONG%3E%3CU%3EThe%20Plan%3C%2FU%3E%3C%2FSTRONG%3E%3C%2FFONT%3E%3C%2FH4%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EHere%20is%20the%20summary%20of%20what%20we%20are%20about%20to%20do.%20In%20the%20following%20diagram%2C%20I%20have%20lookup%20tables%20for%20%3CSTRONG%3ECategory%3C%2FSTRONG%3E%2C%20%3CSTRONG%3ESubcategory%3C%2FSTRONG%3E%20and%20%3CSTRONG%3EChanges%3C%2FSTRONG%3E%20with%20their%20values%20and%20IDs.%20The%20diagram%20illustrates%20how%20these%20IDs%20will%20be%20mapped%20to%20each%20individual%20table.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-center%22%20image-alt%3D%22ThePlan.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222059iC70491BB256226C8%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20title%3D%22ThePlan.png%22%20alt%3D%22ThePlan.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EI%20will%20simplify%20the%20mapping%20process%20by%20consolidating%20all%20the%20values%20for%20%3CSTRONG%3ECategory%3C%2FSTRONG%3E%2C%20%3CSTRONG%3ESubCategory%3C%2FSTRONG%3E%20and%20%3CSTRONG%3EChanges%3C%2FSTRONG%3E%20in%20a%20single%20lookup%20table%20as%20shown%20in%20the%20diagram%20below.%20This%20will%20be%20the%20function%20body%20of%20our%20Parameterized%20Function%20which%20I%20will%20discuss%20in%20the%20next%20section.%20The%20function%20will%20return%20the%20corresponding%20value%20when%20provided%20with%20an%20ID.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-center%22%20image-alt%3D%22Lookup.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222060i773E70D38725F03B%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20title%3D%22Lookup.png%22%20alt%3D%22Lookup.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH4%20id%3D%22toc-hId--1668988333%22%20id%3D%22toc-hId--1668988301%22%20id%3D%22toc-hId--1668988301%22%20id%3D%22toc-hId--1668988301%22%20id%3D%22toc-hId--1668988301%22%20id%3D%22toc-hId--1668988301%22%20id%3D%22toc-hId--1668988301%22%20id%3D%22toc-hId--1668988301%22%3E%3CFONT%20size%3D%225%22%3E%3CSTRONG%3E%3CU%3EWhat%20is%20a%20Parameterized%20Function%3F%3C%2FU%3E%3C%2FSTRONG%3E%3C%2FFONT%3E%3C%2FH4%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EParameterized%20Function%20is%20an%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdata-explorer%2Fkusto%2Fquery%2Ffunctions%2Fuser-defined-functions%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Euser-defined%20function%3C%2FA%3E%20that%20can%20be%20invoked%20through%20the%20function%20alias.%20It%20accepts%20zero%20or%20more%20input%20arguments%20and%20produces%20a%20single%20output%20(which%20can%20be%20scalar%20or%20tabular)%20based%20on%20the%20function%20body.%20However%2C%20Parameterized%20Function%20is%20not%20the%20same%20as%20the%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fazure-monitor%2Flog-query%2Ffunctions%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3EKQL%20function%3C%2FA%3E%20%E2%80%93%20a%20common%20feature%20in%20Log%20Analytics%20(you%20can%20refer%20to%20this%20%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fazure-sentinel%2Fusing-kql-functions-to-speed-up-analysis-in-azure-sentinel%2Fba-p%2F712381%23%3A~%3Atext%3DKQL%2520functions%2520in%2520Azure%2520Sentinel%2Calias%2520to%2520call%2520it%2520by.%22%20target%3D%22_blank%22%20rel%3D%22noopener%22%3Eblog%20post%3C%2FA%3E%20for%20example)%20as%20the%20KQL%20function%20doesn%E2%80%99t%20support%20input%20arguments.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EBelow%20is%20an%20example%20of%20a%20Parameterized%20Function%20with%20a%20single%20argument%20(ID).%20The%20function%20body%20is%20a%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdata-explorer%2Fkusto%2Fquery%2Fscalar-data-types%2Fdynamic%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Edynamic%3C%2FA%3E%20table%20with%20a%20list%20of%20IDs%20and%20the%20corresponding%20values.%20The%20reason%20of%20using%20dynamic%20scalar%20data%20type%20is%20to%20allow%20scalar%20expression%20when%20passing%20a%20column%20value%20as%20the%20argument.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3E%3CFONT%20color%3D%22%230000FF%22%3Elet%3C%2FFONT%3E%20%3CFONT%20color%3D%22%23800080%22%3E%3CSTRONG%3Emyfunc%3C%2FSTRONG%3E%20%3C%2FFONT%3E%3D%20(ID%3Astring)%7B%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3E%26nbsp%3B%26nbsp%3B%20%3CFONT%20color%3D%22%230000FF%22%3Edynamic%3C%2FFONT%3E(%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3E%26nbsp%3B%26nbsp%3B%26nbsp%3B%20%7B%20%3CFONT%20color%3D%22%23800000%22%3E%22%25%258272%22%3A%22System%22%3C%2FFONT%3E%2C%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3E%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B%20%3CFONT%20color%3D%22%23800000%22%3E%22%25%258273%22%3A%22Logon%2FLogoff%22%3C%2FFONT%3E%2C%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3E%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B%20%3CFONT%20color%3D%22%23800000%22%3E%22%25%258274%22%3A%22Object%20Access%22%3C%2FFONT%3E%2C%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3E%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B%20%3CFONT%20color%3D%22%23800000%22%3E%22%25%258275%22%3A%22Privilege%20Use%22%3C%2FFONT%3E%2C%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3E%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B%20%3CFONT%20color%3D%22%23800000%22%3E%22%25%258276%22%3A%22Detailed%20Tracking%22%3C%2FFONT%3E%2C%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3E%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B%20%3CFONT%20color%3D%22%23800000%22%3E%22%25%258277%22%3A%22Policy%20Change%22%3C%2FFONT%3E%2C%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3E%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B%20%3CFONT%20color%3D%22%23800000%22%3E%22%25%258278%22%3A%22Account%20Management%22%3C%2FFONT%3E%2C%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3E%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B%20%3CFONT%20color%3D%22%23800000%22%3E%22%25%258279%22%3A%22DS%20Access%22%3C%2FFONT%3E%2C%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3E%26nbsp%3B%26nbsp%3B%26nbsp%3B%26nbsp%3B%3CFONT%20color%3D%22%23800000%22%3E%20%22%25%258280%22%3A%22Account%20Logon%22%3C%2FFONT%3E%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3E%7D)%5BID%5D%7D%3B%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EHere%20is%20the%20example%20of%20how%20the%20function%20is%20being%20invoked.%20The%20function%20will%20return%20the%20lookup%20value%20of%20the%20provided%20ID%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3ESecurityEvent%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3E%7C%20%3CFONT%20color%3D%22%230000FF%22%3Ewhere%3C%2FFONT%3E%20EventID%20%3D%3D%20%3CFONT%20color%3D%22%23008000%22%3E4719%3C%2FFONT%3E%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3E%7C%20%3CFONT%20color%3D%22%230000FF%22%3Eproject%3C%2FFONT%3E%20TimeGenerated%2C%20Computer%2C%20CategoryId%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3E%7C%20%3CFONT%20color%3D%22%230000FF%22%3Eextend%3C%2FFONT%3E%20Category%20%3D%20%3CFONT%20color%3D%22%23800080%22%3E%3CSTRONG%3Emyfunc%3C%2FSTRONG%3E%3C%2FFONT%3E%3CSTRONG%3E(%3C%2FSTRONG%3ECategoryId%3CSTRONG%3E)%3C%2FSTRONG%3E%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20size%3D%223%22%3E%7C%20%3CFONT%20color%3D%22%230000FF%22%3Eproject-away%3C%2FFONT%3E%20CategoryId%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EHowever%2C%20Parameterized%20Function%20can%20only%20be%20created%20programmatically%20(creation%20in%20UI%20is%20not%20supported%20at%20the%20time%20of%20writing).%20Hence%2C%20I%20will%20provide%20sample%20PowerShell%20scripts%20to%20create%20Parameterized%20Functions%20in%20this%20blog.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH4%20id%3D%22toc-hId-818524500%22%20id%3D%22toc-hId-818524532%22%20id%3D%22toc-hId-818524532%22%20id%3D%22toc-hId-818524532%22%20id%3D%22toc-hId-818524532%22%20id%3D%22toc-hId-818524532%22%20id%3D%22toc-hId-818524532%22%20id%3D%22toc-hId-818524532%22%3E%3CFONT%20size%3D%225%22%3E%3CSTRONG%3E%3CU%3ECreate%20the%20Parameterized%20Function%3C%2FU%3E%3C%2FSTRONG%3E%3C%2FFONT%3E%3C%2FH4%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CA%20href%3D%22https%3A%2F%2Fgithub.com%2FAzure%2FAzure-Sentinel%2Fblob%2Fmaster%2FTools%2FParameterizedFunction%2FAuditEventDataLookup_Func.ps1%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3EHere%3C%2FA%3E%20is%20the%20sample%20Powershell%20script%20to%20create%20the%20Parameterized%20Function%20for%20the%20lookup%20table%20of%20%3CSTRONG%3ECategory%3C%2FSTRONG%3E%2C%20%3CSTRONG%3ESubcategory%3C%2FSTRONG%3E%20and%20%3CSTRONG%3EChanges%3C%2FSTRONG%3E.%20Edit%20the%20Powershell%20script%20to%20provide%20the%20following%20information%20before%20executing%20it%3A%3C%2FP%3E%0A%3CUL%3E%0A%3CLI%3E%3CSTRONG%3E%24ResourceGroup%3C%2FSTRONG%3E%3A%20Resource%20Group%20of%20your%20Azure%20Sentinel%20Workspace.%3C%2FLI%3E%0A%3CLI%3E%3CSTRONG%3E%24WorkspaceName%3C%2FSTRONG%3E%3A%20Name%20of%20your%20Azure%20Sentinel%20Workspace.%3C%2FLI%3E%0A%3CLI%3E%3CSTRONG%3E%24SubscriptionID%3C%2FSTRONG%3E%3A%20Subscription%20ID%20of%20the%20Azure%20Sentinel%20Workspace.%3C%2FLI%3E%0A%3C%2FUL%3E%0A%3CP%3ERun%20the%20script%20after%20you%20have%20updated%20the%20above%20details.%20The%20script%20will%20prompt%20for%20your%20Azure%20credentials%20and%20it%20should%20take%20less%20than%20a%20minute%20to%20complete.%20Below%20is%20the%20sample%20screenshot%20of%20how%20a%20successful%20creation%20looks%20like%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-center%22%20image-alt%3D%22PowerShellOutput.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222061i8BD0A275A1ECFDAE%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20title%3D%22PowerShellOutput.png%22%20alt%3D%22PowerShellOutput.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThe%20script%20will%20create%20a%20Parameterized%20Function%20on%20your%20defined%20workspace%20with%20the%20name%20and%20alias%20of%20%E2%80%9C%3CFONT%20color%3D%22%23800080%22%3E%3CSTRONG%3EAuditEventDataLookup_Func%3C%2FSTRONG%3E%3C%2FFONT%3E%E2%80%9D.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ENote%20that%20the%20Parameterized%20Function%20is%20not%20visible%20in%20the%20workspace%20UI%2C%20but%20you%20can%20use%20API%20to%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Frest%2Fapi%2Floganalytics%2Fsavedsearches%2Fget%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3EGET%3C%2FA%3E%20the%20function%20details%20or%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Frest%2Fapi%2Floganalytics%2Fsavedsearches%2Flistbyworkspace%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3EList%3C%2FA%3E%20all%20Saved%20Searches%20(including%20Parameterized%20functions)%20for%20your%20workspace.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH4%20id%3D%22toc-hId--988929963%22%20id%3D%22toc-hId--988929931%22%20id%3D%22toc-hId--988929931%22%20id%3D%22toc-hId--988929931%22%20id%3D%22toc-hId--988929931%22%20id%3D%22toc-hId--988929931%22%20id%3D%22toc-hId--988929931%22%20id%3D%22toc-hId--988929931%22%3E%3CFONT%20size%3D%225%22%3E%3CSTRONG%3E%3CU%3EUsing%20Parameterized%20Function%20to%20enrich%20Category%20ID%2C%20Subcategory%20ID%20and%20Changes%20ID%3C%2FU%3E%3C%2FSTRONG%3E%3C%2FFONT%3E%3C%2FH4%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ENow%2C%20let%E2%80%99s%20begin%20enriching%20the%20%3CSTRONG%3ECategory%3C%2FSTRONG%3E%20and%20%3CSTRONG%3ESubcategory%3C%2FSTRONG%3E%20fields%20using%20the%20function%20we%20just%20created.%20These%20two%20fields%20will%20only%20have%20a%20single%20value%20and%20they%20are%20more%20straight%20forward.%20We%20just%20need%20to%20invoke%20the%20function%20with%20%3CSTRONG%3ECategoryId%3C%2FSTRONG%3E%2F%3CSTRONG%3ESubcategoryId%3C%2FSTRONG%3E%20as%20the%20input%20argument.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22CategoryAndSub.png%22%20style%3D%22width%3A%20400px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222062i99658F7A6F10DFDA%2Fimage-size%2Fmedium%3Fv%3D1.0%26amp%3Bpx%3D400%22%20title%3D%22CategoryAndSub.png%22%20alt%3D%22CategoryAndSub.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EBelow%20is%20the%20sample%20query%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CEM%3ESecurityEvent%3C%2FEM%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CEM%3E%7C%20%3C%2FEM%3E%3CFONT%20color%3D%22%230000FF%22%3E%3CEM%3Ewhere%3C%2FEM%3E%3C%2FFONT%3E%3CEM%3E%20EventID%20%3D%3D%20%3C%2FEM%3E%3CFONT%20color%3D%22%23008000%22%3E%3CEM%3E4719%3C%2FEM%3E%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CEM%3E%7C%20%3C%2FEM%3E%3CFONT%20color%3D%22%230000FF%22%3E%3CEM%3Eproject%3C%2FEM%3E%3C%2FFONT%3E%3CEM%3E%20TimeGenerated%2C%20Computer%2C%20Activity%2C%20CategoryId%2C%20SubcategoryId%3C%2FEM%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CEM%3E%7C%20%3C%2FEM%3E%3CFONT%20color%3D%22%230000FF%22%3E%3CEM%3Eextend%3C%2FEM%3E%3C%2FFONT%3E%3CEM%3E%20Category%20%3D%20%3C%2FEM%3E%3CFONT%20color%3D%22%23800080%22%3E%3CSTRONG%3E%3CEM%3EAuditEventDataLookup_Func%3C%2FEM%3E%3C%2FSTRONG%3E%3C%2FFONT%3E%3CEM%3E(CategoryId)%3C%2FEM%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CEM%3E%7C%20%3C%2FEM%3E%3CFONT%20color%3D%22%230000FF%22%3E%3CEM%3Eextend%3C%2FEM%3E%3C%2FFONT%3E%3CEM%3E%20SubCategory%20%3D%20%3C%2FEM%3E%3CFONT%20color%3D%22%23800080%22%3E%3CSTRONG%3E%3CEM%3EAuditEventDataLookup_Func%3C%2FEM%3E%3C%2FSTRONG%3E%3C%2FFONT%3E%3CEM%3E(SubcategoryId)%3C%2FEM%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CEM%3E%7C%20%3C%2FEM%3E%3CFONT%20color%3D%22%230000FF%22%3E%3CEM%3Eproject-away%3C%2FEM%3E%3C%2FFONT%3E%3CEM%3E%20CategoryId%2C%20SubcategoryId%3C%2FEM%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThe%20query%20results%20are%20now%20showing%20%3CSTRONG%3ECategory%3C%2FSTRONG%3E%20and%20%3CSTRONG%3ESubcategory%3C%2FSTRONG%3E%20names%20instead%20of%20IDs%20as%20shown%20in%20the%20image%20below%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-center%22%20image-alt%3D%22Pic8.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222063i520D04161A3A9BE6%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20title%3D%22Pic8.png%22%20alt%3D%22Pic8.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ENext%20is%20the%20%3CSTRONG%3EAuditPolicyChanges%20%3C%2FSTRONG%3Efield.%20This%20field%20will%20either%20have%20one%20or%20two%20values%20separated%20by%20a%20comma%20as%20shown%20in%20the%20image%20below.%20Hence%2C%20we%20can%E2%80%99t%20pass%20the%20%3CSTRONG%3EAuditPolicyChanges%20%3C%2FSTRONG%3Evalue%20directly%20to%20the%20function%20like%20what%20we%20did%20earlier%20because%20if%20the%20field%20contained%20two%20values%2C%20the%20function%20will%20not%20be%20able%20to%20find%20a%20match%20in%20the%20lookup%20table.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22AuditPolicyChangesField.png%22%20style%3D%22width%3A%20400px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222064i72A1F518A11C19DC%2Fimage-size%2Fmedium%3Fv%3D1.0%26amp%3Bpx%3D400%22%20title%3D%22AuditPolicyChangesField.png%22%20alt%3D%22AuditPolicyChangesField.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EBut%20this%20can%20be%20resolved%20with%20the%20help%20of%20a%20few%20KQL%20commands.%20First%20of%20all%2C%20we%20can%20use%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdata-explorer%2Fkusto%2Fquery%2Fparsecsvfunction%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Eparse_csv()%3C%2FA%3E%20or%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdata-explorer%2Fkusto%2Fquery%2Fsplitfunction%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Esplit()%3C%2FA%3E%20command%20to%20get%20the%20string%20values%20from%20the%20comma-separated%20record.%20The%20returned%20values%20will%20be%20in%20a%20string%20array.%20Below%20is%20the%20sample%20query%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CEM%3ESecurityEvent%3C%2FEM%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CEM%3E%7C%20%3C%2FEM%3E%3CFONT%20color%3D%22%230000FF%22%3E%3CEM%3Ewhere%3C%2FEM%3E%3C%2FFONT%3E%3CEM%3E%20EventID%20%3D%3D%20%3C%2FEM%3E%3CFONT%20color%3D%22%23008000%22%3E%3CEM%3E4719%3C%2FEM%3E%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CEM%3E%7C%20%3C%2FEM%3E%3CFONT%20color%3D%22%230000FF%22%3E%3CEM%3Eextend%3C%2FEM%3E%3C%2FFONT%3E%3CEM%3E%20Category%20%3D%20%3C%2FEM%3E%3CFONT%20color%3D%22%23800080%22%3E%3CSTRONG%3E%3CEM%3EAuditEventDataLookup_Func%3C%2FEM%3E%3C%2FSTRONG%3E%3C%2FFONT%3E%3CEM%3E(CategoryId)%3C%2FEM%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CEM%3E%7C%20%3C%2FEM%3E%3CFONT%20color%3D%22%230000FF%22%3E%3CEM%3Eextend%3C%2FEM%3E%3C%2FFONT%3E%3CEM%3E%20SubCategory%20%3D%20%3C%2FEM%3E%3CFONT%20color%3D%22%23800080%22%3E%3CSTRONG%3E%3CEM%3EAuditEventDataLookup_Func%3C%2FEM%3E%3C%2FSTRONG%3E%3C%2FFONT%3E%3CEM%3E(SubcategoryId)%3C%2FEM%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CEM%3E%7C%20%3C%2FEM%3E%3CFONT%20color%3D%22%230000FF%22%3E%3CEM%3Eextend%3C%2FEM%3E%3C%2FFONT%3E%3CEM%3E%3CFONT%20color%3D%22%23FF6600%22%3E%20AuditPolicyChangesParse%3C%2FFONT%3E%20%3D%20%3CSTRONG%3Eparse_csv%3C%2FSTRONG%3E(AuditPolicyChanges)%3C%2FEM%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ENext%2C%20We%20will%20invoke%20the%20Parameterized%20function%20for%20each%20AuditPolicyChanges%20value%20using%20the%20array%20index%20(%3CEM%3E%3CFONT%20color%3D%22%23FF6600%22%3EAuditPolicyChangesParse%3C%2FFONT%3E%5B0%5D%3C%2FEM%3E%20and%20%3CEM%3E%3CFONT%20color%3D%22%23FF6600%22%3EAuditPolicyChangesParse%3C%2FFONT%3E%5B1%5D%3C%2FEM%3E).%20But%20be%20aware%20that%20there%20is%20a%20whitespace%20in%20the%20AuditPolicyChanges%20field%20after%20the%20comma%20as%20shown%20in%20the%20below%20image%2C%20which%20also%20appear%20after%20parsing.%20That%20means%20we%20need%20to%20remove%20the%20whitespace%20for%20the%20second%20value%20of%20AuditPolicyChanges%20when%20passing%20it%20to%20our%20function%20and%20we%20can%20do%20that%20by%20using%20the%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdata-explorer%2Fkusto%2Fquery%2Ftrimfunction%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Etrim()%3C%2FA%3E%20command.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-center%22%20image-alt%3D%22whitespace.png%22%20style%3D%22width%3A%20400px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222074i359393D634E86D6C%2Fimage-size%2Fmedium%3Fv%3D1.0%26amp%3Bpx%3D400%22%20title%3D%22whitespace.png%22%20alt%3D%22whitespace.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3CSPAN%20style%3D%22font-family%3A%20inherit%3B%22%3E%26nbsp%3B%3C%2FSPAN%3E%3CSPAN%20style%3D%22font-family%3A%20inherit%3B%22%3E%26nbsp%3B%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EBelow%20is%20the%20sample%20command%20line%20for%20removing%20the%20whitespace%20using%20%3CSTRONG%3Etrim()%3C%2FSTRONG%3E.%20Note%20that%20we%20are%20using%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdata-explorer%2Fkusto%2Fquery%2Fstrcatfunction%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Estrcat()%3C%2FA%3E%20to%20concatenate%20each%20%3CSTRONG%3EAuditPolicyChange%20%3C%2FSTRONG%3Evalue%20returned%20by%20the%20function%20and%20separate%20them%20with%20a%20comma.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CEM%3E%7C%20%3C%2FEM%3E%3CFONT%20color%3D%22%230000FF%22%3E%3CEM%3Eextend%3C%2FEM%3E%3C%2FFONT%3E%3CEM%3E%20AuditPolicyChange%20%3D%20%3CFONT%20color%3D%22%23FF0000%22%3E%3CSTRONG%3Estrcat%3C%2FSTRONG%3E%3C%2FFONT%3E(%3C%2FEM%3E%3CFONT%20color%3D%22%23800080%22%3E%3CSTRONG%3E%3CEM%3EAuditEventDataLookup_Func%3C%2FEM%3E%3C%2FSTRONG%3E%3C%2FFONT%3E%3CEM%3E(%3CFONT%20color%3D%22%23FF6600%22%3EAuditPolicyChangesParse%3C%2FFONT%3E%5B%3C%2FEM%3E%3CEM%3E0%3C%2FEM%3E%3CEM%3E%5D)%20%2C%3C%2FEM%3E%3CSTRONG%3E%3CFONT%20color%3D%22%23FF0000%22%3E%3CEM%3E%22%2C%22%3C%2FEM%3E%3C%2FFONT%3E%3C%2FSTRONG%3E%3CEM%3E%2C%3C%2FEM%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20color%3D%22%23800080%22%3E%3CSTRONG%3E%3CEM%3EAuditEventDataLookup_Func%3C%2FEM%3E%3C%2FSTRONG%3E%3C%2FFONT%3E%3CEM%3E(%3C%2FEM%3E%3CSTRONG%3E%3CEM%3Etrim%3C%2FEM%3E%3C%2FSTRONG%3E%3CEM%3E(%3C%2FEM%3E%3CSTRONG%3E%3CEM%3E%22%20%22%3C%2FEM%3E%3C%2FSTRONG%3E%3CEM%3E%2Ctostring(%3CFONT%20color%3D%22%23FF6600%22%3EAuditPolicyChangesParse%3C%2FFONT%3E%5B%3C%2FEM%3E%3CEM%3E1%3C%2FEM%3E%3CEM%3E%5D))))%3C%2FEM%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EWe%20have%20now%20resolved%20the%20scenario%20of%20enriching%20the%20%3CSTRONG%3EAuditPolicyChange%20%3C%2FSTRONG%3Efield%20which%20might%20consist%20of%20two%20values.%20But%20what%20if%20the%20%3CSTRONG%3EAuditPolicyChange%20%3C%2FSTRONG%3Efield%20only%20have%20a%20single%20value%3F%20Since%20we%20are%20using%20%3CSTRONG%3Estrcat()%3C%2FSTRONG%3E%20in%20the%20above%20query%2C%20the%20record%20will%20look%20like%20the%20below%20image%20if%20there%20is%20only%20a%20single%20value.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-center%22%20image-alt%3D%222020-09-22_14-38-19.png%22%20style%3D%22width%3A%20200px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222072i6555FB5266F8C8F5%2Fimage-size%2Fsmall%3Fv%3D1.0%26amp%3Bpx%3D200%22%20title%3D%222020-09-22_14-38-19.png%22%20alt%3D%222020-09-22_14-38-19.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3CSPAN%20style%3D%22font-family%3A%20inherit%3B%22%3E%26nbsp%3B%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EThis%20will%20be%20an%20easy%20fix%20as%20we%20can%20use%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdata-explorer%2Fkusto%2Fquery%2Ftrimendfunction%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Etrim_end()%3C%2FA%3E%20to%20remove%20the%20comma%20at%20the%20end%20of%20the%20text%20(if%20any).%3C%2FP%3E%0A%3CP%3EBelow%20is%20how%20the%20command%20looks%20like%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CEM%3E%7C%20%3C%2FEM%3E%3CFONT%20color%3D%22%230000FF%22%3E%3CEM%3Eextend%3C%2FEM%3E%3C%2FFONT%3E%3CEM%3E%20AuditPolicyChange%20%3D%20%3CFONT%20color%3D%22%23FF0000%22%3E%3CSTRONG%3Etrim_end%3C%2FSTRONG%3E%3C%2FFONT%3E(%3C%2FEM%3E%3CFONT%20color%3D%22%23FF0000%22%3E%3CSTRONG%3E%3CEM%3E%22%2C%22%3C%2FEM%3E%3C%2FSTRONG%3E%3C%2FFONT%3E%3CEM%3E%2C%3CFONT%20color%3D%22%23FF0000%22%3E%3CSTRONG%3Estrcat%3C%2FSTRONG%3E%3C%2FFONT%3E(%3C%2FEM%3E%3CFONT%20color%3D%22%23800080%22%3E%3CSTRONG%3E%3CEM%3EAuditEventDataLookup_Func%3C%2FEM%3E%3C%2FSTRONG%3E%3C%2FFONT%3E%3CEM%3E(%3CFONT%20color%3D%22%23FF0000%22%3EAuditPolicyChangesParse%3C%2FFONT%3E%5B%3C%2FEM%3E%3CEM%3E0%3C%2FEM%3E%3CEM%3E%5D)%20%2C%3C%2FEM%3E%3CSTRONG%3E%3CFONT%20color%3D%22%23FF0000%22%3E%3CEM%3E%22%2C%22%3C%2FEM%3E%3C%2FFONT%3E%3C%2FSTRONG%3E%3CEM%3E%2C%20%3C%2FEM%3E%3C%2FP%3E%0A%3CP%20class%3D%22lia-indent-padding-left-30px%22%3E%3CFONT%20color%3D%22%23800080%22%3E%3CSTRONG%3E%3CEM%3EAuditEventDataLookup_Func%3C%2FEM%3E%3C%2FSTRONG%3E%3C%2FFONT%3E%3CEM%3E(%3C%2FEM%3E%3CSTRONG%3E%3CEM%3Etrim%3C%2FEM%3E%3C%2FSTRONG%3E%3CEM%3E(%3C%2FEM%3E%3CSTRONG%3E%3CEM%3E%22%20%22%3C%2FEM%3E%3C%2FSTRONG%3E%3CEM%3E%2Ctostring(%3CFONT%20color%3D%22%23FF0000%22%3EAuditPolicyChangesParse%3C%2FFONT%3E%5B%3C%2FEM%3E%3CEM%3E1%3C%2FEM%3E%3CEM%3E%5D)))))%3C%2FEM%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EBelow%20is%20the%20final%20query%20for%20your%20reference%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-powershell%22%3E%3CCODE%3ESecurityEvent%0A%7C%20where%20EventID%20%3D%3D%204719%0A%7C%20extend%20Category%20%3D%20AuditEventDataLookup_Func(CategoryId)%0A%7C%20extend%20SubCategory%20%3D%20AuditEventDataLookup_Func(SubcategoryId)%0A%7C%20extend%20AuditPolicyChangesParse%20%3D%20parse_csv(AuditPolicyChanges)%0A%7C%20extend%20AuditPolicyChange%20%3D%20trim_end(%22%2C%22%2C%20strcat(AuditEventDataLookup_Func(AuditPolicyChangesParse%5B0%5D)%20%2C%22%2C%22%2CAuditEventDataLookup_Func(trim(%22%20%22%2Ctostring(AuditPolicyChangesParse%5B1%5D)))))%0A%7C%20project%20TimeGenerated%2C%20Computer%2C%20Activity%2C%20Category%2C%20SubCategory%2C%20AuditPolicyChange%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CEM%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-center%22%20image-alt%3D%222020-08-28_10-34-39.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222070iE35CB579B69A983E%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20title%3D%222020-08-28_10-34-39.png%22%20alt%3D%222020-08-28_10-34-39.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FEM%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH4%20id%3D%22toc-hId-1498582870%22%20id%3D%22toc-hId-1498582902%22%20id%3D%22toc-hId-1498582902%22%20id%3D%22toc-hId-1498582902%22%20id%3D%22toc-hId-1498582902%22%20id%3D%22toc-hId-1498582902%22%20id%3D%22toc-hId-1498582902%22%20id%3D%22toc-hId-1498582902%22%3E%3CFONT%20size%3D%225%22%3E%3CSTRONG%3E%3CU%3ENested%20Function%3C%2FU%3E%3C%2FSTRONG%3E%3C%2FFONT%3E%3C%2FH4%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ENow%20you%20have%20seen%20how%20the%20function%20works%2C%20there%20might%20be%20times%20where%20you%20need%20to%20create%20multiple%20functions%20for%20different%20purposes%20(such%20as%20enrichment%2C%20parsing%2C%20filtering%20and%20etc)%20and%20the%20ability%20to%20invoke%20another%20function%20within%20a%20function%20will%20be%20useful.%20Let%20me%20show%20you%20that%20in%20the%20next%20example.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EBelow%20is%20the%20query%20from%20the%20previous%20section%20and%20my%20use%20case%20is%20to%20simplify%20the%20query%20by%20configuring%20the%20yellow%20highlighted%20lines%20in%20a%20parameterized%20function%20called%20%3CFONT%20color%3D%22%23800080%22%3E%3CSTRONG%3EEnrichAuditEvents_Func%3C%2FSTRONG%3E%3C%2FFONT%3E.%20This%20function%20will%20take%20the%20table%20records%20(highlighted%20in%20blue)%20as%20the%20input%20argument%20(we%20will%20assign%20the%20table%20records%20to%20a%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdata-explorer%2Fkusto%2Fquery%2Fletstatement%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3ELet()%3C%2FA%3E%20variable%20and%20passing%20it%20as%20an%20argument).%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-center%22%20image-alt%3D%222020-09-24_15-46-44.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222076i792F3816A5336229%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20title%3D%222020-09-24_15-46-44.png%22%20alt%3D%222020-09-24_15-46-44.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3CSPAN%20style%3D%22font-family%3A%20inherit%3B%22%3E%26nbsp%3B%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EYou%20can%20create%20the%20%3CFONT%20color%3D%22%23800080%22%3E%3CSTRONG%3EEnrichAuditEvents_Func%3C%2FSTRONG%3E%3C%2FFONT%3E%20function%20with%20the%20script%20%3CA%20href%3D%22https%3A%2F%2Fgithub.com%2FAzure%2FAzure-Sentinel%2Fblob%2Fmaster%2FTools%2FParameterizedFunction%2FEnrichAuditEvents_Func.ps1%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3Ehere%3C%2FA%3E.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThe%20function%20will%20return%20the%20same%20output%20results%20as%20we%20saw%20earlier%2C%20but%20the%20KQL%20query%20will%20be%20much%20simpler%20and%20shorter.%3C%2FP%3E%0A%3CP%3EBelow%20is%20how%20the%20final%20query%20looks%20like%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-powershell%22%3E%3CCODE%3Elet%20AuditEvents%20%3D%20(SecurityEvent%20%7C%20where%20EventID%20%3D%3D%204719)%3B%0AEnrichAuditEvents_Func(AuditEvents)%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH4%20id%3D%22toc-hId--308871593%22%20id%3D%22toc-hId--308871561%22%20id%3D%22toc-hId--308871561%22%20id%3D%22toc-hId--308871561%22%20id%3D%22toc-hId--308871561%22%20id%3D%22toc-hId--308871561%22%20id%3D%22toc-hId--308871561%22%20id%3D%22toc-hId--308871561%22%3E%3CFONT%20size%3D%225%22%3E%3CSTRONG%3E%3CU%3ESummary%3C%2FU%3E%3C%2FSTRONG%3E%3C%2FFONT%3E%3C%2FH4%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EIn%20summary%2C%20you%20have%20seen%20how%20we%20can%20use%20the%20Parameterized%20Function%20to%20perform%20enrichment%20and%20simplify%20the%20KQL%20query.%20I%20hope%20you%20find%20this%20useful%20and%20this%20information%20will%20help%20you%20in%20analyzing%20Windows%20Security%20Audit%20events%20more%20efficiently.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CFONT%20size%3D%224%22%3E%3CSTRONG%3EDownload%20Scripts%3A%3C%2FSTRONG%3E%3C%2FFONT%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CA%20href%3D%22https%3A%2F%2Fgithub.com%2FAzure%2FAzure-Sentinel%2Fblob%2Fmaster%2FTools%2FParameterizedFunction%2FAuditEventDataLookup_Func.ps1%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3EAuditEventDataLookup_Func%3C%2FA%3E%26nbsp%3B-%20Enrich%20Category%2C%20Subcategory%20and%20AuditPolicyChanges%20fields.%3C%2FP%3E%0A%3CP%3E%3CA%20href%3D%22https%3A%2F%2Fgithub.com%2FAzure%2FAzure-Sentinel%2Fblob%2Fmaster%2FTools%2FParameterizedFunction%2FEnrichAuditEvents_Func.ps1%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%20noopener%20noreferrer%22%3EEnrichAuditEvents_Func%3C%2FA%3E%26nbsp%3B-%20The%20nested%20function.%20Make%20sure%20you%20have%20deployed%20the%20above%20function%20before%20invoking%20this.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ESpecial%20thanks%20to%26nbsp%3B%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F293879%22%20target%3D%22_blank%22%3E%40Ofer_Shezaf%3C%2FA%3E%26nbsp%3B%2C%20%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F538161%22%20target%3D%22_blank%22%3E%40Sarah_Young%3C%2FA%3E%26nbsp%3Band%26nbsp%3B%3CA%20href%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fuser%2Fviewprofilepage%2Fuser-id%2F197035%22%20target%3D%22_blank%22%3E%40Alexander%20Sloutsky%3C%2FA%3E%26nbsp%3Bfor%20your%20help.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-1712564%22%20slang%3D%22en-US%22%3E%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-center%22%20image-alt%3D%22ThePlan.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F222077i6A37EF474E17A9EC%2Fimage-size%2Flarge%3Fv%3D1.0%26amp%3Bpx%3D999%22%20title%3D%22ThePlan.png%22%20alt%3D%22ThePlan.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ELearn%20how%20to%20enrich%20Windows%20Security%20Events%20with%20Parameterized%20Function.%3C%2FP%3E%3C%2FLINGO-TEASER%3E%3CLINGO-LABS%20id%3D%22lingo-labs-1712564%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EAzure%20Sentinel%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EHunting%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EInvestigation%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3ESecurity%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1761851%22%20slang%3D%22en-US%22%3ERe%3A%20Enriching%20Windows%20Security%20Events%20with%20Parameterized%20Function%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1761851%22%20slang%3D%22en-US%22%3E%3CP%3ESo%2C%20in%20addition%20to%20a%20request%20to%20find%20out%20how%20to%20remove%20two%20functions%20with%20the%20same%20name%2C%20I'm%20also%20curious%20if%20there's%20a%20way%20to%20specify%2C%20in%20the%20function%20creation%20powershell%20code%2C%20some%20non-default%20settings%20for%20ClientRequestProperties%20values%2C%20so%20that%20those%20values%20will%20be%20applied%20to%20the%20code%20running%20in%20the%20function%3F%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-SUB%20id%3D%22lingo-sub-1761843%22%20slang%3D%22en-US%22%3ERe%3A%20Enriching%20Windows%20Security%20Events%20with%20Parameterized%20Function%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-1761843%22%20slang%3D%22en-US%22%3E%3CP%3EAnd%20that's%20one%20question%20answered%3A%20Running%20the%20script%20twice%20with%20the%20same%20function%20name%20appears%20to%20create%20a%202nd%20function%20with%20the%20same%20name.%20You%20have%20been%20warned...%26nbsp%3B%3CIMG%20class%3D%22lia-deferred-image%20lia-image-emoji%22%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Fhtml%2Fimages%2Femoticons%2Fsad_40x40_1.gif%22%20alt%3D%22%3Asad%3A%22%20title%3D%22%3Asad%3A%22%20%2F%3E%3CBR%20%2F%3EIn%20the%20above%20case%2C%20attempting%20to%20execute%20the%20function%20by%20name%20returns%20the%20following%20error%3A%3C%2FP%3E%3CP%20class%3D%22lia-indent-padding-left-30px%22%3EDetected%20multiple%20functions%20with%20the%20same%20name%3A%20'name'.%20Resolve%20the%20conflict%20to%20allow%20these%20functions%20to%20be%20used%20in%20a%20query.%3C%2FP%3E%3CP%20class%3D%22lia-indent-padding-left-30px%22%3EIf%20issue%20persists%2C%20please%20open%20a%20support%20ticket.%20Request%20id%3A%20id%3C%2FP%3E%3C%2FLINGO-BODY%3E
Microsoft

 

Overview

 

Monitoring Windows Security Auditing logs is essential in helping SOC analysts to keep track of any unplanned changes in a computer's system audit policy settings. If there is an indication of a suspicious anomalous activity, an investigation needs to be performed as soon as possible. Hence, the ability to analyze collected Windows Security Auditing logs efficiently in Azure Sentinel is crucial.

 

Windows Security Events can be collected in Azure Sentinel with Security Events Connector or Data Collection in Azure Security Center Standard Tier (If both Azure Sentinel and Azure Security Center are running in the same workspace).

 

In this blog post, you will learn how to use Parameterized Function to perform data enrichment and simplify your KQL query. We will use Windows Security Audit Policy Change events as our use case for data enrichment. You can refer to a list of Audit Policy Change Event IDs here if you are unfamiliar with these events.

 

First, let me give you an overview of the use case that I am about to walkthrough: let’s take Event ID 4719 (“System audit policy was changed”) as an example. The following event 4719 is logged when the audit policy was changed.

 

event.png

 

Below is how the event data would look when you query for this event in your Sentinel workspace. As you can see, the Category, Subcategory and AuditPolicyChanges fields are captured in their IDs by design instead of the text values. This might be a challenge when you need to understand more about the event or perform a filter based the string value such as “Object Access”.

 

QueryResultbyDesign.png

  

In the following sections of this blog, you will learn:

  • What is a Parameterized Function?
  • How to enrich Category, Subcategory and Changes fields with parameterized function when analyzing Windows Security Audit Policy Change events in Azure Sentinel.

 

 

The Plan

 

Here is the summary of what we are about to do. In the following diagram, I have lookup tables for Category, Subcategory and Changes with their values and IDs. The diagram illustrates how these IDs will be mapped to each individual table.

 

ThePlan.png

 

I will simplify the mapping process by consolidating all the values for Category, SubCategory and Changes in a single lookup table as shown in the diagram below. This will be the function body of our Parameterized Function which I will discuss in the next section. The function will return the corresponding value when provided with an ID.

 

Lookup.png

 

 

What is a Parameterized Function?

 

Parameterized Function is an user-defined function that can be invoked through the function alias. It accepts zero or more input arguments and produces a single output (which can be scalar or tabular) based on the function body. However, Parameterized Function is not the same as the KQL function – a common feature in Log Analytics (you can refer to this blog post for example) as the KQL function doesn’t support input arguments.

 

Below is an example of a Parameterized Function with a single argument (ID). The function body is a dynamic table with a list of IDs and the corresponding values. The reason of using dynamic scalar data type is to allow scalar expression when passing a column value as the argument.

 

let myfunc = (ID:string){

   dynamic(

    { "%%8272":"System",

     "%%8273":"Logon/Logoff",

     "%%8274":"Object Access",

     "%%8275":"Privilege Use",

     "%%8276":"Detailed Tracking",

     "%%8277":"Policy Change",

     "%%8278":"Account Management",

     "%%8279":"DS Access",

     "%%8280":"Account Logon"

})[ID]};

 

Here is the example of how the function is being invoked. The function will return the lookup value of the provided ID:

 

SecurityEvent

| where EventID == 4719

| project TimeGenerated, Computer, CategoryId

| extend Category = myfunc(CategoryId)

| project-away CategoryId

 

However, Parameterized Function can only be created programmatically (creation in UI is not supported at the time of writing). Hence, I will provide sample PowerShell scripts to create Parameterized Functions in this blog.

 

 

Create the Parameterized Function

 

Here is the sample Powershell script to create the Parameterized Function for the lookup table of Category, Subcategory and Changes. Edit the Powershell script to provide the following information before executing it:

  • $ResourceGroup: Resource Group of your Azure Sentinel Workspace.
  • $WorkspaceName: Name of your Azure Sentinel Workspace.
  • $SubscriptionID: Subscription ID of the Azure Sentinel Workspace.

Run the script after you have updated the above details. The script will prompt for your Azure credentials and it should take less than a minute to complete. Below is the sample screenshot of how a successful creation looks like:

 

PowerShellOutput.png

 

The script will create a Parameterized Function on your defined workspace with the name and alias of “AuditEventDataLookup_Func”.

 

Note that the Parameterized Function is not visible in the workspace UI, but you can use API to GET the function details or List all Saved Searches (including Parameterized functions) for your workspace.

 

 

Using Parameterized Function to enrich Category ID, Subcategory ID and Changes ID

 

Now, let’s begin enriching the Category and Subcategory fields using the function we just created. These two fields will only have a single value and they are more straight forward. We just need to invoke the function with CategoryId/SubcategoryId as the input argument.

 

CategoryAndSub.png

 

Below is the sample query:

 

SecurityEvent

| where EventID == 4719

| project TimeGenerated, Computer, Activity, CategoryId, SubcategoryId

| extend Category = AuditEventDataLookup_Func(CategoryId)

| extend SubCategory = AuditEventDataLookup_Func(SubcategoryId)

| project-away CategoryId, SubcategoryId

 

The query results are now showing Category and Subcategory names instead of IDs as shown in the image below:

 

Pic8.png

 

Next is the AuditPolicyChanges field. This field will either have one or two values separated by a comma as shown in the image below. Hence, we can’t pass the AuditPolicyChanges value directly to the function like what we did earlier because if the field contained two values, the function will not be able to find a match in the lookup table.

 

AuditPolicyChangesField.png

 

But this can be resolved with the help of a few KQL commands. First of all, we can use parse_csv() or split() command to get the string values from the comma-separated record. The returned values will be in a string array. Below is the sample query:

 

SecurityEvent

| where EventID == 4719

| extend Category = AuditEventDataLookup_Func(CategoryId)

| extend SubCategory = AuditEventDataLookup_Func(SubcategoryId)

| extend AuditPolicyChangesParse = parse_csv(AuditPolicyChanges)

 

Next, We will invoke the Parameterized function for each AuditPolicyChanges value using the array index (AuditPolicyChangesParse[0] and AuditPolicyChangesParse[1]). But be aware that there is a whitespace in the AuditPolicyChanges field after the comma as shown in the below image, which also appear after parsing. That means we need to remove the whitespace for the second value of AuditPolicyChanges when passing it to our function and we can do that by using the trim() command.

 

whitespace.png

   

Below is the sample command line for removing the whitespace using trim(). Note that we are using strcat() to concatenate each AuditPolicyChange value returned by the function and separate them with a comma.

 

| extend AuditPolicyChange = strcat(AuditEventDataLookup_Func(AuditPolicyChangesParse[0]) ,",",

AuditEventDataLookup_Func(trim(" ",tostring(AuditPolicyChangesParse[1]))))

 

We have now resolved the scenario of enriching the AuditPolicyChange field which might consist of two values. But what if the AuditPolicyChange field only have a single value? Since we are using strcat() in the above query, the record will look like the below image if there is only a single value.

 

2020-09-22_14-38-19.png

  

This will be an easy fix as we can use trim_end() to remove the comma at the end of the text (if any).

Below is how the command looks like:

 

| extend AuditPolicyChange = trim_end(",",strcat(AuditEventDataLookup_Func(AuditPolicyChangesParse[0]) ,",",

AuditEventDataLookup_Func(trim(" ",tostring(AuditPolicyChangesParse[1])))))

 

Below is the final query for your reference:

 

SecurityEvent
| where EventID == 4719
| extend Category = AuditEventDataLookup_Func(CategoryId)
| extend SubCategory = AuditEventDataLookup_Func(SubcategoryId)
| extend AuditPolicyChangesParse = parse_csv(AuditPolicyChanges)
| extend AuditPolicyChange = trim_end(",", strcat(AuditEventDataLookup_Func(AuditPolicyChangesParse[0]) ,",",AuditEventDataLookup_Func(trim(" ",tostring(AuditPolicyChangesParse[1])))))
| project TimeGenerated, Computer, Activity, Category, SubCategory, AuditPolicyChange

 

 

2020-08-28_10-34-39.png

 

 

Nested Function

 

Now you have seen how the function works, there might be times where you need to create multiple functions for different purposes (such as enrichment, parsing, filtering and etc) and the ability to invoke another function within a function will be useful. Let me show you that in the next example.

 

Below is the query from the previous section and my use case is to simplify the query by configuring the yellow highlighted lines in a parameterized function called EnrichAuditEvents_Func. This function will take the table records (highlighted in blue) as the input argument (we will assign the table records to a Let() variable and passing it as an argument).

2020-09-24_15-46-44.png

  

You can create the EnrichAuditEvents_Func function with the script here.

 

The function will return the same output results as we saw earlier, but the KQL query will be much simpler and shorter.

Below is how the final query looks like:

 

let AuditEvents = (SecurityEvent | where EventID == 4719);
EnrichAuditEvents_Func(AuditEvents)

 

 

 

Summary

 

In summary, you have seen how we can use the Parameterized Function to perform enrichment and simplify the KQL query. I hope you find this useful and this information will help you in analyzing Windows Security Audit events more efficiently.

 

 

Download Scripts:

 

AuditEventDataLookup_Func - Enrich Category, Subcategory and AuditPolicyChanges fields.

EnrichAuditEvents_Func - The nested function. Make sure you have deployed the above function before invoking this.

 

 

Special thanks to @Ofer_Shezaf , @Sarah_Young and @Alexander Sloutsky for your help.

 

8 Comments
Occasional Contributor

Can you share a similar script that will delete the parameterized function(s) just added? I'd like to play with this, but have no idea how to restore my environment to its previous state. Also, I'm unclear on whether running this once, making a change to the configuration of the parameterized function included, and running it again will overwrite the current instance of that function, or simply fail because the function name already exists. That said, Bravo!! I'd been trying to extrapolate some of this content from the documentation for a while.

Thanks

Occasional Contributor

And that's one question answered: Running the script twice with the same function name appears to create a 2nd function with the same name. You have been warned... :sad:
In the above case, attempting to execute the function by name returns the following error:

Detected multiple functions with the same name: 'name'. Resolve the conflict to allow these functions to be used in a query.

If issue persists, please open a support ticket. Request id: id

Occasional Contributor

So, in addition to a request to find out how to remove two functions with the same name, I'm also curious if there's a way to specify, in the function creation powershell code, some non-default settings for ClientRequestProperties values, so that those values will be applied to the code running in the function?

Microsoft

Hi @John_McCash , Thanks for your comments.

 

In order to delete a function, first you need get the Id of your function using List by Workspace. After that, delete your function using the Delete API by supplying the Id that you obtained earlier in the savedSearchId field. You can even click on "Try It" in the browser to perform these tasks. I will upload the sample PowerShell scripts to the Azure Sentinel Github and update this space in the next few days.

 

As for the non-default settings of ClientRequestProperties, I haven't tried it before on Log Analytics. Can you specify which property values you want to change?

Occasional Contributor

So, as the Lead Threat Analyst here, I not infrequently need to go trolling for some data item that I don't know the actual table location of. In these cases, I need to use the 'search' command without preceding pipeline elements. When I do this, I always run afoul of the maxoutputcolumns limitation of 3000. I'm tired of typing 'set maxoutputcolumns=3800;' at the beginning of these searches. (yes, I know I'm whining, and yes, I also know that this would be absolutely terrible usage inside [God forbid] a scheduled search). I'd like to define a saved function, with a name something like 'longsearch', to which I can pass the string I'm searching for, and not have to type or copy/paste 'set maxoutputcolumns=3800;' ever again. Does that make sense?

Occasional Contributor

One further note/clarification about the deletion methodology described above. It's not the 'id' field returned by 'List by Workspace' that you specify to the 'Delete' API, as the 'savedSearchId', but the GUID returned in the 'name' field. And thanks very much!

Occasional Contributor

Very cool man, I've used this method for whitelisting, but I didn't think as far as using it in this way.

 

I just removed a massive case statement in one of my analytic rules and replaced it with a call to the function, I'm sure this also saves a ton of computing time!

Microsoft

Thanks @LodewykV for your feedback. I'm glad this has helped you in your Analytics Rules/Hunting.

 

By the way, feel free to contribute to Azure Sentinel's Github repository or keep me posted if you have any use-cases of using Parameter Functions that would benefit the community.

 

Cheers