From 3509ddf8ba943632ca14db19f9a79a2fb049ee51 Mon Sep 17 00:00:00 2001 From: v-rusraut Date: Thu, 31 Aug 2023 13:20:12 +0530 Subject: [PATCH 1/3] Repackage - Snowflake(Azure Function Changes) --- .../Snowflake_API_FunctionApp.json | 35 +++++++++++++++---- .../Snowflake/Data/Solution_Snowflake.json | 2 +- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/Solutions/Snowflake/Data Connectors/Snowflake_API_FunctionApp.json b/Solutions/Snowflake/Data Connectors/Snowflake_API_FunctionApp.json index fbf0d2cdac8..4e98c5d4387 100644 --- a/Solutions/Snowflake/Data Connectors/Snowflake_API_FunctionApp.json +++ b/Solutions/Snowflake/Data Connectors/Snowflake_API_FunctionApp.json @@ -110,21 +110,42 @@ } ] }, + { + "instructions": [ + { + "parameters":{ + "instructionSteps": [ { "title": "Option 1 - Azure Resource Manager (ARM) Template", "description": "Use this method for automated deployment of the data connector using an ARM Template.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://aka.ms/sentinel-SnowflakeDataConnector-azuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Snowflake Account Identifier**, **Snowflake User**, **Snowflake Password**, **Microsoft Sentinel Workspace Id**, **Microsoft Sentinel Shared Key**\n4. Mark the checkbox labeled **I agree to the terms and conditions stated above**.\n5. Click **Purchase** to deploy." }, { "title": "Option 2 - Manual Deployment of Azure Functions", - "description": "Use the following step-by-step instructions to deploy the data connector manually with Azure Functions (Deployment via Visual Studio Code)." - }, + "description": "Use the following step-by-step instructions to deploy the data connector manually with Azure Functions (Deployment via Visual Studio Code).", + "instructions": [ + { + "parameters": { + + "instructionSteps": [ { - "title": "", - "description": "**1. Deploy a Function App**\n\n> **NOTE:** You will need to [prepare VS code](https://docs.microsoft.com/azure/azure-functions/create-first-function-vs-code-python) for Azure function development.\n\n1. Download the [Azure Function App](https://aka.ms/sentinel-SnowflakeDataConnector-functionapp) file. Extract archive to your local development computer.\n2. Start VS Code. Choose File in the main menu and select Open Folder.\n3. Select the top level folder from extracted files.\n4. Choose the Azure icon in the Activity bar, then in the **Azure: Functions** area, choose the **Deploy to function app** button.\nIf you aren't already signed in, choose the Azure icon in the Activity bar, then in the **Azure: Functions** area, choose **Sign in to Azure**\nIf you're already signed in, go to the next step.\n5. Provide the following information at the prompts:\n\n\ta. **Select folder:** Choose a folder from your workspace or browse to one that contains your function app.\n\n\tb. **Select Subscription:** Choose the subscription to use.\n\n\tc. Select **Create new Function App in Azure** (Don't choose the Advanced option)\n\n\td. **Enter a globally unique name for the function app:** Type a name that is valid in a URL path. The name you type is validated to make sure that it's unique in Azure Functions. (e.g. Snowflake12).\n\n\te. **Select a runtime:** Choose Python 3.8.\n\n\tf. Select a location for new resources. For better performance and lower costs choose the same [region](https://azure.microsoft.com/regions/) where Microsoft Sentinel is located.\n\n6. Deployment will begin. A notification is displayed after your function app is created and the deployment package is applied.\n7. Go to Azure Portal for the Function App configuration." + "title": "Step 1 - Deploy a Function App", + "description": "1. Download the [Azure Function App](https://aka.ms/sentinel-SnowflakeDataConnector-functionapp) file. Extract archive to your local development computer.\n2. Follow the [function app manual deployment instructions](https://github.com/Azure/Azure-Sentinel/blob/master/DataConnectors/AzureFunctionsManualDeployment.md#function-app-manual-deployment-instructions) to deploy the Azure Functions app using VSCode.\n3. After successful deployment of the function app, follow next steps for configuring it." }, - { - "title": "", - "description": "**2. Configure the Function App**\n\n1. In the Function App, select the Function App Name and select **Configuration**.\n2. In the **Application settings** tab, select **+ New application setting**.\n3. Add each of the following application settings individually, with their respective string values (case-sensitive): \n\t\tSNOWFLAKE_ACCOUNT\n\t\tSNOWFLAKE_USER\n\t\tSNOWFLAKE_PASSWORD\n\t\tWORKSPACE_ID\n\t\tSHARED_KEY\n\t\tlogAnalyticsUri (optional)\n - Use logAnalyticsUri to override the log analytics API endpoint for dedicated cloud. For example, for public cloud, leave the value empty; for Azure GovUS cloud environment, specify the value in the following format: `https://WORKSPACE_ID.ods.opinsights.azure.us`. \n4. Once all application settings have been entered, click **Save**." + { + "title": "Step 2 - Configure the Function App", + "description": "1. Go to Azure Portal for the Function App configuration. \n2. In the Function App, select the Function App Name and select **Configuration**.\n3. In the **Application settings** tab, select **+ New application setting**.\n4. Add each of the following application settings individually, with their respective string values (case-sensitive): \n\t\tSNOWFLAKE_ACCOUNT\n\t\tSNOWFLAKE_USER\n\t\tSNOWFLAKE_PASSWORD\n\t\tWORKSPACE_ID\n\t\tSHARED_KEY\n\t\tlogAnalyticsUri (optional)\n - Use logAnalyticsUri to override the log analytics API endpoint for dedicated cloud. For example, for public cloud, leave the value empty; for Azure GovUS cloud environment, specify the value in the following format: `https://WORKSPACE_ID.ods.opinsights.azure.us`. \n4. Once all application settings have been entered, click **Save**." } + ] + }, + "type": "InstructionStepsGroup" + } + ] + } + ] +}, + "type": "InstructionStepsGroup" + } + ] + } ] } diff --git a/Solutions/Snowflake/Data/Solution_Snowflake.json b/Solutions/Snowflake/Data/Solution_Snowflake.json index fb2a02a1ec5..589a92156b2 100644 --- a/Solutions/Snowflake/Data/Solution_Snowflake.json +++ b/Solutions/Snowflake/Data/Solution_Snowflake.json @@ -38,7 +38,7 @@ ], "Metadata": "SolutionMetadata.json", "BasePath": "C:\\GitHub\\Azure-Sentinel\\Solutions\\Snowflake", - "Version": "2.0.0", + "Version": "3.0.0", "TemplateSpec": true, "Is1PConnector": false } \ No newline at end of file From 7bf165e26c465bafe8ede6b9379226843501b315 Mon Sep 17 00:00:00 2001 From: Github Bot Date: Thu, 31 Aug 2023 08:01:34 +0000 Subject: [PATCH 2/3] [skip ci] Github Bot Added package to Pull Request! --- .../Data/system_generated_metadata.json | 33 + Solutions/Snowflake/Package/3.0.0.zip | Bin 0 -> 48411 bytes .../Snowflake/Package/createUiDefinition.json | 40 +- Solutions/Snowflake/Package/mainTemplate.json | 2284 ++++++++--------- 4 files changed, 1178 insertions(+), 1179 deletions(-) create mode 100644 Solutions/Snowflake/Data/system_generated_metadata.json create mode 100644 Solutions/Snowflake/Package/3.0.0.zip diff --git a/Solutions/Snowflake/Data/system_generated_metadata.json b/Solutions/Snowflake/Data/system_generated_metadata.json new file mode 100644 index 00000000000..5954d0e66c4 --- /dev/null +++ b/Solutions/Snowflake/Data/system_generated_metadata.json @@ -0,0 +1,33 @@ +{ + "Name": "Snowflake", + "Author": "Microsoft - support@microsoft.com", + "Logo": "", + "Description": "The Snowflake solution provides the capability to ingest Snowflake [login logs](https://docs.snowflake.com/en/sql-reference/account-usage/login_history.html) and [query logs](https://docs.snowflake.com/en/sql-reference/account-usage/query_history.html) into Microsoft Sentinel using the Snowflake Python Connector. Refer to [Snowflake documentation](https://docs.snowflake.com/en/user-guide/python-connector.html) for more information.\r\n \r\n **Underlying Microsoft Technologies used:** \r\n\r\n This solution takes a dependency on the following technologies, and some of these dependencies either may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs:\r\n\n a. [Azure Monitor HTTP Data Collector API](https://docs.microsoft.com/azure/azure-monitor/logs/data-collector-api) \r\n\n b. [Azure Functions](https://azure.microsoft.com/services/functions/#overview)\r\n\n\n\n", + "Metadata": "SolutionMetadata.json", + "BasePath": "C:\\GitHub\\Azure-Sentinel\\Solutions\\Snowflake", + "Version": "3.0.0", + "TemplateSpec": true, + "Is1PConnector": false, + "publisherId": "azuresentinel", + "offerId": "azure-sentinel-solution-snowflake", + "providers": [ + "Snowflake" + ], + "categories": { + "domains": [ + "Application" + ] + }, + "firstPublishDate": "2021-10-23", + "support": { + "name": "Microsoft Corporation", + "email": "support@microsoft.com", + "tier": "Microsoft", + "link": "https://support.microsoft.com" + }, + "Data Connectors": "[\n \"Data Connectors/Snowflake_API_FunctionApp.json\"\n]", + "Parsers": "[\n \"Snowflake.txt\"\n]", + "Workbooks": "[\n \"Workbooks/Snowflake.json\"\n]", + "Analytic Rules": "[\n \"SnowflakeDiscoveryActivity.yaml\",\n \"SnowflakeLongQueryProcessTime.yaml\",\n \"SnowflakeMultipleFailedQueries.yaml\",\n \"SnowflakeMultipleLoginFailure.yaml\",\n \"SnowflakeMultipleLoginFailureFromIP.yaml\",\n \"SnowflakePossibleDataDestruction.yaml\",\n \"SnowflakePrivilegesDiscovery.yaml\",\n \"SnowflakeQueryOnSensitiveTable.yaml\",\n \"SnowflakeUnusualQuery.yaml\",\n \"SnowflakeUserAddAdminPrivileges.yaml\"\n]", + "Hunting Queries": "[\n \"SnowflakeAdminSources.yaml\",\n \"SnowflakeDeletedDatabases.yaml\",\n \"SnowflakeDeletedTables.yaml\",\n \"SnowflakeDormantUser.yaml\",\n \"SnowflakeFailedLogins.yaml\",\n \"SnowflakeHighCreditConsumingQueries.yaml\",\n \"SnowflakeTimeConsumingQueries.yaml\",\n \"SnowflakeUnknownQueryType.yaml\",\n \"SnowflakeUnusedAdmins.yaml\",\n \"SnowflakeUserSources.yaml\"\n]" +} diff --git a/Solutions/Snowflake/Package/3.0.0.zip b/Solutions/Snowflake/Package/3.0.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..f9bfb26e65fa065e77afc4bba7a0ff73e8c80ed9 GIT binary patch literal 48411 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

