diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1ff0c42
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b06e864
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,212 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+build/
+bld/
+[Bb]in/
+[Oo]bj/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+## TODO: Comment the next line if you want to checkin your
+## web deploy settings but do note that will include unencrypted
+## passwords
+#*.pubxml
+
+*.publishproj
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+
+# Windows Azure Build Output
+csx/
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# LightSwitch generated files
+GeneratedArtifacts/
+_Pvt_Extensions/
+ModelManifest.xml
diff --git a/IaC/O365Hack_IaC.sln b/IaC/O365Hack_IaC.sln
new file mode 100644
index 0000000..51fd7c6
--- /dev/null
+++ b/IaC/O365Hack_IaC.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.23107.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{151D2E53-A2C4-4D7D-83FE-D05416EBD58E}") = "O365Hack_IaC", "O365Hack_IaC\O365Hack_IaC.deployproj", "{1B29A138-5428-49FE-9898-64415733DFB5}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1B29A138-5428-49FE-9898-64415733DFB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1B29A138-5428-49FE-9898-64415733DFB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1B29A138-5428-49FE-9898-64415733DFB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1B29A138-5428-49FE-9898-64415733DFB5}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/IaC/O365Hack_IaC/Deployment.targets b/IaC/O365Hack_IaC/Deployment.targets
new file mode 100644
index 0000000..4616e6b
--- /dev/null
+++ b/IaC/O365Hack_IaC/Deployment.targets
@@ -0,0 +1,123 @@
+
+
+
+ Debug
+ AnyCPU
+ bin\$(Configuration)\
+ false
+ true
+ false
+ None
+ obj\
+ $(BaseIntermediateOutputPath)\
+ $(BaseIntermediateOutputPath)$(Configuration)\
+ $(IntermediateOutputPath)ProjectReferences
+ $(ProjectReferencesOutputPath)\
+ true
+
+
+
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+ Never
+
+
+ false
+ Build
+
+
+
+
+
+
+
+ _GetDeploymentProjectContent;
+ _CalculateContentOutputRelativePaths;
+ _GetReferencedProjectsOutput;
+ _CalculateArtifactStagingDirectory;
+ _CopyOutputToArtifactStagingDirectory;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Configuration=$(Configuration);Platform=$(Platform)
+
+
+
+
+
+
+ $([System.IO.Path]::GetFileNameWithoutExtension('%(ProjectReference.Identity)'))
+
+
+
+
+
+
+ $(OutDir)
+ $(OutputPath)
+ $(ArtifactStagingDirectory)\
+ $(ArtifactStagingDirectory)staging\
+ $(Build_StagingDirectory)
+
+
+
+
+
+
+ <_OriginalIdentity>%(DeploymentProjectContentOutput.Identity)
+ <_RelativePath>$(_OriginalIdentity.Replace('$(MSBuildProjectDirectory)', ''))
+
+
+
+
+ $(_RelativePath)
+
+
+
+
+
+
+
+
+ PrepareForRun
+
+
+
+
+
+
+
+
+
+
+
diff --git a/IaC/O365Hack_IaC/O365Hack_IaC.deployproj b/IaC/O365Hack_IaC/O365Hack_IaC.deployproj
new file mode 100644
index 0000000..9c35505
--- /dev/null
+++ b/IaC/O365Hack_IaC/O365Hack_IaC.deployproj
@@ -0,0 +1,59 @@
+
+
+
+
+ Debug
+ AnyCPU
+
+
+ Release
+ AnyCPU
+
+
+
+ 1b29a138-5428-49fe-9898-64415733dfb5
+
+
+ Deployment
+ 1.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ False
+
+
+
+
+
+
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+
+
\ No newline at end of file
diff --git a/IaC/O365Hack_IaC/Scripts/Deploy-AzureResourceGroup.ps1 b/IaC/O365Hack_IaC/Scripts/Deploy-AzureResourceGroup.ps1
new file mode 100644
index 0000000..af71f1c
--- /dev/null
+++ b/IaC/O365Hack_IaC/Scripts/Deploy-AzureResourceGroup.ps1
@@ -0,0 +1,111 @@
+#Requires -Version 3.0
+
+Param(
+ [string] [Parameter(Mandatory=$true)] $ResourceGroupLocation,
+ [string] $ResourceGroupName = 'O365Hack_IaC',
+ [switch] $UploadArtifacts,
+ [string] $StorageAccountName,
+ [string] $StorageAccountResourceGroupName,
+ [string] $StorageContainerName = $ResourceGroupName.ToLowerInvariant() + '-stageartifacts',
+ [string] $TemplateFile = '..\Templates\WebSite.json',
+ [string] $TemplateParametersFile = '..\Templates\WebSite.param.dev.json',
+ [string] $ArtifactStagingDirectory = '..\bin\Debug\staging',
+ [string] $AzCopyPath = '..\Tools\AzCopy.exe',
+ [string] $DSCSourceFolder = '..\DSC'
+)
+
+if (Get-Module -ListAvailable | Where-Object { $_.Name -eq 'AzureResourceManager' -and $_.Version -ge '0.9.9' }) {
+ Throw "The version of the Azure PowerShell cmdlets installed on this machine are not compatible with this script. For help updating this script visit: http://go.microsoft.com/fwlink/?LinkID=623011"
+}
+
+Import-Module Azure -ErrorAction SilentlyContinue
+
+try {
+ [Microsoft.Azure.Common.Authentication.AzureSession]::ClientFactory.AddUserAgent("VSAzureTools-$UI$($host.name)".replace(" ","_"), "2.7.1")
+} catch { }
+
+Set-StrictMode -Version 3
+
+$OptionalParameters = New-Object -TypeName Hashtable
+$TemplateFile = [System.IO.Path]::Combine($PSScriptRoot, $TemplateFile)
+$TemplateParametersFile = [System.IO.Path]::Combine($PSScriptRoot, $TemplateParametersFile)
+
+if ($UploadArtifacts)
+{
+ # Convert relative paths to absolute paths if needed
+ $AzCopyPath = [System.IO.Path]::Combine($PSScriptRoot, $AzCopyPath)
+ $ArtifactStagingDirectory = [System.IO.Path]::Combine($PSScriptRoot, $ArtifactStagingDirectory)
+ $DSCSourceFolder = [System.IO.Path]::Combine($PSScriptRoot, $DSCSourceFolder)
+
+ Set-Variable ArtifactsLocationName '_artifactsLocation' -Option ReadOnly
+ Set-Variable ArtifactsLocationSasTokenName '_artifactsLocationSasToken' -Option ReadOnly
+
+ $OptionalParameters.Add($ArtifactsLocationName, $null)
+ $OptionalParameters.Add($ArtifactsLocationSasTokenName, $null)
+
+ # Parse the parameter file and update the values of artifacts location and artifacts location SAS token if they are present
+ $JsonContent = Get-Content $TemplateParametersFile -Raw | ConvertFrom-Json
+ $JsonParameters = $JsonContent | Get-Member -Type NoteProperty | Where-Object {$_.Name -eq "parameters"}
+
+ if ($JsonParameters -eq $null) {
+ $JsonParameters = $JsonContent
+ }
+ else {
+ $JsonParameters = $JsonContent.parameters
+ }
+
+ $JsonParameters | Get-Member -Type NoteProperty | ForEach-Object {
+ $ParameterValue = $JsonParameters | Select-Object -ExpandProperty $_.Name
+
+ if ($_.Name -eq $ArtifactsLocationName -or $_.Name -eq $ArtifactsLocationSasTokenName) {
+ $OptionalParameters[$_.Name] = $ParameterValue.value
+ }
+ }
+
+ if ($StorageAccountResourceGroupName) {
+ Switch-AzureMode AzureResourceManager
+ $StorageAccountKey = (Get-AzureStorageAccountKey -ResourceGroupName $StorageAccountResourceGroupName -Name $StorageAccountName).Key1
+ }
+ else {
+ Switch-AzureMode AzureServiceManagement
+ $StorageAccountKey = (Get-AzureStorageKey -StorageAccountName $StorageAccountName).Primary
+ }
+
+ $StorageAccountContext = New-AzureStorageContext -StorageAccountName $StorageAccountName -StorageAccountKey $StorageAccountKey
+
+ # Create DSC configuration archive
+ if (Test-Path $DSCSourceFolder) {
+ Add-Type -Assembly System.IO.Compression.FileSystem
+ $ArchiveFile = Join-Path $ArtifactStagingDirectory "dsc.zip"
+ Remove-Item -Path $ArchiveFile -ErrorAction SilentlyContinue
+ [System.IO.Compression.ZipFile]::CreateFromDirectory($DSCSourceFolder, $ArchiveFile)
+ }
+
+ # Generate the value for artifacts location if it is not provided in the parameter file
+ $ArtifactsLocation = $OptionalParameters[$ArtifactsLocationName]
+ if ($ArtifactsLocation -eq $null) {
+ $ArtifactsLocation = $StorageAccountContext.BlobEndPoint + $StorageContainerName
+ $OptionalParameters[$ArtifactsLocationName] = $ArtifactsLocation
+ }
+
+ # Use AzCopy to copy files from the local storage drop path to the storage account container
+ & $AzCopyPath """$ArtifactStagingDirectory""", $ArtifactsLocation, "/DestKey:$StorageAccountKey", "/S", "/Y", "/Z:$env:LocalAppData\Microsoft\Azure\AzCopy\$ResourceGroupName"
+
+ # Generate the value for artifacts location SAS token if it is not provided in the parameter file
+ $ArtifactsLocationSasToken = $OptionalParameters[$ArtifactsLocationSasTokenName]
+ if ($ArtifactsLocationSasToken -eq $null) {
+ # Create a SAS token for the storage container - this gives temporary read-only access to the container (defaults to 1 hour).
+ $ArtifactsLocationSasToken = New-AzureStorageContainerSASToken -Container $StorageContainerName -Context $StorageAccountContext -Permission r
+ $ArtifactsLocationSasToken = ConvertTo-SecureString $ArtifactsLocationSasToken -AsPlainText -Force
+ $OptionalParameters[$ArtifactsLocationSasTokenName] = $ArtifactsLocationSasToken
+ }
+}
+
+# Create or update the resource group using the specified template file and template parameters file
+Switch-AzureMode AzureResourceManager
+New-AzureResourceGroup -Name $ResourceGroupName `
+ -Location $ResourceGroupLocation `
+ -TemplateFile $TemplateFile `
+ -TemplateParameterFile $TemplateParametersFile `
+ @OptionalParameters `
+ -Force -Verbose
diff --git a/IaC/O365Hack_IaC/Templates/WebSite.json b/IaC/O365Hack_IaC/Templates/WebSite.json
new file mode 100644
index 0000000..6c25dec
--- /dev/null
+++ b/IaC/O365Hack_IaC/Templates/WebSite.json
@@ -0,0 +1,288 @@
+{
+ "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ "siteName": {
+ "type": "string"
+ },
+ "hostingPlanName": {
+ "type": "string"
+ },
+ "siteLocation": {
+ "type": "string"
+ },
+ "sku": {
+ "type": "string",
+ "allowedValues": [
+ "Free",
+ "Shared",
+ "Basic",
+ "Standard",
+ "Premium"
+ ],
+ "defaultValue": "Free"
+ },
+ "workerSize": {
+ "type": "string",
+ "allowedValues": [
+ "0",
+ "1",
+ "2"
+ ],
+ "defaultValue": "0"
+ }
+ },
+ "resources": [
+ {
+ "apiVersion": "2014-06-01",
+ "name": "[parameters('hostingPlanName')]",
+ "type": "Microsoft.Web/serverfarms",
+ "location": "[parameters('siteLocation')]",
+ "tags": {
+ "displayName": "HostingPlan"
+ },
+ "properties": {
+ "name": "[parameters('hostingPlanName')]",
+ "sku": "[parameters('sku')]",
+ "workerSize": "[parameters('workerSize')]",
+ "numberOfWorkers": 1
+ }
+ },
+ {
+ "apiVersion": "2014-06-01",
+ "name": "[parameters('siteName')]",
+ "type": "Microsoft.Web/sites",
+ "location": "[parameters('siteLocation')]",
+ "tags": {
+ "[concat('hidden-related:', resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]": "Resource",
+ "displayName": "Website"
+
+ },
+ "dependsOn": [
+ "[concat('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
+ ],
+ "properties": {
+ "name": "[parameters('siteName')]",
+ "serverFarm": "[parameters('hostingPlanName')]"
+ }
+ },
+ {
+ "apiVersion": "2014-04-01",
+ "name": "[concat(parameters('hostingPlanName'), '-', resourceGroup().name)]",
+ "type": "Microsoft.Insights/autoscalesettings",
+ "location": "East US",
+ "tags": {
+ "[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]": "Resource",
+ "displayName": "AutoScaleSettings"
+ },
+ "dependsOn": [
+ "[concat('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
+ ],
+ "properties": {
+ "profiles": [
+ {
+ "name": "Default",
+ "capacity": {
+ "minimum": 1,
+ "maximum": 2,
+ "default": 1
+ },
+ "rules": [
+ {
+ "metricTrigger": {
+ "metricName": "CpuPercentage",
+ "metricResourceUri": "[concat(resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]",
+ "timeGrain": "PT1M",
+ "statistic": "Average",
+ "timeWindow": "PT10M",
+ "timeAggregation": "Average",
+ "operator": "GreaterThan",
+ "threshold": 80.0
+ },
+ "scaleAction": {
+ "direction": "Increase",
+ "type": "ChangeCount",
+ "value": 1,
+ "cooldown": "PT10M"
+ }
+ },
+ {
+ "metricTrigger": {
+ "metricName": "CpuPercentage",
+ "metricResourceUri": "[concat(resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]",
+ "timeGrain": "PT1M",
+ "statistic": "Average",
+ "timeWindow": "PT1H",
+ "timeAggregation": "Average",
+ "operator": "LessThan",
+ "threshold": 60.0
+ },
+ "scaleAction": {
+ "direction": "Decrease",
+ "type": "ChangeCount",
+ "value": 1,
+ "cooldown": "PT1H"
+ }
+ }
+ ]
+ }
+ ],
+ "enabled": false,
+ "name": "[concat(parameters('hostingPlanName'), '-', resourceGroup().name)]",
+ "targetResourceUri": "[concat(resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
+ }
+ },
+ {
+ "apiVersion": "2014-04-01",
+ "name": "[concat('ServerErrors ', parameters('siteName'))]",
+ "type": "Microsoft.Insights/alertrules",
+ "location": "East US",
+ "dependsOn": [
+ "[concat('Microsoft.Web/sites/', parameters('siteName'))]"
+ ],
+ "tags": {
+ "[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/sites/', parameters('siteName'))]": "Resource",
+ "displayName": "ServerErrorsAlertRule"
+ },
+ "properties": {
+ "name": "[concat('ServerErrors ', parameters('siteName'))]",
+ "description": "[concat(parameters('siteName'), ' has some server errors, status code 5xx.')]",
+ "isEnabled": false,
+ "condition": {
+ "odata.type": "Microsoft.Azure.Management.Insights.Models.ThresholdRuleCondition",
+ "dataSource": {
+ "odata.type": "Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource",
+ "resourceUri": "[concat(resourceGroup().id, '/providers/Microsoft.Web/sites/', parameters('siteName'))]",
+ "metricName": "Http5xx"
+ },
+ "operator": "GreaterThan",
+ "threshold": 0.0,
+ "windowSize": "PT5M"
+ },
+ "action": {
+ "odata.type": "Microsoft.Azure.Management.Insights.Models.RuleEmailAction",
+ "sendToServiceOwners": true,
+ "customEmails": [ ]
+ }
+ }
+ },
+ {
+ "apiVersion": "2014-04-01",
+ "name": "[concat('ForbiddenRequests ', parameters('siteName'))]",
+ "type": "Microsoft.Insights/alertrules",
+ "location": "East US",
+ "dependsOn": [
+ "[concat('Microsoft.Web/sites/', parameters('siteName'))]"
+ ],
+ "tags": {
+ "[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/sites/', parameters('siteName'))]": "Resource",
+ "displayName": "ForbiddenRequestsAlertRule"
+ },
+ "properties": {
+ "name": "[concat('ForbiddenRequests ', parameters('siteName'))]",
+ "description": "[concat(parameters('siteName'), ' has some requests that are forbidden, status code 403.')]",
+ "isEnabled": false,
+ "condition": {
+ "odata.type": "Microsoft.Azure.Management.Insights.Models.ThresholdRuleCondition",
+ "dataSource": {
+ "odata.type": "Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource",
+ "resourceUri": "[concat(resourceGroup().id, '/providers/Microsoft.Web/sites/', parameters('siteName'))]",
+ "metricName": "Http403"
+ },
+ "operator": "GreaterThan",
+ "threshold": 0,
+ "windowSize": "PT5M"
+ },
+ "action": {
+ "odata.type": "Microsoft.Azure.Management.Insights.Models.RuleEmailAction",
+ "sendToServiceOwners": true,
+ "customEmails": [ ]
+ }
+ }
+ },
+ {
+ "apiVersion": "2014-04-01",
+ "name": "[concat('CPUHigh ', parameters('hostingPlanName'))]",
+ "type": "Microsoft.Insights/alertrules",
+ "location": "East US",
+ "dependsOn": [
+ "[concat('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
+ ],
+ "tags": {
+ "[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]": "Resource",
+ "displayName": "CPUHighAlertRule"
+ },
+ "properties": {
+ "name": "[concat('CPUHigh ', parameters('hostingPlanName'))]",
+ "description": "[concat('The average CPU is high across all the instances of ', parameters('hostingPlanName'))]",
+ "isEnabled": false,
+ "condition": {
+ "odata.type": "Microsoft.Azure.Management.Insights.Models.ThresholdRuleCondition",
+ "dataSource": {
+ "odata.type": "Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource",
+ "resourceUri": "[concat(resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]",
+ "metricName": "CpuPercentage"
+ },
+ "operator": "GreaterThan",
+ "threshold": 90,
+ "windowSize": "PT15M"
+ },
+ "action": {
+ "odata.type": "Microsoft.Azure.Management.Insights.Models.RuleEmailAction",
+ "sendToServiceOwners": true,
+ "customEmails": [ ]
+ }
+ }
+ },
+ {
+ "apiVersion": "2014-04-01",
+ "name": "[concat('LongHttpQueue ', parameters('hostingPlanName'))]",
+ "type": "Microsoft.Insights/alertrules",
+ "location": "East US",
+ "dependsOn": [
+ "[concat('Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]"
+ ],
+ "tags": {
+ "[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]": "Resource",
+ "displayName": "LongHttpQueueAlertRule"
+ },
+ "properties": {
+ "name": "[concat('LongHttpQueue ', parameters('hostingPlanName'))]",
+ "description": "[concat('The HTTP queue for the instances of ', parameters('hostingPlanName'), ' has a large number of pending requests.')]",
+ "isEnabled": false,
+ "condition": {
+ "odata.type": "Microsoft.Azure.Management.Insights.Models.ThresholdRuleCondition",
+ "dataSource": {
+ "odata.type": "Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource",
+ "resourceUri": "[concat(resourceGroup().id, '/providers/Microsoft.Web/serverfarms/', parameters('hostingPlanName'))]",
+ "metricName": "HttpQueueLength"
+ },
+ "operator": "GreaterThan",
+ "threshold": 100.0,
+ "windowSize": "PT5M"
+ },
+ "action": {
+ "odata.type": "Microsoft.Azure.Management.Insights.Models.RuleEmailAction",
+ "sendToServiceOwners": true,
+ "customEmails": [ ]
+ }
+ }
+ },
+ {
+ "apiVersion": "2014-04-01",
+ "name": "[parameters('siteName')]",
+ "type": "Microsoft.Insights/components",
+ "location": "Central US",
+ "dependsOn": [
+ "[concat('Microsoft.Web/sites/', parameters('siteName'))]"
+ ],
+ "tags": {
+ "[concat('hidden-link:', resourceGroup().id, '/providers/Microsoft.Web/sites/', parameters('siteName'))]": "Resource",
+ "displayName": "AppInsightsComponent"
+ },
+ "properties": {
+ "applicationId": "[parameters('siteName')]"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/IaC/O365Hack_IaC/Templates/WebSite.param.dev.json b/IaC/O365Hack_IaC/Templates/WebSite.param.dev.json
new file mode 100644
index 0000000..adf7f24
--- /dev/null
+++ b/IaC/O365Hack_IaC/Templates/WebSite.param.dev.json
@@ -0,0 +1,15 @@
+{
+ "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ "siteName": {
+ "value": "turnout"
+ },
+ "hostingPlanName": {
+ "value": "O365HackPlan"
+ },
+ "siteLocation": {
+ "value": "West US"
+ }
+ }
+}
\ No newline at end of file
diff --git a/IaC/O365Hack_IaC/Tools/AzCopy.exe b/IaC/O365Hack_IaC/Tools/AzCopy.exe
new file mode 100644
index 0000000..486f6a4
Binary files /dev/null and b/IaC/O365Hack_IaC/Tools/AzCopy.exe differ
diff --git a/IaC/O365Hack_IaC/Tools/Microsoft.Data.Edm.dll b/IaC/O365Hack_IaC/Tools/Microsoft.Data.Edm.dll
new file mode 100644
index 0000000..12d07d3
Binary files /dev/null and b/IaC/O365Hack_IaC/Tools/Microsoft.Data.Edm.dll differ
diff --git a/IaC/O365Hack_IaC/Tools/Microsoft.Data.OData.dll b/IaC/O365Hack_IaC/Tools/Microsoft.Data.OData.dll
new file mode 100644
index 0000000..884b52a
Binary files /dev/null and b/IaC/O365Hack_IaC/Tools/Microsoft.Data.OData.dll differ
diff --git a/IaC/O365Hack_IaC/Tools/Microsoft.Data.Services.Client.dll b/IaC/O365Hack_IaC/Tools/Microsoft.Data.Services.Client.dll
new file mode 100644
index 0000000..65c265c
Binary files /dev/null and b/IaC/O365Hack_IaC/Tools/Microsoft.Data.Services.Client.dll differ
diff --git a/IaC/O365Hack_IaC/Tools/Microsoft.WindowsAzure.Storage.DataMovement.dll b/IaC/O365Hack_IaC/Tools/Microsoft.WindowsAzure.Storage.DataMovement.dll
new file mode 100644
index 0000000..589e1a9
Binary files /dev/null and b/IaC/O365Hack_IaC/Tools/Microsoft.WindowsAzure.Storage.DataMovement.dll differ
diff --git a/IaC/O365Hack_IaC/Tools/Microsoft.WindowsAzure.Storage.dll b/IaC/O365Hack_IaC/Tools/Microsoft.WindowsAzure.Storage.dll
new file mode 100644
index 0000000..692d64f
Binary files /dev/null and b/IaC/O365Hack_IaC/Tools/Microsoft.WindowsAzure.Storage.dll differ