diff --git a/.azuredevops/platformPipelines/platform.dependencies.yml b/.azuredevops/platformPipelines/platform.dependencies.yml new file mode 100644 index 0000000000..9abe3c0aea --- /dev/null +++ b/.azuredevops/platformPipelines/platform.dependencies.yml @@ -0,0 +1,637 @@ +name: '.Platform - Dependencies' + +parameters: + - name: deploySqlMiDependencies + displayName: Enable SqlMi dependencies deployment + type: boolean + default: false + +trigger: none + +# trigger: +# batch: true +# branches: +# include: +# - main +# paths: +# include: +# - '.azuredevops/pipelineTemplates/module.jobs.deploy.yml' +# - '.azuredevops/platformPipelines/platform.dependencies.yml' +# - 'utilities/pipelines/dependencies/**' + +variables: + - template: '/.azuredevops/pipelineVariables/global.variables.yml' + - group: 'PLATFORM_VARIABLES' + - name: dependencyPath + value: 'utilities/pipelines/dependencies' + - name: modulesPath + value: 'arm' + - name: defaultResourceGroupName + value: 'validation-rg' + +stages: + - stage: deploy_rg + displayName: Deploy resource group + variables: + resourceType: 'Microsoft.Resources/resourceGroups' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/validation.parameters.json + templateFilePath: $(templateFilePath) + displayName: Validation Resource Group + + - stage: deploy_msi + displayName: Deploy user assigned identity + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.ManagedIdentity/userAssignedIdentities' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: User Assigned Identity + + - stage: deploy_pa + displayName: Deploy policy assignment + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.Authorization/policyAssignments' + templateFilePath: $(modulesPath)/$(resourceType)/.bicep/nested_policyAssignments_sub.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Policy assignment + + - stage: deploy_evh + displayName: Deploy event hub + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.EventHub/namespaces' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: EventHub + + - stage: deploy_law + displayName: Deploy log analytics workspace + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.OperationalInsights/workspaces' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default LAW + - path: $(dependencyPath)/$(resourceType)/parameters/appi.parameters.json + templateFilePath: $(templateFilePath) + displayName: AppInsights LAW + + - stage: deploy_sa + displayName: Deploy storage account + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.Storage/storageAccounts' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default storage account + jobName: default_sa + - path: $(dependencyPath)/$(resourceType)/parameters/law.parameters.json + templateFilePath: $(templateFilePath) + displayName: LAW storage account + - path: $(dependencyPath)/$(resourceType)/parameters/fa.parameters.json + templateFilePath: $(templateFilePath) + displayName: FunctionApp storage account + - job: + displayName: Upload files to storage account + dependsOn: + - default_sa + pool: + ${{ if eq(variables['vmImage'], '') }}: + name: $(poolName) + ${{ if eq(variables['poolName'], '') }}: + vmImage: $(vmImage) + steps: + - task: PowerShell@2 + displayName: 'Setup agent' + inputs: + targetType: inline + pwsh: true + script: | + # Load used functions + . (Join-Path '$(System.DefaultWorkingDirectory)' 'utilities' 'pipelines' 'sharedScripts' 'Set-EnvironmentOnAgent.ps1') + + # Define PS modules to install on the runner + $Modules = @( + @{ Name = 'Az.Storage' } + ) + + # Set agent up + Set-EnvironmentOnAgent -PSModules $Modules + - task: AzurePowerShell@5 + displayName: Upload files to storage account + inputs: + azureSubscription: $(serviceConnection) + ScriptType: 'InlineScript' + Inline: | + # Load used functions + . (Join-Path '$(Build.SourcesDirectory)' 'utilities' 'pipelines' 'sharedScripts' 'Export-ContentToBlob.ps1') + + # Get storage account name + $parameterFilePath = Join-Path '$(Build.SourcesDirectory)' '$(dependencyPath)' '$(resourceType)' 'parameters' 'parameters.json' + $storageAccountParameters = (ConvertFrom-Json (Get-Content -path $parameterFilePath -Raw)).parameters + + # Upload files to storage account + $functionInput = @{ + ResourceGroupName = '$(defaultResourceGroupName)' + StorageAccountName = $storageAccountParameters.name.value + contentDirectories = Join-Path '$(Build.SourcesDirectory)' $(dependencyPath) '$(resourceType)' 'uploads' + targetContainer = $storageAccountParameters.blobServices.value.containers[0].name + } + + Write-Verbose "Invoke task with" -Verbose + Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose + + Export-ContentToBlob @functionInput -Verbose + azurePowerShellVersion: 'LatestVersion' + pwsh: true + + - stage: deploy_sig + displayName: Deploy shared image gallery and definition + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.Compute/galleries' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default SIG and SID + + - stage: deploy_ag + displayName: Deploy action groups + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.Insights/actionGroups' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Action Group + + - stage: deploy_asg + displayName: Deploy application security groups + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.Network/applicationSecurityGroups' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Application Security Groups + + - stage: deploy_udr + displayName: Deploy route tables + dependsOn: + - deploy_rg + variables: + resourceType: 'Microsoft.Network/routeTables' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default User Defined Routes + - ${{ if eq( parameters.deploySqlMiDependencies, true) }}: + - path: $(dependencyPath)/$(resourceType)/parameters/sqlMi.parameters.json + templateFilePath: $(templateFilePath) + displayName: SQLMI User Defined Routes + + - stage: deploy_nsg + displayName: Deploy network security groups + dependsOn: + - deploy_sa + - deploy_evh + - deploy_law + variables: + resourceType: 'Microsoft.Network/networkSecurityGroups' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default NSG + - path: $(dependencyPath)/$(resourceType)/parameters/apgw.parameters.json + templateFilePath: $(templateFilePath) + displayName: App Gateway NSG + - path: $(dependencyPath)/$(resourceType)/parameters/ase.parameters.json + templateFilePath: $(templateFilePath) + displayName: ASE NSG + - path: $(dependencyPath)/$(resourceType)/parameters/bastion.parameters.json + templateFilePath: $(templateFilePath) + displayName: Bastion NSG + - ${{ if eq( parameters.deploySqlMiDependencies, true) }}: + - path: $(dependencyPath)/$(resourceType)/parameters/sqlmi.parameters.json + templateFilePath: $(templateFilePath) + displayName: SQLMI NSG + + - stage: deploy_pip + displayName: Deploy public IP addresses + dependsOn: + - deploy_sa + - deploy_evh + - deploy_law + variables: + resourceType: 'Microsoft.Network\publicIPAddresses' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/apgw.parameters.json + templateFilePath: $(templateFilePath) + displayName: App Gateway Public IP + - path: $(dependencyPath)/$(resourceType)/parameters/bas.parameters.json + templateFilePath: $(templateFilePath) + displayName: Bastion Public IP + - path: $(dependencyPath)/$(resourceType)/parameters/lb.parameters.json + templateFilePath: $(templateFilePath) + displayName: Load balancer Public IP + + - stage: deploy_appi + displayName: Deploy application insight + dependsOn: + - deploy_sa + - deploy_evh + - deploy_law + variables: + resourceType: 'Microsoft.Insights/components' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Application Insights + + - stage: deploy_aut + displayName: Deploy automation account + dependsOn: + - deploy_sa + - deploy_evh + - deploy_law + variables: + resourceType: 'Microsoft.Automation/automationAccounts' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Automation Account + + - stage: deploy_avdhp + displayName: Deploy AVD host pool + dependsOn: + - deploy_sa + - deploy_evh + - deploy_law + variables: + resourceType: 'Microsoft.DesktopVirtualization/hostpools' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default AVD Host Pool + + - stage: deploy_rsv + displayName: Deploy recovery services vault + dependsOn: + - deploy_sa + - deploy_evh + - deploy_law + variables: + resourceType: 'Microsoft.RecoveryServices/vaults' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default recovery services vault + + - stage: deploy_kv + displayName: Deploy key vaults + dependsOn: + - deploy_sa + - deploy_evh + - deploy_law + variables: + resourceType: 'Microsoft.KeyVault/vaults' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Key Vault + jobName: default_kv + - path: $(dependencyPath)/$(resourceType)/parameters/pe.parameters.json + templateFilePath: $(templateFilePath) + displayName: Private Endpoint Key Vault + - ${{ if eq( parameters.deploySqlMiDependencies, true) }}: + - path: $(dependencyPath)/$(resourceType)/parameters/sqlmi.parameters.json + templateFilePath: $(templateFilePath) + displayName: SQLMI key vault + jobName: sqlmi_kv + - job: + displayName: Set key vault secrets keys and certificates + dependsOn: + - default_kv + pool: + ${{ if eq(variables['vmImage'], '') }}: + name: $(poolName) + ${{ if eq(variables['poolName'], '') }}: + vmImage: $(vmImage) + steps: + - task: PowerShell@2 + displayName: 'Setup agent' + inputs: + targetType: inline + pwsh: true + script: | + # Load used functions + . (Join-Path '$(System.DefaultWorkingDirectory)' 'utilities' 'pipelines' 'sharedScripts' 'Set-EnvironmentOnAgent.ps1') + + # Define PS modules to install on the runner + $Modules = @( + @{ Name = 'Az.KeyVault' } + ) + + # Set agent up + Set-EnvironmentOnAgent -PSModules $Modules + - task: AzurePowerShell@5 + displayName: Set key vault secrets keys and certificates + inputs: + azureSubscription: $(serviceConnection) + ScriptType: 'InlineScript' + Inline: | + # Get key vault name + $parameterFilePath = Join-Path '$(Build.SourcesDirectory)' '$(dependencyPath)' '$(resourceType)' 'parameters' 'parameters.json' + $keyVaultParameters = (ConvertFrom-Json (Get-Content -Path $parameterFilePath -Raw)).parameters + $keyVaultName = $keyVaultParameters.name.value + + # Generate values + $usernameString = ( -join ((65..90) + (97..122) | Get-Random -Count 9 -SetSeed 1 | ForEach-Object { [char]$_ + "$_" })).substring(0, 19) # max length + $userName = ConvertTo-SecureString -String $usernameString -AsPlainText -Force + $passwordString = (New-Guid).Guid.SubString(0, 19) + $password = ConvertTo-SecureString -String $passwordString -AsPlainText -Force + $vpnSharedKeyString = (New-Guid).Guid.SubString(0, 32) + $vpnSharedKey = ConvertTo-SecureString -String $vpnSharedKeyString -AsPlainText -Force + + # Set secrets + # ------- + @( + @{ name = 'adminUsername'; secretValue = $username } # VirtualMachines and VMSS + @{ name = 'adminPassword'; secretValue = $password } # VirtualMachines and VMSS + @{ name = 'administratorLogin'; secretValue = $username } # Azure SQLServer + @{ name = 'administratorLoginPassword'; secretValue = $password } # Azure SQLServer + @{ name = 'vpnSharedKey'; secretValue = $vpnSharedKey } # VirtualNetworkGateway + @{ name = 'apimClientId'; secretValue = $username } # API management + @{ name = 'apimClientSecret'; secretValue = $password } # API management + ) | ForEach-Object { + $null = Set-AzKeyVaultSecret -VaultName $keyVaultName -Name $_.name -SecretValue $_.secretValue + Write-Verbose ('Added secret [{0}] to key vault [{1}]' -f $_.name, $keyVaultName) -Verbose + } + + # Certificats + # ----------- + $certPolicy = New-AzKeyVaultCertificatePolicy -SecretContentType 'application/x-pkcs12' -SubjectName 'CN=fabrikam.com' -IssuerName 'Self' -ValidityInMonths 12 -ReuseKeyOnRenewal + @( + @{ name = 'applicationGatewaySslCertificate'; CertificatePolicy = $certPolicy } # ApplicationGateway + ) | ForEach-Object { + $null = Add-AzKeyVaultCertificate -VaultName $keyVaultName -Name $_.name -CertificatePolicy $_.CertificatePolicy + Write-Verbose ('Added certificate [{0}] to key vault [{1}]' -f $_.name, $keyVaultName) -Verbose + } + + # Set keys + # ---- + @( + @{ name = 'keyEncryptionKey'; Destination = 'Software' } # DiskEncryptionSet, VirtualMachines and VMSS + ) | ForEach-Object { + $null = Add-AzKeyVaultKey -VaultName $keyVaultName -Name $_.name -Destination $_.Destination + Write-Verbose ('Added key [{0}] to key vault [{1}]' -f $_.name, $keyVaultName) -Verbose + } + azurePowerShellVersion: 'LatestVersion' + pwsh: true + + - ${{ if eq( parameters.deploySqlMiDependencies, true) }}: + - job: + displayName: Set sqlmi key vault secrets and keys + condition: eq(${{ parameters.deploySqlMiDependencies }}, true) + dependsOn: + - sqlmi_kv + pool: + ${{ if eq(variables['vmImage'], '') }}: + name: $(poolName) + ${{ if eq(variables['poolName'], '') }}: + vmImage: $(vmImage) + steps: + - task: PowerShell@2 + displayName: 'Setup agent' + inputs: + targetType: inline + pwsh: true + script: | + # Load used functions + . (Join-Path '$(System.DefaultWorkingDirectory)' 'utilities' 'pipelines' 'sharedScripts' 'Set-EnvironmentOnAgent.ps1') + + # Define PS modules to install on the runner + $Modules = @( + @{ Name = 'Az.KeyVault' } + ) + + # Set agent up + Set-EnvironmentOnAgent -PSModules $Modules + - task: AzurePowerShell@5 + displayName: Set sqlmi key vault secrets and keys + inputs: + azureSubscription: $(serviceConnection) + ScriptType: 'InlineScript' + Inline: | + # Get key vault name + $parameterFilePath = Join-Path '$(Build.SourcesDirectory)' '$(dependencyPath)' '$(resourceType)' 'parameters' 'sqlmi.parameters.json' + $keyVaultParameters = (ConvertFrom-Json (Get-Content -Path $parameterFilePath -Raw)).parameters + $keyVaultName = $keyVaultParameters.name.value + + # Generate values + $usernameString = ( -join ((65..90) + (97..122) | Get-Random -Count 9 -SetSeed 1 | ForEach-Object { [char]$_ + "$_" })).substring(0, 19) # max length + $userName = ConvertTo-SecureString -String $usernameString -AsPlainText -Force + $passwordString = (New-Guid).Guid.SubString(0, 19) + $password = ConvertTo-SecureString -String $passwordString -AsPlainText -Force + + # Set secrets + # ------- + @( + @{ name = 'administratorLogin'; secretValue = $username } # SQLManagedInstances + @{ name = 'administratorLoginPassword'; secretValue = $password } # SQLManagedInstances + ) | ForEach-Object { + $null = Set-AzKeyVaultSecret -VaultName $keyVaultName -Name $_.name -SecretValue $_.secretValue + Write-Verbose ('Added secret [{0}] to key vault [{1}]' -f $_.name, $keyVaultName) -Verbose + } + + # Set keys + # ---- + @( + @{ name = 'keyEncryptionKeySqlMi'; Destination = 'Software' } # SQLManagedInstances + ) | ForEach-Object { + $null = Add-AzKeyVaultKey -VaultName $keyVaultName -Name $_.name -Destination $_.Destination + Write-Verbose ('Added key [{0}] to key vault [{1}]' -f $_.name, $keyVaultName) -Verbose + } + azurePowerShellVersion: 'LatestVersion' + pwsh: true + + - stage: deploy_avdag + displayName: Deploy AVD application group + dependsOn: + - deploy_avdhp + variables: + resourceType: 'Microsoft.DesktopVirtualization/applicationgroups' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Application Group + + - stage: deploy_rolea + displayName: Deploy role assignments + dependsOn: + - deploy_msi + variables: + resourceType: 'Microsoft.Authorization\roleAssignments' + templateFilePath: $(modulesPath)/$(resourceType)/.bicep/nested_rbac_sub.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: MSI Role Assignment + + - stage: deploy_vnet + displayName: Deploy virtual networks + dependsOn: + - deploy_nsg + - ${{ if eq( parameters.deploySqlMiDependencies, true) }}: + - deploy_udr + variables: + resourceType: 'Microsoft.Network/virtualNetworks' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Virtual Network + - path: $(dependencyPath)/$(resourceType)/parameters/1.bastion.parameters.json + templateFilePath: $(templateFilePath) + displayName: Bastion Virtual Network + - path: $(dependencyPath)/$(resourceType)/parameters/2.vnetpeer01.parameters.json + templateFilePath: $(templateFilePath) + displayName: VNET PEering 1 Virtual Network + - path: $(dependencyPath)/$(resourceType)/parameters/3.vnetpeer02.parameters.json + templateFilePath: $(templateFilePath) + displayName: VNET Peering 2 Virtual Network + - path: $(dependencyPath)/$(resourceType)/parameters/4.azfw.parameters.json + templateFilePath: $(templateFilePath) + displayName: Azure Firewall Virtual Network + - path: $(dependencyPath)/$(resourceType)/parameters/5.aks.parameters.json + templateFilePath: $(templateFilePath) + displayName: AKS Virtual Network + - ${{ if eq( parameters.deploySqlMiDependencies, true) }}: + - path: $(dependencyPath)/$(resourceType)/parameters/6.sqlmi.parameters.json + templateFilePath: $(templateFilePath) + displayName: SQL MI Virtual Network + + - stage: deploy_dnszone + displayName: Deploy private DNS zones + dependsOn: + - deploy_vnet + variables: + resourceType: 'Microsoft.Network/privateDnsZones' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Private DNS Zones + + - stage: deploy_vm + displayName: Deploy virtual machines + dependsOn: + - deploy_vnet + - deploy_rsv + - deploy_kv + variables: + resourceType: 'Microsoft.Compute/virtualMachines' + templateFilePath: $(modulesPath)/$(resourceType)/deploy.bicep + jobs: + - template: /.azuredevops/pipelineTemplates/module.jobs.deploy.yml + parameters: + deploymentBlocks: + - path: $(dependencyPath)/$(resourceType)/parameters/parameters.json + templateFilePath: $(templateFilePath) + displayName: Default Virtual Machine diff --git a/.github/workflows/platform.dependencies.yml b/.github/workflows/platform.dependencies.yml index fdce96ce03..3a7c306611 100644 --- a/.github/workflows/platform.dependencies.yml +++ b/.github/workflows/platform.dependencies.yml @@ -13,13 +13,13 @@ on: # branches: # - main # paths: - # - '.github/actions/templates/**' + # - '.github/actions/templates/validateModuleDeployment/**' # - '.github/workflows/platform.dependencies.yml' # - 'utilities/pipelines/dependencies/**' env: defaultLocation: 'WestEurope' - resourceGroupName: 'validation-rg' + defaultResourceGroupName: 'validation-rg' resourceGroupNameArtifacts: 'artifacts-rg' removeDeployment: 'false' dependencyPath: 'utilities/pipelines/dependencies' @@ -38,8 +38,7 @@ jobs: strategy: fail-fast: false matrix: - parameterFilePaths: - ['artifacts.parameters.json', 'validation.parameters.json'] + parameterFilePaths: ['validation.parameters.json'] steps: - name: 'Checkout' uses: actions/checkout@v2 @@ -51,7 +50,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -78,7 +77,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -105,34 +104,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/.bicep/nested_policyAssignments_sub.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' - subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' - managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' - removeDeployment: '${{ env.removeDeployment }}' - - job_deploy_privateBicepRegistry: - runs-on: ubuntu-20.04 - name: 'Deploy private bicep registry' - env: - namespace: 'Microsoft.ContainerRegistry\registries' - needs: - - job_deploy_rg - strategy: - fail-fast: false - matrix: - parameterFilePaths: ['parameters.json'] - steps: - - name: 'Checkout' - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: 'Deploy module' - uses: ./.github/actions/templates/validateModuleDeployment - with: - templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' - parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' - location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupNameArtifacts }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -159,7 +131,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -186,7 +158,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -214,14 +186,16 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' - job_upload_storage_files: + job_sa_upload_storage_files: runs-on: ubuntu-20.04 name: 'Upload files to storage account' + env: + namespace: 'Microsoft.Storage\storageAccounts' needs: - job_deploy_sa steps: @@ -229,6 +203,19 @@ jobs: uses: actions/checkout@v2 with: fetch-depth: 0 + - name: 'Setup agent' + shell: pwsh + run: | + # Load used functions + . (Join-Path $env:GITHUB_WORKSPACE 'utilities' 'pipelines' 'sharedScripts' 'Set-EnvironmentOnAgent.ps1') + + # Define PS modules to install on the runner + $Modules = @( + @{ Name = 'Az.Storage' } + ) + + # Set agent up + Set-EnvironmentOnAgent -PSModules $Modules - name: Azure Login uses: azure/login@v1 with: @@ -242,14 +229,14 @@ jobs: . (Join-Path $env:GITHUB_WORKSPACE 'utilities' 'pipelines' 'sharedScripts' 'Export-ContentToBlob.ps1') # Get storage account name - $parameterFilePath = Join-Path $env:GITHUB_WORKSPACE '${{ env.dependencyPath }}' 'Microsoft.Storage/storageAccounts' 'parameters' 'parameters.json' + $parameterFilePath = Join-Path $env:GITHUB_WORKSPACE '${{ env.dependencyPath }}' '${{ env.namespace }}' 'parameters' 'parameters.json' $storageAccountParameters = (ConvertFrom-Json (Get-Content -path $parameterFilePath -Raw)).parameters # Upload files to storage account $functionInput = @{ - ResourceGroupName = '${{ env.resourceGroupName }}' + ResourceGroupName = '${{ env.defaultResourceGroupName }}' StorageAccountName = $storageAccountParameters.name.value - contentDirectories = Join-Path $env:GITHUB_WORKSPACE '${{ env.dependencyPath }}' 'Microsoft.Storage/storageAccounts' 'uploads' + contentDirectories = Join-Path $env:GITHUB_WORKSPACE '${{ env.dependencyPath }}' '${{ env.namespace }}' 'uploads' targetContainer = $storageAccountParameters.blobServices.value.containers[0].name } @@ -281,7 +268,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -308,7 +295,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -335,14 +322,14 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' job_deploy_udr: runs-on: ubuntu-20.04 - name: 'Deploy sqlmi route tables' + name: 'Deploy route tables' env: namespace: 'Microsoft.Network\routeTables' needs: @@ -362,7 +349,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -390,7 +377,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -425,7 +412,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -455,7 +442,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -485,7 +472,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -514,7 +501,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -543,7 +530,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -572,7 +559,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -601,7 +588,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -630,7 +617,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -638,6 +625,8 @@ jobs: job_deploy_kv_secrets: runs-on: ubuntu-20.04 name: 'Set key vault secrets keys and certificates' + env: + namespace: 'Microsoft.KeyVault\vaults' needs: - job_deploy_kv steps: @@ -645,38 +634,74 @@ jobs: uses: actions/checkout@v2 with: fetch-depth: 0 + - name: 'Setup agent' + shell: pwsh + run: | + # Load used functions + . (Join-Path $env:GITHUB_WORKSPACE 'utilities' 'pipelines' 'sharedScripts' 'Set-EnvironmentOnAgent.ps1') + + # Define PS modules to install on the runner + $Modules = @( + @{ Name = 'Az.KeyVault' } + ) + + # Set agent up + Set-EnvironmentOnAgent -PSModules $Modules - name: Azure Login uses: azure/login@v1 with: creds: ${{ secrets.AZURE_CREDENTIALS }} enable-AzPSSession: true - - name: Run PowerShell + - name: 'Set key vault secrets keys and certificates' uses: azure/powershell@v1 with: inlineScript: | - $usernameString = (-join ((65..90) + (97..122) | Get-Random -Count 9 -SetSeed 1 | % {[char]$_ + "$_"})).substring(0,19) # max length - $passwordString = (New-Guid).Guid.SubString(0,19) - $vpnSharedKeyString = (New-Guid).Guid.SubString(0,32) - $keyVaultName = 'adp-sxx-az-kv-x-001' + # Get key vault name + $parameterFilePath = Join-Path $env:GITHUB_WORKSPACE 'utilities' 'pipelines' 'dependencies' '${{ env.namespace }}' 'parameters' 'parameters.json' + $keyVaultParameters = (ConvertFrom-Json (Get-Content -Path $parameterFilePath -Raw)).parameters + $keyVaultName = $keyVaultParameters.name.value + + # Generate values + $usernameString = ( -join ((65..90) + (97..122) | Get-Random -Count 9 -SetSeed 1 | ForEach-Object { [char]$_ + "$_" })).substring(0, 19) # max length $userName = ConvertTo-SecureString -String $usernameString -AsPlainText -Force + $passwordString = (New-Guid).Guid.SubString(0, 19) $password = ConvertTo-SecureString -String $passwordString -AsPlainText -Force + $vpnSharedKeyString = (New-Guid).Guid.SubString(0, 32) $vpnSharedKey = ConvertTo-SecureString -String $vpnSharedKeyString -AsPlainText -Force - # VirtualMachines and VMSS - Set-AzKeyVaultSecret -VaultName $keyVaultName -Name 'adminUsername' -SecretValue $username - Set-AzKeyVaultSecret -VaultName $keyVaultName -Name 'adminPassword' -SecretValue $password - # Azure SQLServer - Set-AzKeyVaultSecret -VaultName $keyVaultName -Name 'administratorLogin' -SecretValue $username - Set-AzKeyVaultSecret -VaultName $keyVaultName -Name 'administratorLoginPassword' -SecretValue $password - # VirtualNetworkGateway - Set-AzKeyVaultSecret -VaultName $keyVaultName -Name 'vpnSharedKey' -SecretValue $vpnSharedKey - # DiskEncryptionSet, VirtualMachines and VMSS - az keyvault key create --vault-name $keyVaultName --name 'keyEncryptionKey' - # ApplicationGateway - $apgwCertPolicy = New-AzKeyVaultCertificatePolicy -SecretContentType 'application/x-pkcs12' -SubjectName 'CN=fabrikam.com' -IssuerName 'Self' -ValidityInMonths 12 -ReuseKeyOnRenewal - Add-AzKeyVaultCertificate -VaultName $keyVaultName -Name 'applicationGatewaySslCertificate' -CertificatePolicy $apgwCertPolicy - # API management - Set-AzKeyVaultSecret -VaultName $keyVaultName -Name 'apimclientid' -SecretValue $username - Set-AzKeyVaultSecret -VaultName $keyVaultName -Name 'apimclientsecret' -SecretValue $password + + # Set secrets + # ------- + @( + @{ name = 'adminUsername'; secretValue = $username } # VirtualMachines and VMSS + @{ name = 'adminPassword'; secretValue = $password } # VirtualMachines and VMSS + @{ name = 'administratorLogin'; secretValue = $username } # Azure SQLServer + @{ name = 'administratorLoginPassword'; secretValue = $password } # Azure SQLServer + @{ name = 'vpnSharedKey'; secretValue = $vpnSharedKey } # VirtualNetworkGateway + @{ name = 'apimClientId'; secretValue = $username } # API management + @{ name = 'apimClientSecret'; secretValue = $password } # API management + ) | ForEach-Object { + $null = Set-AzKeyVaultSecret -VaultName $keyVaultName -Name $_.name -SecretValue $_.secretValue + Write-Verbose ('Added secret [{0}] to key vault [{1}]' -f $_.name, $keyVaultName) -Verbose + } + + # Set certificates + # ----------- + $certPolicy = New-AzKeyVaultCertificatePolicy -SecretContentType 'application/x-pkcs12' -SubjectName 'CN=fabrikam.com' -IssuerName 'Self' -ValidityInMonths 12 -ReuseKeyOnRenewal + @( + @{ name = 'applicationGatewaySslCertificate'; CertificatePolicy = $certPolicy } # ApplicationGateway + ) | ForEach-Object { + $null = Add-AzKeyVaultCertificate -VaultName $keyVaultName -Name $_.name -CertificatePolicy $_.CertificatePolicy + Write-Verbose ('Added certificate [{0}] to key vault [{1}]' -f $_.name, $keyVaultName) -Verbose + } + + # Set keys + # ---- + @( + @{ name = 'keyEncryptionKey'; Destination = 'Software' } # DiskEncryptionSet, VirtualMachines and VMSS + ) | ForEach-Object { + $null = Add-AzKeyVaultKey -VaultName $keyVaultName -Name $_.name -Destination $_.Destination + Write-Verbose ('Added key [{0}] to key vault [{1}]' -f $_.name, $keyVaultName) -Verbose + } azPSVersion: 'latest' job_deploy_sqlmi_kv: @@ -704,7 +729,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -715,32 +740,64 @@ jobs: if: github.event.inputs.deploySqlMiDependencies == 'true' needs: - job_deploy_sqlmi_kv + env: + namespace: 'Microsoft.KeyVault\vaults' steps: - name: 'Checkout' uses: actions/checkout@v2 with: fetch-depth: 0 + - name: 'Setup agent' + shell: pwsh + run: | + # Load used functions + . (Join-Path $env:GITHUB_WORKSPACE 'utilities' 'pipelines' 'sharedScripts' 'Set-EnvironmentOnAgent.ps1') + + # Define PS modules to install on the runner + $Modules = @( + @{ Name = 'Az.KeyVault' } + ) + + # Set agent up + Set-EnvironmentOnAgent -PSModules $Modules - name: Azure Login uses: azure/login@v1 with: creds: ${{ secrets.AZURE_CREDENTIALS }} enable-AzPSSession: true - - name: Run PowerShell + - name: 'Set sqlmi key vault secrets and keys' uses: azure/powershell@v1 with: inlineScript: | - $usernameString = (-join ((65..90) + (97..122) | Get-Random -Count 9 -SetSeed 1 | % {[char]$_ + "$_"})).substring(0,19) # max length - $passwordString = (New-Guid).Guid.SubString(0,19) - $vpnSharedKeyString = (New-Guid).Guid.SubString(0,32) - $keyVaultName = 'adp-sxx-az-kv-x-sqlmi' + # Get key vault name + $parameterFilePath = Join-Path $env:GITHUB_WORKSPACE 'utilities' 'pipelines' 'dependencies' '${{ env.namespace }}' 'parameters' 'sqlmi.parameters.json' + $keyVaultParameters = (ConvertFrom-Json (Get-Content -Path $parameterFilePath -Raw)).parameters + $keyVaultName = $keyVaultParameters.name.value + + # Generate values + $usernameString = ( -join ((65..90) + (97..122) | Get-Random -Count 9 -SetSeed 1 | ForEach-Object { [char]$_ + "$_" })).substring(0, 19) # max length $userName = ConvertTo-SecureString -String $usernameString -AsPlainText -Force + $passwordString = (New-Guid).Guid.SubString(0, 19) $password = ConvertTo-SecureString -String $passwordString -AsPlainText -Force - $vpnSharedKey = ConvertTo-SecureString -String $vpnSharedKeyString -AsPlainText -Force - # SQLManagedInstances secrets - Set-AzKeyVaultSecret -VaultName $keyVaultName -Name 'administratorLogin' -SecretValue $username - Set-AzKeyVaultSecret -VaultName $keyVaultName -Name 'administratorLoginPassword' -SecretValue $password - # SQLManagedInstances Keys - az keyvault key create --vault-name $keyVaultName --name 'keyEncryptionKeySqlMi' + + # Set secrets + # ------- + @( + @{ name = 'administratorLogin'; secretValue = $username } # SQLManagedInstances + @{ name = 'administratorLoginPassword'; secretValue = $password } # SQLManagedInstances + ) | ForEach-Object { + $null = Set-AzKeyVaultSecret -VaultName $keyVaultName -Name $_.name -SecretValue $_.secretValue + Write-Verbose ('Added secret [{0}] to key vault [{1}]' -f $_.name, $keyVaultName) -Verbose + } + + # Set keys + # ---- + @( + @{ name = 'keyEncryptionKeySqlMi'; Destination = 'Software' } # SQLManagedInstances + ) | ForEach-Object { + $null = Add-AzKeyVaultKey -VaultName $keyVaultName -Name $_.name -Destination $_.Destination + Write-Verbose ('Added key [{0}] to key vault [{1}]' -f $_.name, $keyVaultName) -Verbose + } azPSVersion: 'latest' job_deploy_avdag: @@ -765,7 +822,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -792,7 +849,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/.bicep/nested_rbac_sub.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -827,7 +884,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -856,7 +913,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -883,7 +940,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' @@ -912,7 +969,7 @@ jobs: templateFilePath: 'arm/${{ env.namespace }}/deploy.bicep' parameterFilePath: '${{ env.dependencyPath }}/${{ env.namespace }}/parameters/${{ matrix.parameterFilePaths }}' location: '${{ env.defaultLocation }}' - resourceGroupName: '${{ env.resourceGroupName }}' + resourceGroupName: '${{ env.defaultResourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' removeDeployment: '${{ env.removeDeployment }}' diff --git a/arm/Microsoft.Compute/virtualMachines/deploy.bicep b/arm/Microsoft.Compute/virtualMachines/deploy.bicep index 06ebfb7661..9837490f3d 100644 --- a/arm/Microsoft.Compute/virtualMachines/deploy.bicep +++ b/arm/Microsoft.Compute/virtualMachines/deploy.bicep @@ -582,10 +582,10 @@ module virtualMachine_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, in @description('The name of the VM.') output virtualMachineName string = virtualMachine.name -@description('The Resource ID of the VM.') +@description('The resource ID of the VM.') output virtualMachineResourceId string = virtualMachine.id -@description('The name of the Resource Group the VM was created in.') +@description('The name of the resource group the VM was created in.') output virtualMachineResourceGroup string = resourceGroup().name @description('The principal ID of the system assigned identity.') diff --git a/docs/wiki/KnownIssues.md b/docs/wiki/KnownIssues.md index d01ff00a3f..e16755646c 100644 --- a/docs/wiki/KnownIssues.md +++ b/docs/wiki/KnownIssues.md @@ -33,7 +33,3 @@ We have yet to implement the full set of parameter files we need in order to tes # Pipeline specific This section outlines known issues that currently affect our pipelines. - -## Azure DevOps Dependency pipeline - -There is currently no dependency pipeline for our Azure DevOps solution. diff --git a/docs/wiki/UtilitiesRegisterAzureDevOpsPipeline.md b/docs/wiki/UtilitiesRegisterAzureDevOpsPipeline.md index daf7e74fd2..5cf7f02b2d 100644 --- a/docs/wiki/UtilitiesRegisterAzureDevOpsPipeline.md +++ b/docs/wiki/UtilitiesRegisterAzureDevOpsPipeline.md @@ -13,7 +13,7 @@ Use this script to automatically register all specified Azure DevOps pipelines i --- # Location -You can find the script under `/utilities/tools/Register-AzureDevOpsPipeline.ps1` +You can find the script under `/utilities/tools/AzureDevOps/Register-AzureDevOpsPipeline.ps1` # How it works diff --git a/utilities/pipelines/dependencies/Microsoft.ContainerRegistry/registries/parameters/parameters.json b/utilities/pipelines/dependencies/Microsoft.ContainerRegistry/registries/parameters/parameters.json deleted file mode 100644 index 52597e8a27..0000000000 --- a/utilities/pipelines/dependencies/Microsoft.ContainerRegistry/registries/parameters/parameters.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "name": { - "value": "adpsxxazacrx001" - }, - "acrAdminUserEnabled": { - "value": false - } - } -} diff --git a/utilities/pipelines/dependencies/Microsoft.Resources/resourceGroups/parameters/artifacts.parameters.json b/utilities/pipelines/dependencies/Microsoft.Resources/resourceGroups/parameters/artifacts.parameters.json deleted file mode 100644 index eacecdf787..0000000000 --- a/utilities/pipelines/dependencies/Microsoft.Resources/resourceGroups/parameters/artifacts.parameters.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "name": { - "value": "artifacts-rg" - } - } -} diff --git a/utilities/tools/Register-AzureDevOpsPipeline.ps1 b/utilities/tools/AzureDevOps/Register-AzureDevOpsPipeline.ps1 similarity index 100% rename from utilities/tools/Register-AzureDevOpsPipeline.ps1 rename to utilities/tools/AzureDevOps/Register-AzureDevOpsPipeline.ps1 diff --git a/utilities/tools/AzureDevOps/Set-DevOpsPipelineFiles.ps1 b/utilities/tools/AzureDevOps/Set-DevOpsPipelineFile.ps1 similarity index 99% rename from utilities/tools/AzureDevOps/Set-DevOpsPipelineFiles.ps1 rename to utilities/tools/AzureDevOps/Set-DevOpsPipelineFile.ps1 index 7c59ed44ad..6718e99626 100644 --- a/utilities/tools/AzureDevOps/Set-DevOpsPipelineFiles.ps1 +++ b/utilities/tools/AzureDevOps/Set-DevOpsPipelineFile.ps1 @@ -30,11 +30,11 @@ Optional. The path to the GitHub workflows folder to crawl from Defaults to: '.github/workflows' .EXAMPLE -Set-DevOpsPipelineFiles +Set-DevOpsPipelineFile Generate all Azure DevOps pipeline files in the default DevOps pipeline folder based on the workflows files in the default workflows folder based on the provided default template #> -function Set-DevOpsPipelineFiles { +function Set-DevOpsPipelineFile { [CmdletBinding(SupportsShouldProcess)]