GVB}k#6>KuWqJ~2t#5Lc@=NK(kLmz+k;q$r*g zSPl$O^-p9^i%<>&svI$EYX~=M$BsLxL=9Bpa*0U2wwsn^W#AooIL zuYoy+D(8)DEIyHPBIL`dtZUj~O(3;)U>Z<~qN=T;$bTjkz%${~-44iED@CN+qT>Wk z342)kaqbq+!d99Y7dvhPKStGO)m(;4xQkE`oB1<<5O6cHq`)-F+M;eKX3!^v=+&k1 z3hYeYJPztNC*u{zc1ospl|7j*@eSg?#(HJX7FPWwbk_`nKE)Hl75@37hu=GX8XQ;H!S{YeL@9H5aQFE^scF+VXb$Yzj0vKK@xKe%nM<xvd5lPk2z zx3@9lr!p%=9W-yuEq*Q>+`HX(1c(t7tNYhfW*hdyRDb?}HdP6C(SI3WT&xvut?#Zf z*M^mO|Mb0$VeQUUc9ho1X2aM-u!aAT>{Tv#v4XhUfD_OV@0XE%zn*FjwVBb)uPX_Z z68lC!-2@v-SK)WHpsg`K|2N*~-;goCh(BKCAd~;BNZKh@`FEb=2Sz*gDG!1rk z6wKdXWEn+>M_I7Kl14BQKMz~C2hRV%Sg#khls`Ltot%6;STy!*B`X*sc2b<-X{&&s z%b&}!SL9@MTn}s@93-lf5dVp0fe!l84zJ>=VE30FGMTPxh32?b=GR1KtoeYSpD&=7 z-f4COKaT_Q8!BZ9{evGoJqw5uJ|};Ws{M$Bci{pcsvV!HmiBnJeiZMWK0xtqhYiUT zr0UL`zG@7|GD?fNj)Z1X=N|8pBndjbA(PfBYl-qZ^rm423+RBb1+Fr~HRA(GvGL}# zJsMhdOk}A^bhJeBjV+df6gpxc=pF|ngGr-f%g=1;LB9=qY$+^*dHd)$FC0Nml=r8v zA_etn%~YAD^JjR}tozYnc}(%6PF!Ygu+1~h*FXeLJ8ZlExy&=SdDzFq$GGJVAYtJQWwBbZ4zr5&=Z7TJwk>>Sr2_QPEjkRJ8el zg!JTIwxFl22vh1MpiZDn$t~$bD6YGhKI!Cg>0!>biVk$0<|>*5l0>tlf$37s=~e?I zzo_FR5PdBh@_BGff1Jzrb7~N-RF4=*Bzf{Y;!FFvOSXP1`xnjoC z(`$rJ{z0-jPS}@G(F`I#s@H(mEccK?qLBKVOxj_xkRH)A+Bo7Gi56l5j-Y@8h?N+u zAgvz7`0dmRXmInYlkmKOa?f|CtFvFU|A7sq_oEn`!C?K$cIhaY}p;G_jn1 zg;_Ha5S%7%1lyu7vTw5C$9Q@cZPA75B0NaX(xC#6`gviSihK$NzEX1c%#sR`@O>r; zoDFecJ!#j?O--eOthC^ab$h#KBs4(1>c*bh=IJ2_2Ds~PpVri5(mN*<0_kt^Ckely zx`3i;6STcO{V#@RnuBfn?y`nauQaqia&L?xJBth2DHzn%n zCnq|nRwl#gTCnCRHgZWMcq_@DA+Fz^UVj&!TmA@QtTStH04PgpmI4m*NwQbvsSBSnUdwx#-`! zczr6kJm|tONY?&3)_OTRp3$9xE#=?X4-EPw4t<6D(z_A{17E@;v!hnd5`$_Yq< zDr%jMGvdek%!q;|VjxQ~gQKF0o5PSAC84N9{ABRvv*jZb;=J~2TwgfmC$qK19Te=L zVXplCdwopG&0J{rG&L6RtMyr;1|uBl|62FBzvit#Mi7wzXr*F9{Na7{Q*a-^ z7gpM~99^o`GI7e{suCXq3OyXfLcGr-F3&A!N zdAdcVaQh-J{j%BIU^Yxs7ubY4bsD3zHR;%+MG*rYN#GWKoS<=DUYU$5)?NuXKA{zkX`EdX8*DD-z91}+5NHY`^Zb_ z33fzMy@WpCIrcYYO*_m{AU&`_6>QD^AtDe|slY0HKrqm;5jG{9<503r|G-R)*Dy{2 z3IjFBj>6ZjvO4>Y28kFU%b>#iULnE&*Dw<^u~mm%3Et~w>6thkU23^d0aybh(bv8P zKpIPCf-x~k_fVOFKF*WRgY>|`wdf-m$M1>?4TD1?tm+JN_v`JBv8P#Cu`cuY>%R{n zFV<_<5dk-TvazGnGXK0$uVB|$NXagFKqub?!COG8RetKnJgq7>#-ec-DPCw4zd)a3%0(=E z&xCj!Fhh^I(LWg_%?pK|E|F)rrE}rE3meQLrVR;-Uz9)2gqywc1HKWT^h)KcgR>Gl z8NK)}Jm>J_d6eyolB0iYAwMogC!?QypMV!c=>sYJHO;~2jVB=kq$Pvkx=I#umWW|$ z1_j11Ps|HV_rpWEu6xh(@#Dz<0jZ-%B2cAVD$GXK8onj? zF#3`%cMjineA!~^#49N5^>AJOdQ_+TYf4U~)_0UJtDy=shw)59IjT3?0XpUQn$&CE zqHAFhMPSLvgn}PNA`Pza$f0jh=$D~mMRU2-U~#>SNkb#gjg2DHEAOJkA=300XpHZs z_U=mh3%&&2SC>)@JfP3jBml`hxO>;zh>LXMd)?IhmN=rs?eAcjFZK){(~vGS;Z)IA znj9kyYDIGCzK;hR2w5d^58^sj#6O}NrmsdwkKkNZ*oqvji0wZ?tbc+#R}m(^!vP%! zhQnc&QJ)BdFjx_V`fEY3xS6ePGeVtRNCx`n6X|T4E5T580o}K_4D|w4LNx#t`FFAwnm`cGAKNa)GM4eCAUaxfdQ|l4FrK{RZ0DOY94{=Mp7ouL>)A!Ad zs6CL|0dP4p*m~04MHB2G1?Iv>V4m$jBLv-vcy#G_hIZ-D!X}q@avXYjdUS6VZ48ww z9ZF%sKo{mZ|B(f(x)|

}&>kV1^rg!|Oi*7zhU>t?^KwS%R&K0*Oz6VHE-CTOf0 zH~|{U40WhON1TwhNzJg_H=>wLy;+CiIh`3@B?T}dY?|?4Vzo-*HY|l_yZpB;)>s>y z<+75aBcc$8YoxpoQ{_s16X0SOO8q^tv$U8O{hoOQc0zO!Y{jOm>!q^qTF%fdkDJ~t zY1PbHy4_~;GNnUY(Xs23YTN|B+B22Imo@$phPcd>P-&4S|(nAo$@5d9Zur3M~*O z%oYD!(VMFHxzU}T?yqGfJ_ZefdMqUolfashAc(hpZyQgxj>Lnal~Mu<16+`y@`TN$ON z@E%xa)Md4@dThdafbVh06F=%qdR9+7KuGTzNquvWhclePhmlNzB}lL3rU@G0;!woLAL9&q{+e;V8I`zcn17tIW1--OyGPEk(Q4Q)+H~pkO zJN3e7YB6O|GO~LUe(e_Nlvc|dy34&SM{8_m(ec#K{q2unY?RfUx%`%b3y3APid3>K zWb)yr@(jGZ!l39{el>w1T-F$|BA)}2-jN@2~7~}We;}+Z7{Ti)ZMMh5eqW0J{ zVsJ#X(%7zKGkdM_XC+r!7mf>GDZfDrLaWr8<($Vj-;Pf$pZ1jX zTa>5{$pN-orgphvbFtQfL$IZAmw6P7LZpsb>|t7-jR~dikldipd6o(>NP?0pu25y) z{J#%b2US*~;Es@XwWOrEd2Zr>se4G@n4hEKc(!I~TanI^7ldFb!JcePAnp zNtvpk?em1%Vv$pM8K}2A?r({bhk+JQpWBuPVmsnXsAlF=m?1B>6-;~;1TQ3E0RR_5 z?A5H7o|Y)t2l#~o19Nz(g+973&A+^o(9ZP9qLs)%E^~JU)&vt_Qe!)zr;PNDGz)9+czw#W!op;@NjlH$Zk= zzmRNfAT#;=o6DX>%+i@YGbbgPdbFGf{&0DQ#r3i?uI}$S zsmWRB3}cEur<|nG8un7|ziWv}V$efsUbcO%*_gOx+Eq8Gm#=>1tRadIGc5jTlOMqP z&qT$tuKB5t&O+WQ%X|LTQ|z~ZKX4Z1NbMR)o58vp1;-8pYmSMRAQ(t21ki#bHy;;f z|F5wT40Z4UvAhnk1^As zaV-Tl-ty_?&@A!R9*u2d`QZ;?sJD~Sf+5C&)Y!<@(nqGD;%}Po*_hPC%~M(Eh#hg< zmc;uWmg3rawi;}!V7qyDH7XQ0!X7D*Z|@{9&rydg^1-lwVc#ds9Wr{YVN!rjEk0A9 zZZ2<6m(Pn*o~V+7I+8grWPJPm`C*OYFiz`c>7Gtai(NE$`%Cn*5SL0jXJ0!E>XdyM;BiPBpBEBd2ybpWj-pSenr>Va{aTXexryWxT2x~>+uu92}j|` zPByP@o3<5gEUprV8rxCyka_SL?0Y1OpaSD-jK~~|>fXTJa*ePKidJCeCB9EDw?&Ih zjYpl+4~t|}AuE#Tw9~;a)AN(}8dPbd`_Xw-Rb;Y7wRk^B$}4@tdMIk+jpOlcXf(oE zo(G$maX!)nh0F~y19}t@Z@-a1^H|Qfx8~zVKXfoduw-d3s-t{3c={TlMx+FbeCS+@ zS~P=muU_SLu#E2DDpVHOlQPpkg+Qh1!6`Hw3Q-2s9K{Cz%yK|`^1%#GuCE}_P>4W^ z72D__Gf_uBf09kFnjSBkTtq5>!nNC1r>A6YnhuexBFC!(lfr{g9;?L(M6Ixii61e& ze{KKvl@k{Ve&5@?hH6D`^&J=0yB;dK#t5(DOB}v7Krvx!-qP;%3m%F(W&BP}W)6h& zvIU`vsu}LAhmBFc`_jB0e)fLV296@T$fYxAkD)tw;&NbDJVt6pEP)#fYfM)Ic&kjvFp5z~^8;VSa({Y!`?yVTbvciFX zk{i#{z(uJUl$w~qpLOIGCB^!wS|3VQ#bS_7A-tluutU767yXI#ho#$~-^heugjO81WLFYlpV`i7|+j}GJwiIRYivPs6>H(+k& z3;rUXK~gWR9~$@YDx}FDrvinCm`pj$BZ~OJOGEp~+=RWeqNDW_vnpgt5A(wQrD#Br z_-M|Jedm@dljTUk+B5A7%!%D-)J_tAnHdbZP}fr;%^vsGsI)dPSc3$|b#K=R(I$Sl?n zabg2AVE}D;)*lTiAd%)>kHsAW%gc{iu(y0AmOu!GwE(V_V(=aza+W+u_d@n+@EaMk5PQU_cQ>v$iECYwdu(HqzKV19uWX+`N#+_>Pvm@%{A;)+ zq<=(MP9BEHA8R7;0P3mfA3Z~gTs$7$3b{qP4P$dS7v)DC`i@3#&gXjZ73i!>B3Pr@ z0OOYKysD@B9ft=9M*J9Q%=V9Oa*ip>I*i_r?X$If^5d$au{hPG{b zRAl&i;)x=25C<0dfn$2=YA+7E$=mR*EtaG6oUM_+{0-;wt)`2AB7HY>q~{8xAHYvxh*HR929@*6VIR!wMBNRQTa z@M1}pTpo;6kvVu>50a|2`8*hyWzRT5p=M7F3Hya|Laat!x-e%*Cg8(?(Yk!?BOck9 z3S4p+Hq68F&|EzOv?6`&zSFt$(*PI@gQ9>iGs~rNiMGu(Wvs84j!z%mjG8cmg{ zD;E@C#cVq%JcP9)5EdGc*1!HZ6<_Cb)cHcuPvycb0@)I6eVEAFw$3il(Iv7J7%Pcb z^;iryhS)b{X$ms8b6#IDD!+~5udkMp-ZiR=Ix@DYD-Jhftx=?R+ z^OIj;#}zRT(iSM3Q;#?uvcBMJN_*?1!u&(*)g8@RY_849dMKLjW$4h;w}8MerFKUR zimLPSIe*=DJ61EHsB-z*V_dS}gca(1+X2mw4Jj<8vzcu!En%5QO*$0^T{fIF zbv_@{m8kF?k6C$suW%#qj67!2ScRmCoVKq~|g6r>@hHwRJe920L>;&(}>RiJ<*rz$9fYJ3C<3A|OIpkiJp&lY@QXE;1+$-%_wndk7RUnvz(?KJh1M|k@Da~nYA zbpB~EOKhnWZd_(+V3YZG3^DgOL-=UFPoUJ-N|}7tZKwC?^>RV6Q$)z<9ljmUeTLVm z?9!(l9SFmXO11^JYQ-O-W4Qpo(YMeQnl3(7!)bP9WRg=uHHtO(m@e>37cg1#hvzE+ zRVYqPzAh%(2rHeH7^?8zP&IRL|FKShDJN~ZN?jHAS!e1dUWBnvR<3C!yQm$FqFe+o z8$=sg;=u`x)b5!1<1J8078nE#=>J}V@;?n2i0J<{9GA=MK zFfMv&a74HRj3!+duKl!U+O}=moc6SB+qP}nnx3|8>uKAz?KAK9|2ZeAR8l*2C9AHw zYwuNCUK$J>6#xMI0HlY`D34P0g)qVZ0QKSk0LH&jBS#YhXA>0*Q4>=OTMK6kJ6n27 zCp+6sEgPqGcH}Q#mS+OSvnlmEiR2u1+03@a{f2e&c~TdYl2?5XUc{dfoI&7V{;CVv zW>4qpB|BsL59>lr#ELR`&nJt#N`92@>{WA`b0P;JG^Hm)FjR z(!@>0)=cc-{0xfBu6j*dMRBUrKCb#I*-wjOm{Qgs{lJvIxpgEJR((irp}6T4@R(}Y zV{ZjkL6l{J7XoFE8O}1{1_NKSUuwyy}Qm8^`k-+>!J-5FEa| zQEW<#g+ed|HkIUK*C%+ackvNSm@wpAzGN7R6wknVuh?#N887K8EP?|84_u!>1x&pc z@}3W0?B4^Mn;dhsW*r>|)_W{N5`t>R!=qy!lxak}nj!kaH?YRH6bbQ%%3;aIoeb{; z8*>tx#u|epNl3)NjgFW`PW$CN48cK@3>n94BZZLjqiu&MU^@{#*SV>vfq$u+7WX{P z(70?!I4!39e4LZDNF7XJM0Fg?+^|@atNZ7mKVWxsY$UyWF=t4NitUyc+{ckR30581 z%4#LjB35k}Y5;ef(U^YJesq1Zn?j5sT`ihkd^VCp7UL(U=AizugK~$8H~#aWSXdi!3Mm>1pEehnS?ryf8Zu1P^5U# znc~sfX#%VAKeVBV(w0!kJVc@*Q$a`^V?X^ZUmG~_!LC6EifN%tvvDb^_4Zofu!ZnN zt<58gB&b=?t%Zg-W6(*g(byvum_X&gr!f)pYXfEtU?12C+e6JmNED_UcB3MbOaBl) zB<(P;cI`^pJg`{7G7`FsMz~nrX$qeNbu*AB899o=K~#p+n#Tw2r?D|sIJLZy_7o8& z1bHtRAshhymS-cyy!ac7Oy3pwMT#uHy}+Rxo&|Qu#2ssV->Th#;;cHxOH6&OZ_2Vs zycQ<_-bHpMm{bVMTE7SvUuDMc3l9O6jm#Tlc1C@PM|{?PNJU<>qjo!zyd42SIh}^e zAwLyPWrjMXihx+N!^8YW`CeH>LZid_ zebR;1kdxw#pyaeRJr>B*<=1v@pg4V;=VFj@CoJ2YN?e-06P`ja^Y||UC3VdhwpX?} zYGPXJW#>?_sE+1i+z<8VaXh)GsEPWqU}uYpHvPKN(W5uGNtjls?zrkLQPx}<% z-;5%yR?6Dw$)6ct2|wxUqqDIOok@amAs->}^zgh#Rj8)ND~VO7(j7H+IXTM} z6qWN56=gUrXB%ccfe=Sh#?92Up;0Vs!3DoDKW19(lyDHOzzeY;@sCuD2Z)nIC6j&Y zYcsOWV9@EKw`(x#1nlJp`t0rO*D5lxQbV2&a1}(yay%+wBf$;{VKf z`G4q3)Hkbs!R3qO;h?K?Ayw;tCX4apl|@XIb(zg?0ps;K-WTF8WV{9}rh&zuSBLQ7 z{8hK8ZBuCXnM{S&b;P78JSCz$Q-x3q@Ut;}U`3X>FQ=~Ti>mihWf}SSS@uR|PBwC> z#)>g1)%Y{(X3Yq%%M|nKcGVAYKOerJXd#Yc#Ep|HGh<4?hjuZscJE2q=(G|&!OO(% zJjk-`l*z;t4DS~U!&{A({1~BtspFLI{y?jm;^3iTcySXVh(yvy4Vxvzv8WI1C;&7Y z%$s$h9_n8s*W-u3uI;pXsu&aN23+;Oi`k$c3!JSba!RbnI2M~5&z_RbGNuMf zdfObts7h73*EA+Mo0KG#Z0#$*j4p9y9JKFDSc)vJ42k6?Zgom=FmIo=uXn$^GMK4Dd# z@4Zg4U+k%o>x%U!%EtV`yvIQoG%!lui34QFwK^@)pWy~9^$@7G&fGCi0tHT=st6k%CrA!e(p{#wZLR9aoP=rW+re~LXJA@qxK1yrIVpz>ub4eX*R(hl>m46ooLOBSnu zKlDw`Nq(vusVIJGaXhf-tK+$w-sa*6e( z_pvS*+%4SJ2r{gb^>lra+l#K_q1odx1({c+d{eZ^@^b7P-7Rj!>b|@pXOATR*Hi9j zwChmL+05$3yiF?(kYZ!YW35QpA^vL;>ez3*4RsHhmJKPZP7>KekWq`R0#%F{~`gYF}hcZ&Ds=AL=ch45t#= zZ#iEqXy~Ww8<&%KpXl#$cW;rWO*_W<~(J+beLvUh$Nllj5r+lAa{27SF z{DY0DvPKtx&Um*wJBMxnd|uEJf$#Soz{-2xU`{^O#yj?f?3{C|w~u#rmlJCUQKyI! zYN_~5-aRH>+bnBODlU!4YHDaEYjPYPD@>udp<7UC1EBQegg_G2x5-U{#=eMgX!$F2 zZ!k_+G0vNn^n0R4P63)PJrVswa;w*_&x1R{(C}^CZJ#n?m?~b7Id7_v^V3$dQye>) zt6)(^5(Qb&5*6YeRSj~kQ%E0oNFVhV!al%P(5rZKr1A+Xn#dN!R=ebj(9s~1jolBX zCxah|=#X1nN3ezVm}RjM zaMyiS!GzgXGZ^!!u~pgtHbBY0wX6Vr^z#lrfJIIyJU)y!{+B*v5_qpWb;&8z#xp5I zkIq4gM3E#b0`E_Zly31kImV}r9~keKKm7F&Zw5%kW=M2}xP^9F!YIGuC-b9<3p08G z!XmDJ`{w}=hQ9c!9dX5#EPWk7$3eZsIs{DpylGJ_+fi}04+FG4TDSHP2hpw&s%Pa4*eE$hWagx$y?f;rBA02-D~I>bF*K9_7w zkIb2usO+hU(oHm{)m%9dHrd)9SPA>>|98GSJk%+!wb)8G5ka~cRBA||q+eMo)vMl3 z%k93o(!#H{m6?;$>=R#C?$aM$>m1ZgYfVLGj-z5rpZ@ldSMW8HCM}A7o?0(|n$MD> z5pM#gqtrM9C_jg)k%p_{L<+_Ix4<*Bqytze>n*VOtG>#;iXIo$>2714AUVL3Rrrec zX@2CM@%EbB!qFQ!pOfq`vO|uU6C5|tlep0H0H8y6_@ z{meC9=+`p`4rJVASH@O&>!5$%#0(WP)&|PUq~T#ElPLW5WCqPHZ5EFt#-z%~vBWmQ zJ54M(m!BI>4f(D&k!(%?W7}NVwckLZij*&={E$#+#;1z3FQ(LrLM_3kg56yZ=4{j9 zv@DCGGat*P%g8k}+#PNQ4|{2@q)LsQk#|5_K12MChWz^wrp#7{Q$?NA#j3wNr{5y5 zUx9~pK}StRWo+JBYi?mzy*{jzCc|hbkbRDKb(SZ1J~(*(rQbpe<2MTW@AXW3%`*G; zeES7pAB*g4Xenuhd%yzfW_)%*42G;mP&3tfW@$TK|EX~QsrT+f6-*fnOqrc5XO|ME z$PK>urM8K61-UL+!moOw z&7h&hFJXs*Ux4J&B8&DniWYlb*?i4pL-o9PW4Wj0reXG_@%H3;oKENc8U6hkS}4E^ zR3I{H>{<-kCicFwsBq-26t*Jn*wS#Uu}17};q6SwujS~5;NXUrehn=QATl~|Ez@4L z%)U9_J|pLNHyhawO8FrAHrnYn7im{3m#Gnz_b@+5rbC2NOM)|tA-l_E*V(UrQUZlb|SR*m^dyIAQ?#D~cIK5QF%S>2Asja9q ztI~~zZA5oLKLh9_2kG-i_;~>8y+z7}aPGK)&5VDWEUALsb83cW=o<7o3oLMw*v68M zn;{5$U^-223U-ZupB!&aJE00hYP2=^GZBimbKy#rUha0q6^$j@v{kdR%bHnRrt;y_ zvn#dyi~OvKmdZ%0^*|vDTEx$+AY~p5ur_75}*7|8e`?|2VWIS;YUiwel?T zKR8V|9o77)x5Fb?B1&^N+leOB&>7C7OtODO;9O6ZdcCb_x@~RJ?MT`!`rCghcC$Ip zbGyt#xJ*#yL579yjU`&0!*}m7e`@8Rs*Um;rupar3Jorb3 z{v)IRkJHK11H*(y+wrp&b$RUEl1^pJ=h_q;Yb5)p!-UJR?ux-)k}L5Q+LdX zDfBsc_{-AF)Wt$fz)O1WpB$SQ2TNkBL?d@Y$uyQ^7L#)dU^n46v4i7m zhL)>hZfrz3wA49-dRszmUCV4~dqJhMND)xufBMY7o=r5DTQpZAt#kkJQ1s$1J{x(FftwF-*L~V zNsJy4(Bpn~`U%_jJfLv&C)~U5m40>Q@o%B$gn*QDX~b@5UIg(T`73sX%|MsUAViri zuY)#!x5{fM0;X%61}Tm7h5YU| z4?bB)dV9+Vs0nul+{+7Cs?IkDOYcNpN1Z~4hys||jW9{WP40NcUM2ZJq=dNph*%;( z5xl{YcfY$}CdRizzQ+lgUtgzIA8T4TdUSI($#=5+g8EL%CiEbq&dvM;czm3kd|%&O zot+%-O_kNVxcK;RV*VH~=lyoD|3CrZ=;w+11l!>a#KGJycz^@qNrK~njvzeSeNeq2 zg^)&($3>jZ2Z`}Dp3uFx&YC;M_#$5iprq;Y=TKO%@(oy7zJ+%v*X-$x;<9iP3Jm`E z_B)wNXlqaK+so1|Sc&UY?Ep6@5C3KCNi>}&w`zKi6?+>T{59dB{flP%vj3}6%RJj{ zYqNlJJ;^wZ>l)pOeO-ROSmc`|`?e&LW^zorw0 znc9q7l(kf^Zx!~MTou2+(m6xNI4Ok3*N6Z@S54($s64i_*0RqV8$Al!$oKAVS&2^^ zD;7uaFx_K+gQ#9q?Pk!R|>tj75)Udj1?eH^=^(&2SPIt=_3lPp{6eZnssEE_PB zyCvFbALQ7}vQfD+3*L#lub&=OHl$kcg6tMv5%-1$r8KEu_Q*4J3hylH^o%N45`PZ^hj~+bD_eUbS0`IL2B^EWmEFVL z@#wiQUzCd{$ak#NNm$HxY>;}zHH|Uukt{dpfqG;~GVHM;38J2HZ~ti>bZ<{{&LubP z;R#e)=l$E%R`06$)pk9mwgt_=P-r>rVP5;g9>3|BS8JE|Y?yPp!Xy5z0r2UsrhS04 z7c{}|G*iT$7^(xoHJh)sClKK%Wmb!_69%wb-cJV2WU`nZA3R1|XPci= zGLHia@kQSY`<+h1q#&MB@LH|>;uHScor@xTCI|C~YC%Dj_!dE#IIe9!NQum|51>&Z ztJw7(%U@ZOqO%b}$C)c;U3g8vtUt^Yp=*Z&Jbw@U4U2(IjO zO)i)298ShS^dayv%O^h%xa(QDk7v=@~9U5GrI-heMP8$`1yQCZ24dx0T~6* zX7+4tL~Av+hNVZ_hLUl`W*C!$nba}7pBzh^mB4XLp=I-unz+W+(DV*rfAztzLpq@u zD6S}_IJtAosJbZ{UN-CL?Cw14;qREL{{CGuS$!<^=|)ZWR~v=yF)Xzkv)b63xZ0Re z4Tq_E5GdF?t{ri1hNB&!r7@l2S-s#?vSzwiIhE4%49MdFQ};OU>I~21Q!DHv?oFA@ zrLhU2$;jH5s`I;sI)NuURFma(Dm7+T4An7_`Y)9{6Un9~m39vpYnq$PUDd)_qP=r- z*Y$_X(_g+pHFElnFhPI|Gu1GCdmj%6c5K`S#6LD4UOyhNMDoA15lW<2rL~%!r z={XH?!*kgDQ@9Y9r`b6XTk3Pc9&!I13pP!aEIJVuh%KCPA^yuDyzwKhISuaU8YWa> zPo67QEF#eO28gy9zm~`KvmRS=pgJ-Ce=nItXq6#n7g08n5lR8p(2;%AP3a&Y8Fp@* z^u&y)MW&`Ap3w1%vRgI>;0@L(URia0)q^L$-6DG0_YT$CL_I%JM149+ z8=T-&!wOJvVLba(wu!ajhMLntD?i);l1kDbo7}nHH|-sq0g~_8V!r&CpYNGUm+yH@ zkMDVv{kcv6>A5cBUm?#16fpWGR|EeFxf-ad{O`8YHaQy>Dg>_^lE%pKf!q({U1ERV z@YRMN6>?L)cL8*kp2#14SzRd8Jh!F3t?sOs8Akafhwzu^*HJ$(qXV2_x(2xD7NJM%#rTlUBh-h^1f&MXvmP}9ujgvT zjW*`^u-}De)$68KxN(xgCWpjfV;z_&Ynk!(dDbBD_m`LM>vH4xMEH+Xl%j`Yy(nJP z>7v$P35xWdG>_EId+QhiLtP+7nBgi`F=(!AXKI0jYmji~*xzuowM+J2{ahFnq~9#r zRwAb+k5}5~+ZGwha4T&jR$TJyN_!LsM@`Lj?wjpaLZ|to<0o#4?^jv(E_a8_H`_0* zO-A3bHc+FvmRy~-#~xVRN0XC@(FJ*s(&yh_*&lPboJ1&q4@QJjsyMLUud5qBKa3Mg zSaixwOj3ISZ=o1G^Y^`2g#3B-ou-iE4QVid`TJ18-^ED1RicubRB!C>tGplE2cN!7 zOm&w5=6cCG5Ok1{A29fEXC|$I`utOnyAJg(26VKiOrsz5Q| zPvORVF_R=&97FsJhd#Hze0nG>0bpI^;ZTrBV!0xbXBf=VUGN0FkVoV)!b+d^Nh12A z4HtUsptwbSwF0)JXSY%Qe7OQ%OTgX0a?k}+Kj1mo&oB3o+(r6dvD-#_#PO9z-3*#! z9?Q@qzWX@zp}$vZ;D-7f6E1=P1PlbEP|^hDuYHh^G^#xfRtJ;c(<^0p!L zYNlk!{&go(zV(r|3i%HCDHM)k%lu%DeJi+!qYOJn7rUW1P7N4rsC+37ak8R1o8Y;r z@6KX)&Z-JQ;mEAg*KItJ5-se6y`*iH+UGhasfr}SA|Mh$fcWz;)^gzO+zZ2dx8_`o zOMy~Z{H*ryQk-8N3JvsTF53Znl4__=o$32YB)pKH3Wv-966la_;ye>^WHAJB+nLO` zB8X_Fwb-h`&skIwfldJBtUR)oy|B%;82aiFhZMS%a8(@sBP^ldvBE~+R39jH?& z!MV-v)IA1lE~#1TDrFbRXFI)4cOMU@C$`j!(k+gS<6y2bW|%vQS;mGJ{%~Bz{-GOg z*x%K_vBgzfyYwH;I}V{mmE%-x0SPrWnNU>h5K%t7)ija~>u{T`W+x$o&=I_M>;+iC zDhFvARR#QCJzW*+wpwbyXPt^`|9zZQ{zRj(Z^=!UMlv!jn%GMz$NG6r=`3W6EQ`Bxh`7K9KpMG~AY^w;i+wctz-fbGA0t%pG zWfVLT=0|S3VNgY8ns*6KZBO)tTK~9dH@4*Wt5%B!Obz4=?vvna?^gMsOo>?i=)loX za05YzH4JG`yLQYhiHV#3`UoRcx{d3WW%)xMruF>3|aK zf`q7KT`yNBFlpQqQ~_Oo;;IBFr!)P;TelUiYue^+O^YLn!##4}Y`4Vu=E`-RX8FMfLKfwPmKc1`_8SV4Xr8R~?@vYq~ z(=3TX(6A8Po}b@d_k8>Eb)Pkxcbe61b1d)wDpR>`8Wjt3)=V>dgk)HHtNPl#t6Urr zcsqVXsN!hM=%U2qt!5Vte?2mAaP$Dy# zDf29QJcmeiX*=L6s1$Zf{4QSqdPe6WE4d1LTh)lznRrvVF5K=q(`^Q3-JJD$Em^qK z@atQEGrctWY+W@KY?-yVSB!1CjnycH-1;{^!w ztI4I@17F+_ck?jqucGP)#4;>PdNputMOI(1IDv+)JaENOhdMtyEBtem>jdRwX=r7# zv41O-mIiKMh+jr%y$>9Ul|dQ0uUhz7=QV9LwNpAxdDeVM<5{{+Gw^ruRrJUu*AK8N z4nIX^kH^!w>tQ&~8)s6Q`nr2N-$Mr^J^HItoJw&@(? zmj*>dE~wTO_&Q+P{N?dDb4rAmNMKoqL zihuVVE_8;)WUZBEdD{_aqM#JG2e(!+1BcweNr-AJ>xlGGN z_>ei1%p&kQgDIFFgWdKIwnA)UW^6#!cWoX-M!m}leFF6DE1BGkkSZN7yHoS>V2Yh}cX=tjGmE#P-Aib<967(M8;tG* zsZcrj#2B|rV7{`KY#sQ=#-qNuvMaL+#zE=Vd_J>#rM#2yhLiBSqj|`Nl~M0%kvQbo zKzHv{X-_}COpG_{>7t&FS!ou!g?c-Zn?I@nP9{2mc~~))dV7Iy+ECM_jrx-}1eBam z>rY{CggG;-;Yy~nIRL(IKuXvc!+{aTOIg_EJS!AFE?_fVY5f*o4gUhVS9IRgcQYP`~U1K2nQJ`9M*Y6O=iB*U&m|HuW{?;;iF z=r0^f;G!}f_%e$;!z!tz<3@Q4|6Fyb8fzh+(kKBNUeTX9-N({tVpp=mKrxcp(j>`g zZorWDie)1rxj+=t9l3{M-E$U8j3|+VD6`I zqP;M_a+f+`h>bm5a%?)mY#l>{TukAuBq=rx9u+BU<3X0`HtI3;DsB!c(nlF7g;qn! zL!o2zQcm@L<_iDRxAbW#&(<)y&=48J-al=cl8U0;Ho$`qh981cI6)V;fT`hRJb;7c z6I$Q0Wn_SQ;|vTdHkxK!vDW0Q+QU6Vz}A<~At|6+s*K$?e6RdvE579acXf5;V;z+t^QX+=If5=Jk>8j}y_cG+Lip1;0=M=H z$q0^%Y#lEU>uGA8$9R6FZSz(^uBmy*!}y2H(kN;)`27|l=j6V@vumtJ2u@r%wnI=O zRo}w$>93*dUdJ#E4%~ye!F0t{?E50rcuu2ngf4K~b%~p_atEtOqNaKjQdP+5NcG9= z!83sG>?{^H-t%s3E0Y7GuT`v@L{2mvYXm15`R6$OuxNgSL(o9nC9w z7fxfg@M0^Mm~laMqvcaXXHB6#+>!0+*%zQvzn!3 z=EVK+UGzpTpl(39X15rGqhSZ~UpMnU$ZJ+>#<@%aeu3%I15daM`-| zklaedCd^g{8nF?GY7*%OJ|6pi;T@ z97$cqYmF2kj|=B~ol4$IC&MQbe`aJaWu*hNl814I77|R+*@}Kzv`Z#+sGhcI%sZwL zdH+0Zk=#nRFV@obtdbc#k|@&&V_kDTXLV|~P9T3*wy57dB>uu$OG%p7N0Ch@zI-f` z@RH@{pq=q<%L`+=CJEbXcl=R7sOD>(LsW%8)>VWhlH=bRa4e8ce<%6ent}$n| z2$FNoyDMU-NOIfsgd^3((tlu`oLE~)9g+OoXbBPLvjWod8)5STc{g|Xi43xol3?9?w&vBhP{ z@i|fXg>=ib-mOLezm2=Trr5fiw)PAW}nq?vnPJ4HXSsjB{Oy2Q_=>foCWc_ll*;}HIyBv~tACqPaVM zPAjSF=so#CUdko?kX}MTTzak4Wb>i`t~A-E8VOTIvH|(Pt!i|-E)nuVf96fTUEQ3^ zuGR*0NgavQsf)xeHuo%pD?W(|A`FHLa_-$FcV_0lu{LLhR`{JFSa1%BV<{ zlU>n#Mss&XP*QStZC5)3bs|9)W*1>Gk`Q^qRG1?Fp7uy9=m%D16ngCHS z_7GwG!Hdx?k-8q)d(Iw%TOixN>C(~Z-K{_I__pa-KX%V7 zI-d^3gMJt9oH5hWcTm>rh!1OTpznYD4&j1%A@s8Z7l@G>WZ8Wo9`(uD{rH;i^@!*u zx7hV|Ufy41>Gv?wN_ULfQ8VfgCHD&jf)2i;9c=@1Y>F^&qna)G@RD zU^JIzrf077u1Ow)!c%Ii-M<7CDX!Zeu_ah_o%TJ*`+|j+RX7!;^Mv0qzH7fE{Vb9Vj`lUNY#^Vu+ntn@F|kAH6A;v>^U8@6-TykX{%7e(ePU z3?NrH2p=7QOGX9(5TFITFaut8`vEUC`mH-0y0TCbkf=NR*G-}OVMtj9I=e3g|759L z{F60)6uK{ydKv~>&Nx5K_cz|v*7%FS*tj;XK-PT2#ZRJR$m?1kq*v~7>X8$}+s;{Y z%C#nnLyqG;rXi}rv}gUy+ZxRHdLBE0Kj;QezXOv+FV?P>w(n(0dBiJ{VBhNNVGBUd z@o{BLF89K9$^=Om6YeS}kZrVy$PYKY&**+M`ks{3uXKZ(8#qvQiz?wPAbCy|ewE+p z`AaUKK8MU5I@t#;H?Utx-W?hg@!-!5YVl0Ict{z5j4Y&V=iepmfRcS9qa27~TE94A z@=CwBpbxlsBDcqK&9Y!2Qr5b-f8xghK4^}g2u!|%i<=uqjbFaoY(?Iqmf54U=wa7W znCc4Mj%)G`Mm!tpIefgz%V`%NR#_Rk^79)X@0XI-iO^K-Q5 z=>+yqQciLfdwR6d^>3>9=fs5P+j&B}2vstR1UF~9y+sycyMJ*M-1-;C10BL^P!A}X zwzW8{qO}mCYNYCsJ>h(C8a;ay4CH_FzT1t`VpwvZ}VbO!VejiYXjXM9%fgOgojE9b<;(Ytq9KU>*kM^gN0PGWVo@#jj4`cS9s-@HR^ zZF>zFS*t@FeOT-x$*L2ERf~}$5I@(#w7lt;N7C|=mGm|03f?2`#%;|HyPm`?&-I<- zZ=$dM2XKCSXz-Sy2oEhv@JfaFnTXV7MNEe?H_^x@8Ffn5fnSq{v`~Sg3Hn#fO||z8 zbg71@GHeLmOAnmv1J(U2ajqGYbUPR>v=;K--@WcF%Kt{H?T3+@>WoT_0F=2J43K%J zJ#i7H|I~8TXIGt<)^i%H-$b)%Iuu={M7IhypQphh8~o+ITI#McSi&lq-x2fu{=mOVE*5Fa9Wq`U4}~;1bx={Sm&~}&xEjbPRJ_Ib=J(y z+uuh+T=+ddtbwCtq4#tNfUq^NK4lGl1{1M}ap6|KKQf(f96>)rJ$6V!fFFie_HMo4 z(K12yfQ$pamVg0O1I6@Gx_p`S0<_spnxK`lLC{$E|K2h#=K_ZnJ9hi7Ngwcv;?P=o4D^mtPylY4q&djx z82%lA4Gn+QRFf<~JA9Ht>zwYSO+~pu-~#)EbrRXCA(c&S|C1)xx^!b3dXN4dY!WP_ zX6Z z5L#DZ@^`{9`cZ3ygVpJ@Bf*g&#@b3dfijp+lrmeU-_9*fy!g&((+mSX_#|isQ0-a| z$BqRfKY`5ICrq%@t!{sdmr-=vPFWpVt@k#tE=-jotr)X^f}1^@a zszAHYIz465|NZM|8?I}Na{Xnb$*M!guCsfK6AC z&N4Oc5izV^pHs4frkB_IN8$3?manX*Td8ckm;2Z`W-tCtAPtU8+We0O*fGI@13LFR z{DI|BEqIl&r{F_qVYuF(-OVu0d4SizpY=5E{e z3XOM2X)IXFY6==%jM3;&9w0Q%+S21N0wHRfq=gdzI}w^|c!ZzfcYh~h#_N||k+fUn zTCaFq`PZNWFq6BAaUt&cIqo58T>tr?w%*UZQH`tobR;EHl`YnaLZwQRCm*i(YzT*& zcp;X(o9)Di|IX({CEh@jQ7Bwv`6S+~v7Lk1Pmnn_HWuFPbQ)pnXJe?406UE}4v9Vk zb#UBDptMJR%o&p%;fLY1{O#V0z25DSy_?>m=H*UtbA>xa{A~(yzpdHGY8v9D%lAG_ za#PL-(*DaJZVYC}AGMMZ^==ry4(fD)_N^OPtBH{SQ&gzX!C4F<#BobD$`r4kidcv! z+`{aiy4Dwu57=Eqm{po}8iXFxj*Uo<9{OKb@qSa99JY0~dcYutF$Z@|6kG?uBz5di@1ekghCR&1 zZ_AZlZOpEP6}ZTWN9`#XMT_3Tvb)uM?y3m@Ht$4Gi!AAW$8J>ZZ7yWW@>;YH_3*mx zV07A#RWv8QLM%r0qj%c?0Y z1jkY-Cx!qLMR6wg2|K-IfAtdpMVZn7mXb}U2{T5Xc3U)kb)Yt7(<BXnvQLDmX(Mm7-o`JA7;*bJj@JcD_0F^zGYR~H(&G)=OMrx2fv}Ewr zL}+P?|F-@qI7H?$*U-`}jj<_#j7Ap@S+{m0UVo&9Z&y`ilMx zlQ&Vn5A!hq;zt;a&e|La-DMDj)tS*g23bJtsTQ5VM6P2#5fA~9w}ZfMCYvaU^e2?v z4NfOKNonL@Y%~r*e_wI9F6!k0~BhlJ>Ki0mvJRBhSWZ(Gig zI-3R|0k!GR4e#`{H21@}mPTb3TYDp!tDX1Dc4gQupYGR|0w-q;*Ok{jGYAZQ4LCN& zI2jj&PwJpWpqJe98Mj8e*j)d9j#8!m6nj>+{t$20Ua~M5#cY0)9@utvHZtF`B3Wy4 z6ieR6m={KuVH*fcxNi4qkGc1yI!fmr#1Xk7xXu=cQHtTf{0;|*v4LLkV;EEMEy?J^y#2sT zDd)409oayhE*Jw^#M{%(<-$S`&6<)!bq1zt7|4@YF6A#4ldZ3tGhutaEb{dM7!+PhbDx}f1Oe+e5$9WTX=$~k+|n5QG?p? z8D#>J^f8JZ4&JC3E?Ob3?!q&OMC=e47oBdjUvu>}+U}2D-B;F+484WpB_&0e`lt(2 zQm^C~byvIL;Ad*I!}JkhZ1YtTTvEL|vNh<};kQMdBH4tiZmeZXa@Bv+A7tTVDI~zr z-C$**s$0LW?1B&W^4IAXHt%0v;wLNPPi(>?Zo+(ZDK90&sUHOtW6r-#=YPg(m{{x| zOzmp^H4&=|7!YhcLXR;_snBhu<8IY6?WD)13A>7NW$=jYf!1^lYxu*gj@S5pLvS6; z^YQqH*+7+_<4#V@7;ud{m9bj(@neA1j-7-Ig_A;lu zn$2I$m8|N*kx}e*iLSZ0U@3jpq^gdtvcRlYr-aDLVOn1`&pgXW$FY&rJXFMHp}^4# z!|A|*Gjk%tV0o+J!;F^g=Btfz92eX0;atf9^Ddr@I{NZ&NkU_NrFFd$@07I0#AR>?Pko2iQl&=iPwCG;Xc-z@t-I&HLO`@?m%EaI|EAV2QzG&PUP^}%W}ySdLiUb|?HSE#1&@;mc0 zbc{8HHb0#@ZQcys#c|@-_Do_uW4G9NTcCZu)-hJ?O9v%B@gAKjf6Ckb(CTx-$Lb#Y z+!J5>xT|9FYpa*7@FmgtY%4m0H+?*1>bBDD zY+1O?s|>bBvd8A$^w_j;b!)_9(T(>E?wtypsh=dgh*NmYd>+SX&fd9kQCX{4UE>6j|u&wgV+E?%5&(l>BtQGJV0*iqedU^@p^Xb=6lp zcRzaciRZ`$u}?vh8v>KgTyIdXN@o9mXg^I}F)==Iey7CEtzT9~?bB6W0c@2WSH|;y_D|b1N3!*p{y$Btj#fLfyfZ7`#++kQzPvAcQ}l!zrWRN4 zdgc1doNIf|dXMAhQkLh7|NmGWF;zbDbWGx|*69YGc?!1#_+Bwj@vOZYm)~t=FSdRI zmxZ^j-Q{zVGo`PcnR!O0?D!@7|H1|T{xb%6Gct)V;67#p1Q;00{~D<0|XQR000O8FhCzyc2a6(s0#o93rGL}7XSbN zV{&C-bY)d(L}g}aZfSIBZ*DGXb8l|lTWxdOHWL2sUx86?#*#;(oV01$%%vS)+%}m@ zQa5&*xv?`Dh=e4ZL4pB5D@xA){dNJ80x8NbwJ61%%s4g(?(4IQ-6i>Dhmg)cbU0-( z?K~l!sWGX3G90>6f!H9g!99s~~usbUwL&4$kuqlUeGamdCz z;fBj3c$Epm|BQqGYMFe~=_9KtO(MY*vUHm)s!k4 zGXr~I!xvbAwNNHwJ}Li(6|Ud$&s0UQHl{+eesN($H4nA771koAL&Z~*GyNxzCq%38 z=~-zOMQ6c;n`t)6G*iINplQ%3RtNWUa14t)VPXhY0s)6F-pI$XPP|p#8Ht_S;Mdqv4bIeALWujhxA!)Qm=bdoc%jJ&3#W-hi-HS*O@!#fJM3L2 z2$#~;1|-sil8B`YXeHsC;3_CTmO{vxHHAm7Z@r>r%!nN0K7d+zFY;p$U0|3T<$#RS zBNz1^#%;QY%k*J$QkJGtnW114Du#KY7~ra~>5Ga1L?T2+j{t-Xa0eb3Z2)u)X$m>f zD6)BriX5h>AncP6FEqapN^SHLYYZ?T4alhtYw}7$&V#+rPfm`=AvF|yErj(3IXHSz zb7oa`tB?CRh#eiovmQo32fUio8PJsXNWpqkvi>zoLL1}PScs_$9x^=~7yF0b$O~L# zv!0_`{M*~hHOTR#5daVRfR`hxfX?FYcT$~?q&9DtSPhKJ-$CYW2^$MxqKhR1~b z0g=Ru3&`yBC8H{FK&2y@nTD8J%5PS|BFXj0|Hv|xBBL!Q$I8uRh6Km-I{n3AptF&G z8Z3?pxCXb&Ooi;oB|3Wqoq8LHf4co%z(>C-Pt#$^)?>NqJ}O=$8nLQ}GqAT#DY`K& zcn>KYsK%OmHL(f>>#@~);ke?V-8hB_)*Wx(`||fo&s0K&w8>0xJX6GQZ5_)19znq4 zA^V(12#bP5pUfDUFo;J(#!ALEl|V2++Hkniq_lxA*rl&c=YnfK60A7%8-*@>_?wbh zT9=$+?)v2udz;)J8{9h;TMTwpy!M)QS{@DQekFw_N;9NP0ut~#;06U{Keu*fG3 zXNgOONc?nSOEc9KESZ>Tw_>_(FF^Hr{r%qiPQ|`(Xlm1diK)bLtn=G1Clw4rMQ5g# z9WVzpbo~efEv3(_uow7=SSvzxi?nT#Qa z2Zu_ghfs3)n*|*)fx8|K4bd)Dcnb*v=K zS1)&g^!q9}5zbt(Xek+Z)>@<;Z;Qj$`#eiPKagINBrs!^rJQaAQ0;j3_lyLM*aR~Xfgu3DmQ7U}^MQ=d%z1X&pjC$RZnkm1kkcgWP8f%WqNi6Mgm-bF4f8W7i6 zpiHC`%9gujEgg{m$P9Xq#2zM#5i9Bt0&*}0KziMeWv|PY z$+ewWi(zrg5(*%2ZB{ADuYE?jYV0|so3Pw`>S%=-N<7D8y#ws zeq#-8qb^F7OGl7d5{<2i^QSAiSyXtYxxGrTl@a_i>~mdBK#4Vgjjg;FUd zs4MEnB;sS+>VXuXzP3xq))pO$i+0VW9*x~vr1%8`($T=k0sKdx)P(99E^0<&V5cGL zf@|3P1nnIST8yN z)aMUd#RYO`SogEqQVE|6h{59fp~lq`0b~2)tCd|=QT7jW+5_8T6@+VaFIStm{Jp4% zuPYtuHFvcdSh@kbH5 zR>m6)6@s*s`WF_rQTNq^^;!bgWSCB=C`Kg%Jil!i-y(c(VZ;YFw%;+cbCvr3(hy}8 zQs1#6o|c7c7O*LR-&RO`PtOT^ohFU3M*H+In`a4t)!`h{~`SW-;`)hUx2TX*+80 z3+W0a-BQY2nDOtNG9zZN<}p(=vL3i*=;wDQK^%VI(bFTTa8O=q`N2K1@*m8tHN_T2 zZz08!0XdS|w&PIE>kud1b3) z%#)8c>Pb5S!(J6Gy*OI0LmzF|p|9ebsJt=1e&2H8gF~~3;S-$3yYJ@8@4uF^r_?gD zT5imHkK6TLs-T7wYy$9XyMlfEmALXsl{a<01C%7evoAc@v2AO|w(TCHnQ%7{E%CeXY&BWM{-dNwDV-S}(tquhSO z4z;yVG-&hE^W$}3S$Y_{b**u_m-^Ym3`8|D>{- zbDt3r?#2xelon?@U_>qKJzZeP(i0zXVeWyy?8=M=VfpgL9rPtj2obb!0XT&Dsf*oD zzs=2B-YdPJ4M(bIjU#Ad5^x9^AJMw6)XmNCKV<5|*IPMV(7is!UJdGt6P!V5BGIkc z4t7}7e$nP!&S5%1^f=>c?rnJOH!;KT_o@A1^UtE4?8UJ+!e;HcIyN^e_+)d~{>|;A zo@gaLoJxMIW{mo7jjf*4TKo0!`s7x7#m%yYHU8#e;R96X8*gm^@RJSDTz=~zDIS6V z#mS1aIT;fGRlJ;~u`cb={3ud1C7-0)E~V>P#BzHnFj{{tof~6V_k&th?^9Egkygfb@DTHR#x^aSR!w5P(k{UKMsgFF6}sr4++SbAyq zs8FqVA(axUT#jGvUXmq8x``-f)^YxKz;CVOChZrfVviv<{QEt1i}fUn1nc4e^b5h8 zM@ zw>EAlt+9;Y1BbX05ZR8yG^ zD#<^rd$2etNBF)~uiF*wG}A6eY8tuo+PO5=Sx(Y@{2GVeEvk=&`iF@7weCzP99~0F=*c(|+Iw^#e_av#l zskADLMC(^!kUoPF%+?Tps3_4mpD;f@%{BGTGph8*toE;tZ*-L|6HH0awAMhCIa?+u zWqp@~eM9kDSM^T5{9H=Obahi5Vq*2D9A1C;2aP|v*4_m7{}zGG8-0x5k&TEU1wtnm zAY>rIyTgXoJ5wj}yTGUMZ)iRH=;`eJ;w+x;>xq0L6;Vs=@x4D40&j{3`IyMg%ON_G zi!E7U@LK6Nua5<-)9bCNclv z@V}{@bqRY z1y)*1azrEhTlI18L)KULd3m_ken5iu{vgG$bxf@+M`QHF3sj0Sd2$6kN+4|cA7vo&Q}rTH7YW>WGzx; zYSmut>;%-e)*r}~^{yaV{OBm?eGNjD%;tN`4~1~N8rJ*^cgqxYHkvBfjH$m0a=~O! z9x^O8li6wSWQf&I9qjW&BW+|#MhmyZFq^603ymSn;sl9_jDcdAf^o3356pA-NKUTLB7E>S*cdSAB$2o5$xXmRnJeA8-X~?f7TTR{eG5z&uHCW-OSrEvTfrb<-Ba zTB%u2Q|cG0o6yR6Yh3o}Y|9oEn6ZvyWCZLW1Gdz;XK*wEwpJAL*uN#I{}8Y<2K6LC zJD#)_C>;|c9J7j%(yCYzG_Y96q_t2!2}D-18QpYkUN>JzG0tOW2JWW(;pucCU}p;E z=_DPnH358o_z2pa0e3v9oY&fLa?FyUh~suDs)=RZG2Z zOu)_r#8VpberYXWYaIH1DHWtU1@yT30>YCTXGW`Bz|IVmOLnQE*<@y-Qn7doJK%H< z9Iu=EQmPpsZnImlrh0Z^oY(p-2JH_|uWvETz&yRa#h3!VfBY8X7u@lMa-LfQ@Go+l z<;-7<>AA=?&8X!8RwU)?m~lk_vjxTLwt~@W)QGLIANR3{$G@6EyOYq4f6;<@Qb5db zuOr+8*z(*I1GXl?ol|90DlIYCi@ES)1PiE1EP@41>{Pf|5l?O*TRX=Du1rBZ)gbRL zzZIE;zQ6odBn$L-^IH*ioSDuO2(grC3NaQPl*$LLVfBj9!qf%Km@GvMH*v*E&GNEB zfKIjBK{839R10%q3ZA)S*$~cC#KS=4vjkH5*Ia8pu0FKBzl&Mcac6IvPuJqby(Wcv8LSh9gHOcaG# zA)HtG$q>8WMHmpo+8<_(@fIbOzFB-xo%a{^0&?2c$w3?P!mNfwzCPL7X4>qOkK<3zj_ z@DpPy!Pl!<{H;qQ&c^2i-zy<+w>zd-v`cSutKH{qIEsEx93gPay8tg%bYu+oN#8UB zArtxmw_W&Po5+47Q5!zpA|RcvS*m(!*H-d78aID-NSK3LB8i1Z){=~Rh!yIqb>(xw z2yKG&Lme&M#bQ%_o4bYx_WgLzSL1me8^`cKP7)GCqzUBodF%vp0-bbh5+EdM?aW^h ziSoxWE=$;rVf9?deiKD(fM5&xiJ26J&Yr?Lkd-DcYJO3_`tG?A0R3AAGJk0G`p6z@ z$KFy;xc4Pw$S<;%{A#;bI5+TGSN0ZyF&^KKLjHSIyhNO(u8`v+bwT{#0q~(HUB~*@ zmtJ#lv=M#-P_0ZyCu})lbs)ioy2H&jr2Muq!hCd?be9o0Vl+J7$=QLvnwhN)@S8Z# zAGgN?8+k};k1u-bZ|{a?cL_DCPb<)9lX5ufXGaYWqO1fb{s>o$$TePW@HW_0G6`n4 z67#?Tq=>JdJ!jhs!4_C`O2(`a~x(b-VFNvR{D zaOzoF1z~Y#6)!JYaZdfXy4*@$`4ZvKd|rdj=cqB{q$5ykv1SMW`kZVi0CWGEoNO;d zAHHmaS=RE1=+RP9svmG!D3U|{BqdF5wnoyK69##4rcLf+xxlR?*rE~omu#SzGLAb34$c6!&GmFX`HaB2%>XJ z4Ri_CB<~c~J@7?u_m{u6U)-+HKT>-A-66o%@Dw5l_+$-TE+If!kQETX8e@)faGs{; zBYuD~*6*+KDqOI{3Os(^EOAW25krbd(um-l^6MjKC#jK4mhM5B&W%nxxp|WVI1eGgr?Qw`z8*<}}HViCn7J zbU;pstQDl47sCOLyTK<77l`+|Mqo*V1sh|XtbrbR+jl3ZuF-x5Yfkt0vIqQ6LP2!| zll}cVmV`9nTL(O|`)`%-Nu9^d5b?Vsc{1OV3&=tzl)wQtZb)8xgt#pb?3v`f#F?b) zKskNSxfv*S&&)Ao)<$2!Vg&+DM0!m{1o1qKPZbsV@dgrVxZW>!dmY=@+8<7yantc%tK4>ya1nWOWDwb~!F26H0M`p{`<+>PTu zMdaE}C^F&JzUC3FnG`!jcR!Kgb`t(#fgvYe{E2E97y2_^S47i7Tk&o~GUwe&XGd^7 zU`ck+jOLWe+q|4z3G1|HnvWME63aTWn}~#yNpqrHWz;KTAcQ}2@>I|O6FQRMgK$^+ z8JMdoD1}InH(tjyi}8~MH6<+wL;ji}iVkn?Qi75zl{U!2{B|^(JAhbX3<-<@mFFpZ zt?RsZZh?hGK0G$uMH;o6L|#MC#peg;h>bSCcr5n?rrT!U4=ZLb`x`6}CC4Zto&xu>%(x&YC z&}z3UczK4Q7}=h}dBpcusTLb`W2zTQLf|t0YnGpN-13h*pUDdqxR3c&06`#k^6Enj z!HdD(a{}V{th!X~1p%YW$q^uT3CWst(7!Y^zbTyH54!_~3C(99&khUS9bcm88sQ6Q zu{rFotzG8#!`!au=)yki3>rdrbOr5fE~N}9M{|uI)guX9oPxpQ;Y8?8b$-n~K_2Qq zA`T0RAmKJpl^RzP=RY5HfJ)BxgNJokhh5Mt9Gg}_2}1SZzGNaI1)JLY9X5xiI)ukw z)!&A+JS#ORG1sX`5;05Q*Y!|lVe9^}9VbB>P%T&&4|td`M+bcTNwaN4jun%~Ef0tV zeUk-Z2sj@F4(D%kla-^G967z3t8MvSc*QMTTZ9w(ExI1;=%Yr!1J5}03p5lEpElKg2NLTPzS zvwMWiYpP#sNJHe#n!In^cP4peTZBFyUt$m48PgdYTR3Mdyd_tWwgE|l!8l1{T{&dw z!iuDLiP3bX(BKPNB|)S`JOfvkDFYq|?*3t^jWv|qFq#ri?UiuU5P|qMho=(+RI-u# zsX@2{@-2sram9#+sX+#>acb@E22+*IIT11lBBoB84XiO5pXE=+fTdS(_3akvsG@T^ z?n)BkPAcn+xdDPW8{^hwedk>rsyqke3KIF1+YBpH%9z;-eKX^nd6YicvkL(O_S&R0 z3~AO7G2Vh|fTuYVZhH-s%jmgkq2nE*F%O%p1%k=6#%9 zja*po17J#yK3(}fg&vfD&iRGI{MmUhGG4-T_|(_S>izTWs&#lWFRq4u`gO;%x05xt z_O081Ku5Rm>~m4$YDISGOZ@8nw8~GMZ$syP>TP@0@bt#_oh{t0FSn%F>u(yO@eu{O zXpm4SpWhg1E6K}@BMf;dEWkT?L)QV~*yyU`>yAwFEGF>_4v(rImbM2g`*WJlGtL#_ zsJpRIN5uDh6PEr8oIR-Wa|r5v;l8)?62W##($cUZ-cF7l5LOz0#ZK?>HTZ$1`8e-# zWf*P?-ktjjaeQ0hC%f*Eu*S#IC6m1`W?Pr|(0#9*G$9>?mZyOpG(rIMX`O!--b^4Yk2z*HbHPW5`i< z29T11*{SbBpe5=eBiG_Q=3=VvfWe}Rztp?H8euD8I0du?3$cG+AA+-PJE#D58ed!zGKj`iTeT|uK*MH17eWnpCp+iDrcOjz zU@jhNrk@i05@8=7KTO?+ zC+ch3X=XazC~7d>UJMb3^|?7qb`;&ijoV%LK9(uicV=WU8$&dbaFgbss-izOz?ml} zq}I$#(R|zzTU^9i{rdC!FIfp*3Wp#y{J@U~3iyc5x<6hn@lK?8%|~g4@9-fxbZ>b_ z5)mLJ914KB`2r6BY~nLhV~bQRwa6{D#-9;o)_HjRqPK(nD|>kP^h%~80}IUk@nx8( zB)6m9{x3X5*wk6KZdWz>(U*cB!N9jq_C#`LAJV9-(lvMmp1%!=RKFx4Cy;a9B(lpS^hGPhqR z<`}2l=M$YIWPH6E#;3YyovbuB%t`Nripr^t`yrIEz!~Muf4~x60w%R zMUf4HHKK|{ql)yS9!aDrJ2WM7S4!^B{HtPwsbaj0qy{F-^LcX4vSVmDs30yg#lSz4 zGQ?Zl^4ONhCw%9!l|5RX)2LR_zf=X-SQ|IUnP!zqyZo3iO1src4uCAXv>@}1bnW6- zCgntS+$;y@@Y?KnM_}@%;ghdxG+#JPhlTE==v;^5Im z-_dmbiZiv&7Bz9KzUo1xnCD^QJ@fcsayyum2dD}TewaVi(4^!+Q5+<{@%~Y zLgbz;p~qjxesTHID!Ailjg@oRXqS<^w-SOA>Ah2@eB^z9`17~IZKIdlr5Edcqw_L% z<74hC#%F0Vf*|W=cy1==B!?#f#vFN;OP&QvhRymswYVHs`kMQ;pJ^@G|92=CGpoAL zd6f)V&=2TL80Mf@4KI>nk`^GZAe(F{^ep>#WyFD04sY( zD9QH5j6%-N)OnhN&4Oqj3|X{K+!L{h6H_n@^e>AiXF2Qy>8#vB!fk@@?7slh-7j(5 zpI57Or{lR^2rZniq;UHN zT`Mo$t6LqnX5bi3n=#AxFtz?b6@pABI-tdEogFg(att`2E0i8TFo#^b)xDbaq6_f7@6L!W2KGvjci+ zfNgF)@ykV2;qSp0nJDsk*^X8_SR16LN?7+|2yghyoj6y&gXcsFe{J|1IiwUuuqa2# zi0h3B?p&+gGP-9q1;*eFir$iq?!MmV=|XUdiBP6yT_D$QHPFP?uVfqkCs%?E#{Ytm&A<%o7+lsH}0&jrg#sjhcv)- z()SXd$J1C4^qi!E)-$P4f_0w9zz%mPo2?k*f0JI{iWm#Z2Z4IVr?jJ7K{j=j3W z7hG9MmheXl%1@^(t*5ANrm6h+tZcW2=kk)ykI2AH6W6-~ zh?DW-fbp@er5y>UWm&u!)TfO_aFQ2gQWKH(h?=PcSy)7D8F*Nl}E zEBiQ~4BL8-4Fjb>pnXR_ov91fC?)-T+nQo8tCOwFOX$?TJ!`0a^uNQJ9kr>KmBnwT z9UE%%@BB&K{7S*Yx0mI+rV-dpmj1`tva*bw!L9ALy!#L2xhk*ZT#+H%``>GhODx^p zMvS`fAxYMO9}NWiqIUwW&4pT=bMSa&JY{%tl3xw2IxIGN!;%bvC?H zzk_*!a`N6QUWm=N`6l0pT=LqC_5UCb*V!x40FSli+_$`Y>#K9)?ZU~)dAiCD5`cEp z`11K${sen}URU{=a`nRL|yp4MSqGHptmAfPmxl{-Dq#=bty! zy=Hg)IwFn0T@+M{Dy@%RLi8%qWhwdDvfkc3iUS{HGKC8vOcM)+UpuB%pT*93D>|Hx zz6xTToIpQ5iUE?`l|PCxR>_BbOWbmNcWQkSK%*X%8m^x}Yh=2kToo~));W*%q5UYl zvxD!x=J|;ww=mUcaZt?miM!_Bfj+g|Gt3QNw-e<#YD28S&`?+#6(+-yT0MW+{@UZU-a5~IuI9TdExWU>&6h{l zBanMd#c_p)I>$~Y`_95X?1r6Ex%l|MK%Z6p%XFqYDBf}mvQEr#{ccx1lUE9uoEvbz z_HJW6F>*4_4-rW-5Rcdt?b@nLpTK4*M} zK2e8f2^NOB+DR(QS%L~&v13}+Qp8ehr7fG*T*|eSxD{nclh4y|Nta)3!m=c<1#Ne(+-;N-$*A{>j(5Mbo(2x@}fh2DV zv3~7-u=ldsM1FIJ_CqN(L6k5z=W3V=gbXl|vlF_y7|6s|qBwXe6H;~HP(^%TdTEX8 zv9mEe@FSCEy(S9}uASJSxIP#R^m#dRYw{WVTEOG+6pmwCv>7FHj#iaYqAIb~yf<_F zSk*U|%kGsjj^r1J`WPD2;0Bu_*O0nzs5{%53XT@@nWqi=1d!y0s3mas0ddUfVYlxW zmT*0>xKTG;X6P~fE*u6={LQSrq5SET&<)jaV1+2QsEHigRUN3yd^^iRl>5H(yFx6j z%bZ#RuMC_*Amb?f2wCurWs&%A+W2oAX*3`$-XCnxKI1X*7vod@mEjB<`2Lg)#SM?b zM#La%X}Tmfh7+YEa{_cznZ(&>v?1>EZ&X-UC<(Em?fIx&t9ZAmX^6f9-3_WZ@zv1j~hYcwm!L8|I~X_Msyh~1DxKUKe*O}tRgHQoqxmz z-GSoe$i+CVDqtpZkc{&1shd?4HFDu|M}*8^wMUuNyy!7t$hE34YlNvbOreOIESD8i z?}N%t%}v6^ysOv@)SA`-F{n44cysxi6vwcNvSp*#fG7_Ba(g;LK!-s*`BHt8Qp@$R z_N1G*$P!T>+Cf`oVG`akpu1hHf&@UHJj9iX1+qq8tqos+}1-$-QT)*P1 zTxG7LQK|x?HYj*&NM+oo>_mfkX^XMw(Y0CQ-XGOE7^o(WyrjmE;qCyZz7L!TxxT6% zY@?;ZJV{b|dtAENEUU6$D#Gs{PR`GL2&+PEY-=b9d4Q*=T5j{a#j5c7g}D{5Hr@#x z{OV^Ig0DGeB`_P9FT$iPQVz`A_7dLE?ZlJT)&eIgSCB&Vwv`b)2MABFLBGu z-XlyCnE(!MZ3=@l5&N$UQpM-E1~gmnm<=XlVb{(*4T_m~fd)C)J0YLEhD7r!SU z6$Bw^yKU-0ExJ!MMa^u?Pf`#N$<7aVIpn{8%7)mN&5l>Pt=>~z3}yO%2IwTO%;$s6 zM7uO)ZB4IkWG1jh-Cv;7I5)XaXX69OlbZHpUk1I{+q00Y0R(B2^MeeJ{V>&b6`=htlO zDBox%U+Xm;@%C5l*HBNcKAOewY3q^o3 z?HBl-0^wG|{-$YiSHZb_5v^*G-{MWYj@z5(pSvTNE#cbGnoPROzfd*dZ*_Xwt7sd$ zFkJ8MdkOE^BkRsik0nayi93@PnWavrLlf7cGrb?{)Xy02_k5uXR}z>%??6ZC9Fy*N zV-}o`_!SKKWqO1IK(vUZkvSoK`7;t5iJCC;AEFO52c3C+b@`S3g zQ#i_a6fLzVb#v&qOWN&OqYS?#g0I2U)r*MBc-083^+8D(j%y-^+)8aED!>>*$!wCC zvcou9cgJm=>)!gK=qt|mB|&aDrh zD&mx8S%0ral|QW3xBt9M9(ZKgb`$uDIGrzG4z2FHe1whF{%P8&0nQj*TRZ(4bdasY zv6MDyE$QnaBKd$&1_A(@e<>8ey97k>R06<9tX1iO3Er0274_?RZ~MayNdW6LfD^~= ztTCvwGa2$zj&m-$8!}}z`;z|D;GXx@VD|VoWAqzOKO>pPtNsL++)Oc~&v^6SV|Q=D z+Pc6FDTqT$^$(5oTj(YQC0Qv`qja*zeAEBA@v!Qv`ZNp=Y+0YuA$gs zS@M+**qvthASJKYm_KiEgUr%8+|?lkv%vHFxA@%9f;PkPO<;gad*^}~QXyyRpd zb!(tjPnQw}r-DGI_RIFgc;ddr-dRt^3NIBAS9pzV@9sX_N)4d)9^G1tl^uBR4d24+ zBwW(L%;v?gR#j3ygr60NGN3OfX=j`KY_cgkJmEDJVwxBF5#bbE9*f{G1{hwE)GH?D zZcHzLz1#+yPYx)x=|9!kK;jE9i(+Mmsh=P!~((8{yBlYRKoZV$*Do>eEQ#$}QF1*w8kj)J2J7V>-DpM)`8b0X2*trHIm zTR_VwXC!`oJ^D3an>hI#DdOPmWd%t=#!m(o{_eWNrAI0KQaSZQLQz!dH$=AQAaiE! zoaetbAErIk_I+EfcH|Z5$sUlUdlwh}oS>@qB*nM|fce;&`?DHY3|JPf(@JK`A0`fZ zD3AhdNWRGfIjoXtzjae&s48F(Nkt`*gDgTRkz-nRcOjC(p`rY^GJ#{(^oZ1<;J*al zU64jD32uHjyj85x9vth6<*YMt0!*anLFC-_j0KDyayKQ^papcU1M4jorxMfPX??;l>@wSq{2^OQ zs%g~o5SlNr#BXeeT?Ja-gOG5lh@wOZ&vlWx@_f$Bs;A?j-rdn6sZJ#(vHS@#qx%BP z!eOy*x{XFs6Cbnt85yYoYD8L5VH_(Gm z{{A+lt!TayG6vOCvYa$Q3i*4ZN|?|#7g9o<%@19>f4-3LMk+LhZ^P)dumS0{p#5zq z%b)+Np(ZEm#f6OYS&=E%g0e{!zYW#*m?=@DDoKncPV5oT8eZ)XXfu*I-x|5a6tv(8 z3aeNZ_s;qjh*cz7XCc7m(K!q1RfK@7p z&59irMSo*#ykS`ct66%yOkjM}t8U}5P^8PGqwE9xxImrYv7*N*U!*hn<`XudJy6@I?uQhp9MWm@vJWofN^Nsvn z4+T^?FOqNahzzS#+HXDohy2}d5Pj54)X#QR#I-9~eIp$T&)d#SeT+P$bzQj&kUmkr_#VtKezm5!ew?=47 zg{vSCjMk5AZM#14Y3t>Dg>B?)_I5Wv+1f$)k@@-CSKtLhmj3=ltQczg&c0UIO$k++ zXn#9z$GYQeeM(4uf{QWCp;CE(V!1Oxw)YLx(kU@a3SGpP=x7wR(lI;pe^A}~2i0t; z;d0~boGgb^)M<_bHUd?n?0@QVd_(o0x(=tQ(Mk@{^D&IAM-2ds0WI>(4m*GI$cKbp zc|C?%7Bh3xU?p9?6Y_Kq6pWBm!e9=!NNe#H+^m|(-gc7$w@$KNrCV;@*TiikG}T+~ zdOxz>MzD8)8_73$_=Z(V?X#c#GyV3r>2JCJ(|CIF$~o%DP2}|5k_FI|&uNiu{+NAx z#yZQfC^fc+I=bgiw5+t4!?hS4vb>^Y>fHbA2)1Qa=)C)Dzjh5{;)G|*D2R{A-xyO6 zv{Hhc5J4MtQuaQ+pFGu?BfB5EjsAz|mIk?oZ6CLA(C5wM!^w5)*4WDln8OG5JKOcw zB_4s^mNx9_(S%y0Z^xw$Ec3Mx4H0pVsi5H~9?06#%twLf?cWFDk>IcR2!C+3kf&&& zkU1FfPx~MAc#}5Naw+FHePE>`IWSaIW7UZpp7@S`wjF4^xNJ+9g@mN1y;@?SK3Wdjrtxhf7+ivtys?*7@4!acU7uZgSNfNM96UTS_~Q z>CPbG=8bt07-TcPEwHMI9ENs;wv58GT;62!Q#Chdxszw%zSXmCBn#id25V<^SmuG*%G(9=@Rq ziU_5k4TDfc&^ZxJ2!9ynNtm$x3jfREEl65)hv?C8glbhA5mJ^yBjP|a2(^?Sa)0kc zx^9;dQI;Yja&f?bME9LJ>jS-UVT4DF;2;`ARj5;YAw9ILu_bIN4QIv5RhY$I0Cpu{ z^V{=~4@*UJ`m8a>DyuGM@0O+U0e3xSV}rBVRDp3wYq}s)>a4vfNBZogz4}OVXUQoM zq$RT$*TxDU&6&wt3h5=A>e$_s4AYuy;l9ppO};G6-2QnxVH_sg|EDp*Vn7;{)10ue zou+zkj!QSoMSDBg1s9_*qk3^v9D{8a?!Ytlz0601_Pas?%{`)S ztBZDR8Sq)U8?*P#*~#CjW=EZ@CwBGa9heP~=HB_q2-6Ktd7SRCk0aeO!#-A9RZ*6& zr-@)UoEOatOKSL#Tac%Mt+`R%q=e0t-~>F3v5c7WmC(a)LAC!0I{Gar_G)p04)*G_ zjWIhkdqa{-+ak?{xs{XV+P9z~D^?9nS;fUV*~K5g`{b(A;gO%A(|K9N<(uA|C2RvU z1+E8o1cFB_4fGS?F|w^0-HYA%ddU$y@Bjk~oVSP6mYYoLy+d;Ay*AiMYn%~RLUuR6 zFLh;^o0j^rk~uayo4q+UU)%LIjW!z^#SYcR$ij;W3pDZX%cWlJ7?o{`s)K{-&9wYU zeTd2=CmWpnB8J$_dUJwSam`Yd%ScT%s5x|)w7eolq@jNl)7%{D#}^5r1!d6wsP0q?a*wy%x1vV8utoirz}Rk z6-+j+9gDR~bM&1o1(RV9+>^$um1P`@Bn|Ly*e%d*xb8}th zKhr_V@^JUuio?Fp6{S?=uFVrM`jxiBx_%6gK~zkptGR2{IJllwH@GLn)kucFzWa@O zR{MXb-~C3tbXU`$wDfyB?TzbBs(XcMYbGAPjXi*y=Nt97Ub3$4rA-4-jRSVk^w*_* z;Mn%pt~S>Iiy$}MSh&mG)W{PGk&$|Vx6br%Gj@z#ZEfGK71_p;?TJmttK&7?c`V^e zpcGdJ3yj)Hx=ZVRx>%U030DW}bqA-Tg)q?}R6C3)OR9_AIXb$F-J_N$?vVANh|DER zHixEqPMh8DF^TD%b#-uaj+}0eoZJEYxNy_%S*Am4ZD2Fa2mu1rSY(^l7yJ(g?uE6N z?uqFIbm?AagqOuL(K6GpmewGU6}VFTG{VK#WxgimSQy9{ zgusjc>L0r_FG%6>6nDF5?=sb0kCqf4!n|fTBpgd;&k$pkkc92f)(*AUrkcr1=XI!S zTMNadp*_! zJBi>spT_U)BjF9oC$5wqwmgwPC3gn0@XEy5Zs+DrOD}y)@An*7(v(d=Yp9Lqj%cHe z{FAMlul};$%E(pRJ^><@OEHCx_GRn+m_6Xk6ZICxz{t8G-(jUPykuhrGT8M5 z7sT?UfvdPYk8OfU-!|4fm>EEmdW0@_JPdsnY9Oiyc^u2HbVzxc>TM3 z{iMy`0=}Py0Cxmv#WhVs2-#JZI7u41+kt%kA$%!2*m#Url#|~DX2OQL>BdC{4NzC@ zza4-`{Fw=`;TgpeqA{(&_ufQeGsohiWp&sIPJqCqc=J%qvXo@(^nx}+F+3!z)r071 z?W%uAJEg*y1PXEYmLlMuxD%g=*T^J|wsIB68S8)$fk(lDUqyaMLBOB~g31O!N63d9 z7*4x{DZ_Zh4*#f$a+uSSFry=7RFqk-?{yI$UN|XcF)xL6`Hj)>2#RI*Srn!v=Qa3A zEi21_D;q@v@)nLM&hXX&Fw+Aef;V}R;Buat%g+rPpmqj10dlhCTIl2=>vqy|{Xr{f zj^M^o|B#pP%Y=s=l`1Os(~vKo{-$s{5Mj&irXyB{7nZ#>fG+yN-@6K*kbXABI-xrE zYfpT|N37&U^x6r5d>;zd$(c9o7khe1g9NI9hfp~>wFqhMiGYU?w%88rpVYq8Odh5q zcyST==nrw4TVc^xM*_rt>MfMZfE$2(7jlbo{nS1yQ6__q)_A6pLDuurnscDFG!$$E z89zQi|6y8O1gPUco<*^({!40W6koQFaAavVgOkzbasAiRdj1DP`=-Z&@)7>H9lM#I z5N$e*{nsACs^kbP{pCF!fVdPs60KfjwyeKN2*m@n%6;zS7)BAYai}K z+NL*YR)aD|AeprqyCt=2VGG`7S?x;9tE+R+o1tl}ElW!w&c=wWqjO<9-say>kIC7X zrSIQxNGQbF*Vbp@YNU-~ZJqx$@=E0FnB9!Ey++8nJ@-o~=1z3?PR%Nqo=3np>c-m~ zZH{y5sDJ0vHD`Cc*vq!1>5ao!i_v~_A1`d2Uir@swcvm4NX74)or~4@@Q@8JFuRg0 z^X2TKzeoS$P`bh3J8ZkZJ~9um-i-ahcVh=1&HBf+W~F=&s`E|?pi{YzZCZ_AfZRQ> z4k?JL|M70e4{_VRjKS%gY?-*;a)aZ}-MuQayfLrii_jBsUsPtLQtp-_IoagKeYlY^ ziRT*jm{q&|?k6t|41x-Z`kg}w2}Jf?Hia=uZvQV65D*SC5D?V&(f|Hpq+_6Crt`G0 z|DWAtgxe|Vgn@v*zUjYrgZO5|^xci&e|G!dinRQ{vu(Nl|CVg||DO9FlmD3v`u~`8 b2L3Opq4LsT;QyNZ_ ago(1d)" + ] + } + ], + "availability": { + "status": 1, + "isPreview": false + }, + "permissions": { + "resourceProvider": [ + { + "provider": "Microsoft.OperationalInsights/workspaces", + "permissionsDisplayText": "read and write permissions on the workspace are required.", + "providerDisplayName": "Workspace", + "scope": "Workspace", + "requiredPermissions": { + "write": true, + "read": true, + "delete": true + } + }, + { + "provider": "Microsoft.OperationalInsights/workspaces/sharedKeys", + "permissionsDisplayText": "read permissions to shared keys for the workspace are required. [See the documentation to learn more about workspace keys](https://docs.microsoft.com/azure/azure-monitor/platform/agent-windows#obtain-workspace-id-and-key).", + "providerDisplayName": "Keys", + "scope": "Workspace", + "requiredPermissions": { + "action": true + } + } + ], + "customs": [ + { + "name": "Microsoft.Web/sites permissions", + "description": "Read and write permissions to Azure Functions to create a Function App is required. [See the documentation to learn more about Azure Functions](https://docs.microsoft.com/azure/azure-functions/)." + }, + { + "name": "Snowflake Credentials", + "description": "**Snowflake Account Identifier**, **Snowflake User** and **Snowflake Password** are required for connection. See the documentation to learn more about [Snowflake Account Identifier](https://docs.snowflake.com/en/user-guide/admin-account-identifier.html#). Instructions on how to create user for this connector you can find below." + } + ] + }, + "instructionSteps": [ + { + "description": ">**NOTE:** This connector uses Azure Functions to connect to the Azure Blob Storage API to pull logs into Microsoft Sentinel. This might result in additional costs for data ingestion and for storing data in Azure Blob Storage costs. Check the [Azure Functions pricing page](https://azure.microsoft.com/pricing/details/functions/) and [Azure Blob Storage pricing page](https://azure.microsoft.com/pricing/details/storage/blobs/) for details." + }, + { + "description": ">**(Optional Step)** Securely store workspace and API authorization key(s) or token(s) in Azure Key Vault. Azure Key Vault provides a secure mechanism to store and retrieve key values. [Follow these instructions](https://docs.microsoft.com/azure/app-service/app-service-key-vault-references) to use Azure Key Vault with an Azure Function App." + }, + { + "description": ">**NOTE:** This data connector depends on a parser based on a Kusto Function to work as expected [**Snowflake**](https://aka.ms/sentinel-SnowflakeDataConnector-parser) which is deployed with the Microsoft Sentinel Solution." + }, + { + "description": "**STEP 1 - Creating user in Snowflake**\n\nTo query data from Snowflake you need a user that is assigned to a role with sufficient privileges and a virtual warehouse cluster. The initial size of this cluster will be set to small but if it is insufficient, the cluster size can be increased as necessary.\n\n1. Enter the Snowflake console.\n2. Switch role to SECURITYADMIN and [create a new role](https://docs.snowflake.com/en/sql-reference/sql/create-role.html):\n```\nUSE ROLE SECURITYADMIN;\nCREATE OR REPLACE ROLE EXAMPLE_ROLE_NAME;```\n3. Switch role to SYSADMIN and [create warehouse](https://docs.snowflake.com/en/sql-reference/sql/create-warehouse.html) and [grand access](https://docs.snowflake.com/en/sql-reference/sql/grant-privilege.html) to it:\n```\nUSE ROLE SYSADMIN;\nCREATE OR REPLACE WAREHOUSE EXAMPLE_WAREHOUSE_NAME\n WAREHOUSE_SIZE = 'SMALL' \n AUTO_SUSPEND = 5\n AUTO_RESUME = true\n INITIALLY_SUSPENDED = true;\nGRANT USAGE, OPERATE ON WAREHOUSE EXAMPLE_WAREHOUSE_NAME TO ROLE EXAMPLE_ROLE_NAME;```\n4. Switch role to SECURITYADMIN and [create a new user](https://docs.snowflake.com/en/sql-reference/sql/create-user.html):\n```\nUSE ROLE SECURITYADMIN;\nCREATE OR REPLACE USER EXAMPLE_USER_NAME\n PASSWORD = 'example_password'\n DEFAULT_ROLE = EXAMPLE_ROLE_NAME\n DEFAULT_WAREHOUSE = EXAMPLE_WAREHOUSE_NAME\n;```\n5. Switch role to ACCOUNTADMIN and [grant access to snowflake database](https://docs.snowflake.com/en/sql-reference/account-usage.html#enabling-account-usage-for-other-roles) for role.\n```\nUSE ROLE ACCOUNTADMIN;\nGRANT IMPORTED PRIVILEGES ON DATABASE SNOWFLAKE TO ROLE EXAMPLE_ROLE_NAME;```\n6. Switch role to SECURITYADMIN and [assign role](https://docs.snowflake.com/en/sql-reference/sql/grant-role.html) to user:\n```\nUSE ROLE SECURITYADMIN;\nGRANT ROLE EXAMPLE_ROLE_NAME TO USER EXAMPLE_USER_NAME;```\n\n>**IMPORTANT:** Save user and API password created during this step as they will be used during deployment step." + }, + { + "description": "**STEP 2 - Choose ONE from the following two deployment options to deploy the connector and the associated Azure Function**\n\n>**IMPORTANT:** Before deploying the data connector, have the Workspace ID and Workspace Primary Key (can be copied from the following), as well as Snowflake credentials, readily available.", + "instructions": [ + { + "parameters": { + "fillWith": [ + "WorkspaceId" + ], + "label": "Workspace ID" + }, + "type": "CopyableLabel" + }, + { + "parameters": { + "fillWith": [ + "PrimaryKey" + ], + "label": "Primary Key" + }, + "type": "CopyableLabel" + } + ] + }, + { + "instructions": [ + { + "parameters": { + "instructionSteps": [ + { + "title": "Option 1 - Azure Resource Manager (ARM) Template", + "description": "Use this method for automated deployment of the data connector using an ARM Template.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://aka.ms/sentinel-SnowflakeDataConnector-azuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Snowflake Account Identifier**, **Snowflake User**, **Snowflake Password**, **Microsoft Sentinel Workspace Id**, **Microsoft Sentinel Shared Key**\n4. Mark the checkbox labeled **I agree to the terms and conditions stated above**.\n5. Click **Purchase** to deploy." + }, + { + "title": "Option 2 - Manual Deployment of Azure Functions", + "description": "Use the following step-by-step instructions to deploy the data connector manually with Azure Functions (Deployment via Visual Studio Code).", + "instructions": [ + { + "parameters": { + "instructionSteps": [ + { + "title": "Step 1 - Deploy a Function App", + "description": "1. Download the [Azure Function App](https://aka.ms/sentinel-SnowflakeDataConnector-functionapp) file. Extract archive to your local development computer.\n2. Follow the [function app manual deployment instructions](https://github.com/Azure/Azure-Sentinel/blob/master/DataConnectors/AzureFunctionsManualDeployment.md#function-app-manual-deployment-instructions) to deploy the Azure Functions app using VSCode.\n3. After successful deployment of the function app, follow next steps for configuring it." + }, + { + "title": "Step 2 - Configure the Function App", + "description": "1. Go to Azure Portal for the Function App configuration. \n2. In the Function App, select the Function App Name and select **Configuration**.\n3. In the **Application settings** tab, select **+ New application setting**.\n4. Add each of the following application settings individually, with their respective string values (case-sensitive): \n\t\tSNOWFLAKE_ACCOUNT\n\t\tSNOWFLAKE_USER\n\t\tSNOWFLAKE_PASSWORD\n\t\tWORKSPACE_ID\n\t\tSHARED_KEY\n\t\tlogAnalyticsUri (optional)\n - Use logAnalyticsUri to override the log analytics API endpoint for dedicated cloud. For example, for public cloud, leave the value empty; for Azure GovUS cloud environment, specify the value in the following format: `https://WORKSPACE_ID.ods.opinsights.azure.us`. \n4. Once all application settings have been entered, click **Save**." + } + ] + }, + "type": "InstructionStepsGroup" + } + ] + } + ] + }, + "type": "InstructionStepsGroup" + } + ] + } + ] + } + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "apiVersion": "2023-04-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", + "properties": { + "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", + "contentId": "[variables('_dataConnectorContentId1')]", + "kind": "DataConnector", + "version": "[variables('dataConnectorVersion1')]", + "source": { + "kind": "Solution", + "name": "Snowflake", + "sourceId": "[variables('_solutionId')]" + }, + "author": { + "name": "Microsoft", + "email": "[variables('_email')]" + }, + "support": { + "name": "Microsoft Corporation", + "email": "support@microsoft.com", + "tier": "Microsoft", + "link": "https://support.microsoft.com" + } + } + } + ] + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_dataConnectorContentId1')]", + "contentKind": "DataConnector", + "displayName": "Snowflake (using Azure Function) (using Azure Functions)", + "contentProductId": "[variables('_dataConnectorcontentProductId1')]", + "id": "[variables('_dataConnectorcontentProductId1')]", + "version": "[variables('dataConnectorVersion1')]" + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "apiVersion": "2023-04-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", + "dependsOn": [ + "[variables('_dataConnectorId1')]" + ], + "location": "[parameters('workspace-location')]", + "properties": { + "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", + "contentId": "[variables('_dataConnectorContentId1')]", + "kind": "DataConnector", + "version": "[variables('dataConnectorVersion1')]", + "source": { + "kind": "Solution", + "name": "Snowflake", + "sourceId": "[variables('_solutionId')]" + }, + "author": { + "name": "Microsoft", + "email": "[variables('_email')]" + }, + "support": { + "name": "Microsoft Corporation", + "email": "support@microsoft.com", + "tier": "Microsoft", + "link": "https://support.microsoft.com" + } + } + }, + { + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId1'))]", + "apiVersion": "2021-03-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", + "location": "[parameters('workspace-location')]", + "kind": "GenericUI", + "properties": { + "connectorUiConfig": { + "title": "Snowflake (using Azure Function) (using Azure Functions)", + "publisher": "Snowflake", + "descriptionMarkdown": "The Snowflake data connector provides the capability to ingest Snowflake [login logs](https://docs.snowflake.com/en/sql-reference/account-usage/login_history.html) and [query logs](https://docs.snowflake.com/en/sql-reference/account-usage/query_history.html) into Microsoft Sentinel using the Snowflake Python Connector. Refer to [Snowflake documentation](https://docs.snowflake.com/en/user-guide/python-connector.html) for more information.", + "graphQueries": [ + { + "metricName": "Snowflake Events", + "legend": "Snowflake_CL", + "baseQuery": "Snowflake_CL" + } + ], + "dataTypes": [ + { + "name": "Snowflake_CL", + "lastDataReceivedQuery": "Snowflake_CL\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" + } + ], + "connectivityCriterias": [ + { + "type": "IsConnectedQuery", + "value": [ + "Snowflake_CL\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(1d)" + ] + } + ], + "sampleQueries": [ + { + "description": "All Snowflake Events", + "query": "Snowflake_CL\n| sort by TimeGenerated desc" + } + ], + "availability": { + "status": 1, + "isPreview": false + }, + "permissions": { + "resourceProvider": [ + { + "provider": "Microsoft.OperationalInsights/workspaces", + "permissionsDisplayText": "read and write permissions on the workspace are required.", + "providerDisplayName": "Workspace", + "scope": "Workspace", + "requiredPermissions": { + "write": true, + "read": true, + "delete": true + } + }, + { + "provider": "Microsoft.OperationalInsights/workspaces/sharedKeys", + "permissionsDisplayText": "read permissions to shared keys for the workspace are required. [See the documentation to learn more about workspace keys](https://docs.microsoft.com/azure/azure-monitor/platform/agent-windows#obtain-workspace-id-and-key).", + "providerDisplayName": "Keys", + "scope": "Workspace", + "requiredPermissions": { + "action": true + } + } + ], + "customs": [ + { + "name": "Microsoft.Web/sites permissions", + "description": "Read and write permissions to Azure Functions to create a Function App is required. [See the documentation to learn more about Azure Functions](https://docs.microsoft.com/azure/azure-functions/)." + }, + { + "name": "Snowflake Credentials", + "description": "**Snowflake Account Identifier**, **Snowflake User** and **Snowflake Password** are required for connection. See the documentation to learn more about [Snowflake Account Identifier](https://docs.snowflake.com/en/user-guide/admin-account-identifier.html#). Instructions on how to create user for this connector you can find below." + } + ] + }, + "instructionSteps": [ + { + "description": ">**NOTE:** This connector uses Azure Functions to connect to the Azure Blob Storage API to pull logs into Microsoft Sentinel. This might result in additional costs for data ingestion and for storing data in Azure Blob Storage costs. Check the [Azure Functions pricing page](https://azure.microsoft.com/pricing/details/functions/) and [Azure Blob Storage pricing page](https://azure.microsoft.com/pricing/details/storage/blobs/) for details." + }, + { + "description": ">**(Optional Step)** Securely store workspace and API authorization key(s) or token(s) in Azure Key Vault. Azure Key Vault provides a secure mechanism to store and retrieve key values. [Follow these instructions](https://docs.microsoft.com/azure/app-service/app-service-key-vault-references) to use Azure Key Vault with an Azure Function App." + }, + { + "description": ">**NOTE:** This data connector depends on a parser based on a Kusto Function to work as expected [**Snowflake**](https://aka.ms/sentinel-SnowflakeDataConnector-parser) which is deployed with the Microsoft Sentinel Solution." + }, + { + "description": "**STEP 1 - Creating user in Snowflake**\n\nTo query data from Snowflake you need a user that is assigned to a role with sufficient privileges and a virtual warehouse cluster. The initial size of this cluster will be set to small but if it is insufficient, the cluster size can be increased as necessary.\n\n1. Enter the Snowflake console.\n2. Switch role to SECURITYADMIN and [create a new role](https://docs.snowflake.com/en/sql-reference/sql/create-role.html):\n```\nUSE ROLE SECURITYADMIN;\nCREATE OR REPLACE ROLE EXAMPLE_ROLE_NAME;```\n3. Switch role to SYSADMIN and [create warehouse](https://docs.snowflake.com/en/sql-reference/sql/create-warehouse.html) and [grand access](https://docs.snowflake.com/en/sql-reference/sql/grant-privilege.html) to it:\n```\nUSE ROLE SYSADMIN;\nCREATE OR REPLACE WAREHOUSE EXAMPLE_WAREHOUSE_NAME\n WAREHOUSE_SIZE = 'SMALL' \n AUTO_SUSPEND = 5\n AUTO_RESUME = true\n INITIALLY_SUSPENDED = true;\nGRANT USAGE, OPERATE ON WAREHOUSE EXAMPLE_WAREHOUSE_NAME TO ROLE EXAMPLE_ROLE_NAME;```\n4. Switch role to SECURITYADMIN and [create a new user](https://docs.snowflake.com/en/sql-reference/sql/create-user.html):\n```\nUSE ROLE SECURITYADMIN;\nCREATE OR REPLACE USER EXAMPLE_USER_NAME\n PASSWORD = 'example_password'\n DEFAULT_ROLE = EXAMPLE_ROLE_NAME\n DEFAULT_WAREHOUSE = EXAMPLE_WAREHOUSE_NAME\n;```\n5. Switch role to ACCOUNTADMIN and [grant access to snowflake database](https://docs.snowflake.com/en/sql-reference/account-usage.html#enabling-account-usage-for-other-roles) for role.\n```\nUSE ROLE ACCOUNTADMIN;\nGRANT IMPORTED PRIVILEGES ON DATABASE SNOWFLAKE TO ROLE EXAMPLE_ROLE_NAME;```\n6. Switch role to SECURITYADMIN and [assign role](https://docs.snowflake.com/en/sql-reference/sql/grant-role.html) to user:\n```\nUSE ROLE SECURITYADMIN;\nGRANT ROLE EXAMPLE_ROLE_NAME TO USER EXAMPLE_USER_NAME;```\n\n>**IMPORTANT:** Save user and API password created during this step as they will be used during deployment step." + }, + { + "description": "**STEP 2 - Choose ONE from the following two deployment options to deploy the connector and the associated Azure Function**\n\n>**IMPORTANT:** Before deploying the data connector, have the Workspace ID and Workspace Primary Key (can be copied from the following), as well as Snowflake credentials, readily available.", + "instructions": [ + { + "parameters": { + "fillWith": [ + "WorkspaceId" + ], + "label": "Workspace ID" + }, + "type": "CopyableLabel" + }, + { + "parameters": { + "fillWith": [ + "PrimaryKey" + ], + "label": "Primary Key" + }, + "type": "CopyableLabel" + } + ] + }, + { + "instructions": [ + { + "parameters": { + "instructionSteps": [ + { + "title": "Option 1 - Azure Resource Manager (ARM) Template", + "description": "Use this method for automated deployment of the data connector using an ARM Template.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://aka.ms/sentinel-SnowflakeDataConnector-azuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Snowflake Account Identifier**, **Snowflake User**, **Snowflake Password**, **Microsoft Sentinel Workspace Id**, **Microsoft Sentinel Shared Key**\n4. Mark the checkbox labeled **I agree to the terms and conditions stated above**.\n5. Click **Purchase** to deploy." + }, + { + "title": "Option 2 - Manual Deployment of Azure Functions", + "description": "Use the following step-by-step instructions to deploy the data connector manually with Azure Functions (Deployment via Visual Studio Code).", + "instructions": [ + { + "parameters": { + "instructionSteps": [ + { + "title": "Step 1 - Deploy a Function App", + "description": "1. Download the [Azure Function App](https://aka.ms/sentinel-SnowflakeDataConnector-functionapp) file. Extract archive to your local development computer.\n2. Follow the [function app manual deployment instructions](https://github.com/Azure/Azure-Sentinel/blob/master/DataConnectors/AzureFunctionsManualDeployment.md#function-app-manual-deployment-instructions) to deploy the Azure Functions app using VSCode.\n3. After successful deployment of the function app, follow next steps for configuring it." + }, + { + "title": "Step 2 - Configure the Function App", + "description": "1. Go to Azure Portal for the Function App configuration. \n2. In the Function App, select the Function App Name and select **Configuration**.\n3. In the **Application settings** tab, select **+ New application setting**.\n4. Add each of the following application settings individually, with their respective string values (case-sensitive): \n\t\tSNOWFLAKE_ACCOUNT\n\t\tSNOWFLAKE_USER\n\t\tSNOWFLAKE_PASSWORD\n\t\tWORKSPACE_ID\n\t\tSHARED_KEY\n\t\tlogAnalyticsUri (optional)\n - Use logAnalyticsUri to override the log analytics API endpoint for dedicated cloud. For example, for public cloud, leave the value empty; for Azure GovUS cloud environment, specify the value in the following format: `https://WORKSPACE_ID.ods.opinsights.azure.us`. \n4. Once all application settings have been entered, click **Save**." + } + ] + }, + "type": "InstructionStepsGroup" + } + ] + } + ] + }, + "type": "InstructionStepsGroup" + } + ] + } + ], + "id": "[variables('_uiConfigId1')]", + "additionalRequirementBanner": "This data connector depends on a parser based on a Kusto Function to work as expected [**Snowflake**](https://aka.ms/sentinel-SnowflakeDataConnector-parser) which is deployed with the Microsoft Sentinel Solution." + } + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('parserTemplateSpecName1')]", + "location": "[parameters('workspace-location')]", + "dependsOn": [ + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" + ], + "properties": { + "description": "Snowflake Data Parser with template version 3.0.0", + "mainTemplate": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "[variables('parserVersion1')]", + "parameters": {}, + "variables": {}, + "resources": [ + { + "name": "[variables('_parserName1')]", + "apiVersion": "2022-10-01", + "type": "Microsoft.OperationalInsights/workspaces/savedSearches", + "location": "[parameters('workspace-location')]", + "properties": { + "eTag": "*", + "displayName": "Snowflake Data Parser", + "category": "Samples", + "functionAlias": "Snowflake", + "query": "\nSnowflake_CL\n| extend EventVendor = 'Snowflake'\n| extend EventProduct = 'Snowflake'\n| project-rename \n EventStartTime=START_TIME_t,\n EventType=EVENT_TYPE_s,\n TargetUsername=USER_NAME_s,\n SrcDvcIpAddr=CLIENT_IP_s\n| extend \n User=TargetUsername,\n EventEndTime=iff(isnotempty(EVENT_TIMESTAMP_t), EVENT_TIMESTAMP_t, END_TIME_t)", + "functionParameters": "", + "version": 1, + "tags": [ + { + "name": "description", + "value": "Snowflake Data Parser" + } + ] + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "apiVersion": "2022-01-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Parser-', last(split(variables('_parserId1'),'/'))))]", + "dependsOn": [ + "[variables('_parserName1')]" + ], + "properties": { + "parentId": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), variables('parserName1'))]", + "contentId": "[variables('_parserContentId1')]", + "kind": "Parser", + "version": "[variables('parserVersion1')]", + "source": { + "name": "Snowflake", + "kind": "Solution", + "sourceId": "[variables('_solutionId')]" + }, + "author": { + "name": "Microsoft", + "email": "[variables('_email')]" + }, + "support": { + "name": "Microsoft Corporation", + "email": "support@microsoft.com", + "tier": "Microsoft", + "link": "https://support.microsoft.com" + } + } + } + ] + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_parserContentId1')]", + "contentKind": "Parser", + "displayName": "Snowflake Data Parser", + "contentProductId": "[variables('_parsercontentProductId1')]", + "id": "[variables('_parsercontentProductId1')]", + "version": "[variables('parserVersion1')]" + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/savedSearches", + "apiVersion": "2022-10-01", + "name": "[variables('_parserName1')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "properties": { - "description": "Snowflake Analytics Rule 1 with template", - "displayName": "Snowflake Analytics Rule template" + "eTag": "*", + "displayName": "Snowflake Data Parser", + "category": "Samples", + "functionAlias": "Snowflake", + "query": "\nSnowflake_CL\n| extend EventVendor = 'Snowflake'\n| extend EventProduct = 'Snowflake'\n| project-rename \n EventStartTime=START_TIME_t,\n EventType=EVENT_TYPE_s,\n TargetUsername=USER_NAME_s,\n SrcDvcIpAddr=CLIENT_IP_s\n| extend \n User=TargetUsername,\n EventEndTime=iff(isnotempty(EVENT_TIMESTAMP_t), EVENT_TIMESTAMP_t, END_TIME_t)", + "functionParameters": "", + "version": 1, + "tags": [ + { + "name": "description", + "value": "Snowflake Data Parser" + } + ] } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('analyticRuleTemplateSpecName1'),'/',variables('analyticRuleVersion1'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "apiVersion": "2022-01-01-preview", + "location": "[parameters('workspace-location')]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Parser-', last(split(variables('_parserId1'),'/'))))]", + "dependsOn": [ + "[variables('_parserId1')]" + ], + "properties": { + "parentId": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), variables('parserName1'))]", + "contentId": "[variables('_parserContentId1')]", + "kind": "Parser", + "version": "[variables('parserVersion1')]", + "source": { + "kind": "Solution", + "name": "Snowflake", + "sourceId": "[variables('_solutionId')]" + }, + "author": { + "name": "Microsoft", + "email": "[variables('_email')]" + }, + "support": { + "name": "Microsoft Corporation", + "email": "support@microsoft.com", + "tier": "Microsoft", + "link": "https://support.microsoft.com" + } + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('workbookTemplateSpecName1')]", + "location": "[parameters('workspace-location')]", + "dependsOn": [ + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" + ], + "properties": { + "description": "SnowflakeWorkbook Workbook with template version 3.0.0", + "mainTemplate": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "[variables('workbookVersion1')]", + "parameters": {}, + "variables": {}, + "resources": [ + { + "type": "Microsoft.Insights/workbooks", + "name": "[variables('workbookContentId1')]", + "location": "[parameters('workspace-location')]", + "kind": "shared", + "apiVersion": "2021-08-01", + "metadata": { + "description": "Sets the time name for analysis" + }, + "properties": { + "displayName": "[parameters('workbook1-name')]", + "serializedData": "{\"version\":\"Notebook/1.0\",\"items\":[{\"type\":1,\"content\":{\"json\":\"**NOTE**: This data connector depends on a parser based on Kusto Function **Snowflake** to work as expected. [Follow steps to get this Kusto Function](https://aka.ms/sentinel-SnowflakeDataConnector-parser)\"},\"name\":\"text - 8\"},{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"parameters\":[{\"id\":\"cd8447d9-b096-4673-92d8-2a1e8291a125\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"TimeRange\",\"type\":4,\"description\":\"Sets the time name for analysis\",\"value\":{\"durationMs\":7776000000},\"typeSettings\":{\"selectableValues\":[{\"durationMs\":1800000},{\"durationMs\":3600000},{\"durationMs\":86400000},{\"durationMs\":604800000},{\"durationMs\":2592000000},{\"durationMs\":7776000000}]},\"timeContext\":{\"durationMs\":86400000}}],\"style\":\"pills\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"parameters - 11\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\r\\n| make-series TotalEvents = count() default = 0 on TimeGenerated from {TimeRange:start} to {TimeRange:end} step {TimeRange:grain};\",\"size\":0,\"title\":\"Events Over Time\",\"color\":\"green\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"timechart\",\"graphSettings\":{\"type\":0}},\"customWidth\":\"60\",\"name\":\"query - 12\",\"styleSettings\":{\"maxWidth\":\"55\"}},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(DATABASE_NAME_s)\\n| summarize dcount(DATABASE_NAME_s)\",\"size\":3,\"title\":\"Total Databases\",\"timeContext\":{\"durationMs\":7776000000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"50\",\"name\":\"query - 1\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(source_table_s)\\n| summarize dcount(source_table_s)\",\"size\":3,\"title\":\"Total Tables\",\"timeContext\":{\"durationMs\":7776000000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"50\",\"name\":\"query - 2\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| summarize s=sum(EXECUTION_TIME_d)\\n| project s_time = strcat(s/1000, ' sec')\",\"size\":3,\"title\":\"Total Query Time\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"30\",\"name\":\"query - 0\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(QUERY_TYPE_s)\\n| summarize count()\",\"size\":3,\"title\":\"Total Queries Run\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"30\",\"name\":\"query - 3\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| summarize cs = sum(CREDITS_USED_CLOUD_SERVICES_d)\\n| project round(cs, 8)\",\"size\":3,\"title\":\"Credits Spent\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"40\",\"name\":\"query - 4\"}]},\"customWidth\":\"40\",\"name\":\"group - 0\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(source_table_s)\\n| summarize count() by source_table_s\",\"size\":3,\"title\":\"Table Events Summary\",\"color\":\"orange\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"tiles\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"source_table_s\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"count_\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"maximumSignificantDigits\":3,\"maximumFractionDigits\":2}}},\"showBorder\":false}},\"customWidth\":\"50\",\"name\":\"query - 0\",\"styleSettings\":{\"showBorder\":true}},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(DATABASE_NAME_s)\\n| summarize count() by DATABASE_NAME_s\",\"size\":3,\"title\":\"Database Events Summary\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"tiles\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"DATABASE_NAME_s\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"count_\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"style\":\"decimal\",\"maximumFractionDigits\":2,\"maximumSignificantDigits\":3}}},\"showBorder\":false}},\"customWidth\":\"50\",\"name\":\"query - 1\",\"styleSettings\":{\"showBorder\":true}}]},\"customWidth\":\"30\",\"name\":\"group - 11\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(SrcDvcIpAddr)\\n| summarize count() by SrcDvcIpAddr\",\"size\":3,\"title\":\"Source Addresses\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"piechart\"},\"customWidth\":\"30\",\"name\":\"query - 9\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where EXECUTION_TIME_d > 0\\n| top 10 by EXECUTION_TIME_d desc\\n| project Query=QUERY_TEXT_s, User=TargetUsername, ExecutionTime=EXECUTION_TIME_d\\n\",\"size\":0,\"title\":\"Query Execution Time\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"ExecutionTime\",\"formatter\":8,\"formatOptions\":{\"palette\":\"coldHot\"}}]}},\"customWidth\":\"35\",\"name\":\"query - 11\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where CREDITS_USED_CLOUD_SERVICES_d > 0\\n| summarize by QUERY_TEXT_s, CREDITS_USED_CLOUD_SERVICES_d\\n| top 10 by CREDITS_USED_CLOUD_SERVICES_d desc\\n| project Query=QUERY_TEXT_s, CreditsSpent=CREDITS_USED_CLOUD_SERVICES_d\",\"size\":0,\"title\":\"Credits Spent by Queriws\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"CreditsSpent\",\"formatter\":8,\"formatOptions\":{\"palette\":\"coldHot\",\"compositeBarSettings\":{\"labelText\":\"\",\"columnSettings\":[]}},\"numberFormat\":{\"unit\":0,\"options\":{\"style\":\"decimal\",\"maximumFractionDigits\":10}}}]}},\"customWidth\":\"35\",\"name\":\"query - 9\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\r\\n| where QUERY_TYPE_s == 'CREATE_USER'\\r\\n| extend n_usr = extract(@'USER\\\\s(\\\\S+)', 1, QUERY_TEXT_s)\\r\\n| project Username=n_usr\",\"size\":0,\"title\":\"New Users\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"URL Category\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"count_\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"style\":\"decimal\",\"maximumFractionDigits\":2,\"maximumSignificantDigits\":3}}},\"secondaryContent\":{\"columnMatch\":\"Trend\",\"formatter\":9,\"formatOptions\":{\"palette\":\"purple\"}},\"showBorder\":false},\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"20\",\"name\":\"query - 0\",\"styleSettings\":{\"maxWidth\":\"30\"}},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n\\n| where QUERY_TYPE_s =~ 'SELECT'\\n| summarize roles = makeset(ROLE_NAME_s) by TargetUsername\\n| join(Snowflake\\n | where EventType =~ 'LOGIN') on TargetUsername\\n| project EventTime=TimeGenerated, TargetUsername, SourceAddress=SrcDvcIpAddr, Status=strcat(iif(IS_SUCCESS_s =~ 'No', '❌ - Login Failure' , '✅ - Logged in'))\",\"size\":0,\"title\":\"Privileged Sessions\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"User\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"TotalMailsReceived\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"maximumSignificantDigits\":3,\"maximumFractionDigits\":2}}},\"secondaryContent\":{\"columnMatch\":\"Trend\",\"formatter\":10,\"formatOptions\":{\"palette\":\"magenta\"}},\"showBorder\":false}},\"customWidth\":\"45\",\"name\":\"query - 10\"}],\"fromTemplateId\":\"sentinel-SnowflakeWorkbook\",\"$schema\":\"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"}\n", + "version": "1.0", + "sourceId": "[variables('workspaceResourceId')]", + "category": "sentinel" + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "apiVersion": "2022-01-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Workbook-', last(split(variables('workbookId1'),'/'))))]", + "properties": { + "description": "@{workbookKey=SnowflakeWorkbook; logoFileName=Azure_Sentinel.svg; description=Sets the time name for analysis; dataTypesDependencies=System.Object[]; dataConnectorsDependencies=System.Object[]; previewImagesFileNames=System.Object[]; version=1.0.0; title=Snowflake; templateRelativePath=Snowflake.json; subtitle=; provider=Snowflake}.description", + "parentId": "[variables('workbookId1')]", + "contentId": "[variables('_workbookContentId1')]", + "kind": "Workbook", + "version": "[variables('workbookVersion1')]", + "source": { + "kind": "Solution", + "name": "Snowflake", + "sourceId": "[variables('_solutionId')]" + }, + "author": { + "name": "Microsoft", + "email": "[variables('_email')]" + }, + "support": { + "name": "Microsoft Corporation", + "email": "support@microsoft.com", + "tier": "Microsoft", + "link": "https://support.microsoft.com" + }, + "dependencies": { + "operator": "AND", + "criteria": [ + { + "contentId": "Snowflake_CL", + "kind": "DataType" + }, + { + "contentId": "SnowflakeDataConnector", + "kind": "DataConnector" + } + ] + } + } + } + ] + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_workbookContentId1')]", + "contentKind": "Workbook", + "displayName": "[parameters('workbook1-name')]", + "contentProductId": "[variables('_workbookcontentProductId1')]", + "id": "[variables('_workbookcontentProductId1')]", + "version": "[variables('workbookVersion1')]" + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName1')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName1'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeDiscoveryActivity_AnalyticalRules Analytics Rule with template version 2.0.0", + "description": "SnowflakeDiscoveryActivity_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion1')]", @@ -202,7 +825,7 @@ "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId1')]", + "name": "[variables('analyticRulecontentId1')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", @@ -271,37 +894,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId1')]", + "contentKind": "AnalyticsRule", + "displayName": "Snowflake - Possible discovery activity", + "contentProductId": "[variables('_analyticRulecontentProductId1')]", + "id": "[variables('_analyticRulecontentProductId1')]", + "version": "[variables('analyticRuleVersion1')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('analyticRuleTemplateSpecName2')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Snowflake Analytics Rule 2 with template", - "displayName": "Snowflake Analytics Rule template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('analyticRuleTemplateSpecName2'),'/',variables('analyticRuleVersion2'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName2'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeLongQueryProcessTime_AnalyticalRules Analytics Rule with template version 2.0.0", + "description": "SnowflakeLongQueryProcessTime_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion2')]", @@ -310,7 +926,7 @@ "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId2')]", + "name": "[variables('analyticRulecontentId2')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", @@ -338,6 +954,9 @@ "tactics": [ "Impact" ], + "techniques": [ + "T1499" + ], "entityMappings": [ { "entityType": "Account", @@ -379,37 +998,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId2')]", + "contentKind": "AnalyticsRule", + "displayName": "Snowflake - Abnormal query process time", + "contentProductId": "[variables('_analyticRulecontentProductId2')]", + "id": "[variables('_analyticRulecontentProductId2')]", + "version": "[variables('analyticRuleVersion2')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('analyticRuleTemplateSpecName3')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Snowflake Analytics Rule 3 with template", - "displayName": "Snowflake Analytics Rule template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('analyticRuleTemplateSpecName3'),'/',variables('analyticRuleVersion3'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName3'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeMultipleFailedQueries_AnalyticalRules Analytics Rule with template version 2.0.0", + "description": "SnowflakeMultipleFailedQueries_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion3')]", @@ -418,7 +1030,7 @@ "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId3')]", + "name": "[variables('analyticRulecontentId3')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", @@ -446,6 +1058,10 @@ "tactics": [ "Discovery" ], + "techniques": [ + "T1518", + "T1082" + ], "entityMappings": [ { "entityType": "Account", @@ -487,37 +1103,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId3')]", + "contentKind": "AnalyticsRule", + "displayName": "Snowflake - Multiple failed queries", + "contentProductId": "[variables('_analyticRulecontentProductId3')]", + "id": "[variables('_analyticRulecontentProductId3')]", + "version": "[variables('analyticRuleVersion3')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('analyticRuleTemplateSpecName4')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Snowflake Analytics Rule 4 with template", - "displayName": "Snowflake Analytics Rule template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('analyticRuleTemplateSpecName4'),'/',variables('analyticRuleVersion4'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName4'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeMultipleLoginFailure_AnalyticalRules Analytics Rule with template version 2.0.0", + "description": "SnowflakeMultipleLoginFailure_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion4')]", @@ -526,7 +1135,7 @@ "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId4')]", + "name": "[variables('analyticRulecontentId4')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", @@ -554,6 +1163,9 @@ "tactics": [ "InitialAccess" ], + "techniques": [ + "T1078" + ], "entityMappings": [ { "entityType": "Account", @@ -595,37 +1207,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId4')]", + "contentKind": "AnalyticsRule", + "displayName": "Snowflake - Multiple login failures by user", + "contentProductId": "[variables('_analyticRulecontentProductId4')]", + "id": "[variables('_analyticRulecontentProductId4')]", + "version": "[variables('analyticRuleVersion4')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('analyticRuleTemplateSpecName5')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Snowflake Analytics Rule 5 with template", - "displayName": "Snowflake Analytics Rule template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('analyticRuleTemplateSpecName5'),'/',variables('analyticRuleVersion5'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName5'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeMultipleLoginFailureFromIP_AnalyticalRules Analytics Rule with template version 2.0.0", + "description": "SnowflakeMultipleLoginFailureFromIP_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion5')]", @@ -634,7 +1239,7 @@ "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId5')]", + "name": "[variables('analyticRulecontentId5')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", @@ -662,6 +1267,9 @@ "tactics": [ "InitialAccess" ], + "techniques": [ + "T1078" + ], "entityMappings": [ { "entityType": "IP", @@ -700,40 +1308,33 @@ "tier": "Microsoft", "link": "https://support.microsoft.com" } - } - } - ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", - "name": "[variables('analyticRuleTemplateSpecName6')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Snowflake Analytics Rule 6 with template", - "displayName": "Snowflake Analytics Rule template" + } + } + ] + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId5')]", + "contentKind": "AnalyticsRule", + "displayName": "Snowflake - Multiple login failures from single IP", + "contentProductId": "[variables('_analyticRulecontentProductId5')]", + "id": "[variables('_analyticRulecontentProductId5')]", + "version": "[variables('analyticRuleVersion5')]" } }, { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('analyticRuleTemplateSpecName6'),'/',variables('analyticRuleVersion6'))]", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('analyticRuleTemplateSpecName6')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName6'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakePossibleDataDestruction_AnalyticalRules Analytics Rule with template version 2.0.0", + "description": "SnowflakePossibleDataDestruction_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion6')]", @@ -742,7 +1343,7 @@ "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId6')]", + "name": "[variables('analyticRulecontentId6')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", @@ -770,6 +1371,9 @@ "tactics": [ "Impact" ], + "techniques": [ + "T1485" + ], "entityMappings": [ { "entityType": "Account", @@ -811,37 +1415,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId6')]", + "contentKind": "AnalyticsRule", + "displayName": "Snowflake - Possible data destraction", + "contentProductId": "[variables('_analyticRulecontentProductId6')]", + "id": "[variables('_analyticRulecontentProductId6')]", + "version": "[variables('analyticRuleVersion6')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('analyticRuleTemplateSpecName7')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Snowflake Analytics Rule 7 with template", - "displayName": "Snowflake Analytics Rule template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('analyticRuleTemplateSpecName7'),'/',variables('analyticRuleVersion7'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName7'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakePrivilegesDiscovery_AnalyticalRules Analytics Rule with template version 2.0.0", + "description": "SnowflakePrivilegesDiscovery_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion7')]", @@ -850,7 +1447,7 @@ "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId7')]", + "name": "[variables('analyticRulecontentId7')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", @@ -878,6 +1475,9 @@ "tactics": [ "Discovery" ], + "techniques": [ + "T1087" + ], "entityMappings": [ { "entityType": "Account", @@ -919,37 +1519,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId7')]", + "contentKind": "AnalyticsRule", + "displayName": "Snowflake - Possible privileges discovery activity", + "contentProductId": "[variables('_analyticRulecontentProductId7')]", + "id": "[variables('_analyticRulecontentProductId7')]", + "version": "[variables('analyticRuleVersion7')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('analyticRuleTemplateSpecName8')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Snowflake Analytics Rule 8 with template", - "displayName": "Snowflake Analytics Rule template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('analyticRuleTemplateSpecName8'),'/',variables('analyticRuleVersion8'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName8'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeQueryOnSensitiveTable_AnalyticalRules Analytics Rule with template version 2.0.0", + "description": "SnowflakeQueryOnSensitiveTable_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion8')]", @@ -958,7 +1551,7 @@ "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId8')]", + "name": "[variables('analyticRulecontentId8')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", @@ -986,6 +1579,9 @@ "tactics": [ "Collection" ], + "techniques": [ + "T1119" + ], "entityMappings": [ { "entityType": "Account", @@ -1027,37 +1623,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId8')]", + "contentKind": "AnalyticsRule", + "displayName": "Snowflake - Query on sensitive or restricted table", + "contentProductId": "[variables('_analyticRulecontentProductId8')]", + "id": "[variables('_analyticRulecontentProductId8')]", + "version": "[variables('analyticRuleVersion8')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('analyticRuleTemplateSpecName9')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Snowflake Analytics Rule 9 with template", - "displayName": "Snowflake Analytics Rule template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('analyticRuleTemplateSpecName9'),'/',variables('analyticRuleVersion9'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName9'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeUnusualQuery_AnalyticalRules Analytics Rule with template version 2.0.0", + "description": "SnowflakeUnusualQuery_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion9')]", @@ -1066,7 +1655,7 @@ "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId9')]", + "name": "[variables('analyticRulecontentId9')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", @@ -1094,6 +1683,9 @@ "tactics": [ "Collection" ], + "techniques": [ + "T1119" + ], "entityMappings": [ { "entityType": "Account", @@ -1135,37 +1727,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId9')]", + "contentKind": "AnalyticsRule", + "displayName": "Snowflake - Unusual query", + "contentProductId": "[variables('_analyticRulecontentProductId9')]", + "id": "[variables('_analyticRulecontentProductId9')]", + "version": "[variables('analyticRuleVersion9')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('analyticRuleTemplateSpecName10')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, - "properties": { - "description": "Snowflake Analytics Rule 10 with template", - "displayName": "Snowflake Analytics Rule template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('analyticRuleTemplateSpecName10'),'/',variables('analyticRuleVersion10'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "AnalyticsRule" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('analyticRuleTemplateSpecName10'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeUserAddAdminPrivileges_AnalyticalRules Analytics Rule with template version 2.0.0", + "description": "SnowflakeUserAddAdminPrivileges_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion10')]", @@ -1174,253 +1759,60 @@ "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('AnalyticRulecontentId10')]", + "name": "[variables('analyticRulecontentId10')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", - "properties": { - "description": "Detects when user asigned admin privileges.", - "displayName": "Snowflake - User granted admin privileges", - "enabled": false, - "query": "let adm_roles = dynamic(['SECURITYADMIN', 'SYSADMIN', 'ACCOUNTADMIN']);\nSnowflake\n| where QUERY_TYPE_s =~ 'GRANT'\n| where QUERY_TEXT_s startswith 'GRANT ROLE'\n| extend granted_role = extract(@'GRANT ROLE\\s(\\S+)\\sto\\suser', 1, QUERY_TEXT_s)\n| where granted_role in~ (adm_roles)\n| extend usr = extract(@'GRANT ROLE\\s(\\S+)\\sto\\suser(\\S+)', 2, QUERY_TEXT_s)\n| extend AccountCustomEntity = usr\n", - "queryFrequency": "PT1H", - "queryPeriod": "PT1H", - "severity": "Medium", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 0, - "status": "Available", - "requiredDataConnectors": [ - { - "connectorId": "Snowflake", - "dataTypes": [ - "Snowflake" - ] - } - ], - "tactics": [ - "PrivilegeEscalation" - ], - "entityMappings": [ - { - "entityType": "Account", - "fieldMappings": [ - { - "columnName": "AccountCustomEntity", - "identifier": "Name" - } - ] - } - ] - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId10'),'/'))))]", - "properties": { - "description": "Snowflake Analytics Rule 10", - "parentId": "[variables('analyticRuleId10')]", - "contentId": "[variables('_analyticRulecontentId10')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion10')]", - "source": { - "kind": "Solution", - "name": "Snowflake", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" - }, - "support": { - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "tier": "Microsoft", - "link": "https://support.microsoft.com" - } - } - } - ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", - "name": "[variables('dataConnectorTemplateSpecName1')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "DataConnector" - }, - "properties": { - "description": "Snowflake data connector with template", - "displayName": "Snowflake template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('dataConnectorTemplateSpecName1'),'/',variables('dataConnectorVersion1'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "DataConnector" - }, - "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('dataConnectorTemplateSpecName1'))]" - ], - "properties": { - "description": "Snowflake data connector with template version 2.0.0", - "mainTemplate": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('dataConnectorVersion1')]", - "parameters": {}, - "variables": {}, - "resources": [ - { - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId1'))]", - "apiVersion": "2021-03-01-preview", - "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", - "location": "[parameters('workspace-location')]", - "kind": "GenericUI", - "properties": { - "connectorUiConfig": { - "id": "[variables('_uiConfigId1')]", - "title": "Snowflake (using Azure Function)", - "publisher": "Snowflake", - "descriptionMarkdown": "The Snowflake data connector provides the capability to ingest Snowflake [login logs](https://docs.snowflake.com/en/sql-reference/account-usage/login_history.html) and [query logs](https://docs.snowflake.com/en/sql-reference/account-usage/query_history.html) into Microsoft Sentinel using the Snowflake Python Connector. Refer to [Snowflake documentation](https://docs.snowflake.com/en/user-guide/python-connector.html) for more information.", - "additionalRequirementBanner": "This data connector depends on a parser based on a Kusto Function to work as expected [**Snowflake**](https://aka.ms/sentinel-SnowflakeDataConnector-parser) which is deployed with the Microsoft Sentinel Solution.", - "graphQueries": [ - { - "metricName": "Snowflake Events", - "legend": "Snowflake_CL", - "baseQuery": "Snowflake_CL" - } - ], - "sampleQueries": [ - { - "description": "All Snowflake Events", - "query": "Snowflake_CL\n| sort by TimeGenerated desc" - } - ], - "dataTypes": [ - { - "name": "Snowflake_CL", - "lastDataReceivedQuery": "Snowflake_CL\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" - } - ], - "connectivityCriterias": [ - { - "type": "IsConnectedQuery", - "value": [ - "Snowflake_CL\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(1d)" - ] - } - ], - "availability": { - "status": 1, - "isPreview": false - }, - "permissions": { - "resourceProvider": [ - { - "provider": "Microsoft.OperationalInsights/workspaces", - "permissionsDisplayText": "read and write permissions on the workspace are required.", - "providerDisplayName": "Workspace", - "scope": "Workspace", - "requiredPermissions": { - "write": true, - "read": true, - "delete": true - } - }, - { - "provider": "Microsoft.OperationalInsights/workspaces/sharedKeys", - "permissionsDisplayText": "read permissions to shared keys for the workspace are required. [See the documentation to learn more about workspace keys](https://docs.microsoft.com/azure/azure-monitor/platform/agent-windows#obtain-workspace-id-and-key).", - "providerDisplayName": "Keys", - "scope": "Workspace", - "requiredPermissions": { - "action": true - } - } - ], - "customs": [ - { - "name": "Microsoft.Web/sites permissions", - "description": "Read and write permissions to Azure Functions to create a Function App is required. [See the documentation to learn more about Azure Functions](https://docs.microsoft.com/azure/azure-functions/)." - }, - { - "name": "Snowflake Credentials", - "description": "**Snowflake Account Identifier**, **Snowflake User** and **Snowflake Password** are required for connection. See the documentation to learn more about [Snowflake Account Identifier](https://docs.snowflake.com/en/user-guide/admin-account-identifier.html#). Instructions on how to create user for this connector you can find below." - } - ] - }, - "instructionSteps": [ - { - "description": ">**NOTE:** This connector uses Azure Functions to connect to the Azure Blob Storage API to pull logs into Microsoft Sentinel. This might result in additional costs for data ingestion and for storing data in Azure Blob Storage costs. Check the [Azure Functions pricing page](https://azure.microsoft.com/pricing/details/functions/) and [Azure Blob Storage pricing page](https://azure.microsoft.com/pricing/details/storage/blobs/) for details." - }, - { - "description": ">**(Optional Step)** Securely store workspace and API authorization key(s) or token(s) in Azure Key Vault. Azure Key Vault provides a secure mechanism to store and retrieve key values. [Follow these instructions](https://docs.microsoft.com/azure/app-service/app-service-key-vault-references) to use Azure Key Vault with an Azure Function App." - }, - { - "description": ">**NOTE:** This data connector depends on a parser based on a Kusto Function to work as expected [**Snowflake**](https://aka.ms/sentinel-SnowflakeDataConnector-parser) which is deployed with the Microsoft Sentinel Solution." - }, - { - "description": "**STEP 1 - Creating user in Snowflake**\n\nTo query data from Snowflake you need a user that is assigned to a role with sufficient privileges and a virtual warehouse cluster. The initial size of this cluster will be set to small but if it is insufficient, the cluster size can be increased as necessary.\n\n1. Enter the Snowflake console.\n2. Switch role to SECURITYADMIN and [create a new role](https://docs.snowflake.com/en/sql-reference/sql/create-role.html):\n```\nUSE ROLE SECURITYADMIN;\nCREATE OR REPLACE ROLE EXAMPLE_ROLE_NAME;```\n3. Switch role to SYSADMIN and [create warehouse](https://docs.snowflake.com/en/sql-reference/sql/create-warehouse.html) and [grand access](https://docs.snowflake.com/en/sql-reference/sql/grant-privilege.html) to it:\n```\nUSE ROLE SYSADMIN;\nCREATE OR REPLACE WAREHOUSE EXAMPLE_WAREHOUSE_NAME\n WAREHOUSE_SIZE = 'SMALL' \n AUTO_SUSPEND = 5\n AUTO_RESUME = true\n INITIALLY_SUSPENDED = true;\nGRANT USAGE, OPERATE ON WAREHOUSE EXAMPLE_WAREHOUSE_NAME TO ROLE EXAMPLE_ROLE_NAME;```\n4. Switch role to SECURITYADMIN and [create a new user](https://docs.snowflake.com/en/sql-reference/sql/create-user.html):\n```\nUSE ROLE SECURITYADMIN;\nCREATE OR REPLACE USER EXAMPLE_USER_NAME\n PASSWORD = 'example_password'\n DEFAULT_ROLE = EXAMPLE_ROLE_NAME\n DEFAULT_WAREHOUSE = EXAMPLE_WAREHOUSE_NAME\n;```\n5. Switch role to ACCOUNTADMIN and [grant access to snowflake database](https://docs.snowflake.com/en/sql-reference/account-usage.html#enabling-account-usage-for-other-roles) for role.\n```\nUSE ROLE ACCOUNTADMIN;\nGRANT IMPORTED PRIVILEGES ON DATABASE SNOWFLAKE TO ROLE EXAMPLE_ROLE_NAME;```\n6. Switch role to SECURITYADMIN and [assign role](https://docs.snowflake.com/en/sql-reference/sql/grant-role.html) to user:\n```\nUSE ROLE SECURITYADMIN;\nGRANT ROLE EXAMPLE_ROLE_NAME TO USER EXAMPLE_USER_NAME;```\n\n>**IMPORTANT:** Save user and API password created during this step as they will be used during deployment step." - }, - { - "description": "**STEP 2 - Choose ONE from the following two deployment options to deploy the connector and the associated Azure Function**\n\n>**IMPORTANT:** Before deploying the data connector, have the Workspace ID and Workspace Primary Key (can be copied from the following), as well as Snowflake credentials, readily available.", - "instructions": [ - { - "parameters": { - "fillWith": [ - "WorkspaceId" - ], - "label": "Workspace ID" - }, - "type": "CopyableLabel" - }, - { - "parameters": { - "fillWith": [ - "PrimaryKey" - ], - "label": "Primary Key" - }, - "type": "CopyableLabel" - } - ] - }, - { - "description": "Use this method for automated deployment of the data connector using an ARM Template.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://aka.ms/sentinel-SnowflakeDataConnector-azuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Snowflake Account Identifier**, **Snowflake User**, **Snowflake Password**, **Microsoft Sentinel Workspace Id**, **Microsoft Sentinel Shared Key**\n4. Mark the checkbox labeled **I agree to the terms and conditions stated above**.\n5. Click **Purchase** to deploy.", - "title": "Option 1 - Azure Resource Manager (ARM) Template" - }, - { - "description": "Use the following step-by-step instructions to deploy the data connector manually with Azure Functions (Deployment via Visual Studio Code).", - "title": "Option 2 - Manual Deployment of Azure Functions" - }, - { - "description": "**1. Deploy a Function App**\n\n> **NOTE:** You will need to [prepare VS code](https://docs.microsoft.com/azure/azure-functions/create-first-function-vs-code-python) for Azure function development.\n\n1. Download the [Azure Function App](https://aka.ms/sentinel-SnowflakeDataConnector-functionapp) file. Extract archive to your local development computer.\n2. Start VS Code. Choose File in the main menu and select Open Folder.\n3. Select the top level folder from extracted files.\n4. Choose the Azure icon in the Activity bar, then in the **Azure: Functions** area, choose the **Deploy to function app** button.\nIf you aren't already signed in, choose the Azure icon in the Activity bar, then in the **Azure: Functions** area, choose **Sign in to Azure**\nIf you're already signed in, go to the next step.\n5. Provide the following information at the prompts:\n\n\ta. **Select folder:** Choose a folder from your workspace or browse to one that contains your function app.\n\n\tb. **Select Subscription:** Choose the subscription to use.\n\n\tc. Select **Create new Function App in Azure** (Don't choose the Advanced option)\n\n\td. **Enter a globally unique name for the function app:** Type a name that is valid in a URL path. The name you type is validated to make sure that it's unique in Azure Functions. (e.g. Snowflake12).\n\n\te. **Select a runtime:** Choose Python 3.8.\n\n\tf. Select a location for new resources. For better performance and lower costs choose the same [region](https://azure.microsoft.com/regions/) where Microsoft Sentinel is located.\n\n6. Deployment will begin. A notification is displayed after your function app is created and the deployment package is applied.\n7. Go to Azure Portal for the Function App configuration." - }, - { - "description": "**2. Configure the Function App**\n\n1. In the Function App, select the Function App Name and select **Configuration**.\n2. In the **Application settings** tab, select **+ New application setting**.\n3. Add each of the following application settings individually, with their respective string values (case-sensitive): \n\t\tSNOWFLAKE_ACCOUNT\n\t\tSNOWFLAKE_USER\n\t\tSNOWFLAKE_PASSWORD\n\t\tWORKSPACE_ID\n\t\tSHARED_KEY\n\t\tlogAnalyticsUri (optional)\n - Use logAnalyticsUri to override the log analytics API endpoint for dedicated cloud. For example, for public cloud, leave the value empty; for Azure GovUS cloud environment, specify the value in the following format: `https://WORKSPACE_ID.ods.opinsights.azure.us`. \n4. Once all application settings have been entered, click **Save**." - } - ] - } + "properties": { + "description": "Detects when user asigned admin privileges.", + "displayName": "Snowflake - User granted admin privileges", + "enabled": false, + "query": "let adm_roles = dynamic(['SECURITYADMIN', 'SYSADMIN', 'ACCOUNTADMIN']);\nSnowflake\n| where QUERY_TYPE_s =~ 'GRANT'\n| where QUERY_TEXT_s startswith 'GRANT ROLE'\n| extend granted_role = extract(@'GRANT ROLE\\s(\\S+)\\sto\\suser', 1, QUERY_TEXT_s)\n| where granted_role in~ (adm_roles)\n| extend usr = extract(@'GRANT ROLE\\s(\\S+)\\sto\\suser(\\S+)', 2, QUERY_TEXT_s)\n| extend AccountCustomEntity = usr\n", + "queryFrequency": "PT1H", + "queryPeriod": "PT1H", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ + { + "connectorId": "Snowflake", + "dataTypes": [ + "Snowflake" + ] + } + ], + "tactics": [ + "PrivilegeEscalation" + ], + "techniques": [ + "T1078" + ], + "entityMappings": [ + { + "entityType": "Account", + "fieldMappings": [ + { + "columnName": "AccountCustomEntity", + "identifier": "Name" + } + ] + } + ] } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId10'),'/'))))]", "properties": { - "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", - "contentId": "[variables('_dataConnectorContentId1')]", - "kind": "DataConnector", - "version": "[variables('dataConnectorVersion1')]", + "description": "Snowflake Analytics Rule 10", + "parentId": "[variables('analyticRuleId10')]", + "contentId": "[variables('_analyticRulecontentId10')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion10')]", "source": { "kind": "Solution", "name": "Snowflake", @@ -1439,199 +1831,30 @@ } } ] - } - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", - "dependsOn": [ - "[variables('_dataConnectorId1')]" - ], - "location": "[parameters('workspace-location')]", - "properties": { - "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", - "contentId": "[variables('_dataConnectorContentId1')]", - "kind": "DataConnector", - "version": "[variables('dataConnectorVersion1')]", - "source": { - "kind": "Solution", - "name": "Snowflake", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" }, - "support": { - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "tier": "Microsoft", - "link": "https://support.microsoft.com" - } - } - }, - { - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId1'))]", - "apiVersion": "2021-03-01-preview", - "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", - "location": "[parameters('workspace-location')]", - "kind": "GenericUI", - "properties": { - "connectorUiConfig": { - "title": "Snowflake (using Azure Function)", - "publisher": "Snowflake", - "descriptionMarkdown": "The Snowflake data connector provides the capability to ingest Snowflake [login logs](https://docs.snowflake.com/en/sql-reference/account-usage/login_history.html) and [query logs](https://docs.snowflake.com/en/sql-reference/account-usage/query_history.html) into Microsoft Sentinel using the Snowflake Python Connector. Refer to [Snowflake documentation](https://docs.snowflake.com/en/user-guide/python-connector.html) for more information.", - "graphQueries": [ - { - "metricName": "Snowflake Events", - "legend": "Snowflake_CL", - "baseQuery": "Snowflake_CL" - } - ], - "dataTypes": [ - { - "name": "Snowflake_CL", - "lastDataReceivedQuery": "Snowflake_CL\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" - } - ], - "connectivityCriterias": [ - { - "type": "IsConnectedQuery", - "value": [ - "Snowflake_CL\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(1d)" - ] - } - ], - "sampleQueries": [ - { - "description": "All Snowflake Events", - "query": "Snowflake_CL\n| sort by TimeGenerated desc" - } - ], - "availability": { - "status": 1, - "isPreview": false - }, - "permissions": { - "resourceProvider": [ - { - "provider": "Microsoft.OperationalInsights/workspaces", - "permissionsDisplayText": "read and write permissions on the workspace are required.", - "providerDisplayName": "Workspace", - "scope": "Workspace", - "requiredPermissions": { - "write": true, - "read": true, - "delete": true - } - }, - { - "provider": "Microsoft.OperationalInsights/workspaces/sharedKeys", - "permissionsDisplayText": "read permissions to shared keys for the workspace are required. [See the documentation to learn more about workspace keys](https://docs.microsoft.com/azure/azure-monitor/platform/agent-windows#obtain-workspace-id-and-key).", - "providerDisplayName": "Keys", - "scope": "Workspace", - "requiredPermissions": { - "action": true - } - } - ], - "customs": [ - { - "name": "Microsoft.Web/sites permissions", - "description": "Read and write permissions to Azure Functions to create a Function App is required. [See the documentation to learn more about Azure Functions](https://docs.microsoft.com/azure/azure-functions/)." - }, - { - "name": "Snowflake Credentials", - "description": "**Snowflake Account Identifier**, **Snowflake User** and **Snowflake Password** are required for connection. See the documentation to learn more about [Snowflake Account Identifier](https://docs.snowflake.com/en/user-guide/admin-account-identifier.html#). Instructions on how to create user for this connector you can find below." - } - ] - }, - "instructionSteps": [ - { - "description": ">**NOTE:** This connector uses Azure Functions to connect to the Azure Blob Storage API to pull logs into Microsoft Sentinel. This might result in additional costs for data ingestion and for storing data in Azure Blob Storage costs. Check the [Azure Functions pricing page](https://azure.microsoft.com/pricing/details/functions/) and [Azure Blob Storage pricing page](https://azure.microsoft.com/pricing/details/storage/blobs/) for details." - }, - { - "description": ">**(Optional Step)** Securely store workspace and API authorization key(s) or token(s) in Azure Key Vault. Azure Key Vault provides a secure mechanism to store and retrieve key values. [Follow these instructions](https://docs.microsoft.com/azure/app-service/app-service-key-vault-references) to use Azure Key Vault with an Azure Function App." - }, - { - "description": ">**NOTE:** This data connector depends on a parser based on a Kusto Function to work as expected [**Snowflake**](https://aka.ms/sentinel-SnowflakeDataConnector-parser) which is deployed with the Microsoft Sentinel Solution." - }, - { - "description": "**STEP 1 - Creating user in Snowflake**\n\nTo query data from Snowflake you need a user that is assigned to a role with sufficient privileges and a virtual warehouse cluster. The initial size of this cluster will be set to small but if it is insufficient, the cluster size can be increased as necessary.\n\n1. Enter the Snowflake console.\n2. Switch role to SECURITYADMIN and [create a new role](https://docs.snowflake.com/en/sql-reference/sql/create-role.html):\n```\nUSE ROLE SECURITYADMIN;\nCREATE OR REPLACE ROLE EXAMPLE_ROLE_NAME;```\n3. Switch role to SYSADMIN and [create warehouse](https://docs.snowflake.com/en/sql-reference/sql/create-warehouse.html) and [grand access](https://docs.snowflake.com/en/sql-reference/sql/grant-privilege.html) to it:\n```\nUSE ROLE SYSADMIN;\nCREATE OR REPLACE WAREHOUSE EXAMPLE_WAREHOUSE_NAME\n WAREHOUSE_SIZE = 'SMALL' \n AUTO_SUSPEND = 5\n AUTO_RESUME = true\n INITIALLY_SUSPENDED = true;\nGRANT USAGE, OPERATE ON WAREHOUSE EXAMPLE_WAREHOUSE_NAME TO ROLE EXAMPLE_ROLE_NAME;```\n4. Switch role to SECURITYADMIN and [create a new user](https://docs.snowflake.com/en/sql-reference/sql/create-user.html):\n```\nUSE ROLE SECURITYADMIN;\nCREATE OR REPLACE USER EXAMPLE_USER_NAME\n PASSWORD = 'example_password'\n DEFAULT_ROLE = EXAMPLE_ROLE_NAME\n DEFAULT_WAREHOUSE = EXAMPLE_WAREHOUSE_NAME\n;```\n5. Switch role to ACCOUNTADMIN and [grant access to snowflake database](https://docs.snowflake.com/en/sql-reference/account-usage.html#enabling-account-usage-for-other-roles) for role.\n```\nUSE ROLE ACCOUNTADMIN;\nGRANT IMPORTED PRIVILEGES ON DATABASE SNOWFLAKE TO ROLE EXAMPLE_ROLE_NAME;```\n6. Switch role to SECURITYADMIN and [assign role](https://docs.snowflake.com/en/sql-reference/sql/grant-role.html) to user:\n```\nUSE ROLE SECURITYADMIN;\nGRANT ROLE EXAMPLE_ROLE_NAME TO USER EXAMPLE_USER_NAME;```\n\n>**IMPORTANT:** Save user and API password created during this step as they will be used during deployment step." - }, - { - "description": "**STEP 2 - Choose ONE from the following two deployment options to deploy the connector and the associated Azure Function**\n\n>**IMPORTANT:** Before deploying the data connector, have the Workspace ID and Workspace Primary Key (can be copied from the following), as well as Snowflake credentials, readily available.", - "instructions": [ - { - "parameters": { - "fillWith": [ - "WorkspaceId" - ], - "label": "Workspace ID" - }, - "type": "CopyableLabel" - }, - { - "parameters": { - "fillWith": [ - "PrimaryKey" - ], - "label": "Primary Key" - }, - "type": "CopyableLabel" - } - ] - }, - { - "description": "Use this method for automated deployment of the data connector using an ARM Template.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://aka.ms/sentinel-SnowflakeDataConnector-azuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Snowflake Account Identifier**, **Snowflake User**, **Snowflake Password**, **Microsoft Sentinel Workspace Id**, **Microsoft Sentinel Shared Key**\n4. Mark the checkbox labeled **I agree to the terms and conditions stated above**.\n5. Click **Purchase** to deploy.", - "title": "Option 1 - Azure Resource Manager (ARM) Template" - }, - { - "description": "Use the following step-by-step instructions to deploy the data connector manually with Azure Functions (Deployment via Visual Studio Code).", - "title": "Option 2 - Manual Deployment of Azure Functions" - }, - { - "description": "**1. Deploy a Function App**\n\n> **NOTE:** You will need to [prepare VS code](https://docs.microsoft.com/azure/azure-functions/create-first-function-vs-code-python) for Azure function development.\n\n1. Download the [Azure Function App](https://aka.ms/sentinel-SnowflakeDataConnector-functionapp) file. Extract archive to your local development computer.\n2. Start VS Code. Choose File in the main menu and select Open Folder.\n3. Select the top level folder from extracted files.\n4. Choose the Azure icon in the Activity bar, then in the **Azure: Functions** area, choose the **Deploy to function app** button.\nIf you aren't already signed in, choose the Azure icon in the Activity bar, then in the **Azure: Functions** area, choose **Sign in to Azure**\nIf you're already signed in, go to the next step.\n5. Provide the following information at the prompts:\n\n\ta. **Select folder:** Choose a folder from your workspace or browse to one that contains your function app.\n\n\tb. **Select Subscription:** Choose the subscription to use.\n\n\tc. Select **Create new Function App in Azure** (Don't choose the Advanced option)\n\n\td. **Enter a globally unique name for the function app:** Type a name that is valid in a URL path. The name you type is validated to make sure that it's unique in Azure Functions. (e.g. Snowflake12).\n\n\te. **Select a runtime:** Choose Python 3.8.\n\n\tf. Select a location for new resources. For better performance and lower costs choose the same [region](https://azure.microsoft.com/regions/) where Microsoft Sentinel is located.\n\n6. Deployment will begin. A notification is displayed after your function app is created and the deployment package is applied.\n7. Go to Azure Portal for the Function App configuration." - }, - { - "description": "**2. Configure the Function App**\n\n1. In the Function App, select the Function App Name and select **Configuration**.\n2. In the **Application settings** tab, select **+ New application setting**.\n3. Add each of the following application settings individually, with their respective string values (case-sensitive): \n\t\tSNOWFLAKE_ACCOUNT\n\t\tSNOWFLAKE_USER\n\t\tSNOWFLAKE_PASSWORD\n\t\tWORKSPACE_ID\n\t\tSHARED_KEY\n\t\tlogAnalyticsUri (optional)\n - Use logAnalyticsUri to override the log analytics API endpoint for dedicated cloud. For example, for public cloud, leave the value empty; for Azure GovUS cloud environment, specify the value in the following format: `https://WORKSPACE_ID.ods.opinsights.azure.us`. \n4. Once all application settings have been entered, click **Save**." - } - ], - "id": "[variables('_uiConfigId1')]", - "additionalRequirementBanner": "This data connector depends on a parser based on a Kusto Function to work as expected [**Snowflake**](https://aka.ms/sentinel-SnowflakeDataConnector-parser) which is deployed with the Microsoft Sentinel Solution." - } + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_analyticRulecontentId10')]", + "contentKind": "AnalyticsRule", + "displayName": "Snowflake - User granted admin privileges", + "contentProductId": "[variables('_analyticRulecontentProductId10')]", + "id": "[variables('_analyticRulecontentProductId10')]", + "version": "[variables('analyticRuleVersion10')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('huntingQueryTemplateSpecName1')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Snowflake Hunting Query 1 with template", - "displayName": "Snowflake Hunting Query template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('huntingQueryTemplateSpecName1'),'/',variables('huntingQueryVersion1'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName1'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeAdminSources_HuntingQueries Hunting Query with template version 2.0.0", + "description": "SnowflakeAdminSources_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('huntingQueryVersion1')]", @@ -1640,7 +1863,7 @@ "resources": [ { "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", + "apiVersion": "2022-10-01", "name": "Snowflake_Hunting_Query_1", "location": "[parameters('workspace-location')]", "properties": { @@ -1693,37 +1916,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId1')]", + "contentKind": "HuntingQuery", + "displayName": "Snowflake - Privileged users' source IP addresses", + "contentProductId": "[variables('_huntingQuerycontentProductId1')]", + "id": "[variables('_huntingQuerycontentProductId1')]", + "version": "[variables('huntingQueryVersion1')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('huntingQueryTemplateSpecName2')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Snowflake Hunting Query 2 with template", - "displayName": "Snowflake Hunting Query template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('huntingQueryTemplateSpecName2'),'/',variables('huntingQueryVersion2'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName2'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeDeletedDatabases_HuntingQueries Hunting Query with template version 2.0.0", + "description": "SnowflakeDeletedDatabases_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('huntingQueryVersion2')]", @@ -1732,7 +1948,7 @@ "resources": [ { "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", + "apiVersion": "2022-10-01", "name": "Snowflake_Hunting_Query_2", "location": "[parameters('workspace-location')]", "properties": { @@ -1785,37 +2001,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId2')]", + "contentKind": "HuntingQuery", + "displayName": "Snowflake - Deleted databases", + "contentProductId": "[variables('_huntingQuerycontentProductId2')]", + "id": "[variables('_huntingQuerycontentProductId2')]", + "version": "[variables('huntingQueryVersion2')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('huntingQueryTemplateSpecName3')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Snowflake Hunting Query 3 with template", - "displayName": "Snowflake Hunting Query template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('huntingQueryTemplateSpecName3'),'/',variables('huntingQueryVersion3'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName3'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeDeletedTables_HuntingQueries Hunting Query with template version 2.0.0", + "description": "SnowflakeDeletedTables_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('huntingQueryVersion3')]", @@ -1824,7 +2033,7 @@ "resources": [ { "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", + "apiVersion": "2022-10-01", "name": "Snowflake_Hunting_Query_3", "location": "[parameters('workspace-location')]", "properties": { @@ -1877,37 +2086,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId3')]", + "contentKind": "HuntingQuery", + "displayName": "Snowflake - Deleted tables", + "contentProductId": "[variables('_huntingQuerycontentProductId3')]", + "id": "[variables('_huntingQuerycontentProductId3')]", + "version": "[variables('huntingQueryVersion3')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('huntingQueryTemplateSpecName4')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Snowflake Hunting Query 4 with template", - "displayName": "Snowflake Hunting Query template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('huntingQueryTemplateSpecName4'),'/',variables('huntingQueryVersion4'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName4'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeDormantUser_HuntingQueries Hunting Query with template version 2.0.0", + "description": "SnowflakeDormantUser_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('huntingQueryVersion4')]", @@ -1916,7 +2118,7 @@ "resources": [ { "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", + "apiVersion": "2022-10-01", "name": "Snowflake_Hunting_Query_4", "location": "[parameters('workspace-location')]", "properties": { @@ -1969,37 +2171,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId4')]", + "contentKind": "HuntingQuery", + "displayName": "Snowflake - Rarely used account", + "contentProductId": "[variables('_huntingQuerycontentProductId4')]", + "id": "[variables('_huntingQuerycontentProductId4')]", + "version": "[variables('huntingQueryVersion4')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('huntingQueryTemplateSpecName5')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Snowflake Hunting Query 5 with template", - "displayName": "Snowflake Hunting Query template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('huntingQueryTemplateSpecName5'),'/',variables('huntingQueryVersion5'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName5'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeFailedLogins_HuntingQueries Hunting Query with template version 2.0.0", + "description": "SnowflakeFailedLogins_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('huntingQueryVersion5')]", @@ -2008,7 +2203,7 @@ "resources": [ { "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", + "apiVersion": "2022-10-01", "name": "Snowflake_Hunting_Query_5", "location": "[parameters('workspace-location')]", "properties": { @@ -2061,37 +2256,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId5')]", + "contentKind": "HuntingQuery", + "displayName": "Snowflake - Failed logins", + "contentProductId": "[variables('_huntingQuerycontentProductId5')]", + "id": "[variables('_huntingQuerycontentProductId5')]", + "version": "[variables('huntingQueryVersion5')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('huntingQueryTemplateSpecName6')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Snowflake Hunting Query 6 with template", - "displayName": "Snowflake Hunting Query template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('huntingQueryTemplateSpecName6'),'/',variables('huntingQueryVersion6'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName6'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeHighCreditConsumingQueries_HuntingQueries Hunting Query with template version 2.0.0", + "description": "SnowflakeHighCreditConsumingQueries_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('huntingQueryVersion6')]", @@ -2100,14 +2288,14 @@ "resources": [ { "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", + "apiVersion": "2022-10-01", "name": "Snowflake_Hunting_Query_6", "location": "[parameters('workspace-location')]", "properties": { "eTag": "*", "displayName": "Snowflake - Credit consuming queries", "category": "Hunting Queries", - "query": "| let acceptable_credits = 0.00001;\nSnowflake\n| where TimeGenerated > ago(24h)\n| where CREDITS_USED_CLOUD_SERVICES_d > acceptable_credits\n| summarize by QUERY_TEXT_s, CREDITS_USED_CLOUD_SERVICES_d, TargetUsername\n| order by CREDITS_USED_CLOUD_SERVICES_d\n| extend AccountCustomEntity = TargetUsername\n", + "query": "let acceptable_credits = 0.00001;\nSnowflake\n| where TimeGenerated > ago(24h)\n| where CREDITS_USED_CLOUD_SERVICES_d > acceptable_credits\n| summarize by QUERY_TEXT_s, CREDITS_USED_CLOUD_SERVICES_d, TargetUsername\n| order by CREDITS_USED_CLOUD_SERVICES_d\n| extend AccountCustomEntity = TargetUsername\n", "version": 2, "tags": [ { @@ -2153,37 +2341,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId6')]", + "contentKind": "HuntingQuery", + "displayName": "Snowflake - Credit consuming queries", + "contentProductId": "[variables('_huntingQuerycontentProductId6')]", + "id": "[variables('_huntingQuerycontentProductId6')]", + "version": "[variables('huntingQueryVersion6')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('huntingQueryTemplateSpecName7')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Snowflake Hunting Query 7 with template", - "displayName": "Snowflake Hunting Query template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('huntingQueryTemplateSpecName7'),'/',variables('huntingQueryVersion7'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName7'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeTimeConsumingQueries_HuntingQueries Hunting Query with template version 2.0.0", + "description": "SnowflakeTimeConsumingQueries_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('huntingQueryVersion7')]", @@ -2192,14 +2373,14 @@ "resources": [ { "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", + "apiVersion": "2022-10-01", "name": "Snowflake_Hunting_Query_7", "location": "[parameters('workspace-location')]", "properties": { "eTag": "*", "displayName": "Snowflake - Time consuming queries", "category": "Hunting Queries", - "query": "| let acceptable_duration = 1000;\nSnowflake\n| where TimeGenerated > ago(24h)\n| where TOTAL_ELAPSED_TIME_d > acceptable_duration\n| summarize by QUERY_TEXT_s, TOTAL_ELAPSED_TIME_d, TargetUsername\n| order by TOTAL_ELAPSED_TIME_d\n| extend AccountCustomEntity = TargetUsername\n", + "query": "let acceptable_duration = 1000;\nSnowflake\n| where TimeGenerated > ago(24h)\n| where TOTAL_ELAPSED_TIME_d > acceptable_duration\n| summarize by QUERY_TEXT_s, TOTAL_ELAPSED_TIME_d, TargetUsername\n| order by TOTAL_ELAPSED_TIME_d\n| extend AccountCustomEntity = TargetUsername\n", "version": 2, "tags": [ { @@ -2245,37 +2426,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId7')]", + "contentKind": "HuntingQuery", + "displayName": "Snowflake - Time consuming queries", + "contentProductId": "[variables('_huntingQuerycontentProductId7')]", + "id": "[variables('_huntingQuerycontentProductId7')]", + "version": "[variables('huntingQueryVersion7')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('huntingQueryTemplateSpecName8')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Snowflake Hunting Query 8 with template", - "displayName": "Snowflake Hunting Query template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('huntingQueryTemplateSpecName8'),'/',variables('huntingQueryVersion8'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName8'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeUnknownQueryType_HuntingQueries Hunting Query with template version 2.0.0", + "description": "SnowflakeUnknownQueryType_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('huntingQueryVersion8')]", @@ -2284,7 +2458,7 @@ "resources": [ { "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", + "apiVersion": "2022-10-01", "name": "Snowflake_Hunting_Query_8", "location": "[parameters('workspace-location')]", "properties": { @@ -2337,37 +2511,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId8')]", + "contentKind": "HuntingQuery", + "displayName": "Snowflake - Unknown query type", + "contentProductId": "[variables('_huntingQuerycontentProductId8')]", + "id": "[variables('_huntingQuerycontentProductId8')]", + "version": "[variables('huntingQueryVersion8')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('huntingQueryTemplateSpecName9')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Snowflake Hunting Query 9 with template", - "displayName": "Snowflake Hunting Query template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('huntingQueryTemplateSpecName9'),'/',variables('huntingQueryVersion9'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName9'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeUnusedAdmins_HuntingQueries Hunting Query with template version 2.0.0", + "description": "SnowflakeUnusedAdmins_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('huntingQueryVersion9')]", @@ -2376,7 +2543,7 @@ "resources": [ { "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", + "apiVersion": "2022-10-01", "name": "Snowflake_Hunting_Query_9", "location": "[parameters('workspace-location')]", "properties": { @@ -2429,37 +2596,30 @@ } } ] - } + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId9')]", + "contentKind": "HuntingQuery", + "displayName": "Snowflake - Rarely used privileged users", + "contentProductId": "[variables('_huntingQuerycontentProductId9')]", + "id": "[variables('_huntingQuerycontentProductId9')]", + "version": "[variables('huntingQueryVersion9')]" } }, { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", "name": "[variables('huntingQueryTemplateSpecName10')]", "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, - "properties": { - "description": "Snowflake Hunting Query 10 with template", - "displayName": "Snowflake Hunting Query template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('huntingQueryTemplateSpecName10'),'/',variables('huntingQueryVersion10'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "HuntingQuery" - }, "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('huntingQueryTemplateSpecName10'))]" + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeUserSources_HuntingQueries Hunting Query with template version 2.0.0", + "description": "SnowflakeUserSources_HuntingQueries Hunting Query with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('huntingQueryVersion10')]", @@ -2468,7 +2628,7 @@ "resources": [ { "type": "Microsoft.OperationalInsights/savedSearches", - "apiVersion": "2020-08-01", + "apiVersion": "2022-10-01", "name": "Snowflake_Hunting_Query_10", "location": "[parameters('workspace-location')]", "properties": { @@ -2521,243 +2681,35 @@ } } ] - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", - "name": "[variables('parserTemplateSpecName1')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "Parser" - }, - "properties": { - "description": "Snowflake Data Parser with template", - "displayName": "Snowflake Data Parser template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('parserTemplateSpecName1'),'/',variables('parserVersion1'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "Parser" - }, - "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('parserTemplateSpecName1'))]" - ], - "properties": { - "description": "Snowflake Data Parser with template version 2.0.0", - "mainTemplate": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('parserVersion1')]", - "parameters": {}, - "variables": {}, - "resources": [ - { - "name": "[variables('_parserName1')]", - "apiVersion": "2020-08-01", - "type": "Microsoft.OperationalInsights/workspaces/savedSearches", - "location": "[parameters('workspace-location')]", - "properties": { - "eTag": "*", - "displayName": "Snowflake Data Parser", - "category": "Samples", - "functionAlias": "Snowflake", - "query": "\nSnowflake_CL\r\n| extend EventVendor = 'Snowflake'\r\n| extend EventProduct = 'Snowflake'\r\n| project-rename \r\n EventStartTime=START_TIME_t,\r\n EventType=EVENT_TYPE_s,\r\n TargetUsername=USER_NAME_s,\r\n SrcDvcIpAddr=CLIENT_IP_s\r\n| extend \r\n User=TargetUsername,\r\n EventEndTime=iff(isnotempty(EVENT_TIMESTAMP_t), EVENT_TIMESTAMP_t, END_TIME_t)", - "version": 1, - "tags": [ - { - "name": "description", - "value": "Snowflake Data Parser" - } - ] - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Parser-', last(split(variables('_parserId1'),'/'))))]", - "dependsOn": [ - "[variables('_parserName1')]" - ], - "properties": { - "parentId": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), variables('parserName1'))]", - "contentId": "[variables('_parserContentId1')]", - "kind": "Parser", - "version": "[variables('parserVersion1')]", - "source": { - "name": "Snowflake", - "kind": "Solution", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" - }, - "support": { - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "tier": "Microsoft", - "link": "https://support.microsoft.com" - } - } - } - ] - } - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/savedSearches", - "apiVersion": "2021-06-01", - "name": "[variables('_parserName1')]", - "location": "[parameters('workspace-location')]", - "properties": { - "eTag": "*", - "displayName": "Snowflake Data Parser", - "category": "Samples", - "functionAlias": "Snowflake", - "query": "\nSnowflake_CL\r\n| extend EventVendor = 'Snowflake'\r\n| extend EventProduct = 'Snowflake'\r\n| project-rename \r\n EventStartTime=START_TIME_t,\r\n EventType=EVENT_TYPE_s,\r\n TargetUsername=USER_NAME_s,\r\n SrcDvcIpAddr=CLIENT_IP_s\r\n| extend \r\n User=TargetUsername,\r\n EventEndTime=iff(isnotempty(EVENT_TIMESTAMP_t), EVENT_TIMESTAMP_t, END_TIME_t)", - "version": 1 - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", - "location": "[parameters('workspace-location')]", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Parser-', last(split(variables('_parserId1'),'/'))))]", - "dependsOn": [ - "[variables('_parserId1')]" - ], - "properties": { - "parentId": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), variables('parserName1'))]", - "contentId": "[variables('_parserContentId1')]", - "kind": "Parser", - "version": "[variables('parserVersion1')]", - "source": { - "kind": "Solution", - "name": "Snowflake", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" }, - "support": { - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "tier": "Microsoft", - "link": "https://support.microsoft.com" - } - } - }, - { - "type": "Microsoft.Resources/templateSpecs", - "apiVersion": "2021-05-01", - "name": "[variables('workbookTemplateSpecName1')]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "Workbook" - }, - "properties": { - "description": "Snowflake Workbook with template", - "displayName": "Snowflake workbook template" - } - }, - { - "type": "Microsoft.Resources/templateSpecs/versions", - "apiVersion": "2021-05-01", - "name": "[concat(variables('workbookTemplateSpecName1'),'/',variables('workbookVersion1'))]", - "location": "[parameters('workspace-location')]", - "tags": { - "hidden-sentinelWorkspaceId": "[variables('workspaceResourceId')]", - "hidden-sentinelContentType": "Workbook" - }, - "dependsOn": [ - "[resourceId('Microsoft.Resources/templateSpecs', variables('workbookTemplateSpecName1'))]" - ], - "properties": { - "description": "SnowflakeWorkbook Workbook with template version 2.0.0", - "mainTemplate": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('workbookVersion1')]", - "parameters": {}, - "variables": {}, - "resources": [ - { - "type": "Microsoft.Insights/workbooks", - "name": "[variables('workbookContentId1')]", - "location": "[parameters('workspace-location')]", - "kind": "shared", - "apiVersion": "2021-08-01", - "metadata": { - "description": "Sets the time name for analysis" - }, - "properties": { - "displayName": "[parameters('workbook1-name')]", - "serializedData": "{\"version\":\"Notebook/1.0\",\"items\":[{\"type\":1,\"content\":{\"json\":\"**NOTE**: This data connector depends on a parser based on Kusto Function **Snowflake** to work as expected. [Follow steps to get this Kusto Function](https://aka.ms/sentinel-SnowflakeDataConnector-parser)\"},\"name\":\"text - 8\"},{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"parameters\":[{\"id\":\"cd8447d9-b096-4673-92d8-2a1e8291a125\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"TimeRange\",\"type\":4,\"description\":\"Sets the time name for analysis\",\"value\":{\"durationMs\":7776000000},\"typeSettings\":{\"selectableValues\":[{\"durationMs\":1800000},{\"durationMs\":3600000},{\"durationMs\":86400000},{\"durationMs\":604800000},{\"durationMs\":2592000000},{\"durationMs\":7776000000}]},\"timeContext\":{\"durationMs\":86400000}}],\"style\":\"pills\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"parameters - 11\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\r\\n| make-series TotalEvents = count() default = 0 on TimeGenerated from {TimeRange:start} to {TimeRange:end} step {TimeRange:grain};\",\"size\":0,\"title\":\"Events Over Time\",\"color\":\"green\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"timechart\",\"graphSettings\":{\"type\":0}},\"customWidth\":\"60\",\"name\":\"query - 12\",\"styleSettings\":{\"maxWidth\":\"55\"}},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(DATABASE_NAME_s)\\n| summarize dcount(DATABASE_NAME_s)\",\"size\":3,\"title\":\"Total Databases\",\"timeContext\":{\"durationMs\":7776000000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"50\",\"name\":\"query - 1\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(source_table_s)\\n| summarize dcount(source_table_s)\",\"size\":3,\"title\":\"Total Tables\",\"timeContext\":{\"durationMs\":7776000000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"50\",\"name\":\"query - 2\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| summarize s=sum(EXECUTION_TIME_d)\\n| project s_time = strcat(s/1000, ' sec')\",\"size\":3,\"title\":\"Total Query Time\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"30\",\"name\":\"query - 0\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(QUERY_TYPE_s)\\n| summarize count()\",\"size\":3,\"title\":\"Total Queries Run\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"30\",\"name\":\"query - 3\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| summarize cs = sum(CREDITS_USED_CLOUD_SERVICES_d)\\n| project round(cs, 8)\",\"size\":3,\"title\":\"Credits Spent\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"40\",\"name\":\"query - 4\"}]},\"customWidth\":\"40\",\"name\":\"group - 0\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(source_table_s)\\n| summarize count() by source_table_s\",\"size\":3,\"title\":\"Table Events Summary\",\"color\":\"orange\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"tiles\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"source_table_s\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"count_\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"maximumSignificantDigits\":3,\"maximumFractionDigits\":2}}},\"showBorder\":false}},\"customWidth\":\"50\",\"name\":\"query - 0\",\"styleSettings\":{\"showBorder\":true}},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(DATABASE_NAME_s)\\n| summarize count() by DATABASE_NAME_s\",\"size\":3,\"title\":\"Database Events Summary\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"tiles\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"DATABASE_NAME_s\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"count_\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"style\":\"decimal\",\"maximumFractionDigits\":2,\"maximumSignificantDigits\":3}}},\"showBorder\":false}},\"customWidth\":\"50\",\"name\":\"query - 1\",\"styleSettings\":{\"showBorder\":true}}]},\"customWidth\":\"30\",\"name\":\"group - 11\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(SrcDvcIpAddr)\\n| summarize count() by SrcDvcIpAddr\",\"size\":3,\"title\":\"Source Addresses\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"piechart\"},\"customWidth\":\"30\",\"name\":\"query - 9\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where EXECUTION_TIME_d > 0\\n| top 10 by EXECUTION_TIME_d desc\\n| project Query=QUERY_TEXT_s, User=TargetUsername, ExecutionTime=EXECUTION_TIME_d\\n\",\"size\":0,\"title\":\"Query Execution Time\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"ExecutionTime\",\"formatter\":8,\"formatOptions\":{\"palette\":\"coldHot\"}}]}},\"customWidth\":\"35\",\"name\":\"query - 11\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where CREDITS_USED_CLOUD_SERVICES_d > 0\\n| summarize by QUERY_TEXT_s, CREDITS_USED_CLOUD_SERVICES_d\\n| top 10 by CREDITS_USED_CLOUD_SERVICES_d desc\\n| project Query=QUERY_TEXT_s, CreditsSpent=CREDITS_USED_CLOUD_SERVICES_d\",\"size\":0,\"title\":\"Credits Spent by Queriws\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"CreditsSpent\",\"formatter\":8,\"formatOptions\":{\"palette\":\"coldHot\",\"compositeBarSettings\":{\"labelText\":\"\"}},\"numberFormat\":{\"unit\":0,\"options\":{\"style\":\"decimal\",\"maximumFractionDigits\":10}}}]}},\"customWidth\":\"35\",\"name\":\"query - 9\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\r\\n| where QUERY_TYPE_s == 'CREATE_USER'\\r\\n| extend n_usr = extract(@'USER\\\\s(\\\\S+)', 1, QUERY_TEXT_s)\\r\\n| project Username=n_usr\",\"size\":0,\"title\":\"New Users\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"URL Category\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"count_\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"style\":\"decimal\",\"maximumFractionDigits\":2,\"maximumSignificantDigits\":3}}},\"secondaryContent\":{\"columnMatch\":\"Trend\",\"formatter\":9,\"formatOptions\":{\"palette\":\"purple\"}},\"showBorder\":false},\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"20\",\"name\":\"query - 0\",\"styleSettings\":{\"maxWidth\":\"30\"}},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n\\n| where QUERY_TYPE_s =~ 'SELECT'\\n| summarize roles = makeset(ROLE_NAME_s) by TargetUsername\\n| join(Snowflake\\n | where EventType =~ 'LOGIN') on TargetUsername\\n| project EventTime=TimeGenerated, TargetUsername, SourceAddress=SrcDvcIpAddr, Status=strcat(iif(IS_SUCCESS_s =~ 'No', '❌ - Login Failure' , '✅ - Logged in'))\",\"size\":0,\"title\":\"Privileged Sessions\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"User\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"TotalMailsReceived\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"maximumSignificantDigits\":3,\"maximumFractionDigits\":2}}},\"secondaryContent\":{\"columnMatch\":\"Trend\",\"formatter\":10,\"formatOptions\":{\"palette\":\"magenta\"}},\"showBorder\":false}},\"customWidth\":\"45\",\"name\":\"query - 10\"}],\"fromTemplateId\":\"sentinel-SnowflakeWorkbook\",\"$schema\":\"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"}\r\n", - "version": "1.0", - "sourceId": "[variables('workspaceResourceId')]", - "category": "sentinel" - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Workbook-', last(split(variables('workbookId1'),'/'))))]", - "properties": { - "description": "@{workbookKey=SnowflakeWorkbook; logoFileName=Azure_Sentinel.svg; description=Sets the time name for analysis; dataTypesDependencies=System.Object[]; dataConnectorsDependencies=System.Object[]; previewImagesFileNames=System.Object[]; version=1.0.0; title=Snowflake; templateRelativePath=Snowflake.json; subtitle=; provider=Snowflake}.description", - "parentId": "[variables('workbookId1')]", - "contentId": "[variables('_workbookContentId1')]", - "kind": "Workbook", - "version": "[variables('workbookVersion1')]", - "source": { - "kind": "Solution", - "name": "Snowflake", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" - }, - "support": { - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "tier": "Microsoft", - "link": "https://support.microsoft.com" - }, - "dependencies": { - "operator": "AND", - "criteria": [ - { - "contentId": "Snowflake_CL", - "kind": "DataType" - }, - { - "contentId": "SnowflakeDataConnector", - "kind": "DataConnector" - } - ] - } - } - } - ] - } + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_huntingQuerycontentId10')]", + "contentKind": "HuntingQuery", + "displayName": "Snowflake - Users' source IP addresses", + "contentProductId": "[variables('_huntingQuerycontentProductId10')]", + "id": "[variables('_huntingQuerycontentProductId10')]", + "version": "[variables('huntingQueryVersion10')]" } }, { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/contentPackages", + "apiVersion": "2023-04-01-preview", "location": "[parameters('workspace-location')]", "properties": { - "version": "2.0.0", + "version": "3.0.0", "kind": "Solution", - "contentSchemaVersion": "2.0.0", + "contentSchemaVersion": "3.0.0", + "displayName": "Snowflake", + "publisherDisplayName": "Microsoft Sentinel, Microsoft Corporation", + "descriptionHtml": "

Note: There may be known issues pertaining to this Solution, please refer to them before installing.

\n

The Snowflake solution provides the capability to ingest Snowflake login logs and query logs into Microsoft Sentinel using the Snowflake Python Connector. Refer to Snowflake documentation for more information.

\n

Underlying Microsoft Technologies used:

\n

This solution takes a dependency on the following technologies, and some of these dependencies either may be in Preview state or might result in additional ingestion or operational costs:

\n
    \n
  1. Azure Monitor HTTP Data Collector API

    \n
  2. \n
  3. Azure Functions

    \n
  4. \n
\n

Data Connectors: 1, Parsers: 1, Workbooks: 1, Analytic Rules: 10, Hunting Queries: 10

\n

Learn more about Microsoft Sentinel | Learn more about Solutions

\n", + "contentKind": "Solution", + "contentProductId": "[variables('_solutioncontentProductId')]", + "id": "[variables('_solutioncontentProductId')]", + "icon": "", "contentId": "[variables('_solutionId')]", "parentId": "[variables('_solutionId')]", "source": { @@ -2778,6 +2730,21 @@ "dependencies": { "operator": "AND", "criteria": [ + { + "kind": "DataConnector", + "contentId": "[variables('_dataConnectorContentId1')]", + "version": "[variables('dataConnectorVersion1')]" + }, + { + "kind": "Parser", + "contentId": "[variables('_parserContentId1')]", + "version": "[variables('parserVersion1')]" + }, + { + "kind": "Workbook", + "contentId": "[variables('_workbookContentId1')]", + "version": "[variables('workbookVersion1')]" + }, { "kind": "AnalyticsRule", "contentId": "[variables('analyticRulecontentId1')]", @@ -2828,11 +2795,6 @@ "contentId": "[variables('analyticRulecontentId10')]", "version": "[variables('analyticRuleVersion10')]" }, - { - "kind": "DataConnector", - "contentId": "[variables('_dataConnectorContentId1')]", - "version": "[variables('dataConnectorVersion1')]" - }, { "kind": "HuntingQuery", "contentId": "[variables('_huntingQuerycontentId1')]", @@ -2882,16 +2844,6 @@ "kind": "HuntingQuery", "contentId": "[variables('_huntingQuerycontentId10')]", "version": "[variables('huntingQueryVersion10')]" - }, - { - "kind": "Parser", - "contentId": "[variables('_parserContentId1')]", - "version": "[variables('parserVersion1')]" - }, - { - "kind": "Workbook", - "contentId": "[variables('_workbookContentId1')]", - "version": "[variables('workbookVersion1')]" } ] }, From 2c11dfbf4c025abaa6bb45c4e367683364ab5f2e Mon Sep 17 00:00:00 2001 From: v-rusraut Date: Thu, 31 Aug 2023 15:46:16 +0530 Subject: [PATCH 3/3] Update Package --- .../Snowflake_API_FunctionApp.json | 2 +- .../Snowflake/Data/Solution_Snowflake.json | 2 +- Solutions/Snowflake/Package/3.0.0.zip | Bin 48411 -> 18670 bytes .../Snowflake/Package/createUiDefinition.json | 8 +- Solutions/Snowflake/Package/mainTemplate.json | 1848 ++++++++--------- Solutions/Snowflake/Parsers/Snowflake.txt | 15 - Solutions/Snowflake/ReleaseNotes.md | 5 + 7 files changed, 935 insertions(+), 945 deletions(-) delete mode 100644 Solutions/Snowflake/Parsers/Snowflake.txt create mode 100644 Solutions/Snowflake/ReleaseNotes.md diff --git a/Solutions/Snowflake/Data Connectors/Snowflake_API_FunctionApp.json b/Solutions/Snowflake/Data Connectors/Snowflake_API_FunctionApp.json index 4e98c5d4387..9bdc4495f2a 100644 --- a/Solutions/Snowflake/Data Connectors/Snowflake_API_FunctionApp.json +++ b/Solutions/Snowflake/Data Connectors/Snowflake_API_FunctionApp.json @@ -1,6 +1,6 @@ { "id": "SnowflakeDataConnector", - "title": "Snowflake (using Azure Function)", + "title": "Snowflake", "publisher": "Snowflake", "descriptionMarkdown": "The Snowflake data connector provides the capability to ingest Snowflake [login logs](https://docs.snowflake.com/en/sql-reference/account-usage/login_history.html) and [query logs](https://docs.snowflake.com/en/sql-reference/account-usage/query_history.html) into Microsoft Sentinel using the Snowflake Python Connector. Refer to [Snowflake documentation](https://docs.snowflake.com/en/user-guide/python-connector.html) for more information.", "additionalRequirementBanner": "This data connector depends on a parser based on a Kusto Function to work as expected [**Snowflake**](https://aka.ms/sentinel-SnowflakeDataConnector-parser) which is deployed with the Microsoft Sentinel Solution.", diff --git a/Solutions/Snowflake/Data/Solution_Snowflake.json b/Solutions/Snowflake/Data/Solution_Snowflake.json index 589a92156b2..655ea814b93 100644 --- a/Solutions/Snowflake/Data/Solution_Snowflake.json +++ b/Solutions/Snowflake/Data/Solution_Snowflake.json @@ -31,7 +31,7 @@ "Hunting Queries/SnowflakeUserSources.yaml" ], "Parsers" : [ - "Parsers/Snowflake.txt" + "Parsers/Snowflake.yaml" ], "Workbooks" : [ "Workbooks/Snowflake.json" diff --git a/Solutions/Snowflake/Package/3.0.0.zip b/Solutions/Snowflake/Package/3.0.0.zip index f9bfb26e65fa065e77afc4bba7a0ff73e8c80ed9..588bd65a82739a09c409acc4a8ebb7e321a78ed4 100644 GIT binary patch literal 18670 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 A<^TWy literal 48411 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

GVB}k#6>KuWqJ~2t#5Lc@=NK(kLmz+k;q$r*g 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 b2L3Opq4LsT;QyNZ_\n\n**Note:** _There may be [known issues](https://aka.ms/sentinelsolutionsknownissues) pertaining to this Solution, please refer to them before installing._\n\nThe Snowflake solution provides the capability to ingest Snowflake [login logs](https://docs.snowflake.com/en/sql-reference/account-usage/login_history.html) and [query logs](https://docs.snowflake.com/en/sql-reference/account-usage/query_history.html) into Microsoft Sentinel using the Snowflake Python Connector. Refer to [Snowflake documentation](https://docs.snowflake.com/en/user-guide/python-connector.html) for more information.\r\n \r\n **Underlying Microsoft Technologies used:** \r\n\r\n This solution takes a dependency on the following technologies, and some of these dependencies either may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs:\r\n\n a. [Azure Monitor HTTP Data Collector API](https://docs.microsoft.com/azure/azure-monitor/logs/data-collector-api) \r\n\n b. [Azure Functions](https://azure.microsoft.com/services/functions/#overview)\r\n\n\n\n\n\n**Data Connectors:** 1, **Parsers:** 1, **Workbooks:** 1, **Analytic Rules:** 10, **Hunting Queries:** 10\n\n[Learn more about Microsoft Sentinel](https://aka.ms/azuresentinel) | [Learn more about Solutions](https://aka.ms/azuresentinelsolutionsdoc)", + "description": "\n\n**Note:** Please refer to the following before installing the solution: \r \n • Review the solution [Release Notes](https://github.com/Azure/Azure-Sentinel/tree/master/Solutions/Snowflake/ReleaseNotes.md)\r \n • There may be [known issues](https://aka.ms/sentinelsolutionsknownissues) pertaining to this Solution, please refer to them before installing.\n\nThe Snowflake solution provides the capability to ingest Snowflake [login logs](https://docs.snowflake.com/en/sql-reference/account-usage/login_history.html) and [query logs](https://docs.snowflake.com/en/sql-reference/account-usage/query_history.html) into Microsoft Sentinel using the Snowflake Python Connector. Refer to [Snowflake documentation](https://docs.snowflake.com/en/user-guide/python-connector.html) for more information.\r\n \r\n **Underlying Microsoft Technologies used:** \r\n\r\n This solution takes a dependency on the following technologies, and some of these dependencies either may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs:\r\n\n a. [Azure Monitor HTTP Data Collector API](https://docs.microsoft.com/azure/azure-monitor/logs/data-collector-api) \r\n\n b. [Azure Functions](https://azure.microsoft.com/services/functions/#overview)\r\n\n\n\n\n\n**Data Connectors:** 1, **Parsers:** 1, **Workbooks:** 1, **Analytic Rules:** 10, **Hunting Queries:** 10\n\n[Learn more about Microsoft Sentinel](https://aka.ms/azuresentinel) | [Learn more about Solutions](https://aka.ms/azuresentinelsolutionsdoc)", "subscription": { "resourceProviders": [ "Microsoft.OperationsManagement/solutions", @@ -60,14 +60,14 @@ "name": "dataconnectors1-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "This Solution installs the data connector for Snowflake. You can get Snowflake custom log data in your Microsoft Sentinel workspace. After installing the solution, configure and enable this data connector by following guidance in Manage solution view." + "text": "This solution installs the data connector that ingest Snowflake login logs and query logs into Microsoft Sentinel using the Snowflake Python Connector. After installing the solution, configure and enable this data connector by following guidance in Manage solution view." } }, { "name": "dataconnectors-parser-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "The Solution installs a parser that transforms the ingested data into Microsoft Sentinel normalized format. The normalized format enables better correlation of different types of data from different data sources to drive end-to-end outcomes seamlessly in security monitoring, hunting, incident investigation and response scenarios in Microsoft Sentinel." + "text": "The solution installs a parser that transforms ingested data. The transformed logs can be accessed using the Snowflake Kusto Function alias." } }, { @@ -95,7 +95,7 @@ "name": "workbooks-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "This solution installs workbook(s) to help you gain insights into the telemetry collected in Microsoft Sentinel. After installing the solution, start using the workbook in Manage solution view." + "text": "The workbook installed with the Snowflake help’s you gain insights into the telemetry collected in Microsoft Sentinel. After installing the solution, start using the workbook in Manage solution view." } }, { diff --git a/Solutions/Snowflake/Package/mainTemplate.json b/Solutions/Snowflake/Package/mainTemplate.json index bf05ea40297..d7bb2fa1bb2 100644 --- a/Solutions/Snowflake/Package/mainTemplate.json +++ b/Solutions/Snowflake/Package/mainTemplate.json @@ -38,37 +38,12 @@ } }, "variables": { - "solutionId": "azuresentinel.azure-sentinel-solution-snowflake", - "_solutionId": "[variables('solutionId')]", "email": "support@microsoft.com", "_email": "[variables('email')]", "_solutionName": "Snowflake", "_solutionVersion": "3.0.0", - "uiConfigId1": "SnowflakeDataConnector", - "_uiConfigId1": "[variables('uiConfigId1')]", - "dataConnectorContentId1": "SnowflakeDataConnector", - "_dataConnectorContentId1": "[variables('dataConnectorContentId1')]", - "dataConnectorId1": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", - "_dataConnectorId1": "[variables('dataConnectorId1')]", - "dataConnectorTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-dc-',uniquestring(variables('_dataConnectorContentId1'))))]", - "dataConnectorVersion1": "1.0.0", - "_dataConnectorcontentProductId1": "[concat(take(variables('_solutionId'),50),'-','dc','-', uniqueString(concat(variables('_solutionId'),'-','DataConnector','-',variables('_dataConnectorContentId1'),'-', variables('dataConnectorVersion1'))))]", - "parserName1": "Snowflake Data Parser", - "_parserName1": "[concat(parameters('workspace'),'/',variables('parserName1'))]", - "parserId1": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), variables('parserName1'))]", - "_parserId1": "[variables('parserId1')]", - "parserTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-pr-',uniquestring(variables('_parserContentId1'))))]", - "parserVersion1": "1.0.0", - "parserContentId1": "Snowflake-Parser", - "_parserContentId1": "[variables('parserContentId1')]", - "_parsercontentProductId1": "[concat(take(variables('_solutionId'),50),'-','pr','-', uniqueString(concat(variables('_solutionId'),'-','Parser','-',variables('_parserContentId1'),'-', variables('parserVersion1'))))]", - "workbookVersion1": "1.0.0", - "workbookContentId1": "SnowflakeWorkbook", - "workbookId1": "[resourceId('Microsoft.Insights/workbooks', variables('workbookContentId1'))]", - "workbookTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-wb-',uniquestring(variables('_workbookContentId1'))))]", - "_workbookContentId1": "[variables('workbookContentId1')]", - "workspaceResourceId": "[resourceId('microsoft.OperationalInsights/Workspaces', parameters('workspace'))]", - "_workbookcontentProductId1": "[concat(take(variables('_solutionId'),50),'-','wb','-', uniqueString(concat(variables('_solutionId'),'-','Workbook','-',variables('_workbookContentId1'),'-', variables('workbookVersion1'))))]", + "solutionId": "azuresentinel.azure-sentinel-solution-snowflake", + "_solutionId": "[variables('solutionId')]", "analyticRuleVersion1": "1.0.0", "analyticRulecontentId1": "09b8dfc7-87b0-4215-b34b-bab363d685cb", "_analyticRulecontentId1": "[variables('analyticRulecontentId1')]", @@ -129,6 +104,15 @@ "analyticRuleId10": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId10'))]", "analyticRuleTemplateSpecName10": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId10'))))]", "_analyticRulecontentProductId10": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId10'),'-', variables('analyticRuleVersion10'))))]", + "uiConfigId1": "SnowflakeDataConnector", + "_uiConfigId1": "[variables('uiConfigId1')]", + "dataConnectorContentId1": "SnowflakeDataConnector", + "_dataConnectorContentId1": "[variables('dataConnectorContentId1')]", + "dataConnectorId1": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", + "_dataConnectorId1": "[variables('dataConnectorId1')]", + "dataConnectorTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-dc-',uniquestring(variables('_dataConnectorContentId1'))))]", + "dataConnectorVersion1": "1.0.0", + "_dataConnectorcontentProductId1": "[concat(take(variables('_solutionId'),50),'-','dc','-', uniqueString(concat(variables('_solutionId'),'-','DataConnector','-',variables('_dataConnectorContentId1'),'-', variables('dataConnectorVersion1'))))]", "huntingQueryVersion1": "1.0.0", "huntingQuerycontentId1": "6aae5700-79da-4b41-98cc-f77bf7489f01", "_huntingQuerycontentId1": "[variables('huntingQuerycontentId1')]", @@ -189,188 +173,94 @@ "huntingQueryId10": "[resourceId('Microsoft.OperationalInsights/savedSearches', variables('_huntingQuerycontentId10'))]", "huntingQueryTemplateSpecName10": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId10'))))]", "_huntingQuerycontentProductId10": "[concat(take(variables('_solutionId'),50),'-','hq','-', uniqueString(concat(variables('_solutionId'),'-','HuntingQuery','-',variables('_huntingQuerycontentId10'),'-', variables('huntingQueryVersion10'))))]", + "parserName1": "Snowflake Data Parser", + "_parserName1": "[concat(parameters('workspace'),'/',variables('parserName1'))]", + "parserId1": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), variables('parserName1'))]", + "_parserId1": "[variables('parserId1')]", + "parserTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-pr-',uniquestring(variables('_parserContentId1'))))]", + "parserVersion1": "1.0.0", + "parserContentId1": "Snowflake-Parser", + "_parserContentId1": "[variables('parserContentId1')]", + "_parsercontentProductId1": "[concat(take(variables('_solutionId'),50),'-','pr','-', uniqueString(concat(variables('_solutionId'),'-','Parser','-',variables('_parserContentId1'),'-', variables('parserVersion1'))))]", + "workbookVersion1": "1.0.0", + "workbookContentId1": "SnowflakeWorkbook", + "workbookId1": "[resourceId('Microsoft.Insights/workbooks', variables('workbookContentId1'))]", + "workbookTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-wb-',uniquestring(variables('_workbookContentId1'))))]", + "_workbookContentId1": "[variables('workbookContentId1')]", + "workspaceResourceId": "[resourceId('microsoft.OperationalInsights/Workspaces', parameters('workspace'))]", + "_workbookcontentProductId1": "[concat(take(variables('_solutionId'),50),'-','wb','-', uniqueString(concat(variables('_solutionId'),'-','Workbook','-',variables('_workbookContentId1'),'-', variables('workbookVersion1'))))]", "_solutioncontentProductId": "[concat(take(variables('_solutionId'),50),'-','sl','-', uniqueString(concat(variables('_solutionId'),'-','Solution','-',variables('_solutionId'),'-', variables('_solutionVersion'))))]" }, "resources": [ { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", - "name": "[variables('dataConnectorTemplateSpecName1')]", + "name": "[variables('analyticRuleTemplateSpecName1')]", "location": "[parameters('workspace-location')]", "dependsOn": [ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Snowflake data connector with template version 3.0.0", + "description": "SnowflakeDiscoveryActivity_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('dataConnectorVersion1')]", + "contentVersion": "[variables('analyticRuleVersion1')]", "parameters": {}, "variables": {}, "resources": [ { - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId1'))]", - "apiVersion": "2021-03-01-preview", - "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId1')]", + "apiVersion": "2022-04-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", - "kind": "GenericUI", "properties": { - "connectorUiConfig": { - "id": "[variables('_uiConfigId1')]", - "title": "Snowflake (using Azure Function) (using Azure Functions)", - "publisher": "Snowflake", - "descriptionMarkdown": "The Snowflake data connector provides the capability to ingest Snowflake [login logs](https://docs.snowflake.com/en/sql-reference/account-usage/login_history.html) and [query logs](https://docs.snowflake.com/en/sql-reference/account-usage/query_history.html) into Microsoft Sentinel using the Snowflake Python Connector. Refer to [Snowflake documentation](https://docs.snowflake.com/en/user-guide/python-connector.html) for more information.", - "additionalRequirementBanner": "This data connector depends on a parser based on a Kusto Function to work as expected [**Snowflake**](https://aka.ms/sentinel-SnowflakeDataConnector-parser) which is deployed with the Microsoft Sentinel Solution.", - "graphQueries": [ - { - "metricName": "Snowflake Events", - "legend": "Snowflake_CL", - "baseQuery": "Snowflake_CL" - } - ], - "sampleQueries": [ - { - "description": "All Snowflake Events", - "query": "Snowflake_CL\n| sort by TimeGenerated desc" - } - ], - "dataTypes": [ - { - "name": "Snowflake_CL", - "lastDataReceivedQuery": "Snowflake_CL\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" - } - ], - "connectivityCriterias": [ - { - "type": "IsConnectedQuery", - "value": [ - "Snowflake_CL\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(1d)" - ] - } - ], - "availability": { - "status": 1, - "isPreview": false - }, - "permissions": { - "resourceProvider": [ - { - "provider": "Microsoft.OperationalInsights/workspaces", - "permissionsDisplayText": "read and write permissions on the workspace are required.", - "providerDisplayName": "Workspace", - "scope": "Workspace", - "requiredPermissions": { - "write": true, - "read": true, - "delete": true - } - }, + "description": "Detects possible discovery activity.", + "displayName": "Snowflake - Possible discovery activity", + "enabled": false, + "query": "let threshold = 20;\nSnowflake\n| where QUERY_TYPE_s =~ 'SHOW'\n| where EXECUTION_STATUS_s =~ 'SUCCESS'\n| summarize count() by TargetUsername, bin(TimeGenerated, 5m)\n| where count_ > threshold\n| extend AccountCustomEntity = TargetUsername\n", + "queryFrequency": "PT1H", + "queryPeriod": "PT1H", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ + { + "connectorId": "Snowflake", + "dataTypes": [ + "Snowflake" + ] + } + ], + "tactics": [ + "Discovery" + ], + "entityMappings": [ + { + "fieldMappings": [ { - "provider": "Microsoft.OperationalInsights/workspaces/sharedKeys", - "permissionsDisplayText": "read permissions to shared keys for the workspace are required. [See the documentation to learn more about workspace keys](https://docs.microsoft.com/azure/azure-monitor/platform/agent-windows#obtain-workspace-id-and-key).", - "providerDisplayName": "Keys", - "scope": "Workspace", - "requiredPermissions": { - "action": true - } + "identifier": "Name", + "columnName": "AccountCustomEntity" } ], - "customs": [ - { - "name": "Microsoft.Web/sites permissions", - "description": "Read and write permissions to Azure Functions to create a Function App is required. [See the documentation to learn more about Azure Functions](https://docs.microsoft.com/azure/azure-functions/)." - }, - { - "name": "Snowflake Credentials", - "description": "**Snowflake Account Identifier**, **Snowflake User** and **Snowflake Password** are required for connection. See the documentation to learn more about [Snowflake Account Identifier](https://docs.snowflake.com/en/user-guide/admin-account-identifier.html#). Instructions on how to create user for this connector you can find below." - } - ] - }, - "instructionSteps": [ - { - "description": ">**NOTE:** This connector uses Azure Functions to connect to the Azure Blob Storage API to pull logs into Microsoft Sentinel. This might result in additional costs for data ingestion and for storing data in Azure Blob Storage costs. Check the [Azure Functions pricing page](https://azure.microsoft.com/pricing/details/functions/) and [Azure Blob Storage pricing page](https://azure.microsoft.com/pricing/details/storage/blobs/) for details." - }, - { - "description": ">**(Optional Step)** Securely store workspace and API authorization key(s) or token(s) in Azure Key Vault. Azure Key Vault provides a secure mechanism to store and retrieve key values. [Follow these instructions](https://docs.microsoft.com/azure/app-service/app-service-key-vault-references) to use Azure Key Vault with an Azure Function App." - }, - { - "description": ">**NOTE:** This data connector depends on a parser based on a Kusto Function to work as expected [**Snowflake**](https://aka.ms/sentinel-SnowflakeDataConnector-parser) which is deployed with the Microsoft Sentinel Solution." - }, - { - "description": "**STEP 1 - Creating user in Snowflake**\n\nTo query data from Snowflake you need a user that is assigned to a role with sufficient privileges and a virtual warehouse cluster. The initial size of this cluster will be set to small but if it is insufficient, the cluster size can be increased as necessary.\n\n1. Enter the Snowflake console.\n2. Switch role to SECURITYADMIN and [create a new role](https://docs.snowflake.com/en/sql-reference/sql/create-role.html):\n```\nUSE ROLE SECURITYADMIN;\nCREATE OR REPLACE ROLE EXAMPLE_ROLE_NAME;```\n3. Switch role to SYSADMIN and [create warehouse](https://docs.snowflake.com/en/sql-reference/sql/create-warehouse.html) and [grand access](https://docs.snowflake.com/en/sql-reference/sql/grant-privilege.html) to it:\n```\nUSE ROLE SYSADMIN;\nCREATE OR REPLACE WAREHOUSE EXAMPLE_WAREHOUSE_NAME\n WAREHOUSE_SIZE = 'SMALL' \n AUTO_SUSPEND = 5\n AUTO_RESUME = true\n INITIALLY_SUSPENDED = true;\nGRANT USAGE, OPERATE ON WAREHOUSE EXAMPLE_WAREHOUSE_NAME TO ROLE EXAMPLE_ROLE_NAME;```\n4. Switch role to SECURITYADMIN and [create a new user](https://docs.snowflake.com/en/sql-reference/sql/create-user.html):\n```\nUSE ROLE SECURITYADMIN;\nCREATE OR REPLACE USER EXAMPLE_USER_NAME\n PASSWORD = 'example_password'\n DEFAULT_ROLE = EXAMPLE_ROLE_NAME\n DEFAULT_WAREHOUSE = EXAMPLE_WAREHOUSE_NAME\n;```\n5. Switch role to ACCOUNTADMIN and [grant access to snowflake database](https://docs.snowflake.com/en/sql-reference/account-usage.html#enabling-account-usage-for-other-roles) for role.\n```\nUSE ROLE ACCOUNTADMIN;\nGRANT IMPORTED PRIVILEGES ON DATABASE SNOWFLAKE TO ROLE EXAMPLE_ROLE_NAME;```\n6. Switch role to SECURITYADMIN and [assign role](https://docs.snowflake.com/en/sql-reference/sql/grant-role.html) to user:\n```\nUSE ROLE SECURITYADMIN;\nGRANT ROLE EXAMPLE_ROLE_NAME TO USER EXAMPLE_USER_NAME;```\n\n>**IMPORTANT:** Save user and API password created during this step as they will be used during deployment step." - }, - { - "description": "**STEP 2 - Choose ONE from the following two deployment options to deploy the connector and the associated Azure Function**\n\n>**IMPORTANT:** Before deploying the data connector, have the Workspace ID and Workspace Primary Key (can be copied from the following), as well as Snowflake credentials, readily available.", - "instructions": [ - { - "parameters": { - "fillWith": [ - "WorkspaceId" - ], - "label": "Workspace ID" - }, - "type": "CopyableLabel" - }, - { - "parameters": { - "fillWith": [ - "PrimaryKey" - ], - "label": "Primary Key" - }, - "type": "CopyableLabel" - } - ] - }, - { - "instructions": [ - { - "parameters": { - "instructionSteps": [ - { - "title": "Option 1 - Azure Resource Manager (ARM) Template", - "description": "Use this method for automated deployment of the data connector using an ARM Template.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://aka.ms/sentinel-SnowflakeDataConnector-azuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Snowflake Account Identifier**, **Snowflake User**, **Snowflake Password**, **Microsoft Sentinel Workspace Id**, **Microsoft Sentinel Shared Key**\n4. Mark the checkbox labeled **I agree to the terms and conditions stated above**.\n5. Click **Purchase** to deploy." - }, - { - "title": "Option 2 - Manual Deployment of Azure Functions", - "description": "Use the following step-by-step instructions to deploy the data connector manually with Azure Functions (Deployment via Visual Studio Code).", - "instructions": [ - { - "parameters": { - "instructionSteps": [ - { - "title": "Step 1 - Deploy a Function App", - "description": "1. Download the [Azure Function App](https://aka.ms/sentinel-SnowflakeDataConnector-functionapp) file. Extract archive to your local development computer.\n2. Follow the [function app manual deployment instructions](https://github.com/Azure/Azure-Sentinel/blob/master/DataConnectors/AzureFunctionsManualDeployment.md#function-app-manual-deployment-instructions) to deploy the Azure Functions app using VSCode.\n3. After successful deployment of the function app, follow next steps for configuring it." - }, - { - "title": "Step 2 - Configure the Function App", - "description": "1. Go to Azure Portal for the Function App configuration. \n2. In the Function App, select the Function App Name and select **Configuration**.\n3. In the **Application settings** tab, select **+ New application setting**.\n4. Add each of the following application settings individually, with their respective string values (case-sensitive): \n\t\tSNOWFLAKE_ACCOUNT\n\t\tSNOWFLAKE_USER\n\t\tSNOWFLAKE_PASSWORD\n\t\tWORKSPACE_ID\n\t\tSHARED_KEY\n\t\tlogAnalyticsUri (optional)\n - Use logAnalyticsUri to override the log analytics API endpoint for dedicated cloud. For example, for public cloud, leave the value empty; for Azure GovUS cloud environment, specify the value in the following format: `https://WORKSPACE_ID.ods.opinsights.azure.us`. \n4. Once all application settings have been entered, click **Save**." - } - ] - }, - "type": "InstructionStepsGroup" - } - ] - } - ] - }, - "type": "InstructionStepsGroup" - } - ] - } - ] - } + "entityType": "Account" + } + ] } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2023-04-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", + "apiVersion": "2022-01-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId1'),'/'))))]", "properties": { - "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", - "contentId": "[variables('_dataConnectorContentId1')]", - "kind": "DataConnector", - "version": "[variables('dataConnectorVersion1')]", + "description": "Snowflake Analytics Rule 1", + "parentId": "[variables('analyticRuleId1')]", + "contentId": "[variables('_analyticRulecontentId1')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion1')]", "source": { "kind": "Solution", "name": "Snowflake", @@ -395,231 +285,72 @@ "packageName": "[variables('_solutionName')]", "packageId": "[variables('_solutionId')]", "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_dataConnectorContentId1')]", - "contentKind": "DataConnector", - "displayName": "Snowflake (using Azure Function) (using Azure Functions)", - "contentProductId": "[variables('_dataConnectorcontentProductId1')]", - "id": "[variables('_dataConnectorcontentProductId1')]", - "version": "[variables('dataConnectorVersion1')]" - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2023-04-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", - "dependsOn": [ - "[variables('_dataConnectorId1')]" - ], - "location": "[parameters('workspace-location')]", - "properties": { - "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", - "contentId": "[variables('_dataConnectorContentId1')]", - "kind": "DataConnector", - "version": "[variables('dataConnectorVersion1')]", - "source": { - "kind": "Solution", - "name": "Snowflake", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" - }, - "support": { - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "tier": "Microsoft", - "link": "https://support.microsoft.com" - } - } - }, - { - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId1'))]", - "apiVersion": "2021-03-01-preview", - "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", - "location": "[parameters('workspace-location')]", - "kind": "GenericUI", - "properties": { - "connectorUiConfig": { - "title": "Snowflake (using Azure Function) (using Azure Functions)", - "publisher": "Snowflake", - "descriptionMarkdown": "The Snowflake data connector provides the capability to ingest Snowflake [login logs](https://docs.snowflake.com/en/sql-reference/account-usage/login_history.html) and [query logs](https://docs.snowflake.com/en/sql-reference/account-usage/query_history.html) into Microsoft Sentinel using the Snowflake Python Connector. Refer to [Snowflake documentation](https://docs.snowflake.com/en/user-guide/python-connector.html) for more information.", - "graphQueries": [ - { - "metricName": "Snowflake Events", - "legend": "Snowflake_CL", - "baseQuery": "Snowflake_CL" - } - ], - "dataTypes": [ - { - "name": "Snowflake_CL", - "lastDataReceivedQuery": "Snowflake_CL\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" - } - ], - "connectivityCriterias": [ - { - "type": "IsConnectedQuery", - "value": [ - "Snowflake_CL\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(1d)" - ] - } - ], - "sampleQueries": [ - { - "description": "All Snowflake Events", - "query": "Snowflake_CL\n| sort by TimeGenerated desc" - } - ], - "availability": { - "status": 1, - "isPreview": false - }, - "permissions": { - "resourceProvider": [ - { - "provider": "Microsoft.OperationalInsights/workspaces", - "permissionsDisplayText": "read and write permissions on the workspace are required.", - "providerDisplayName": "Workspace", - "scope": "Workspace", - "requiredPermissions": { - "write": true, - "read": true, - "delete": true - } - }, - { - "provider": "Microsoft.OperationalInsights/workspaces/sharedKeys", - "permissionsDisplayText": "read permissions to shared keys for the workspace are required. [See the documentation to learn more about workspace keys](https://docs.microsoft.com/azure/azure-monitor/platform/agent-windows#obtain-workspace-id-and-key).", - "providerDisplayName": "Keys", - "scope": "Workspace", - "requiredPermissions": { - "action": true - } - } - ], - "customs": [ - { - "name": "Microsoft.Web/sites permissions", - "description": "Read and write permissions to Azure Functions to create a Function App is required. [See the documentation to learn more about Azure Functions](https://docs.microsoft.com/azure/azure-functions/)." - }, - { - "name": "Snowflake Credentials", - "description": "**Snowflake Account Identifier**, **Snowflake User** and **Snowflake Password** are required for connection. See the documentation to learn more about [Snowflake Account Identifier](https://docs.snowflake.com/en/user-guide/admin-account-identifier.html#). Instructions on how to create user for this connector you can find below." - } - ] - }, - "instructionSteps": [ - { - "description": ">**NOTE:** This connector uses Azure Functions to connect to the Azure Blob Storage API to pull logs into Microsoft Sentinel. This might result in additional costs for data ingestion and for storing data in Azure Blob Storage costs. Check the [Azure Functions pricing page](https://azure.microsoft.com/pricing/details/functions/) and [Azure Blob Storage pricing page](https://azure.microsoft.com/pricing/details/storage/blobs/) for details." - }, - { - "description": ">**(Optional Step)** Securely store workspace and API authorization key(s) or token(s) in Azure Key Vault. Azure Key Vault provides a secure mechanism to store and retrieve key values. [Follow these instructions](https://docs.microsoft.com/azure/app-service/app-service-key-vault-references) to use Azure Key Vault with an Azure Function App." - }, - { - "description": ">**NOTE:** This data connector depends on a parser based on a Kusto Function to work as expected [**Snowflake**](https://aka.ms/sentinel-SnowflakeDataConnector-parser) which is deployed with the Microsoft Sentinel Solution." - }, - { - "description": "**STEP 1 - Creating user in Snowflake**\n\nTo query data from Snowflake you need a user that is assigned to a role with sufficient privileges and a virtual warehouse cluster. The initial size of this cluster will be set to small but if it is insufficient, the cluster size can be increased as necessary.\n\n1. Enter the Snowflake console.\n2. Switch role to SECURITYADMIN and [create a new role](https://docs.snowflake.com/en/sql-reference/sql/create-role.html):\n```\nUSE ROLE SECURITYADMIN;\nCREATE OR REPLACE ROLE EXAMPLE_ROLE_NAME;```\n3. Switch role to SYSADMIN and [create warehouse](https://docs.snowflake.com/en/sql-reference/sql/create-warehouse.html) and [grand access](https://docs.snowflake.com/en/sql-reference/sql/grant-privilege.html) to it:\n```\nUSE ROLE SYSADMIN;\nCREATE OR REPLACE WAREHOUSE EXAMPLE_WAREHOUSE_NAME\n WAREHOUSE_SIZE = 'SMALL' \n AUTO_SUSPEND = 5\n AUTO_RESUME = true\n INITIALLY_SUSPENDED = true;\nGRANT USAGE, OPERATE ON WAREHOUSE EXAMPLE_WAREHOUSE_NAME TO ROLE EXAMPLE_ROLE_NAME;```\n4. Switch role to SECURITYADMIN and [create a new user](https://docs.snowflake.com/en/sql-reference/sql/create-user.html):\n```\nUSE ROLE SECURITYADMIN;\nCREATE OR REPLACE USER EXAMPLE_USER_NAME\n PASSWORD = 'example_password'\n DEFAULT_ROLE = EXAMPLE_ROLE_NAME\n DEFAULT_WAREHOUSE = EXAMPLE_WAREHOUSE_NAME\n;```\n5. Switch role to ACCOUNTADMIN and [grant access to snowflake database](https://docs.snowflake.com/en/sql-reference/account-usage.html#enabling-account-usage-for-other-roles) for role.\n```\nUSE ROLE ACCOUNTADMIN;\nGRANT IMPORTED PRIVILEGES ON DATABASE SNOWFLAKE TO ROLE EXAMPLE_ROLE_NAME;```\n6. Switch role to SECURITYADMIN and [assign role](https://docs.snowflake.com/en/sql-reference/sql/grant-role.html) to user:\n```\nUSE ROLE SECURITYADMIN;\nGRANT ROLE EXAMPLE_ROLE_NAME TO USER EXAMPLE_USER_NAME;```\n\n>**IMPORTANT:** Save user and API password created during this step as they will be used during deployment step." - }, - { - "description": "**STEP 2 - Choose ONE from the following two deployment options to deploy the connector and the associated Azure Function**\n\n>**IMPORTANT:** Before deploying the data connector, have the Workspace ID and Workspace Primary Key (can be copied from the following), as well as Snowflake credentials, readily available.", - "instructions": [ - { - "parameters": { - "fillWith": [ - "WorkspaceId" - ], - "label": "Workspace ID" - }, - "type": "CopyableLabel" - }, - { - "parameters": { - "fillWith": [ - "PrimaryKey" - ], - "label": "Primary Key" - }, - "type": "CopyableLabel" - } - ] - }, - { - "instructions": [ - { - "parameters": { - "instructionSteps": [ - { - "title": "Option 1 - Azure Resource Manager (ARM) Template", - "description": "Use this method for automated deployment of the data connector using an ARM Template.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://aka.ms/sentinel-SnowflakeDataConnector-azuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Snowflake Account Identifier**, **Snowflake User**, **Snowflake Password**, **Microsoft Sentinel Workspace Id**, **Microsoft Sentinel Shared Key**\n4. Mark the checkbox labeled **I agree to the terms and conditions stated above**.\n5. Click **Purchase** to deploy." - }, - { - "title": "Option 2 - Manual Deployment of Azure Functions", - "description": "Use the following step-by-step instructions to deploy the data connector manually with Azure Functions (Deployment via Visual Studio Code).", - "instructions": [ - { - "parameters": { - "instructionSteps": [ - { - "title": "Step 1 - Deploy a Function App", - "description": "1. Download the [Azure Function App](https://aka.ms/sentinel-SnowflakeDataConnector-functionapp) file. Extract archive to your local development computer.\n2. Follow the [function app manual deployment instructions](https://github.com/Azure/Azure-Sentinel/blob/master/DataConnectors/AzureFunctionsManualDeployment.md#function-app-manual-deployment-instructions) to deploy the Azure Functions app using VSCode.\n3. After successful deployment of the function app, follow next steps for configuring it." - }, - { - "title": "Step 2 - Configure the Function App", - "description": "1. Go to Azure Portal for the Function App configuration. \n2. In the Function App, select the Function App Name and select **Configuration**.\n3. In the **Application settings** tab, select **+ New application setting**.\n4. Add each of the following application settings individually, with their respective string values (case-sensitive): \n\t\tSNOWFLAKE_ACCOUNT\n\t\tSNOWFLAKE_USER\n\t\tSNOWFLAKE_PASSWORD\n\t\tWORKSPACE_ID\n\t\tSHARED_KEY\n\t\tlogAnalyticsUri (optional)\n - Use logAnalyticsUri to override the log analytics API endpoint for dedicated cloud. For example, for public cloud, leave the value empty; for Azure GovUS cloud environment, specify the value in the following format: `https://WORKSPACE_ID.ods.opinsights.azure.us`. \n4. Once all application settings have been entered, click **Save**." - } - ] - }, - "type": "InstructionStepsGroup" - } - ] - } - ] - }, - "type": "InstructionStepsGroup" - } - ] - } - ], - "id": "[variables('_uiConfigId1')]", - "additionalRequirementBanner": "This data connector depends on a parser based on a Kusto Function to work as expected [**Snowflake**](https://aka.ms/sentinel-SnowflakeDataConnector-parser) which is deployed with the Microsoft Sentinel Solution." - } + "contentId": "[variables('_analyticRulecontentId1')]", + "contentKind": "AnalyticsRule", + "displayName": "Snowflake - Possible discovery activity", + "contentProductId": "[variables('_analyticRulecontentProductId1')]", + "id": "[variables('_analyticRulecontentProductId1')]", + "version": "[variables('analyticRuleVersion1')]" } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", - "name": "[variables('parserTemplateSpecName1')]", + "name": "[variables('analyticRuleTemplateSpecName2')]", "location": "[parameters('workspace-location')]", "dependsOn": [ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Snowflake Data Parser with template version 3.0.0", + "description": "SnowflakeLongQueryProcessTime_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('parserVersion1')]", + "contentVersion": "[variables('analyticRuleVersion2')]", "parameters": {}, "variables": {}, "resources": [ { - "name": "[variables('_parserName1')]", - "apiVersion": "2022-10-01", - "type": "Microsoft.OperationalInsights/workspaces/savedSearches", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId2')]", + "apiVersion": "2022-04-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "eTag": "*", - "displayName": "Snowflake Data Parser", - "category": "Samples", - "functionAlias": "Snowflake", - "query": "\nSnowflake_CL\n| extend EventVendor = 'Snowflake'\n| extend EventProduct = 'Snowflake'\n| project-rename \n EventStartTime=START_TIME_t,\n EventType=EVENT_TYPE_s,\n TargetUsername=USER_NAME_s,\n SrcDvcIpAddr=CLIENT_IP_s\n| extend \n User=TargetUsername,\n EventEndTime=iff(isnotempty(EVENT_TIMESTAMP_t), EVENT_TIMESTAMP_t, END_TIME_t)", - "functionParameters": "", - "version": 1, - "tags": [ + "description": "Detects query with abnormal proccess time.", + "displayName": "Snowflake - Abnormal query process time", + "enabled": false, + "query": "let threshold = 10000;\nSnowflake\n| where TOTAL_ELAPSED_TIME_d > threshold\n| extend AccountCustomEntity = TargetUsername\n", + "queryFrequency": "PT1H", + "queryPeriod": "PT1H", + "severity": "Medium", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ { - "name": "description", - "value": "Snowflake Data Parser" + "connectorId": "Snowflake", + "dataTypes": [ + "Snowflake" + ] + } + ], + "tactics": [ + "Impact" + ], + "techniques": [ + "T1499" + ], + "entityMappings": [ + { + "fieldMappings": [ + { + "identifier": "Name", + "columnName": "AccountCustomEntity" + } + ], + "entityType": "Account" } ] } @@ -627,18 +358,16 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Parser-', last(split(variables('_parserId1'),'/'))))]", - "dependsOn": [ - "[variables('_parserName1')]" - ], + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId2'),'/'))))]", "properties": { - "parentId": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), variables('parserName1'))]", - "contentId": "[variables('_parserContentId1')]", - "kind": "Parser", - "version": "[variables('parserVersion1')]", + "description": "Snowflake Analytics Rule 2", + "parentId": "[variables('analyticRuleId2')]", + "contentId": "[variables('_analyticRulecontentId2')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion2')]", "source": { - "name": "Snowflake", "kind": "Solution", + "name": "Snowflake", "sourceId": "[variables('_solutionId')]" }, "author": { @@ -660,108 +389,87 @@ "packageName": "[variables('_solutionName')]", "packageId": "[variables('_solutionId')]", "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_parserContentId1')]", - "contentKind": "Parser", - "displayName": "Snowflake Data Parser", - "contentProductId": "[variables('_parsercontentProductId1')]", - "id": "[variables('_parsercontentProductId1')]", - "version": "[variables('parserVersion1')]" - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/savedSearches", - "apiVersion": "2022-10-01", - "name": "[variables('_parserName1')]", - "location": "[parameters('workspace-location')]", - "properties": { - "eTag": "*", - "displayName": "Snowflake Data Parser", - "category": "Samples", - "functionAlias": "Snowflake", - "query": "\nSnowflake_CL\n| extend EventVendor = 'Snowflake'\n| extend EventProduct = 'Snowflake'\n| project-rename \n EventStartTime=START_TIME_t,\n EventType=EVENT_TYPE_s,\n TargetUsername=USER_NAME_s,\n SrcDvcIpAddr=CLIENT_IP_s\n| extend \n User=TargetUsername,\n EventEndTime=iff(isnotempty(EVENT_TIMESTAMP_t), EVENT_TIMESTAMP_t, END_TIME_t)", - "functionParameters": "", - "version": 1, - "tags": [ - { - "name": "description", - "value": "Snowflake Data Parser" - } - ] - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", - "location": "[parameters('workspace-location')]", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Parser-', last(split(variables('_parserId1'),'/'))))]", - "dependsOn": [ - "[variables('_parserId1')]" - ], - "properties": { - "parentId": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), variables('parserName1'))]", - "contentId": "[variables('_parserContentId1')]", - "kind": "Parser", - "version": "[variables('parserVersion1')]", - "source": { - "kind": "Solution", - "name": "Snowflake", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" - }, - "support": { - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "tier": "Microsoft", - "link": "https://support.microsoft.com" - } + "contentId": "[variables('_analyticRulecontentId2')]", + "contentKind": "AnalyticsRule", + "displayName": "Snowflake - Abnormal query process time", + "contentProductId": "[variables('_analyticRulecontentProductId2')]", + "id": "[variables('_analyticRulecontentProductId2')]", + "version": "[variables('analyticRuleVersion2')]" } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", - "name": "[variables('workbookTemplateSpecName1')]", + "name": "[variables('analyticRuleTemplateSpecName3')]", "location": "[parameters('workspace-location')]", "dependsOn": [ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeWorkbook Workbook with template version 3.0.0", + "description": "SnowflakeMultipleFailedQueries_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('workbookVersion1')]", + "contentVersion": "[variables('analyticRuleVersion3')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.Insights/workbooks", - "name": "[variables('workbookContentId1')]", + "type": "Microsoft.SecurityInsights/AlertRuleTemplates", + "name": "[variables('analyticRulecontentId3')]", + "apiVersion": "2022-04-01-preview", + "kind": "Scheduled", "location": "[parameters('workspace-location')]", - "kind": "shared", - "apiVersion": "2021-08-01", - "metadata": { - "description": "Sets the time name for analysis" - }, "properties": { - "displayName": "[parameters('workbook1-name')]", - "serializedData": "{\"version\":\"Notebook/1.0\",\"items\":[{\"type\":1,\"content\":{\"json\":\"**NOTE**: This data connector depends on a parser based on Kusto Function **Snowflake** to work as expected. [Follow steps to get this Kusto Function](https://aka.ms/sentinel-SnowflakeDataConnector-parser)\"},\"name\":\"text - 8\"},{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"parameters\":[{\"id\":\"cd8447d9-b096-4673-92d8-2a1e8291a125\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"TimeRange\",\"type\":4,\"description\":\"Sets the time name for analysis\",\"value\":{\"durationMs\":7776000000},\"typeSettings\":{\"selectableValues\":[{\"durationMs\":1800000},{\"durationMs\":3600000},{\"durationMs\":86400000},{\"durationMs\":604800000},{\"durationMs\":2592000000},{\"durationMs\":7776000000}]},\"timeContext\":{\"durationMs\":86400000}}],\"style\":\"pills\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"parameters - 11\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\r\\n| make-series TotalEvents = count() default = 0 on TimeGenerated from {TimeRange:start} to {TimeRange:end} step {TimeRange:grain};\",\"size\":0,\"title\":\"Events Over Time\",\"color\":\"green\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"timechart\",\"graphSettings\":{\"type\":0}},\"customWidth\":\"60\",\"name\":\"query - 12\",\"styleSettings\":{\"maxWidth\":\"55\"}},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(DATABASE_NAME_s)\\n| summarize dcount(DATABASE_NAME_s)\",\"size\":3,\"title\":\"Total Databases\",\"timeContext\":{\"durationMs\":7776000000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"50\",\"name\":\"query - 1\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(source_table_s)\\n| summarize dcount(source_table_s)\",\"size\":3,\"title\":\"Total Tables\",\"timeContext\":{\"durationMs\":7776000000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"50\",\"name\":\"query - 2\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| summarize s=sum(EXECUTION_TIME_d)\\n| project s_time = strcat(s/1000, ' sec')\",\"size\":3,\"title\":\"Total Query Time\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"30\",\"name\":\"query - 0\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(QUERY_TYPE_s)\\n| summarize count()\",\"size\":3,\"title\":\"Total Queries Run\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"30\",\"name\":\"query - 3\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| summarize cs = sum(CREDITS_USED_CLOUD_SERVICES_d)\\n| project round(cs, 8)\",\"size\":3,\"title\":\"Credits Spent\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"40\",\"name\":\"query - 4\"}]},\"customWidth\":\"40\",\"name\":\"group - 0\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(source_table_s)\\n| summarize count() by source_table_s\",\"size\":3,\"title\":\"Table Events Summary\",\"color\":\"orange\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"tiles\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"source_table_s\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"count_\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"maximumSignificantDigits\":3,\"maximumFractionDigits\":2}}},\"showBorder\":false}},\"customWidth\":\"50\",\"name\":\"query - 0\",\"styleSettings\":{\"showBorder\":true}},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(DATABASE_NAME_s)\\n| summarize count() by DATABASE_NAME_s\",\"size\":3,\"title\":\"Database Events Summary\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"tiles\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"DATABASE_NAME_s\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"count_\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"style\":\"decimal\",\"maximumFractionDigits\":2,\"maximumSignificantDigits\":3}}},\"showBorder\":false}},\"customWidth\":\"50\",\"name\":\"query - 1\",\"styleSettings\":{\"showBorder\":true}}]},\"customWidth\":\"30\",\"name\":\"group - 11\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(SrcDvcIpAddr)\\n| summarize count() by SrcDvcIpAddr\",\"size\":3,\"title\":\"Source Addresses\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"piechart\"},\"customWidth\":\"30\",\"name\":\"query - 9\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where EXECUTION_TIME_d > 0\\n| top 10 by EXECUTION_TIME_d desc\\n| project Query=QUERY_TEXT_s, User=TargetUsername, ExecutionTime=EXECUTION_TIME_d\\n\",\"size\":0,\"title\":\"Query Execution Time\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"ExecutionTime\",\"formatter\":8,\"formatOptions\":{\"palette\":\"coldHot\"}}]}},\"customWidth\":\"35\",\"name\":\"query - 11\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where CREDITS_USED_CLOUD_SERVICES_d > 0\\n| summarize by QUERY_TEXT_s, CREDITS_USED_CLOUD_SERVICES_d\\n| top 10 by CREDITS_USED_CLOUD_SERVICES_d desc\\n| project Query=QUERY_TEXT_s, CreditsSpent=CREDITS_USED_CLOUD_SERVICES_d\",\"size\":0,\"title\":\"Credits Spent by Queriws\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"CreditsSpent\",\"formatter\":8,\"formatOptions\":{\"palette\":\"coldHot\",\"compositeBarSettings\":{\"labelText\":\"\",\"columnSettings\":[]}},\"numberFormat\":{\"unit\":0,\"options\":{\"style\":\"decimal\",\"maximumFractionDigits\":10}}}]}},\"customWidth\":\"35\",\"name\":\"query - 9\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\r\\n| where QUERY_TYPE_s == 'CREATE_USER'\\r\\n| extend n_usr = extract(@'USER\\\\s(\\\\S+)', 1, QUERY_TEXT_s)\\r\\n| project Username=n_usr\",\"size\":0,\"title\":\"New Users\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"URL Category\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"count_\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"style\":\"decimal\",\"maximumFractionDigits\":2,\"maximumSignificantDigits\":3}}},\"secondaryContent\":{\"columnMatch\":\"Trend\",\"formatter\":9,\"formatOptions\":{\"palette\":\"purple\"}},\"showBorder\":false},\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"20\",\"name\":\"query - 0\",\"styleSettings\":{\"maxWidth\":\"30\"}},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n\\n| where QUERY_TYPE_s =~ 'SELECT'\\n| summarize roles = makeset(ROLE_NAME_s) by TargetUsername\\n| join(Snowflake\\n | where EventType =~ 'LOGIN') on TargetUsername\\n| project EventTime=TimeGenerated, TargetUsername, SourceAddress=SrcDvcIpAddr, Status=strcat(iif(IS_SUCCESS_s =~ 'No', '❌ - Login Failure' , '✅ - Logged in'))\",\"size\":0,\"title\":\"Privileged Sessions\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"User\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"TotalMailsReceived\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"maximumSignificantDigits\":3,\"maximumFractionDigits\":2}}},\"secondaryContent\":{\"columnMatch\":\"Trend\",\"formatter\":10,\"formatOptions\":{\"palette\":\"magenta\"}},\"showBorder\":false}},\"customWidth\":\"45\",\"name\":\"query - 10\"}],\"fromTemplateId\":\"sentinel-SnowflakeWorkbook\",\"$schema\":\"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"}\n", - "version": "1.0", - "sourceId": "[variables('workspaceResourceId')]", - "category": "sentinel" + "description": "Detects multiple failed queries in short timeframe.", + "displayName": "Snowflake - Multiple failed queries", + "enabled": false, + "query": "let threshold = 50;\nSnowflake\n| where EXECUTION_STATUS_s !~ 'SUCCESS'\n| summarize count() by TargetUsername, bin(TimeGenerated, 5m)\n| where count_ > threshold\n| extend AccountCustomEntity = TargetUsername\n", + "queryFrequency": "PT1H", + "queryPeriod": "PT1H", + "severity": "High", + "suppressionDuration": "PT1H", + "suppressionEnabled": false, + "triggerOperator": "GreaterThan", + "triggerThreshold": 0, + "status": "Available", + "requiredDataConnectors": [ + { + "connectorId": "Snowflake", + "dataTypes": [ + "Snowflake" + ] + } + ], + "tactics": [ + "Discovery" + ], + "techniques": [ + "T1518", + "T1082" + ], + "entityMappings": [ + { + "fieldMappings": [ + { + "identifier": "Name", + "columnName": "AccountCustomEntity" + } + ], + "entityType": "Account" + } + ] } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Workbook-', last(split(variables('workbookId1'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId3'),'/'))))]", "properties": { - "description": "@{workbookKey=SnowflakeWorkbook; logoFileName=Azure_Sentinel.svg; description=Sets the time name for analysis; dataTypesDependencies=System.Object[]; dataConnectorsDependencies=System.Object[]; previewImagesFileNames=System.Object[]; version=1.0.0; title=Snowflake; templateRelativePath=Snowflake.json; subtitle=; provider=Snowflake}.description", - "parentId": "[variables('workbookId1')]", - "contentId": "[variables('_workbookContentId1')]", - "kind": "Workbook", - "version": "[variables('workbookVersion1')]", + "description": "Snowflake Analytics Rule 3", + "parentId": "[variables('analyticRuleId3')]", + "contentId": "[variables('_analyticRulecontentId3')]", + "kind": "AnalyticsRule", + "version": "[variables('analyticRuleVersion3')]", "source": { "kind": "Solution", "name": "Snowflake", @@ -776,19 +484,6 @@ "email": "support@microsoft.com", "tier": "Microsoft", "link": "https://support.microsoft.com" - }, - "dependencies": { - "operator": "AND", - "criteria": [ - { - "contentId": "Snowflake_CL", - "kind": "DataType" - }, - { - "contentId": "SnowflakeDataConnector", - "kind": "DataConnector" - } - ] } } } @@ -799,44 +494,44 @@ "packageName": "[variables('_solutionName')]", "packageId": "[variables('_solutionId')]", "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_workbookContentId1')]", - "contentKind": "Workbook", - "displayName": "[parameters('workbook1-name')]", - "contentProductId": "[variables('_workbookcontentProductId1')]", - "id": "[variables('_workbookcontentProductId1')]", - "version": "[variables('workbookVersion1')]" + "contentId": "[variables('_analyticRulecontentId3')]", + "contentKind": "AnalyticsRule", + "displayName": "Snowflake - Multiple failed queries", + "contentProductId": "[variables('_analyticRulecontentProductId3')]", + "id": "[variables('_analyticRulecontentProductId3')]", + "version": "[variables('analyticRuleVersion3')]" } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", - "name": "[variables('analyticRuleTemplateSpecName1')]", + "name": "[variables('analyticRuleTemplateSpecName4')]", "location": "[parameters('workspace-location')]", "dependsOn": [ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeDiscoveryActivity_AnalyticalRules Analytics Rule with template version 3.0.0", + "description": "SnowflakeMultipleLoginFailure_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion1')]", + "contentVersion": "[variables('analyticRuleVersion4')]", "parameters": {}, "variables": {}, "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('analyticRulecontentId1')]", + "name": "[variables('analyticRulecontentId4')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "description": "Detects possible discovery activity.", - "displayName": "Snowflake - Possible discovery activity", + "description": "Detects multiple login failures by user.", + "displayName": "Snowflake - Multiple login failures by user", "enabled": false, - "query": "let threshold = 20;\nSnowflake\n| where QUERY_TYPE_s =~ 'SHOW'\n| where EXECUTION_STATUS_s =~ 'SUCCESS'\n| summarize count() by TargetUsername, bin(TimeGenerated, 5m)\n| where count_ > threshold\n| extend AccountCustomEntity = TargetUsername\n", + "query": "let threshold = 10;\nSnowflake\n| where EventType =~ 'LOGIN'\n| where IS_SUCCESS_s =~ 'No'\n| summarize count() by TargetUsername, bin(TimeGenerated, 5m)\n| where count_ > threshold\n| extend AccountCustomEntity = TargetUsername\n", "queryFrequency": "PT1H", "queryPeriod": "PT1H", - "severity": "Medium", + "severity": "High", "suppressionDuration": "PT1H", "suppressionEnabled": false, "triggerOperator": "GreaterThan", @@ -851,17 +546,20 @@ } ], "tactics": [ - "Discovery" + "InitialAccess" + ], + "techniques": [ + "T1078" ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "columnName": "AccountCustomEntity", - "identifier": "Name" + "identifier": "Name", + "columnName": "AccountCustomEntity" } - ] + ], + "entityType": "Account" } ] } @@ -869,13 +567,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId1'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId4'),'/'))))]", "properties": { - "description": "Snowflake Analytics Rule 1", - "parentId": "[variables('analyticRuleId1')]", - "contentId": "[variables('_analyticRulecontentId1')]", + "description": "Snowflake Analytics Rule 4", + "parentId": "[variables('analyticRuleId4')]", + "contentId": "[variables('_analyticRulecontentId4')]", "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion1')]", + "version": "[variables('analyticRuleVersion4')]", "source": { "kind": "Solution", "name": "Snowflake", @@ -900,44 +598,44 @@ "packageName": "[variables('_solutionName')]", "packageId": "[variables('_solutionId')]", "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_analyticRulecontentId1')]", + "contentId": "[variables('_analyticRulecontentId4')]", "contentKind": "AnalyticsRule", - "displayName": "Snowflake - Possible discovery activity", - "contentProductId": "[variables('_analyticRulecontentProductId1')]", - "id": "[variables('_analyticRulecontentProductId1')]", - "version": "[variables('analyticRuleVersion1')]" + "displayName": "Snowflake - Multiple login failures by user", + "contentProductId": "[variables('_analyticRulecontentProductId4')]", + "id": "[variables('_analyticRulecontentProductId4')]", + "version": "[variables('analyticRuleVersion4')]" } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", - "name": "[variables('analyticRuleTemplateSpecName2')]", + "name": "[variables('analyticRuleTemplateSpecName5')]", "location": "[parameters('workspace-location')]", "dependsOn": [ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeLongQueryProcessTime_AnalyticalRules Analytics Rule with template version 3.0.0", + "description": "SnowflakeMultipleLoginFailureFromIP_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion2')]", + "contentVersion": "[variables('analyticRuleVersion5')]", "parameters": {}, "variables": {}, "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('analyticRulecontentId2')]", + "name": "[variables('analyticRulecontentId5')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "description": "Detects query with abnormal proccess time.", - "displayName": "Snowflake - Abnormal query process time", + "description": "Detects Mmltiple login failures from single IP.", + "displayName": "Snowflake - Multiple login failures from single IP", "enabled": false, - "query": "let threshold = 10000;\nSnowflake\n| where TOTAL_ELAPSED_TIME_d > threshold\n| extend AccountCustomEntity = TargetUsername\n", + "query": "let threshold = 10;\nSnowflake\n| where EventType =~ 'LOGIN'\n| where IS_SUCCESS_s =~ 'No'\n| summarize count() by SrcDvcIpAddr, bin(TimeGenerated, 5m)\n| where count_ > threshold\n| extend IPCustomEntity = SrcDvcIpAddr\n", "queryFrequency": "PT1H", "queryPeriod": "PT1H", - "severity": "Medium", + "severity": "High", "suppressionDuration": "PT1H", "suppressionEnabled": false, "triggerOperator": "GreaterThan", @@ -952,20 +650,20 @@ } ], "tactics": [ - "Impact" + "InitialAccess" ], "techniques": [ - "T1499" + "T1078" ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "columnName": "AccountCustomEntity", - "identifier": "Name" + "identifier": "Address", + "columnName": "IPCustomEntity" } - ] + ], + "entityType": "IP" } ] } @@ -973,13 +671,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId2'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId5'),'/'))))]", "properties": { - "description": "Snowflake Analytics Rule 2", - "parentId": "[variables('analyticRuleId2')]", - "contentId": "[variables('_analyticRulecontentId2')]", + "description": "Snowflake Analytics Rule 5", + "parentId": "[variables('analyticRuleId5')]", + "contentId": "[variables('_analyticRulecontentId5')]", "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion2')]", + "version": "[variables('analyticRuleVersion5')]", "source": { "kind": "Solution", "name": "Snowflake", @@ -1004,44 +702,44 @@ "packageName": "[variables('_solutionName')]", "packageId": "[variables('_solutionId')]", "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_analyticRulecontentId2')]", + "contentId": "[variables('_analyticRulecontentId5')]", "contentKind": "AnalyticsRule", - "displayName": "Snowflake - Abnormal query process time", - "contentProductId": "[variables('_analyticRulecontentProductId2')]", - "id": "[variables('_analyticRulecontentProductId2')]", - "version": "[variables('analyticRuleVersion2')]" + "displayName": "Snowflake - Multiple login failures from single IP", + "contentProductId": "[variables('_analyticRulecontentProductId5')]", + "id": "[variables('_analyticRulecontentProductId5')]", + "version": "[variables('analyticRuleVersion5')]" } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", - "name": "[variables('analyticRuleTemplateSpecName3')]", + "name": "[variables('analyticRuleTemplateSpecName6')]", "location": "[parameters('workspace-location')]", "dependsOn": [ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeMultipleFailedQueries_AnalyticalRules Analytics Rule with template version 3.0.0", + "description": "SnowflakePossibleDataDestruction_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion3')]", + "contentVersion": "[variables('analyticRuleVersion6')]", "parameters": {}, "variables": {}, "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('analyticRulecontentId3')]", + "name": "[variables('analyticRulecontentId6')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "description": "Detects multiple failed queries in short timeframe.", - "displayName": "Snowflake - Multiple failed queries", + "description": "Detects possible data destruction.", + "displayName": "Snowflake - Possible data destraction", "enabled": false, - "query": "let threshold = 50;\nSnowflake\n| where EXECUTION_STATUS_s !~ 'SUCCESS'\n| summarize count() by TargetUsername, bin(TimeGenerated, 5m)\n| where count_ > threshold\n| extend AccountCustomEntity = TargetUsername\n", + "query": "let threshold = 10;\nSnowflake\n| where QUERY_TYPE_s =~ 'DROP'\n| where EXECUTION_STATUS_s =~ 'SUCCESS'\n| summarize count() by TargetUsername, bin(TimeGenerated, 5m)\n| where count_ > threshold\n| extend AccountCustomEntity = TargetUsername\n", "queryFrequency": "PT1H", "queryPeriod": "PT1H", - "severity": "High", + "severity": "Medium", "suppressionDuration": "PT1H", "suppressionEnabled": false, "triggerOperator": "GreaterThan", @@ -1056,21 +754,20 @@ } ], "tactics": [ - "Discovery" + "Impact" ], "techniques": [ - "T1518", - "T1082" + "T1485" ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "columnName": "AccountCustomEntity", - "identifier": "Name" + "identifier": "Name", + "columnName": "AccountCustomEntity" } - ] + ], + "entityType": "Account" } ] } @@ -1078,13 +775,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId3'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId6'),'/'))))]", "properties": { - "description": "Snowflake Analytics Rule 3", - "parentId": "[variables('analyticRuleId3')]", - "contentId": "[variables('_analyticRulecontentId3')]", + "description": "Snowflake Analytics Rule 6", + "parentId": "[variables('analyticRuleId6')]", + "contentId": "[variables('_analyticRulecontentId6')]", "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion3')]", + "version": "[variables('analyticRuleVersion6')]", "source": { "kind": "Solution", "name": "Snowflake", @@ -1109,44 +806,44 @@ "packageName": "[variables('_solutionName')]", "packageId": "[variables('_solutionId')]", "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_analyticRulecontentId3')]", + "contentId": "[variables('_analyticRulecontentId6')]", "contentKind": "AnalyticsRule", - "displayName": "Snowflake - Multiple failed queries", - "contentProductId": "[variables('_analyticRulecontentProductId3')]", - "id": "[variables('_analyticRulecontentProductId3')]", - "version": "[variables('analyticRuleVersion3')]" + "displayName": "Snowflake - Possible data destraction", + "contentProductId": "[variables('_analyticRulecontentProductId6')]", + "id": "[variables('_analyticRulecontentProductId6')]", + "version": "[variables('analyticRuleVersion6')]" } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", - "name": "[variables('analyticRuleTemplateSpecName4')]", + "name": "[variables('analyticRuleTemplateSpecName7')]", "location": "[parameters('workspace-location')]", "dependsOn": [ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeMultipleLoginFailure_AnalyticalRules Analytics Rule with template version 3.0.0", + "description": "SnowflakePrivilegesDiscovery_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion4')]", + "contentVersion": "[variables('analyticRuleVersion7')]", "parameters": {}, "variables": {}, "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('analyticRulecontentId4')]", + "name": "[variables('analyticRulecontentId7')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "description": "Detects multiple login failures by user.", - "displayName": "Snowflake - Multiple login failures by user", + "description": "Detects possible privileges discovery activity.", + "displayName": "Snowflake - Possible privileges discovery activity", "enabled": false, - "query": "let threshold = 10;\nSnowflake\n| where EventType =~ 'LOGIN'\n| where IS_SUCCESS_s =~ 'No'\n| summarize count() by TargetUsername, bin(TimeGenerated, 5m)\n| where count_ > threshold\n| extend AccountCustomEntity = TargetUsername\n", + "query": "Snowflake\n| where QUERY_TYPE_s =~ 'SHOW'\n| where QUERY_TEXT_s has_all ('SHOW', 'ROLES')\n| extend AccountCustomEntity = TargetUsername\n", "queryFrequency": "PT1H", "queryPeriod": "PT1H", - "severity": "High", + "severity": "Medium", "suppressionDuration": "PT1H", "suppressionEnabled": false, "triggerOperator": "GreaterThan", @@ -1161,20 +858,20 @@ } ], "tactics": [ - "InitialAccess" + "Discovery" ], "techniques": [ - "T1078" + "T1087" ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "columnName": "AccountCustomEntity", - "identifier": "Name" + "identifier": "Name", + "columnName": "AccountCustomEntity" } - ] + ], + "entityType": "Account" } ] } @@ -1182,13 +879,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId4'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId7'),'/'))))]", "properties": { - "description": "Snowflake Analytics Rule 4", - "parentId": "[variables('analyticRuleId4')]", - "contentId": "[variables('_analyticRulecontentId4')]", + "description": "Snowflake Analytics Rule 7", + "parentId": "[variables('analyticRuleId7')]", + "contentId": "[variables('_analyticRulecontentId7')]", "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion4')]", + "version": "[variables('analyticRuleVersion7')]", "source": { "kind": "Solution", "name": "Snowflake", @@ -1213,44 +910,44 @@ "packageName": "[variables('_solutionName')]", "packageId": "[variables('_solutionId')]", "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_analyticRulecontentId4')]", + "contentId": "[variables('_analyticRulecontentId7')]", "contentKind": "AnalyticsRule", - "displayName": "Snowflake - Multiple login failures by user", - "contentProductId": "[variables('_analyticRulecontentProductId4')]", - "id": "[variables('_analyticRulecontentProductId4')]", - "version": "[variables('analyticRuleVersion4')]" + "displayName": "Snowflake - Possible privileges discovery activity", + "contentProductId": "[variables('_analyticRulecontentProductId7')]", + "id": "[variables('_analyticRulecontentProductId7')]", + "version": "[variables('analyticRuleVersion7')]" } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", - "name": "[variables('analyticRuleTemplateSpecName5')]", + "name": "[variables('analyticRuleTemplateSpecName8')]", "location": "[parameters('workspace-location')]", "dependsOn": [ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeMultipleLoginFailureFromIP_AnalyticalRules Analytics Rule with template version 3.0.0", + "description": "SnowflakeQueryOnSensitiveTable_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion5')]", + "contentVersion": "[variables('analyticRuleVersion8')]", "parameters": {}, "variables": {}, "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('analyticRulecontentId5')]", + "name": "[variables('analyticRulecontentId8')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "description": "Detects Mmltiple login failures from single IP.", - "displayName": "Snowflake - Multiple login failures from single IP", + "description": "Detects query on sensitive or restricted table.", + "displayName": "Snowflake - Query on sensitive or restricted table", "enabled": false, - "query": "let threshold = 10;\nSnowflake\n| where EventType =~ 'LOGIN'\n| where IS_SUCCESS_s =~ 'No'\n| summarize count() by SrcDvcIpAddr, bin(TimeGenerated, 5m)\n| where count_ > threshold\n| extend IPCustomEntity = SrcDvcIpAddr\n", + "query": "let r_tbl = dynamic(['table_name']);\nSnowflake\n| where QUERY_TYPE_s =~ 'SELECT'\n| where EXECUTION_STATUS_s =~ 'SUCCESS'\n| extend tbl = extract(@'(FROM|from)\\s(\\S+)\\s', 2, QUERY_TEXT_s)\n| where tbl in~ (r_tbl)\n| extend AccountCustomEntity = TargetUsername\n", "queryFrequency": "PT1H", "queryPeriod": "PT1H", - "severity": "High", + "severity": "Medium", "suppressionDuration": "PT1H", "suppressionEnabled": false, "triggerOperator": "GreaterThan", @@ -1265,20 +962,20 @@ } ], "tactics": [ - "InitialAccess" + "Collection" ], "techniques": [ - "T1078" + "T1119" ], "entityMappings": [ { - "entityType": "IP", "fieldMappings": [ { - "columnName": "IPCustomEntity", - "identifier": "Address" + "identifier": "Name", + "columnName": "AccountCustomEntity" } - ] + ], + "entityType": "Account" } ] } @@ -1286,13 +983,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId5'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId8'),'/'))))]", "properties": { - "description": "Snowflake Analytics Rule 5", - "parentId": "[variables('analyticRuleId5')]", - "contentId": "[variables('_analyticRulecontentId5')]", + "description": "Snowflake Analytics Rule 8", + "parentId": "[variables('analyticRuleId8')]", + "contentId": "[variables('_analyticRulecontentId8')]", "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion5')]", + "version": "[variables('analyticRuleVersion8')]", "source": { "kind": "Solution", "name": "Snowflake", @@ -1317,41 +1014,41 @@ "packageName": "[variables('_solutionName')]", "packageId": "[variables('_solutionId')]", "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_analyticRulecontentId5')]", + "contentId": "[variables('_analyticRulecontentId8')]", "contentKind": "AnalyticsRule", - "displayName": "Snowflake - Multiple login failures from single IP", - "contentProductId": "[variables('_analyticRulecontentProductId5')]", - "id": "[variables('_analyticRulecontentProductId5')]", - "version": "[variables('analyticRuleVersion5')]" + "displayName": "Snowflake - Query on sensitive or restricted table", + "contentProductId": "[variables('_analyticRulecontentProductId8')]", + "id": "[variables('_analyticRulecontentProductId8')]", + "version": "[variables('analyticRuleVersion8')]" } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", - "name": "[variables('analyticRuleTemplateSpecName6')]", + "name": "[variables('analyticRuleTemplateSpecName9')]", "location": "[parameters('workspace-location')]", "dependsOn": [ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakePossibleDataDestruction_AnalyticalRules Analytics Rule with template version 3.0.0", + "description": "SnowflakeUnusualQuery_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion6')]", + "contentVersion": "[variables('analyticRuleVersion9')]", "parameters": {}, "variables": {}, "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('analyticRulecontentId6')]", + "name": "[variables('analyticRulecontentId9')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "description": "Detects possible data destruction.", - "displayName": "Snowflake - Possible data destraction", + "description": "Detects unusual query.", + "displayName": "Snowflake - Unusual query", "enabled": false, - "query": "let threshold = 10;\nSnowflake\n| where QUERY_TYPE_s =~ 'DROP'\n| where EXECUTION_STATUS_s =~ 'SUCCESS'\n| summarize count() by TargetUsername, bin(TimeGenerated, 5m)\n| where count_ > threshold\n| extend AccountCustomEntity = TargetUsername\n", + "query": "Snowflake\n| where QUERY_TYPE_s =~ 'SELECT'\n| where EXECUTION_STATUS_s =~ 'SUCCESS'\n| where QUERY_TEXT_s startswith @'SELECT *'\n| extend AccountCustomEntity = TargetUsername\n", "queryFrequency": "PT1H", "queryPeriod": "PT1H", "severity": "Medium", @@ -1369,20 +1066,20 @@ } ], "tactics": [ - "Impact" + "Collection" ], "techniques": [ - "T1485" + "T1119" ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "columnName": "AccountCustomEntity", - "identifier": "Name" + "identifier": "Name", + "columnName": "AccountCustomEntity" } - ] + ], + "entityType": "Account" } ] } @@ -1390,13 +1087,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId6'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId9'),'/'))))]", "properties": { - "description": "Snowflake Analytics Rule 6", - "parentId": "[variables('analyticRuleId6')]", - "contentId": "[variables('_analyticRulecontentId6')]", + "description": "Snowflake Analytics Rule 9", + "parentId": "[variables('analyticRuleId9')]", + "contentId": "[variables('_analyticRulecontentId9')]", "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion6')]", + "version": "[variables('analyticRuleVersion9')]", "source": { "kind": "Solution", "name": "Snowflake", @@ -1421,41 +1118,41 @@ "packageName": "[variables('_solutionName')]", "packageId": "[variables('_solutionId')]", "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_analyticRulecontentId6')]", + "contentId": "[variables('_analyticRulecontentId9')]", "contentKind": "AnalyticsRule", - "displayName": "Snowflake - Possible data destraction", - "contentProductId": "[variables('_analyticRulecontentProductId6')]", - "id": "[variables('_analyticRulecontentProductId6')]", - "version": "[variables('analyticRuleVersion6')]" + "displayName": "Snowflake - Unusual query", + "contentProductId": "[variables('_analyticRulecontentProductId9')]", + "id": "[variables('_analyticRulecontentProductId9')]", + "version": "[variables('analyticRuleVersion9')]" } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", - "name": "[variables('analyticRuleTemplateSpecName7')]", + "name": "[variables('analyticRuleTemplateSpecName10')]", "location": "[parameters('workspace-location')]", "dependsOn": [ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakePrivilegesDiscovery_AnalyticalRules Analytics Rule with template version 3.0.0", + "description": "SnowflakeUserAddAdminPrivileges_AnalyticalRules Analytics Rule with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion7')]", + "contentVersion": "[variables('analyticRuleVersion10')]", "parameters": {}, "variables": {}, "resources": [ { "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('analyticRulecontentId7')]", + "name": "[variables('analyticRulecontentId10')]", "apiVersion": "2022-04-01-preview", "kind": "Scheduled", "location": "[parameters('workspace-location')]", "properties": { - "description": "Detects possible privileges discovery activity.", - "displayName": "Snowflake - Possible privileges discovery activity", + "description": "Detects when user asigned admin privileges.", + "displayName": "Snowflake - User granted admin privileges", "enabled": false, - "query": "Snowflake\n| where QUERY_TYPE_s =~ 'SHOW'\n| where QUERY_TEXT_s has_all ('SHOW', 'ROLES')\n| extend AccountCustomEntity = TargetUsername\n", + "query": "let adm_roles = dynamic(['SECURITYADMIN', 'SYSADMIN', 'ACCOUNTADMIN']);\nSnowflake\n| where QUERY_TYPE_s =~ 'GRANT'\n| where QUERY_TEXT_s startswith 'GRANT ROLE'\n| extend granted_role = extract(@'GRANT ROLE\\s(\\S+)\\sto\\suser', 1, QUERY_TEXT_s)\n| where granted_role in~ (adm_roles)\n| extend usr = extract(@'GRANT ROLE\\s(\\S+)\\sto\\suser(\\S+)', 2, QUERY_TEXT_s)\n| extend AccountCustomEntity = usr\n", "queryFrequency": "PT1H", "queryPeriod": "PT1H", "severity": "Medium", @@ -1473,20 +1170,20 @@ } ], "tactics": [ - "Discovery" + "PrivilegeEscalation" ], "techniques": [ - "T1087" + "T1078" ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "columnName": "AccountCustomEntity", - "identifier": "Name" + "identifier": "Name", + "columnName": "AccountCustomEntity" } - ] + ], + "entityType": "Account" } ] } @@ -1494,13 +1191,13 @@ { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId7'),'/'))))]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId10'),'/'))))]", "properties": { - "description": "Snowflake Analytics Rule 7", - "parentId": "[variables('analyticRuleId7')]", - "contentId": "[variables('_analyticRulecontentId7')]", + "description": "Snowflake Analytics Rule 10", + "parentId": "[variables('analyticRuleId10')]", + "contentId": "[variables('_analyticRulecontentId10')]", "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion7')]", + "version": "[variables('analyticRuleVersion10')]", "source": { "kind": "Solution", "name": "Snowflake", @@ -1525,190 +1222,193 @@ "packageName": "[variables('_solutionName')]", "packageId": "[variables('_solutionId')]", "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_analyticRulecontentId7')]", + "contentId": "[variables('_analyticRulecontentId10')]", "contentKind": "AnalyticsRule", - "displayName": "Snowflake - Possible privileges discovery activity", - "contentProductId": "[variables('_analyticRulecontentProductId7')]", - "id": "[variables('_analyticRulecontentProductId7')]", - "version": "[variables('analyticRuleVersion7')]" + "displayName": "Snowflake - User granted admin privileges", + "contentProductId": "[variables('_analyticRulecontentProductId10')]", + "id": "[variables('_analyticRulecontentProductId10')]", + "version": "[variables('analyticRuleVersion10')]" } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", - "name": "[variables('analyticRuleTemplateSpecName8')]", + "name": "[variables('dataConnectorTemplateSpecName1')]", "location": "[parameters('workspace-location')]", "dependsOn": [ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "SnowflakeQueryOnSensitiveTable_AnalyticalRules Analytics Rule with template version 3.0.0", + "description": "Snowflake data connector with template version 3.0.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion8')]", + "contentVersion": "[variables('dataConnectorVersion1')]", "parameters": {}, "variables": {}, "resources": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('analyticRulecontentId8')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId1'))]", + "apiVersion": "2021-03-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", "location": "[parameters('workspace-location')]", + "kind": "GenericUI", "properties": { - "description": "Detects query on sensitive or restricted table.", - "displayName": "Snowflake - Query on sensitive or restricted table", - "enabled": false, - "query": "let r_tbl = dynamic(['table_name']);\nSnowflake\n| where QUERY_TYPE_s =~ 'SELECT'\n| where EXECUTION_STATUS_s =~ 'SUCCESS'\n| extend tbl = extract(@'(FROM|from)\\s(\\S+)\\s', 2, QUERY_TEXT_s)\n| where tbl in~ (r_tbl)\n| extend AccountCustomEntity = TargetUsername\n", - "queryFrequency": "PT1H", - "queryPeriod": "PT1H", - "severity": "Medium", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 0, - "status": "Available", - "requiredDataConnectors": [ - { - "connectorId": "Snowflake", - "dataTypes": [ - "Snowflake" - ] - } - ], - "tactics": [ - "Collection" - ], - "techniques": [ - "T1119" - ], - "entityMappings": [ - { - "entityType": "Account", - "fieldMappings": [ - { - "columnName": "AccountCustomEntity", - "identifier": "Name" - } - ] - } - ] - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId8'),'/'))))]", - "properties": { - "description": "Snowflake Analytics Rule 8", - "parentId": "[variables('analyticRuleId8')]", - "contentId": "[variables('_analyticRulecontentId8')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion8')]", - "source": { - "kind": "Solution", - "name": "Snowflake", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" - }, - "support": { - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "tier": "Microsoft", - "link": "https://support.microsoft.com" - } - } - } - ] - }, - "packageKind": "Solution", - "packageVersion": "[variables('_solutionVersion')]", - "packageName": "[variables('_solutionName')]", - "packageId": "[variables('_solutionId')]", - "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_analyticRulecontentId8')]", - "contentKind": "AnalyticsRule", - "displayName": "Snowflake - Query on sensitive or restricted table", - "contentProductId": "[variables('_analyticRulecontentProductId8')]", - "id": "[variables('_analyticRulecontentProductId8')]", - "version": "[variables('analyticRuleVersion8')]" - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", - "apiVersion": "2023-04-01-preview", - "name": "[variables('analyticRuleTemplateSpecName9')]", - "location": "[parameters('workspace-location')]", - "dependsOn": [ - "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" - ], - "properties": { - "description": "SnowflakeUnusualQuery_AnalyticalRules Analytics Rule with template version 3.0.0", - "mainTemplate": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion9')]", - "parameters": {}, - "variables": {}, - "resources": [ - { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('analyticRulecontentId9')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", - "location": "[parameters('workspace-location')]", - "properties": { - "description": "Detects unusual query.", - "displayName": "Snowflake - Unusual query", - "enabled": false, - "query": "Snowflake\n| where QUERY_TYPE_s =~ 'SELECT'\n| where EXECUTION_STATUS_s =~ 'SUCCESS'\n| where QUERY_TEXT_s startswith @'SELECT *'\n| extend AccountCustomEntity = TargetUsername\n", - "queryFrequency": "PT1H", - "queryPeriod": "PT1H", - "severity": "Medium", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 0, - "status": "Available", - "requiredDataConnectors": [ - { - "connectorId": "Snowflake", - "dataTypes": [ - "Snowflake" - ] - } - ], - "tactics": [ - "Collection" - ], - "techniques": [ - "T1119" - ], - "entityMappings": [ - { - "entityType": "Account", - "fieldMappings": [ + "connectorUiConfig": { + "id": "[variables('_uiConfigId1')]", + "title": "Snowflake (using Azure Functions)", + "publisher": "Snowflake", + "descriptionMarkdown": "The Snowflake data connector provides the capability to ingest Snowflake [login logs](https://docs.snowflake.com/en/sql-reference/account-usage/login_history.html) and [query logs](https://docs.snowflake.com/en/sql-reference/account-usage/query_history.html) into Microsoft Sentinel using the Snowflake Python Connector. Refer to [Snowflake documentation](https://docs.snowflake.com/en/user-guide/python-connector.html) for more information.", + "additionalRequirementBanner": "This data connector depends on a parser based on a Kusto Function to work as expected [**Snowflake**](https://aka.ms/sentinel-SnowflakeDataConnector-parser) which is deployed with the Microsoft Sentinel Solution.", + "graphQueries": [ + { + "metricName": "Snowflake Events", + "legend": "Snowflake_CL", + "baseQuery": "Snowflake_CL" + } + ], + "sampleQueries": [ + { + "description": "All Snowflake Events", + "query": "Snowflake_CL\n| sort by TimeGenerated desc" + } + ], + "dataTypes": [ + { + "name": "Snowflake_CL", + "lastDataReceivedQuery": "Snowflake_CL\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" + } + ], + "connectivityCriterias": [ + { + "type": "IsConnectedQuery", + "value": [ + "Snowflake_CL\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(1d)" + ] + } + ], + "availability": { + "status": 1, + "isPreview": false + }, + "permissions": { + "resourceProvider": [ { - "columnName": "AccountCustomEntity", - "identifier": "Name" + "provider": "Microsoft.OperationalInsights/workspaces", + "permissionsDisplayText": "read and write permissions on the workspace are required.", + "providerDisplayName": "Workspace", + "scope": "Workspace", + "requiredPermissions": { + "write": true, + "read": true, + "delete": true + } + }, + { + "provider": "Microsoft.OperationalInsights/workspaces/sharedKeys", + "permissionsDisplayText": "read permissions to shared keys for the workspace are required. [See the documentation to learn more about workspace keys](https://docs.microsoft.com/azure/azure-monitor/platform/agent-windows#obtain-workspace-id-and-key).", + "providerDisplayName": "Keys", + "scope": "Workspace", + "requiredPermissions": { + "action": true + } + } + ], + "customs": [ + { + "name": "Microsoft.Web/sites permissions", + "description": "Read and write permissions to Azure Functions to create a Function App is required. [See the documentation to learn more about Azure Functions](https://docs.microsoft.com/azure/azure-functions/)." + }, + { + "name": "Snowflake Credentials", + "description": "**Snowflake Account Identifier**, **Snowflake User** and **Snowflake Password** are required for connection. See the documentation to learn more about [Snowflake Account Identifier](https://docs.snowflake.com/en/user-guide/admin-account-identifier.html#). Instructions on how to create user for this connector you can find below." } ] - } - ] + }, + "instructionSteps": [ + { + "description": ">**NOTE:** This connector uses Azure Functions to connect to the Azure Blob Storage API to pull logs into Microsoft Sentinel. This might result in additional costs for data ingestion and for storing data in Azure Blob Storage costs. Check the [Azure Functions pricing page](https://azure.microsoft.com/pricing/details/functions/) and [Azure Blob Storage pricing page](https://azure.microsoft.com/pricing/details/storage/blobs/) for details." + }, + { + "description": ">**(Optional Step)** Securely store workspace and API authorization key(s) or token(s) in Azure Key Vault. Azure Key Vault provides a secure mechanism to store and retrieve key values. [Follow these instructions](https://docs.microsoft.com/azure/app-service/app-service-key-vault-references) to use Azure Key Vault with an Azure Function App." + }, + { + "description": ">**NOTE:** This data connector depends on a parser based on a Kusto Function to work as expected [**Snowflake**](https://aka.ms/sentinel-SnowflakeDataConnector-parser) which is deployed with the Microsoft Sentinel Solution." + }, + { + "description": "**STEP 1 - Creating user in Snowflake**\n\nTo query data from Snowflake you need a user that is assigned to a role with sufficient privileges and a virtual warehouse cluster. The initial size of this cluster will be set to small but if it is insufficient, the cluster size can be increased as necessary.\n\n1. Enter the Snowflake console.\n2. Switch role to SECURITYADMIN and [create a new role](https://docs.snowflake.com/en/sql-reference/sql/create-role.html):\n```\nUSE ROLE SECURITYADMIN;\nCREATE OR REPLACE ROLE EXAMPLE_ROLE_NAME;```\n3. Switch role to SYSADMIN and [create warehouse](https://docs.snowflake.com/en/sql-reference/sql/create-warehouse.html) and [grand access](https://docs.snowflake.com/en/sql-reference/sql/grant-privilege.html) to it:\n```\nUSE ROLE SYSADMIN;\nCREATE OR REPLACE WAREHOUSE EXAMPLE_WAREHOUSE_NAME\n WAREHOUSE_SIZE = 'SMALL' \n AUTO_SUSPEND = 5\n AUTO_RESUME = true\n INITIALLY_SUSPENDED = true;\nGRANT USAGE, OPERATE ON WAREHOUSE EXAMPLE_WAREHOUSE_NAME TO ROLE EXAMPLE_ROLE_NAME;```\n4. Switch role to SECURITYADMIN and [create a new user](https://docs.snowflake.com/en/sql-reference/sql/create-user.html):\n```\nUSE ROLE SECURITYADMIN;\nCREATE OR REPLACE USER EXAMPLE_USER_NAME\n PASSWORD = 'example_password'\n DEFAULT_ROLE = EXAMPLE_ROLE_NAME\n DEFAULT_WAREHOUSE = EXAMPLE_WAREHOUSE_NAME\n;```\n5. Switch role to ACCOUNTADMIN and [grant access to snowflake database](https://docs.snowflake.com/en/sql-reference/account-usage.html#enabling-account-usage-for-other-roles) for role.\n```\nUSE ROLE ACCOUNTADMIN;\nGRANT IMPORTED PRIVILEGES ON DATABASE SNOWFLAKE TO ROLE EXAMPLE_ROLE_NAME;```\n6. Switch role to SECURITYADMIN and [assign role](https://docs.snowflake.com/en/sql-reference/sql/grant-role.html) to user:\n```\nUSE ROLE SECURITYADMIN;\nGRANT ROLE EXAMPLE_ROLE_NAME TO USER EXAMPLE_USER_NAME;```\n\n>**IMPORTANT:** Save user and API password created during this step as they will be used during deployment step." + }, + { + "description": "**STEP 2 - Choose ONE from the following two deployment options to deploy the connector and the associated Azure Function**\n\n>**IMPORTANT:** Before deploying the data connector, have the Workspace ID and Workspace Primary Key (can be copied from the following), as well as Snowflake credentials, readily available.", + "instructions": [ + { + "parameters": { + "fillWith": [ + "WorkspaceId" + ], + "label": "Workspace ID" + }, + "type": "CopyableLabel" + }, + { + "parameters": { + "fillWith": [ + "PrimaryKey" + ], + "label": "Primary Key" + }, + "type": "CopyableLabel" + } + ] + }, + { + "instructions": [ + { + "parameters": { + "instructionSteps": [ + { + "title": "Option 1 - Azure Resource Manager (ARM) Template", + "description": "Use this method for automated deployment of the data connector using an ARM Template.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://aka.ms/sentinel-SnowflakeDataConnector-azuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Snowflake Account Identifier**, **Snowflake User**, **Snowflake Password**, **Microsoft Sentinel Workspace Id**, **Microsoft Sentinel Shared Key**\n4. Mark the checkbox labeled **I agree to the terms and conditions stated above**.\n5. Click **Purchase** to deploy." + }, + { + "title": "Option 2 - Manual Deployment of Azure Functions", + "description": "Use the following step-by-step instructions to deploy the data connector manually with Azure Functions (Deployment via Visual Studio Code).", + "instructions": [ + { + "parameters": { + "instructionSteps": [ + { + "title": "Step 1 - Deploy a Function App", + "description": "1. Download the [Azure Function App](https://aka.ms/sentinel-SnowflakeDataConnector-functionapp) file. Extract archive to your local development computer.\n2. Follow the [function app manual deployment instructions](https://github.com/Azure/Azure-Sentinel/blob/master/DataConnectors/AzureFunctionsManualDeployment.md#function-app-manual-deployment-instructions) to deploy the Azure Functions app using VSCode.\n3. After successful deployment of the function app, follow next steps for configuring it." + }, + { + "title": "Step 2 - Configure the Function App", + "description": "1. Go to Azure Portal for the Function App configuration. \n2. In the Function App, select the Function App Name and select **Configuration**.\n3. In the **Application settings** tab, select **+ New application setting**.\n4. Add each of the following application settings individually, with their respective string values (case-sensitive): \n\t\tSNOWFLAKE_ACCOUNT\n\t\tSNOWFLAKE_USER\n\t\tSNOWFLAKE_PASSWORD\n\t\tWORKSPACE_ID\n\t\tSHARED_KEY\n\t\tlogAnalyticsUri (optional)\n - Use logAnalyticsUri to override the log analytics API endpoint for dedicated cloud. For example, for public cloud, leave the value empty; for Azure GovUS cloud environment, specify the value in the following format: `https://WORKSPACE_ID.ods.opinsights.azure.us`. \n4. Once all application settings have been entered, click **Save**." + } + ] + }, + "type": "InstructionStepsGroup" + } + ] + } + ] + }, + "type": "InstructionStepsGroup" + } + ] + } + ] + } } }, { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId9'),'/'))))]", + "apiVersion": "2023-04-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", "properties": { - "description": "Snowflake Analytics Rule 9", - "parentId": "[variables('analyticRuleId9')]", - "contentId": "[variables('_analyticRulecontentId9')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion9')]", + "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", + "contentId": "[variables('_dataConnectorContentId1')]", + "kind": "DataConnector", + "version": "[variables('dataConnectorVersion1')]", "source": { "kind": "Solution", "name": "Snowflake", @@ -1733,116 +1433,196 @@ "packageName": "[variables('_solutionName')]", "packageId": "[variables('_solutionId')]", "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_analyticRulecontentId9')]", - "contentKind": "AnalyticsRule", - "displayName": "Snowflake - Unusual query", - "contentProductId": "[variables('_analyticRulecontentProductId9')]", - "id": "[variables('_analyticRulecontentProductId9')]", - "version": "[variables('analyticRuleVersion9')]" + "contentId": "[variables('_dataConnectorContentId1')]", + "contentKind": "DataConnector", + "displayName": "Snowflake (using Azure Functions)", + "contentProductId": "[variables('_dataConnectorcontentProductId1')]", + "id": "[variables('_dataConnectorcontentProductId1')]", + "version": "[variables('dataConnectorVersion1')]" } }, { - "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", "apiVersion": "2023-04-01-preview", - "name": "[variables('analyticRuleTemplateSpecName10')]", - "location": "[parameters('workspace-location')]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", "dependsOn": [ - "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" + "[variables('_dataConnectorId1')]" ], + "location": "[parameters('workspace-location')]", "properties": { - "description": "SnowflakeUserAddAdminPrivileges_AnalyticalRules Analytics Rule with template version 3.0.0", - "mainTemplate": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('analyticRuleVersion10')]", - "parameters": {}, - "variables": {}, - "resources": [ + "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", + "contentId": "[variables('_dataConnectorContentId1')]", + "kind": "DataConnector", + "version": "[variables('dataConnectorVersion1')]", + "source": { + "kind": "Solution", + "name": "Snowflake", + "sourceId": "[variables('_solutionId')]" + }, + "author": { + "name": "Microsoft", + "email": "[variables('_email')]" + }, + "support": { + "name": "Microsoft Corporation", + "email": "support@microsoft.com", + "tier": "Microsoft", + "link": "https://support.microsoft.com" + } + } + }, + { + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId1'))]", + "apiVersion": "2021-03-01-preview", + "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", + "location": "[parameters('workspace-location')]", + "kind": "GenericUI", + "properties": { + "connectorUiConfig": { + "title": "Snowflake (using Azure Functions)", + "publisher": "Snowflake", + "descriptionMarkdown": "The Snowflake data connector provides the capability to ingest Snowflake [login logs](https://docs.snowflake.com/en/sql-reference/account-usage/login_history.html) and [query logs](https://docs.snowflake.com/en/sql-reference/account-usage/query_history.html) into Microsoft Sentinel using the Snowflake Python Connector. Refer to [Snowflake documentation](https://docs.snowflake.com/en/user-guide/python-connector.html) for more information.", + "graphQueries": [ { - "type": "Microsoft.SecurityInsights/AlertRuleTemplates", - "name": "[variables('analyticRulecontentId10')]", - "apiVersion": "2022-04-01-preview", - "kind": "Scheduled", - "location": "[parameters('workspace-location')]", - "properties": { - "description": "Detects when user asigned admin privileges.", - "displayName": "Snowflake - User granted admin privileges", - "enabled": false, - "query": "let adm_roles = dynamic(['SECURITYADMIN', 'SYSADMIN', 'ACCOUNTADMIN']);\nSnowflake\n| where QUERY_TYPE_s =~ 'GRANT'\n| where QUERY_TEXT_s startswith 'GRANT ROLE'\n| extend granted_role = extract(@'GRANT ROLE\\s(\\S+)\\sto\\suser', 1, QUERY_TEXT_s)\n| where granted_role in~ (adm_roles)\n| extend usr = extract(@'GRANT ROLE\\s(\\S+)\\sto\\suser(\\S+)', 2, QUERY_TEXT_s)\n| extend AccountCustomEntity = usr\n", - "queryFrequency": "PT1H", - "queryPeriod": "PT1H", - "severity": "Medium", - "suppressionDuration": "PT1H", - "suppressionEnabled": false, - "triggerOperator": "GreaterThan", - "triggerThreshold": 0, - "status": "Available", - "requiredDataConnectors": [ - { - "connectorId": "Snowflake", - "dataTypes": [ - "Snowflake" - ] - } - ], - "tactics": [ - "PrivilegeEscalation" - ], - "techniques": [ - "T1078" - ], - "entityMappings": [ - { - "entityType": "Account", - "fieldMappings": [ - { - "columnName": "AccountCustomEntity", - "identifier": "Name" - } - ] - } - ] + "metricName": "Snowflake Events", + "legend": "Snowflake_CL", + "baseQuery": "Snowflake_CL" + } + ], + "dataTypes": [ + { + "name": "Snowflake_CL", + "lastDataReceivedQuery": "Snowflake_CL\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" + } + ], + "connectivityCriterias": [ + { + "type": "IsConnectedQuery", + "value": [ + "Snowflake_CL\n | summarize LastLogReceived = max(TimeGenerated)\n | project IsConnected = LastLogReceived > ago(1d)" + ] + } + ], + "sampleQueries": [ + { + "description": "All Snowflake Events", + "query": "Snowflake_CL\n| sort by TimeGenerated desc" + } + ], + "availability": { + "status": 1, + "isPreview": false + }, + "permissions": { + "resourceProvider": [ + { + "provider": "Microsoft.OperationalInsights/workspaces", + "permissionsDisplayText": "read and write permissions on the workspace are required.", + "providerDisplayName": "Workspace", + "scope": "Workspace", + "requiredPermissions": { + "write": true, + "read": true, + "delete": true + } + }, + { + "provider": "Microsoft.OperationalInsights/workspaces/sharedKeys", + "permissionsDisplayText": "read permissions to shared keys for the workspace are required. [See the documentation to learn more about workspace keys](https://docs.microsoft.com/azure/azure-monitor/platform/agent-windows#obtain-workspace-id-and-key).", + "providerDisplayName": "Keys", + "scope": "Workspace", + "requiredPermissions": { + "action": true + } } + ], + "customs": [ + { + "name": "Microsoft.Web/sites permissions", + "description": "Read and write permissions to Azure Functions to create a Function App is required. [See the documentation to learn more about Azure Functions](https://docs.microsoft.com/azure/azure-functions/)." + }, + { + "name": "Snowflake Credentials", + "description": "**Snowflake Account Identifier**, **Snowflake User** and **Snowflake Password** are required for connection. See the documentation to learn more about [Snowflake Account Identifier](https://docs.snowflake.com/en/user-guide/admin-account-identifier.html#). Instructions on how to create user for this connector you can find below." + } + ] + }, + "instructionSteps": [ + { + "description": ">**NOTE:** This connector uses Azure Functions to connect to the Azure Blob Storage API to pull logs into Microsoft Sentinel. This might result in additional costs for data ingestion and for storing data in Azure Blob Storage costs. Check the [Azure Functions pricing page](https://azure.microsoft.com/pricing/details/functions/) and [Azure Blob Storage pricing page](https://azure.microsoft.com/pricing/details/storage/blobs/) for details." }, { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2022-01-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('AnalyticsRule-', last(split(variables('analyticRuleId10'),'/'))))]", - "properties": { - "description": "Snowflake Analytics Rule 10", - "parentId": "[variables('analyticRuleId10')]", - "contentId": "[variables('_analyticRulecontentId10')]", - "kind": "AnalyticsRule", - "version": "[variables('analyticRuleVersion10')]", - "source": { - "kind": "Solution", - "name": "Snowflake", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" + "description": ">**(Optional Step)** Securely store workspace and API authorization key(s) or token(s) in Azure Key Vault. Azure Key Vault provides a secure mechanism to store and retrieve key values. [Follow these instructions](https://docs.microsoft.com/azure/app-service/app-service-key-vault-references) to use Azure Key Vault with an Azure Function App." + }, + { + "description": ">**NOTE:** This data connector depends on a parser based on a Kusto Function to work as expected [**Snowflake**](https://aka.ms/sentinel-SnowflakeDataConnector-parser) which is deployed with the Microsoft Sentinel Solution." + }, + { + "description": "**STEP 1 - Creating user in Snowflake**\n\nTo query data from Snowflake you need a user that is assigned to a role with sufficient privileges and a virtual warehouse cluster. The initial size of this cluster will be set to small but if it is insufficient, the cluster size can be increased as necessary.\n\n1. Enter the Snowflake console.\n2. Switch role to SECURITYADMIN and [create a new role](https://docs.snowflake.com/en/sql-reference/sql/create-role.html):\n```\nUSE ROLE SECURITYADMIN;\nCREATE OR REPLACE ROLE EXAMPLE_ROLE_NAME;```\n3. Switch role to SYSADMIN and [create warehouse](https://docs.snowflake.com/en/sql-reference/sql/create-warehouse.html) and [grand access](https://docs.snowflake.com/en/sql-reference/sql/grant-privilege.html) to it:\n```\nUSE ROLE SYSADMIN;\nCREATE OR REPLACE WAREHOUSE EXAMPLE_WAREHOUSE_NAME\n WAREHOUSE_SIZE = 'SMALL' \n AUTO_SUSPEND = 5\n AUTO_RESUME = true\n INITIALLY_SUSPENDED = true;\nGRANT USAGE, OPERATE ON WAREHOUSE EXAMPLE_WAREHOUSE_NAME TO ROLE EXAMPLE_ROLE_NAME;```\n4. Switch role to SECURITYADMIN and [create a new user](https://docs.snowflake.com/en/sql-reference/sql/create-user.html):\n```\nUSE ROLE SECURITYADMIN;\nCREATE OR REPLACE USER EXAMPLE_USER_NAME\n PASSWORD = 'example_password'\n DEFAULT_ROLE = EXAMPLE_ROLE_NAME\n DEFAULT_WAREHOUSE = EXAMPLE_WAREHOUSE_NAME\n;```\n5. Switch role to ACCOUNTADMIN and [grant access to snowflake database](https://docs.snowflake.com/en/sql-reference/account-usage.html#enabling-account-usage-for-other-roles) for role.\n```\nUSE ROLE ACCOUNTADMIN;\nGRANT IMPORTED PRIVILEGES ON DATABASE SNOWFLAKE TO ROLE EXAMPLE_ROLE_NAME;```\n6. Switch role to SECURITYADMIN and [assign role](https://docs.snowflake.com/en/sql-reference/sql/grant-role.html) to user:\n```\nUSE ROLE SECURITYADMIN;\nGRANT ROLE EXAMPLE_ROLE_NAME TO USER EXAMPLE_USER_NAME;```\n\n>**IMPORTANT:** Save user and API password created during this step as they will be used during deployment step." + }, + { + "description": "**STEP 2 - Choose ONE from the following two deployment options to deploy the connector and the associated Azure Function**\n\n>**IMPORTANT:** Before deploying the data connector, have the Workspace ID and Workspace Primary Key (can be copied from the following), as well as Snowflake credentials, readily available.", + "instructions": [ + { + "parameters": { + "fillWith": [ + "WorkspaceId" + ], + "label": "Workspace ID" + }, + "type": "CopyableLabel" }, - "support": { - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "tier": "Microsoft", - "link": "https://support.microsoft.com" + { + "parameters": { + "fillWith": [ + "PrimaryKey" + ], + "label": "Primary Key" + }, + "type": "CopyableLabel" } - } - } - ] - }, - "packageKind": "Solution", - "packageVersion": "[variables('_solutionVersion')]", - "packageName": "[variables('_solutionName')]", - "packageId": "[variables('_solutionId')]", - "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_analyticRulecontentId10')]", - "contentKind": "AnalyticsRule", - "displayName": "Snowflake - User granted admin privileges", - "contentProductId": "[variables('_analyticRulecontentProductId10')]", - "id": "[variables('_analyticRulecontentProductId10')]", - "version": "[variables('analyticRuleVersion10')]" + ] + }, + { + "instructions": [ + { + "parameters": { + "instructionSteps": [ + { + "title": "Option 1 - Azure Resource Manager (ARM) Template", + "description": "Use this method for automated deployment of the data connector using an ARM Template.\n\n1. Click the **Deploy to Azure** button below. \n\n\t[![Deploy To Azure](https://aka.ms/deploytoazurebutton)](https://aka.ms/sentinel-SnowflakeDataConnector-azuredeploy)\n2. Select the preferred **Subscription**, **Resource Group** and **Location**. \n3. Enter the **Snowflake Account Identifier**, **Snowflake User**, **Snowflake Password**, **Microsoft Sentinel Workspace Id**, **Microsoft Sentinel Shared Key**\n4. Mark the checkbox labeled **I agree to the terms and conditions stated above**.\n5. Click **Purchase** to deploy." + }, + { + "title": "Option 2 - Manual Deployment of Azure Functions", + "description": "Use the following step-by-step instructions to deploy the data connector manually with Azure Functions (Deployment via Visual Studio Code).", + "instructions": [ + { + "parameters": { + "instructionSteps": [ + { + "title": "Step 1 - Deploy a Function App", + "description": "1. Download the [Azure Function App](https://aka.ms/sentinel-SnowflakeDataConnector-functionapp) file. Extract archive to your local development computer.\n2. Follow the [function app manual deployment instructions](https://github.com/Azure/Azure-Sentinel/blob/master/DataConnectors/AzureFunctionsManualDeployment.md#function-app-manual-deployment-instructions) to deploy the Azure Functions app using VSCode.\n3. After successful deployment of the function app, follow next steps for configuring it." + }, + { + "title": "Step 2 - Configure the Function App", + "description": "1. Go to Azure Portal for the Function App configuration. \n2. In the Function App, select the Function App Name and select **Configuration**.\n3. In the **Application settings** tab, select **+ New application setting**.\n4. Add each of the following application settings individually, with their respective string values (case-sensitive): \n\t\tSNOWFLAKE_ACCOUNT\n\t\tSNOWFLAKE_USER\n\t\tSNOWFLAKE_PASSWORD\n\t\tWORKSPACE_ID\n\t\tSHARED_KEY\n\t\tlogAnalyticsUri (optional)\n - Use logAnalyticsUri to override the log analytics API endpoint for dedicated cloud. For example, for public cloud, leave the value empty; for Azure GovUS cloud environment, specify the value in the following format: `https://WORKSPACE_ID.ods.opinsights.azure.us`. \n4. Once all application settings have been entered, click **Save**." + } + ] + }, + "type": "InstructionStepsGroup" + } + ] + } + ] + }, + "type": "InstructionStepsGroup" + } + ] + } + ], + "id": "[variables('_uiConfigId1')]", + "additionalRequirementBanner": "This data connector depends on a parser based on a Kusto Function to work as expected [**Snowflake**](https://aka.ms/sentinel-SnowflakeDataConnector-parser) which is deployed with the Microsoft Sentinel Solution." + } } }, { @@ -2695,6 +2475,226 @@ "version": "[variables('huntingQueryVersion10')]" } }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('parserTemplateSpecName1')]", + "location": "[parameters('workspace-location')]", + "dependsOn": [ + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" + ], + "properties": { + "description": "Snowflake Data Parser with template version 3.0.0", + "mainTemplate": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "[variables('parserVersion1')]", + "parameters": {}, + "variables": {}, + "resources": [ + { + "name": "[variables('_parserName1')]", + "apiVersion": "2022-10-01", + "type": "Microsoft.OperationalInsights/workspaces/savedSearches", + "location": "[parameters('workspace-location')]", + "properties": { + "eTag": "*", + "displayName": "Snowflake Data Parser", + "category": "Microsoft Sentinel Parser", + "functionAlias": "Snowflake", + "query": "Snowflake_CL\n| extend EventVendor = 'Snowflake'\n| extend EventProduct = 'Snowflake'\n| project-rename \n EventStartTime=START_TIME_t,\n EventType=EVENT_TYPE_s,\n TargetUsername=USER_NAME_s,\n SrcDvcIpAddr=CLIENT_IP_s\n| extend \n User=TargetUsername,\n EventEndTime=iff(isnotempty(EVENT_TIMESTAMP_t), EVENT_TIMESTAMP_t, END_TIME_t)\n", + "functionParameters": "", + "version": 2, + "tags": [ + { + "name": "description", + "value": "" + } + ] + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "apiVersion": "2022-01-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Parser-', last(split(variables('_parserId1'),'/'))))]", + "dependsOn": [ + "[variables('_parserName1')]" + ], + "properties": { + "parentId": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), variables('parserName1'))]", + "contentId": "[variables('_parserContentId1')]", + "kind": "Parser", + "version": "[variables('parserVersion1')]", + "source": { + "name": "Snowflake", + "kind": "Solution", + "sourceId": "[variables('_solutionId')]" + }, + "author": { + "name": "Microsoft", + "email": "[variables('_email')]" + }, + "support": { + "name": "Microsoft Corporation", + "email": "support@microsoft.com", + "tier": "Microsoft", + "link": "https://support.microsoft.com" + } + } + } + ] + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_parserContentId1')]", + "contentKind": "Parser", + "displayName": "Snowflake Data Parser", + "contentProductId": "[variables('_parsercontentProductId1')]", + "id": "[variables('_parsercontentProductId1')]", + "version": "[variables('parserVersion1')]" + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/savedSearches", + "apiVersion": "2022-10-01", + "name": "[variables('_parserName1')]", + "location": "[parameters('workspace-location')]", + "properties": { + "eTag": "*", + "displayName": "Snowflake Data Parser", + "category": "Microsoft Sentinel Parser", + "functionAlias": "Snowflake", + "query": "Snowflake_CL\n| extend EventVendor = 'Snowflake'\n| extend EventProduct = 'Snowflake'\n| project-rename \n EventStartTime=START_TIME_t,\n EventType=EVENT_TYPE_s,\n TargetUsername=USER_NAME_s,\n SrcDvcIpAddr=CLIENT_IP_s\n| extend \n User=TargetUsername,\n EventEndTime=iff(isnotempty(EVENT_TIMESTAMP_t), EVENT_TIMESTAMP_t, END_TIME_t)\n", + "functionParameters": "", + "version": 2, + "tags": [ + { + "name": "description", + "value": "" + } + ] + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "apiVersion": "2022-01-01-preview", + "location": "[parameters('workspace-location')]", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Parser-', last(split(variables('_parserId1'),'/'))))]", + "dependsOn": [ + "[variables('_parserId1')]" + ], + "properties": { + "parentId": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('workspace'), variables('parserName1'))]", + "contentId": "[variables('_parserContentId1')]", + "kind": "Parser", + "version": "[variables('parserVersion1')]", + "source": { + "kind": "Solution", + "name": "Snowflake", + "sourceId": "[variables('_solutionId')]" + }, + "author": { + "name": "Microsoft", + "email": "[variables('_email')]" + }, + "support": { + "name": "Microsoft Corporation", + "email": "support@microsoft.com", + "tier": "Microsoft", + "link": "https://support.microsoft.com" + } + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[variables('workbookTemplateSpecName1')]", + "location": "[parameters('workspace-location')]", + "dependsOn": [ + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" + ], + "properties": { + "description": "SnowflakeWorkbook Workbook with template version 3.0.0", + "mainTemplate": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "[variables('workbookVersion1')]", + "parameters": {}, + "variables": {}, + "resources": [ + { + "type": "Microsoft.Insights/workbooks", + "name": "[variables('workbookContentId1')]", + "location": "[parameters('workspace-location')]", + "kind": "shared", + "apiVersion": "2021-08-01", + "metadata": { + "description": "Sets the time name for analysis" + }, + "properties": { + "displayName": "[parameters('workbook1-name')]", + "serializedData": "{\"version\":\"Notebook/1.0\",\"items\":[{\"type\":1,\"content\":{\"json\":\"**NOTE**: This data connector depends on a parser based on Kusto Function **Snowflake** to work as expected. [Follow steps to get this Kusto Function](https://aka.ms/sentinel-SnowflakeDataConnector-parser)\"},\"name\":\"text - 8\"},{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"parameters\":[{\"id\":\"cd8447d9-b096-4673-92d8-2a1e8291a125\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"TimeRange\",\"type\":4,\"description\":\"Sets the time name for analysis\",\"value\":{\"durationMs\":7776000000},\"typeSettings\":{\"selectableValues\":[{\"durationMs\":1800000},{\"durationMs\":3600000},{\"durationMs\":86400000},{\"durationMs\":604800000},{\"durationMs\":2592000000},{\"durationMs\":7776000000}]},\"timeContext\":{\"durationMs\":86400000}}],\"style\":\"pills\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"parameters - 11\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\r\\n| make-series TotalEvents = count() default = 0 on TimeGenerated from {TimeRange:start} to {TimeRange:end} step {TimeRange:grain};\",\"size\":0,\"title\":\"Events Over Time\",\"color\":\"green\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"timechart\",\"graphSettings\":{\"type\":0}},\"customWidth\":\"60\",\"name\":\"query - 12\",\"styleSettings\":{\"maxWidth\":\"55\"}},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(DATABASE_NAME_s)\\n| summarize dcount(DATABASE_NAME_s)\",\"size\":3,\"title\":\"Total Databases\",\"timeContext\":{\"durationMs\":7776000000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"50\",\"name\":\"query - 1\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(source_table_s)\\n| summarize dcount(source_table_s)\",\"size\":3,\"title\":\"Total Tables\",\"timeContext\":{\"durationMs\":7776000000},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"50\",\"name\":\"query - 2\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| summarize s=sum(EXECUTION_TIME_d)\\n| project s_time = strcat(s/1000, ' sec')\",\"size\":3,\"title\":\"Total Query Time\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"30\",\"name\":\"query - 0\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(QUERY_TYPE_s)\\n| summarize count()\",\"size\":3,\"title\":\"Total Queries Run\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"30\",\"name\":\"query - 3\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| summarize cs = sum(CREDITS_USED_CLOUD_SERVICES_d)\\n| project round(cs, 8)\",\"size\":3,\"title\":\"Credits Spent\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"card\",\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"40\",\"name\":\"query - 4\"}]},\"customWidth\":\"40\",\"name\":\"group - 0\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(source_table_s)\\n| summarize count() by source_table_s\",\"size\":3,\"title\":\"Table Events Summary\",\"color\":\"orange\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"tiles\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"source_table_s\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"count_\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"maximumSignificantDigits\":3,\"maximumFractionDigits\":2}}},\"showBorder\":false}},\"customWidth\":\"50\",\"name\":\"query - 0\",\"styleSettings\":{\"showBorder\":true}},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(DATABASE_NAME_s)\\n| summarize count() by DATABASE_NAME_s\",\"size\":3,\"title\":\"Database Events Summary\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"tiles\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"DATABASE_NAME_s\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"count_\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"style\":\"decimal\",\"maximumFractionDigits\":2,\"maximumSignificantDigits\":3}}},\"showBorder\":false}},\"customWidth\":\"50\",\"name\":\"query - 1\",\"styleSettings\":{\"showBorder\":true}}]},\"customWidth\":\"30\",\"name\":\"group - 11\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where isnotempty(SrcDvcIpAddr)\\n| summarize count() by SrcDvcIpAddr\",\"size\":3,\"title\":\"Source Addresses\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"piechart\"},\"customWidth\":\"30\",\"name\":\"query - 9\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where EXECUTION_TIME_d > 0\\n| top 10 by EXECUTION_TIME_d desc\\n| project Query=QUERY_TEXT_s, User=TargetUsername, ExecutionTime=EXECUTION_TIME_d\\n\",\"size\":0,\"title\":\"Query Execution Time\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"ExecutionTime\",\"formatter\":8,\"formatOptions\":{\"palette\":\"coldHot\"}}]}},\"customWidth\":\"35\",\"name\":\"query - 11\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n| where CREDITS_USED_CLOUD_SERVICES_d > 0\\n| summarize by QUERY_TEXT_s, CREDITS_USED_CLOUD_SERVICES_d\\n| top 10 by CREDITS_USED_CLOUD_SERVICES_d desc\\n| project Query=QUERY_TEXT_s, CreditsSpent=CREDITS_USED_CLOUD_SERVICES_d\",\"size\":0,\"title\":\"Credits Spent by Queriws\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"CreditsSpent\",\"formatter\":8,\"formatOptions\":{\"palette\":\"coldHot\",\"compositeBarSettings\":{\"labelText\":\"\"}},\"numberFormat\":{\"unit\":0,\"options\":{\"style\":\"decimal\",\"maximumFractionDigits\":10}}}]}},\"customWidth\":\"35\",\"name\":\"query - 9\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\r\\n| where QUERY_TYPE_s == 'CREATE_USER'\\r\\n| extend n_usr = extract(@'USER\\\\s(\\\\S+)', 1, QUERY_TEXT_s)\\r\\n| project Username=n_usr\",\"size\":0,\"title\":\"New Users\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"URL Category\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"count_\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"style\":\"decimal\",\"maximumFractionDigits\":2,\"maximumSignificantDigits\":3}}},\"secondaryContent\":{\"columnMatch\":\"Trend\",\"formatter\":9,\"formatOptions\":{\"palette\":\"purple\"}},\"showBorder\":false},\"textSettings\":{\"style\":\"bignumber\"}},\"customWidth\":\"20\",\"name\":\"query - 0\",\"styleSettings\":{\"maxWidth\":\"30\"}},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"Snowflake\\n\\n| where QUERY_TYPE_s =~ 'SELECT'\\n| summarize roles = makeset(ROLE_NAME_s) by TargetUsername\\n| join(Snowflake\\n | where EventType =~ 'LOGIN') on TargetUsername\\n| project EventTime=TimeGenerated, TargetUsername, SourceAddress=SrcDvcIpAddr, Status=strcat(iif(IS_SUCCESS_s =~ 'No', '❌ - Login Failure' , '✅ - Logged in'))\",\"size\":0,\"title\":\"Privileged Sessions\",\"timeContext\":{\"durationMs\":0},\"timeContextFromParameter\":\"TimeRange\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"visualization\":\"table\",\"tileSettings\":{\"titleContent\":{\"columnMatch\":\"User\",\"formatter\":1},\"leftContent\":{\"columnMatch\":\"TotalMailsReceived\",\"formatter\":12,\"formatOptions\":{\"palette\":\"auto\"},\"numberFormat\":{\"unit\":17,\"options\":{\"maximumSignificantDigits\":3,\"maximumFractionDigits\":2}}},\"secondaryContent\":{\"columnMatch\":\"Trend\",\"formatter\":10,\"formatOptions\":{\"palette\":\"magenta\"}},\"showBorder\":false}},\"customWidth\":\"45\",\"name\":\"query - 10\"}],\"fromTemplateId\":\"sentinel-SnowflakeWorkbook\",\"$schema\":\"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"}\r\n", + "version": "1.0", + "sourceId": "[variables('workspaceResourceId')]", + "category": "sentinel" + } + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", + "apiVersion": "2022-01-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Workbook-', last(split(variables('workbookId1'),'/'))))]", + "properties": { + "description": "@{workbookKey=SnowflakeWorkbook; logoFileName=Azure_Sentinel.svg; description=Sets the time name for analysis; dataTypesDependencies=System.Object[]; dataConnectorsDependencies=System.Object[]; previewImagesFileNames=System.Object[]; version=1.0.0; title=Snowflake; templateRelativePath=Snowflake.json; subtitle=; provider=Snowflake}.description", + "parentId": "[variables('workbookId1')]", + "contentId": "[variables('_workbookContentId1')]", + "kind": "Workbook", + "version": "[variables('workbookVersion1')]", + "source": { + "kind": "Solution", + "name": "Snowflake", + "sourceId": "[variables('_solutionId')]" + }, + "author": { + "name": "Microsoft", + "email": "[variables('_email')]" + }, + "support": { + "name": "Microsoft Corporation", + "email": "support@microsoft.com", + "tier": "Microsoft", + "link": "https://support.microsoft.com" + }, + "dependencies": { + "operator": "AND", + "criteria": [ + { + "contentId": "Snowflake_CL", + "kind": "DataType" + }, + { + "contentId": "SnowflakeDataConnector", + "kind": "DataConnector" + } + ] + } + } + } + ] + }, + "packageKind": "Solution", + "packageVersion": "[variables('_solutionVersion')]", + "packageName": "[variables('_solutionName')]", + "packageId": "[variables('_solutionId')]", + "contentSchemaVersion": "3.0.0", + "contentId": "[variables('_workbookContentId1')]", + "contentKind": "Workbook", + "displayName": "[parameters('workbook1-name')]", + "contentProductId": "[variables('_workbookcontentProductId1')]", + "id": "[variables('_workbookcontentProductId1')]", + "version": "[variables('workbookVersion1')]" + } + }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentPackages", "apiVersion": "2023-04-01-preview", @@ -2730,21 +2730,6 @@ "dependencies": { "operator": "AND", "criteria": [ - { - "kind": "DataConnector", - "contentId": "[variables('_dataConnectorContentId1')]", - "version": "[variables('dataConnectorVersion1')]" - }, - { - "kind": "Parser", - "contentId": "[variables('_parserContentId1')]", - "version": "[variables('parserVersion1')]" - }, - { - "kind": "Workbook", - "contentId": "[variables('_workbookContentId1')]", - "version": "[variables('workbookVersion1')]" - }, { "kind": "AnalyticsRule", "contentId": "[variables('analyticRulecontentId1')]", @@ -2795,6 +2780,11 @@ "contentId": "[variables('analyticRulecontentId10')]", "version": "[variables('analyticRuleVersion10')]" }, + { + "kind": "DataConnector", + "contentId": "[variables('_dataConnectorContentId1')]", + "version": "[variables('dataConnectorVersion1')]" + }, { "kind": "HuntingQuery", "contentId": "[variables('_huntingQuerycontentId1')]", @@ -2844,6 +2834,16 @@ "kind": "HuntingQuery", "contentId": "[variables('_huntingQuerycontentId10')]", "version": "[variables('huntingQueryVersion10')]" + }, + { + "kind": "Parser", + "contentId": "[variables('_parserContentId1')]", + "version": "[variables('parserVersion1')]" + }, + { + "kind": "Workbook", + "contentId": "[variables('_workbookContentId1')]", + "version": "[variables('workbookVersion1')]" } ] }, diff --git a/Solutions/Snowflake/Parsers/Snowflake.txt b/Solutions/Snowflake/Parsers/Snowflake.txt deleted file mode 100644 index 8c9e0cca29c..00000000000 --- a/Solutions/Snowflake/Parsers/Snowflake.txt +++ /dev/null @@ -1,15 +0,0 @@ -// Usage Instruction : -// Paste below query in log analytics, click on Save button and select as Function from drop down by specifying function name and alias as Snowflake. -// Function usually takes 10-15 minutes to activate. You can then use function alias from any other queries (e.g. Snowflake | take 10). -// Reference : Using functions in Azure monitor log queries : https://docs.microsoft.com/azure/azure-monitor/log-query/functions -Snowflake_CL -| extend EventVendor = 'Snowflake' -| extend EventProduct = 'Snowflake' -| project-rename - EventStartTime=START_TIME_t, - EventType=EVENT_TYPE_s, - TargetUsername=USER_NAME_s, - SrcDvcIpAddr=CLIENT_IP_s -| extend - User=TargetUsername, - EventEndTime=iff(isnotempty(EVENT_TIMESTAMP_t), EVENT_TIMESTAMP_t, END_TIME_t) \ No newline at end of file diff --git a/Solutions/Snowflake/ReleaseNotes.md b/Solutions/Snowflake/ReleaseNotes.md new file mode 100644 index 00000000000..b759abdc0a8 --- /dev/null +++ b/Solutions/Snowflake/ReleaseNotes.md @@ -0,0 +1,5 @@ +| **Version** | **Date Modified (DD-MM-YYYY)** | **Change History** | +|-------------|--------------------------------|--------------------------------------------------------------------| +| 3.0.0 | 31-08-2023 | Manual deployment instructions updated for **Data Connector** | +| | | Convert **Parser** file from text to yaml | +