From f4210f7c954270d2262fb6707f9c821052f30e76 Mon Sep 17 00:00:00 2001 From: Nan Zang Date: Thu, 16 Sep 2021 09:00:39 -0700 Subject: [PATCH 1/3] Sentinel Content Deployment Script --- .github/workflows/azure-sentinel-deploy.ps1 | 154 ++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 .github/workflows/azure-sentinel-deploy.ps1 diff --git a/.github/workflows/azure-sentinel-deploy.ps1 b/.github/workflows/azure-sentinel-deploy.ps1 new file mode 100644 index 00000000..ede090b4 --- /dev/null +++ b/.github/workflows/azure-sentinel-deploy.ps1 @@ -0,0 +1,154 @@ +## Globals ## +$CloudEnv = $Env:cloudEnv +$ResourceGroupName = $Env:resourceGroupName +$WorkspaceName = $Env:workspaceName +$Directory = $Env:directory +$Creds = $Env:creds + +$MaxRetries = 3 +$secondsBetweenAttempts = 5 + +function AttemptAzLogin($psCredential, $tenantId, $cloudEnv) { + $maxLoginRetries = 3 + $delayInSeconds = 30 + $retryCount = 1 + $stopTrying = $false + do { + try { + Connect-AzAccount -ServicePrincipal -Tenant $tenantId -Credential $psCredential -Environment $cloudEnv | out-null; + Write-Host "Login Successful" + $stopTrying = $true + } + catch { + if ($retryCount -ge $maxLoginRetries) { + Write-Host "Login failed after $maxLoginRetries attempts." + $stopTrying = $true + } + else { + Write-Host "Login attempt failed, retrying in $delayInSeconds seconds." + Start-Sleep -Seconds $delayInSeconds + $retryCount++ + } + } + } + while (-not $stopTrying) +} + +function ConnectAzCloud { + $RawCreds = $Creds | ConvertFrom-Json + + Clear-AzContext -Scope Process; + Clear-AzContext -Scope CurrentUser -Force -ErrorAction SilentlyContinue; + + Add-AzEnvironment ` + -Name $CloudEnv ` + -ActiveDirectoryEndpoint $RawCreds.activeDirectoryEndpointUrl ` + -ResourceManagerEndpoint $RawCreds.resourceManagerEndpointUrl ` + -ActiveDirectoryServiceEndpointResourceId $RawCreds.activeDirectoryServiceEndpointResourceId ` + -GraphEndpoint $RawCreds.graphEndpointUrl | out-null; + + $servicePrincipalKey = ConvertTo-SecureString $RawCreds.clientSecret.replace("'", "''") -AsPlainText -Force + $psCredential = New-Object System.Management.Automation.PSCredential($RawCreds.clientId, $servicePrincipalKey) + + AttemptAzLogin $psCredential $RawCreds.tenantId $CloudEnv + Set-AzContext -Tenant $RawCreds.tenantId | out-null; +} + +function IsValidTemplate($path) { + Try { + Test-AzResourceGroupDeployment -ResourceGroupName $ResourceGroupName -TemplateFile $path -workspace $WorkspaceName + return $true + } + Catch { + Write-Host "[Warning] The file $path is not valid: $_" + return $false + } +} + +function IsRetryable($deploymentName) { + $retryableStatusCodes = "Conflict","TooManyRequests","InternalServerError" + Try { + $deploymentResult = Get-AzResourceGroupDeploymentOperation -DeploymentName $deploymentName -ResourceGroupName $ResourceGroupName -ErrorAction Stop + return $retryableStatusCodes -contains $deploymentResult.StatusCode + } + Catch { + return $false + } +} + +function AttemptDeployment($path, $deploymentName) { + $isValid = IsValidTemplate $path + if (-not $isValid) { + return $false + } + $isSuccess = $false + $currentAttempt = 0 + While (($currentAttempt -lt $MaxRetries) -and (-not $isSuccess)) + { + $currentAttempt ++ + Try + { + + New-AzResourceGroupDeployment -ResourceGroupName $ResourceGroupName -TemplateFile $path -workspace $workspaceName -ErrorAction Stop | Out-Host + $isSuccess = $true + } + Catch [Exception] + { + $error = $_ + if (-not (IsRetryable $deploymentName)) + { + Write-Host "[Warning] Failed to deploy $path with error: $error" + break + } + else + { + if ($currentAttempt -le $MaxRetries) + { + Write-Host "[Warning] Failed to deploy $path with error: $error. Retrying in $secondsBetweenAttempts seconds..." + Start-Sleep -Seconds $secondsBetweenAttempts + } + else + { + Write-Host "[Warning] Failed to deploy $path after $currentAttempt attempts with error: $error" + } + } + } + } + return $isSuccess +} + +function main() { + if ($CloudEnv -ne 'AzureCloud') + { + Write-Output "Attempting Sign In to Azure Cloud" + ConnectAzCloud + } + + Write-Output "Starting Deployment for Files in path: $Directory" + + if (Test-Path -Path $Directory) + { + $totalFiles = 0; + $totalFailed = 0; + Get-ChildItem -Path $Directory -Recurse -Filter *.json | + ForEach-Object { + $totalFiles ++ + $isSuccess = AttemptDeployment $_.FullName $_.Basename + if (-not $isSuccess) + { + $totalFailed++ + } + } + if ($totalFiles -gt 0 -and $totalFailed -gt 0) + { + $error = "$totalFailed of $totalFiles deployments failed." + Throw $error + } + } + else + { + Write-Output "[Warning] $Directory not found. nothing to deploy" + } +} + +main \ No newline at end of file From 7b889ab80579fb6ec18ac8b66a8fcf7ded10b8dc Mon Sep 17 00:00:00 2001 From: Nan Zang Date: Thu, 16 Sep 2021 09:00:39 -0700 Subject: [PATCH 2/3] Workflow file for Sentinel-Deploy --- ...y-19225073-b8db-47df-bf5e-c4812ab15bd2.yml | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 .github/workflows/sentinel-deploy-19225073-b8db-47df-bf5e-c4812ab15bd2.yml diff --git a/.github/workflows/sentinel-deploy-19225073-b8db-47df-bf5e-c4812ab15bd2.yml b/.github/workflows/sentinel-deploy-19225073-b8db-47df-bf5e-c4812ab15bd2.yml new file mode 100644 index 00000000..6e5af7b4 --- /dev/null +++ b/.github/workflows/sentinel-deploy-19225073-b8db-47df-bf5e-c4812ab15bd2.yml @@ -0,0 +1,73 @@ +name: Deploy Content to Azure Sentinel +on: + push: + branches: [ bugbash-2 ] + paths: + - 'Detections/**' + - '.github/workflows/sentinel-deploy**' + +jobs: + deploy-content: + runs-on: windows-latest + env: + resourceGroupName: 'cac-test-rg' + workspaceName: 'cac-bugbash-workspace' + directory: '${{ github.workspace }}/Detections' + cloudEnv: 'AzureCloud' + creds: ${{ secrets.AZURE_SENTINEL_CREDENTIALS_19225073b8db47dfbf5ec4812ab15bd2 }} + + steps: + - name: Login to Azure (Attempt 1) + continue-on-error: true + id: login1 + uses: azure/login@v1 + if: ${{ env.cloudEnv == 'AzureCloud' }} + with: + creds: ${{ secrets.AZURE_SENTINEL_CREDENTIALS_19225073b8db47dfbf5ec4812ab15bd2 }} + enable-AzPSSession: true + + - name: Wait 30 seconds if login attempt 1 failed + uses: juliangruber/sleep-action@v1 + if: ${{ env.cloudEnv == 'AzureCloud' && steps.login1.outcome=='failure' }} + with: + time: 30s + + - name: Login to Azure (Attempt 2) + continue-on-error: true + id: login2 + uses: azure/login@v1 + if: ${{ env.cloudEnv == 'AzureCloud' && steps.login1.outcome=='failure' }} + with: + creds: ${{ secrets.AZURE_SENTINEL_CREDENTIALS_19225073b8db47dfbf5ec4812ab15bd2 }} + enable-AzPSSession: true + + - name: Wait 30 seconds if login attempt 2 failed + uses: juliangruber/sleep-action@v1 + if: ${{ env.cloudEnv == 'AzureCloud' && steps.login2.outcome=='failure' }} + with: + time: 30s + + - name: Login to Azure (Attempt 3) + continue-on-error: false + id: login3 + uses: azure/login@v1 + if: ${{ env.cloudEnv == 'AzureCloud' && steps.login2.outcome=='failure' }} + with: + creds: ${{ secrets.AZURE_SENTINEL_CREDENTIALS_19225073b8db47dfbf5ec4812ab15bd2 }} + enable-AzPSSession: true + + - name: Checkout + uses: actions/checkout@v1 + + - name: Read deployment script + id: deploymentScript + uses: juliangruber/read-file-action@v1 + with: + path: '${{ github.workspace }}/.github/workflows\azure-sentinel-deploy.ps1' + + - name: Deploy Analytic Rules + uses: azure/powershell@v1 + with: + azPSVersion: 'latest' + inlineScript: | + ${{ steps.deploymentScript.outputs.content }} \ No newline at end of file From 2d293229666ac6a9f2dd6435f23450e00eef17dd Mon Sep 17 00:00:00 2001 From: "azure-sentinel[bot]" <81647488+azure-sentinel[bot]@users.noreply.github.com> Date: Fri, 17 Sep 2021 17:56:08 +0000 Subject: [PATCH 3/3] Remove sentinel-deploy-19225073-b8db-47df-bf5e-c4812ab15bd2.yml --- ...y-19225073-b8db-47df-bf5e-c4812ab15bd2.yml | 73 ------------------- 1 file changed, 73 deletions(-) delete mode 100644 .github/workflows/sentinel-deploy-19225073-b8db-47df-bf5e-c4812ab15bd2.yml diff --git a/.github/workflows/sentinel-deploy-19225073-b8db-47df-bf5e-c4812ab15bd2.yml b/.github/workflows/sentinel-deploy-19225073-b8db-47df-bf5e-c4812ab15bd2.yml deleted file mode 100644 index 6e5af7b4..00000000 --- a/.github/workflows/sentinel-deploy-19225073-b8db-47df-bf5e-c4812ab15bd2.yml +++ /dev/null @@ -1,73 +0,0 @@ -name: Deploy Content to Azure Sentinel -on: - push: - branches: [ bugbash-2 ] - paths: - - 'Detections/**' - - '.github/workflows/sentinel-deploy**' - -jobs: - deploy-content: - runs-on: windows-latest - env: - resourceGroupName: 'cac-test-rg' - workspaceName: 'cac-bugbash-workspace' - directory: '${{ github.workspace }}/Detections' - cloudEnv: 'AzureCloud' - creds: ${{ secrets.AZURE_SENTINEL_CREDENTIALS_19225073b8db47dfbf5ec4812ab15bd2 }} - - steps: - - name: Login to Azure (Attempt 1) - continue-on-error: true - id: login1 - uses: azure/login@v1 - if: ${{ env.cloudEnv == 'AzureCloud' }} - with: - creds: ${{ secrets.AZURE_SENTINEL_CREDENTIALS_19225073b8db47dfbf5ec4812ab15bd2 }} - enable-AzPSSession: true - - - name: Wait 30 seconds if login attempt 1 failed - uses: juliangruber/sleep-action@v1 - if: ${{ env.cloudEnv == 'AzureCloud' && steps.login1.outcome=='failure' }} - with: - time: 30s - - - name: Login to Azure (Attempt 2) - continue-on-error: true - id: login2 - uses: azure/login@v1 - if: ${{ env.cloudEnv == 'AzureCloud' && steps.login1.outcome=='failure' }} - with: - creds: ${{ secrets.AZURE_SENTINEL_CREDENTIALS_19225073b8db47dfbf5ec4812ab15bd2 }} - enable-AzPSSession: true - - - name: Wait 30 seconds if login attempt 2 failed - uses: juliangruber/sleep-action@v1 - if: ${{ env.cloudEnv == 'AzureCloud' && steps.login2.outcome=='failure' }} - with: - time: 30s - - - name: Login to Azure (Attempt 3) - continue-on-error: false - id: login3 - uses: azure/login@v1 - if: ${{ env.cloudEnv == 'AzureCloud' && steps.login2.outcome=='failure' }} - with: - creds: ${{ secrets.AZURE_SENTINEL_CREDENTIALS_19225073b8db47dfbf5ec4812ab15bd2 }} - enable-AzPSSession: true - - - name: Checkout - uses: actions/checkout@v1 - - - name: Read deployment script - id: deploymentScript - uses: juliangruber/read-file-action@v1 - with: - path: '${{ github.workspace }}/.github/workflows\azure-sentinel-deploy.ps1' - - - name: Deploy Analytic Rules - uses: azure/powershell@v1 - with: - azPSVersion: 'latest' - inlineScript: | - ${{ steps.deploymentScript.outputs.content }} \ No newline at end of file