Deploy to Dev environment upon Release #101
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Deploy to Dev environment upon Release | |
on: | |
workflow_run: | |
workflows: [Azure CAC Release] | |
types: | |
- completed | |
concurrency: | |
group: Deploy-Azure-CAC-Dev | |
cancel-in-progress: false | |
permissions: | |
id-token: write | |
env: | |
ARTIFACT_NAME: PowerShell.Workflows.ScriptSigning | |
jobs: | |
sign-scripts: | |
name: Validate, test and publish Powershell scripts as pipeline artifacts | |
runs-on: windows-2019 | |
environment: test | |
steps: | |
- name: Check out repository | |
uses: actions/checkout@v2 | |
- name: Test Module Imports | |
shell: powershell | |
run: | | |
$ErrorActionPreference = 'Stop' | |
$moduleFiles = Get-ChildItem -path ./* -recurse -include *.psm1 | |
Write-Host "Count of module files: $($moduleFiles.count)" | |
try { | |
ForEach ($moduleFile in $moduleFiles) { | |
Import-Module $moduleFile.Fullname -ErrorAction Stop | |
} | |
} | |
catch { | |
throw "Failed test import module '$moduleFile' with error: $_" | |
} | |
$importedModules = Get-Module | |
Write-Host "Imported modules: `n $($importedModules.Path | Out-String)" | |
$missingModules = $moduleFiles | Where-object {$_ -inotin ($importedModules).Path} | |
If ($missingModules) { | |
throw "The following modules failed import test: $missingModules" | |
} | |
- name: Zip Signed Modules | |
shell: powershell | |
run: | | |
$moduleCodeFilesObjs = Get-ChildItem -Path .\src -Recurse -Include *.psm1 -Exclude '*-GSA*','*GuardrailsSolutionAcceleratorSetup*','*Deploy-GuardrailsSolutionAccelerator*' | |
Write-Host "'$($moduleCodeFilesObjs.count)' module manifest files " | |
ForEach ($moduleCodeFile in $moduleCodeFilesObjs) { | |
$moduleManifestFile = Get-Item -Path $moduleCodeFile.FullName.replace('psm1','psd1') | |
If ($moduleCodeFilesObjs.FullName -icontains $moduleCodeFile.FullName -or $moduleCodeFilesObjs.FullName -icontains $moduleManifestFile.FullName) { | |
Write-Host "Module '$($moduleCodeFile.BaseName)' found, zipping module files..." | |
$destPath = "./psmodules/$($moduleCodeFile.BaseName).zip" | |
If ($moduleCodeFile.DIrectory.Name -eq 'Guardrails-Localization') { | |
Compress-Archive -Path "$($moduleCodeFile.Directory)/*" -DestinationPath $destPath -Force | |
} | |
Else { | |
$filesToZip = $moduleManifestFile,$moduleCodeFile | |
Compress-Archive -Path $filesToZip -DestinationPath $destPath -Force | |
} | |
} | |
Else { | |
Write-Host "Neither the manifest '$($moduleCodeFile.FullName.toLower())' or script file '$($moduleManifestFile.FullName.ToLower())' for module '$($moduleCodeFile.BaseName)' was changed, skipping zipping..." | |
} | |
} | |
- name: Publish artifacts | |
uses: actions/upload-artifact@v4 | |
with: | |
name: ${{ env.ARTIFACT_NAME }} | |
path: ./psmodules/*.zip | |
deploy: | |
name: Deploy CaC to Dev Tenant | |
needs: sign-scripts | |
runs-on: ubuntu-latest | |
environment: dev | |
steps: | |
- name: Check out | |
uses: actions/checkout@v3 | |
- name: Download zipped modules and replace old ones | |
uses: actions/download-artifact@v4 | |
with: | |
name: ${{env.ARTIFACT_NAME}} | |
path: ./psmodules | |
- name: AZ Login | |
uses: azure/login@v2 | |
with: | |
creds: ${{ secrets.DEV_AZURE_CREDENTIALS }} | |
enable-AzPSSession: true | |
- name: Stage zipped/signed modules in Storage Account | |
uses: azure/powershell@v2 | |
with: | |
inlineScript: | | |
Set-AzContext -SubscriptionId $env:DEVSUBSCRIPTION_ID | |
$storageContext = (Get-AzStorageAccount -ResourceGroupName $env:PIPELINEMODULESTAGING_RGNAME -Name $env:PIPELINEMODULESTAGING_STORAGEACCOUNTNAME).Context | |
$zippedModules = Get-ChildItem -Path ./psmodules/* -Include *.zip -File | |
ForEach ($moduleZip in $zippedModules) { | |
Set-AzStorageBlobContent -Context $storageContext -Container psmodules -File $moduleZip.FullName -Blob $moduleZip.Name -Force -ErrorAction Stop | |
} | |
azPSVersion: "latest" | |
env: | |
PIPELINEMODULESTAGING_RGNAME: ${{ vars.PIPELINEMODULESTAGING_RGNAME }} | |
PIPELINEMODULESTAGING_STORAGEACCOUNTNAME: ${{ vars.PIPELINEMODULESTAGING_SANAME_DEV }} | |
DEVSUBSCRIPTION_ID: ${{ secrets.DEV_AZURE_SUBSCRIPTION_ID}} | |
- name: Pre-Clean Dev environment | |
if: ${{ env.DEV_UPGRADE_VAR != 'true'}} | |
uses: azure/powershell@v2 | |
continue-on-error: true | |
with: | |
inlineScript: | | |
Set-AzContext -SubscriptionId $env:DEVSUBSCRIPTION_ID | |
ipmo ./src/GuardrailsSolutionAcceleratorSetup | |
$configFilePath = Join-Path -Path $env:GITHUB_WORKSPACE -ChildPath 'config.json' | |
$CBSSUBSCRIPTION_DEV_NAME = $env:CBSSUBSCRIPTION_DEV_NAME | |
$DEVSUBSCRIPTION_ID = $env:DEVSUBSCRIPTION_ID | |
$LIGHTHOUSEPROVIDER_TENANTID = $env:LIGHTHOUSEPROVIDER_TENANTID | |
$LIGHTHOUSEPROVIDER_PRINCIPALID = $env:LIGHTHOUSEPROVIDER_PRINCIPALID | |
$LIGHTHOUSEPROVIDER_MGMTGRPID_DEV = $env:LIGHTHOUSEPROVIDER_MGMTGRPID_DEV | |
$UNIQUENAME_SUFFIX_DEV = $env:UNIQUENAME_SUFFIX_DEV | |
$DEVTENANT_BGA1 = $env:DEVTENANT_BGA1 | |
$DEVTENANT_BGA2 = $env:DEVTENANT_BGA2 | |
$PBMMPOLICY_ID = $env:PBMMPOLICY_ID | |
$LOCATIONPOLICY_ID = $env:LOCATIONPOLICY_ID | |
$INITIATIVELOCATION_ID = $env:INITIATIVELOCATION_ID_DEV | |
$DEVLAW_SEC = $env:DEVLAW_SEC | |
$DEVLAW_HEALTH = $env:DEVLAW_HEALTH | |
$ENABLE_MULTICLOUD_PROFILES = $env:ENABLE_MULTICLOUD_PROFILES | |
$DEV_UPGRADE_VAR = $env:DEV_UPGRADE_VAR | |
$configContent = @" | |
{ | |
"keyVaultName": "kvcac", | |
"resourcegroup": "guardrailscac", | |
"region": "CanadaCentral", | |
"storageaccountName": "stcac", | |
"logAnalyticsworkspaceName": "logcac", | |
"autoMationAccountName": "aacac", | |
"FirstBreakGlassAccountUPN": "$DEVTENANT_BGA1", | |
"SecondBreakGlassAccountUPN": "$DEVTENANT_BGA2", | |
"PBMMPolicyID": "$PBMMPOLICY_ID", | |
"AllowedLocationPolicyId": "$LOCATIONPOLICY_ID", | |
"AllowedLocationInitiativeId": "$INITIATIVELOCATION_ID", | |
"DepartmentNumber": "163", | |
"CBSSubscriptionName": "$CBSSUBSCRIPTION_DEV_NAME", | |
"securityLAWResourceId": "$DEVLAW_SEC", | |
"healthLAWResourceId": "$DEVLAW_HEALTH", | |
"Locale": "en-CA", | |
"lighthouseServiceProviderTenantID": "$LIGHTHOUSEPROVIDER_TENANTID", | |
"lighthousePrincipalDisplayName": "GcPc-CTO-Guardrails_Compliance-Owners", | |
"lighthousePrincipalId": "$LIGHTHOUSEPROVIDER_PRINCIPALID", | |
"lighthouseTargetManagementGroupID": "$LIGHTHOUSEPROVIDER_MGMTGRPID_DEV", | |
"subscriptionId": "$DEVSUBSCRIPTION_ID", | |
"SSCReadOnlyServicePrincipalNameAPPID": "00000000-0000-0000-0000-000000000000", | |
"uniqueNameSuffix": "$UNIQUENAME_SUFFIX_DEV", | |
"securityRetentionDays": "730", | |
"cloudUsageProfiles": "3", | |
"enableMultiCloudProfiles": "$ENABLE_MULTICLOUD_PROFILES" | |
} | |
"@ | |
Set-Content -Path $configFilePath -Value $configContent | |
Push-Location -Path setup | |
try { | |
$ErrorActionPreference = 'Stop' | |
remove-gsacentralizedReportingCustomerComponents -Force -configFilePath $configFilePath -verbose | |
Remove-GSACentralizedDefenderCustomerComponents -Force -configFilePath $configFilePath -verbose | |
Remove-GSACoreResources -Force -Wait -configFilePath $configFilePath -verbose | |
} | |
catch { | |
throw "Failed test deploy of solution with error: $_" | |
} | |
finally { | |
If (!$?) {throw "Failed test deploy of solution with error: $($error[0]) $_"} | |
Pop-Location | |
} | |
azPSVersion: "latest" | |
env: | |
DEVTENANT_DOMAIN: ${{ vars.DEVTENANT_DOMAIN }} | |
DEVSUBSCRIPTION_ID: ${{ vars.DEVSUBSCRIPTION_ID }} | |
CBSSUBSCRIPTION_DEV_NAME: ${{ vars.CBSSUBSCRIPTION_DEV_NAME }} | |
LIGHTHOUSEPROVIDER_TENANTID: ${{ vars.LIGHTHOUSEPROVIDER_TENANTID }} | |
LIGHTHOUSEPROVIDER_PRINCIPALID: ${{ vars.LIGHTHOUSEPROVIDER_PRINCIPALID }} | |
LIGHTHOUSEPROVIDER_MGMTGRPID_DEV: ${{ vars.LIGHTHOUSEPROVIDER_MGMTGRPID_DEV }} | |
UNIQUENAME_SUFFIX_DEV: ${{ vars.UNIQUENAME_SUFFIX_DEV }} | |
DEVTENANT_BGA1: ${{ vars.DEVTENANT_BGA1 }} | |
DEVTENANT_BGA2: ${{ vars.DEVTENANT_BGA2 }} | |
PBMMPOLICY_ID: ${{ vars.PBMMPOLICY_ID }} | |
LOCATIONPOLICY_ID: ${{ vars.LOCATIONPOLICY_ID }} | |
INITIATIVELOCATION_ID_DEV: ${{ vars.INITIATIVELOCATION_ID_DEV}} | |
DEVLAW_SEC: ${{ vars.DEVLAW_SEC }} | |
DEVLAW_HEALTH: ${{ vars.DEVLAW_HEALTH }} | |
DEV_UPGRADE_VAR: ${{ vars.DEV_UPGRADE_VAR}} | |
ENABLE_MULTICLOUD_PROFILES: ${{ vars.DEV_ENABLE_MULTICLOUD_PROFILE }} | |
# - name: Relogin AZ | |
# uses: azure/login@v2 | |
# with: | |
# client-id: ${{ secrets.DEV_AZURE_CLIENT_ID}} | |
# tenant-id: ${{ secrets.DEV_AZURE_TENANT_ID}} | |
# subscription-id: ${{ secrets.DEV_AZURE_SUBSCRIPTION_ID}} | |
# enable-AzPSSession: true | |
- name: Deploy Dev Environment | |
uses: azure/powershell@v2 | |
with: | |
inlineScript: | | |
Set-AzContext -SubscriptionId $env:DEVSUBSCRIPTION_ID | |
$configFilePath = Join-Path -Path $env:GITHUB_WORKSPACE -ChildPath 'config.json' | |
$CBSSUBSCRIPTION_DEV_NAME = $env:CBSSUBSCRIPTION_DEV_NAME | |
$DEVSUBSCRIPTION_ID = $env:DEVSUBSCRIPTION_ID | |
$LIGHTHOUSEPROVIDER_TENANTID = $env:LIGHTHOUSEPROVIDER_TENANTID | |
$LIGHTHOUSEPROVIDER_PRINCIPALID = $env:LIGHTHOUSEPROVIDER_PRINCIPALID | |
$LIGHTHOUSEPROVIDER_MGMTGRPID_DEV = $env:LIGHTHOUSEPROVIDER_MGMTGRPID_DEV | |
$UNIQUENAME_SUFFIX_DEV = $env:UNIQUENAME_SUFFIX_DEV | |
$DEVTENANT_BGA1 = $env:DEVTENANT_BGA1 | |
$DEVTENANT_BGA2 = $env:DEVTENANT_BGA2 | |
$PBMMPOLICY_ID = $env:PBMMPOLICY_ID | |
$LOCATIONPOLICY_ID = $env:LOCATIONPOLICY_ID | |
$INITIATIVELOCATION_ID = $env:INITIATIVELOCATION_ID_DEV | |
$DEVLAW_SEC = $env:DEVLAW_SEC | |
$DEVLAW_HEALTH = $env:DEVLAW_HEALTH | |
$ENABLE_MULTICLOUD_PROFILES = $env:ENABLE_MULTICLOUD_PROFILES | |
$DEV_UPGRADE_VAR = $env:DEV_UPGRADE_VAR | |
$configContent = @" | |
{ | |
"keyVaultName": "kvcac", | |
"resourcegroup": "guardrailscac", | |
"region": "CanadaCentral", | |
"storageaccountName": "stcac", | |
"logAnalyticsworkspaceName": "logcac", | |
"autoMationAccountName": "aacac", | |
"FirstBreakGlassAccountUPN": "$DEVTENANT_BGA1", | |
"SecondBreakGlassAccountUPN": "$DEVTENANT_BGA2", | |
"PBMMPolicyID": "$PBMMPOLICY_ID", | |
"AllowedLocationPolicyId": "$LOCATIONPOLICY_ID", | |
"AllowedLocationInitiativeId": "$INITIATIVELOCATION_ID", | |
"DepartmentNumber": "163", | |
"CBSSubscriptionName": "$CBSSUBSCRIPTION_DEV_NAME", | |
"securityLAWResourceId": "$DEVLAW_SEC", | |
"healthLAWResourceId": "$DEVLAW_HEALTH", | |
"Locale": "en-CA", | |
"lighthouseServiceProviderTenantID": "$LIGHTHOUSEPROVIDER_TENANTID", | |
"lighthousePrincipalDisplayName": "GcPc-CTO-Guardrails_Compliance-Owners", | |
"lighthousePrincipalId": "$LIGHTHOUSEPROVIDER_PRINCIPALID", | |
"lighthouseTargetManagementGroupID": "$LIGHTHOUSEPROVIDER_MGMTGRPID_DEV", | |
"subscriptionId": "$DEVSUBSCRIPTION_ID", | |
"SSCReadOnlyServicePrincipalNameAPPID": "00000000-0000-0000-0000-000000000000", | |
"uniqueNameSuffix": "$UNIQUENAME_SUFFIX_DEV", | |
"securityRetentionDays": "730", | |
"cloudUsageProfiles": "3", | |
"enableMultiCloudProfiles": "$ENABLE_MULTICLOUD_PROFILES" | |
} | |
"@ | |
Set-Content -Path $configFilePath -Value $configContent | |
# Load tags JSON content into a variable | |
$setupFileRelativePath = "setup/tags.json" | |
$setupFullPath = Join-Path $env:GITHUB_WORKSPACE $setupFileRelativePath | |
$jsonContent = Get-Content -Raw -Path $setupFullPath | ConvertFrom-Json | |
# Add additional tags for dev tenant | |
$jsonContent | Add-Member -Type NoteProperty -Name 'ClientOrganization' -Value 'SSC' | |
$jsonContent | Add-Member -Type NoteProperty -Name 'CostCenter' -Value 'SSC Cloud Operations' | |
$jsonContent | Add-Member -Type NoteProperty -Name 'DataSensitivity' -Value 'PB' | |
$jsonContent | Add-Member -Type NoteProperty -Name 'ProjectContact' -Value 'Amrinder' | |
$jsonContent | Add-Member -Type NoteProperty -Name 'ProjectName' -Value 'ComplianceAsCodeAzure' | |
$jsonContent | Add-Member -Type NoteProperty -Name 'TechnicalContact' -Value 'Amrinder' | |
# Save the modified content back to the tags JSON file | |
$jsonContent | ConvertTo-Json | Set-Content -Path $setupFullPath | |
$storageContext = (Get-AzStorageAccount -ResourceGroupName $env:PIPELINEMODULESTAGING_RGNAME -Name $env:PIPELINEMODULESTAGING_STORAGEACCOUNTNAME).context | |
$modulesStagingURI = $storageContext.BlobEndpoint.ToString() + 'psmodules' | |
$alternatePSModulesURL = $modulesStagingURI | |
Write-Output "alternatePSModulesURL is '$alternatePSModulesURL'" | |
$optionalParams = @{} | |
if ($alternatePSModulesURL) { | |
$optionalParams['alternatePSModulesURL'] = $alternatePSModulesURL | |
} | |
try { | |
$ErrorActionPreference = 'Stop' | |
ipmo ./src/GuardrailsSolutionAcceleratorSetup | |
if ($DEV_UPGRADE_VAR -eq "true"){ | |
Write-Output "Upgrade workflow flag is set to '$DEV_UPGRADE_VAR'" | |
Write-Output "Upgrading the CaC solution" | |
Deploy-GuardrailsSolutionAccelerator -configFilePath $configFilePath -update -Yes @optionalParams -verbose | |
} | |
else { | |
Write-Output "Upgrade workflow flag is set to '$DEV_UPGRADE_VAR'" | |
Write-Output "Deploying a new installation of the CaC solution" | |
Deploy-GuardrailsSolutionAccelerator -configFilePath $configFilePath -newComponents CoreComponents, CentralizedCustomerDefenderForCloudSupport, CentralizedCustomerReportingSupport -Yes @optionalParams -verbose | |
} | |
} | |
catch { | |
throw "Failed test deploy of solution with error: $_" | |
} | |
finally { | |
If (!$?) {throw "Failed test deploy of solution with error: $($error[0]) $_"} | |
Pop-Location | |
} | |
azPSVersion: "latest" | |
env: | |
PIPELINEMODULESTAGING_RGNAME: ${{ vars.PIPELINEMODULESTAGING_RGNAME }} | |
PIPELINEMODULESTAGING_STORAGEACCOUNTNAME: ${{ vars.PIPELINEMODULESTAGING_SANAME_DEV }} | |
DEVSUBSCRIPTION_ID: ${{ vars.DEVSUBSCRIPTION_ID }} | |
CBSSUBSCRIPTION_DEV_NAME: ${{ vars.CBSSUBSCRIPTION_DEV_NAME }} | |
LIGHTHOUSEPROVIDER_TENANTID: ${{ vars.LIGHTHOUSEPROVIDER_TENANTID }} | |
LIGHTHOUSEPROVIDER_PRINCIPALID: ${{ vars.LIGHTHOUSEPROVIDER_PRINCIPALID }} | |
LIGHTHOUSEPROVIDER_MGMTGRPID_DEV: ${{ vars.LIGHTHOUSEPROVIDER_MGMTGRPID_DEV }} | |
UNIQUENAME_SUFFIX_DEV: ${{ vars.UNIQUENAME_SUFFIX_DEV }} | |
DEVTENANT_BGA1: ${{ vars.DEVTENANT_BGA1 }} | |
DEVTENANT_BGA2: ${{ vars.DEVTENANT_BGA2 }} | |
PBMMPOLICY_ID: ${{ vars.PBMMPOLICY_ID }} | |
LOCATIONPOLICY_ID: ${{ vars.LOCATIONPOLICY_ID }} | |
INITIATIVELOCATION_ID_DEV: ${{ vars.INITIATIVELOCATION_ID_DEV}} | |
DEVLAW_SEC: ${{ vars.DEVLAW_SEC }} | |
DEVLAW_HEALTH: ${{ vars.DEVLAW_HEALTH }} | |
DEV_UPGRADE_VAR: ${{ vars.DEV_UPGRADE_VAR}} | |
ENABLE_MULTICLOUD_PROFILES: ${{ vars.DEV_ENABLE_MULTICLOUD_PROFILE }} | |
- name: Check for AA Job Errors | |
uses: azure/powershell@v2 | |
with: | |
inlineScript: | | |
ipmo ./src/GuardrailsSolutionAcceleratorSetup | |
$c = Get-GSAExportedConfig -KeyVaultName kvcac-$env:UNIQUENAME_SUFFIX_DEV -y | |
$config = $c.configString | ConvertFrom-Json | |
Write-Output "Waiting for 'main' and 'backend' runbook jobs to complete (up to 5 mins)" | |
$timeout = New-TimeSpan -Minutes 5 | |
$timer = [System.Diagnostics.Stopwatch]::StartNew() | |
do { | |
$jobMain = Get-AzAutomationJob -RunbookName 'main' -ResourceGroupName $config.runtime.resourceGroup -AutomationAccountName $config.runtime.automationAccountName | | |
Sort-Object StartTIme -Descending | | |
Select-Object -First 1 | |
$jobBackend = Get-AzAutomationJob -RunbookName 'backend' -ResourceGroupName $config.runtime.resourceGroup -AutomationAccountName $config.runtime.automationAccountName | | |
Sort-Object StartTIme -Descending | | |
Select-Object -First 1 | |
Start-Sleep 1 | |
} | |
until (($jobMain.Status -in 'Completed','Failed' -and $jobBackend -in 'Completed','Failed') -or ($timer.Elapsed -ge $timeout)) | |
If ($jobMain.Status -eq 'Failed') { | |
throw "main runbook failed to execute" | |
} | |
If ($jobMain.Status -eq 'Completed') { | |
Write-Output "'main' runbook completed successfully, checking for errors in output. " | |
} | |
If ($jobBackend.Status -eq 'Failed') { | |
throw "backend runbook failed to execute" | |
} | |
If ($jobBackend.Status -eq 'Completed') { | |
Write-Output "'backend' runbook completed successfully, checking for errors in output. " | |
} | |
$jobMainOutput = Get-AzAutomationJobOutput -Id $jobMain.JobId -ResourceGroupName $config.runtime.resourceGroup -AutomationAccountName $config.runtime.automationAccountName -Stream 'Error' | |
$jobBackendOutput = Get-AzAutomationJobOutput -Id $jobBackend.JobId -ResourceGroupName $config.runtime.resourceGroup -AutomationAccountName $config.runtime.automationAccountName -Stream 'Error' | |
$errorsFound = $false | |
ForEach ($outputRecord in $jobMainOutput) { | |
If ($outputRecord.Summary -like 'Failed invoke the module execution script for module*') { | |
throw 'Errors found in "main" runbook Azure Automation jobs' | |
} | |
} | |
ForEach ($outputRecord in $jobBackendOutput) { | |
If ($outputRecord.Summary -like 'Failed invoke the module execution script for module*') { | |
throw 'Errors found in "backend" runbook Azure Automation jobs' | |
} | |
} | |
azPSVersion: "latest" | |
env: | |
UNIQUENAME_SUFFIX_DEV: ${{ vars.UNIQUENAME_SUFFIX_DEV }} |