From 78b4b7745d122732625f5eefb45b4e1bb979cb39 Mon Sep 17 00:00:00 2001 From: Manuel Date: Wed, 2 Sep 2026 09:24:12 +0200 Subject: [PATCH] update automation lab for GHCP App Mod --- .../labautomation/deploy-lab.ps1 | 19 ++++- .../labautomation/lab-defaults.json | 2 +- .../labautomation/main.bicep | 0 .../labautomation/shared-deploy-lab.ps1 | 78 +++++++++++++++++++ 4 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 03-Azure/01-01-App Innovation/03_GHCPAppModernization/labautomation/main.bicep create mode 100644 03-Azure/01-01-App Innovation/03_GHCPAppModernization/labautomation/shared-deploy-lab.ps1 diff --git a/03-Azure/01-01-App Innovation/03_GHCPAppModernization/labautomation/deploy-lab.ps1 b/03-Azure/01-01-App Innovation/03_GHCPAppModernization/labautomation/deploy-lab.ps1 index 03547a904..94f09bed6 100644 --- a/03-Azure/01-01-App Innovation/03_GHCPAppModernization/labautomation/deploy-lab.ps1 +++ b/03-Azure/01-01-App Innovation/03_GHCPAppModernization/labautomation/deploy-lab.ps1 @@ -48,7 +48,12 @@ if($DeploymentType -eq 'subscription') { $stableHash = Get-MhhStablehash $AllowedEntraUserIds -Length 24 $effectiveResourceGroup = "lab-$stableHash" Write-Host "Deploying lab resources at the subscription level in subscription $SubscriptionId..." - New-AzResourceGroup -Name $effectiveResourceGroup -Location $effectiveLocation -Verbose + if(-not (Get-AzResourceGroup -Name $effectiveResourceGroup -ErrorAction SilentlyContinue)) { + Write-Host "Creating resource group '$effectiveResourceGroup' in location '$effectiveLocation'..." + New-AzResourceGroup -Name $effectiveResourceGroup -Location $effectiveLocation -Verbose + } else { + Write-Host "Resource group '$effectiveResourceGroup' already exists." + } } else { $effectiveResourceGroup = $ResourceGroupName @@ -56,9 +61,19 @@ else { # feed the effective resource group back to the console @{"HackboxCredential" = @{ name = "ResourceGroupName" ; value = $effectiveResourceGroup; note = "The name of the resource group where lab resources are deployed" }} + # $template = Join-Path $scriptPath "template.bicep" # $template = Join-Path $scriptPath "template.json" -# New-AzResourceGroupDeployment -ResourceGroupName $effectiveResourceGroup -TemplateFile $template -Verbose +<# +$result = Invoke-MhhDeploymentWithRegionFallback ` + -PreferredLocations $PreferredLocation ` + -ResourceGroupName $effectiveResourceGroup ` + -RgOwnerEntraObjectIds $AllowedEntraUserIds ` + -TemplateFile $template ` + -TemplateParameterObject @{ + userObjectId = $AllowedEntraUserIds[0] + } +#> # You can send back information to the hackbox console (credentials) - Simply return a hashtable like this: # @{"HackboxCredential" = @{ name = "AdminPassword" ; value = "TopSecret"; note = "Useful info here" }} diff --git a/03-Azure/01-01-App Innovation/03_GHCPAppModernization/labautomation/lab-defaults.json b/03-Azure/01-01-App Innovation/03_GHCPAppModernization/labautomation/lab-defaults.json index 0f3a7bd25..86fd26023 100644 --- a/03-Azure/01-01-App Innovation/03_GHCPAppModernization/labautomation/lab-defaults.json +++ b/03-Azure/01-01-App Innovation/03_GHCPAppModernization/labautomation/lab-defaults.json @@ -2,7 +2,7 @@ "$schema": "https://raw.githubusercontent.com/microsoft/MicroHack/refs/heads/main/lab-defaults-schema.json", "groups": [ "GHCPUsers" ], "deploymentType": "resourcegroup", - "labsPerSubscription": 8, + "labsPerSubscription": 20, "preferredLocation": "swedencentral, norwayeast, spaincentral", "estimatedDailyCostsUsd": 25.0 } diff --git a/03-Azure/01-01-App Innovation/03_GHCPAppModernization/labautomation/main.bicep b/03-Azure/01-01-App Innovation/03_GHCPAppModernization/labautomation/main.bicep new file mode 100644 index 000000000..e69de29bb diff --git a/03-Azure/01-01-App Innovation/03_GHCPAppModernization/labautomation/shared-deploy-lab.ps1 b/03-Azure/01-01-App Innovation/03_GHCPAppModernization/labautomation/shared-deploy-lab.ps1 new file mode 100644 index 000000000..48473f08e --- /dev/null +++ b/03-Azure/01-01-App Innovation/03_GHCPAppModernization/labautomation/shared-deploy-lab.ps1 @@ -0,0 +1,78 @@ +<# +.SYNOPSIS +Hook that runs once per subscription before any deploy-lab.ps1 run starts. +.DESCRIPTION +Hook that runs before the per-user deploy-lab.ps1 runs are started. It can be used to deploy shared resources on a subscription level +(e.g. a hub VNet) or to prepare the subscription once instead of once per lab (e.g. registering resource providers). +If it fails for any subscription, no deploy-lab.ps1 runs at all. Emitted HackboxCredential entries are stored for every lab in this subscription. +.PARAMETER SubscriptionId +Specifies the Azure subscription that contains the lab resources. +.PARAMETER PreferredLocation +Specifies the preferred Azure regions (ordered by preference) for resource deployment. +.PARAMETER AllowedEntraUserIds +Entra user object IDs of every participant holding a lab in this subscription. +#> +param( + [Parameter(Mandatory=$true)] + [string]$SubscriptionId, + + [Parameter(Mandatory=$true)] + [string[]]$PreferredLocation = @(), + + [Parameter(Mandatory=$false)] + [string[]]$AllowedEntraUserIds = @() +) + +$scriptPath = Split-Path -Parent $MyInvocation.MyCommand.Definition + + +<# +# EXAMPLE: Register Resource Providers here if needed +$requiredProviders = @( + "Microsoft.Compute", + "Microsoft.Network", + "Microsoft.Storage" +) +foreach($provider in $requiredProviders) { + $state = (Get-AzResourceProvider -ProviderNamespace $provider -ErrorAction SilentlyContinue | Select-Object -First 1).RegistrationState + if($state -ne "Registered") { + Write-Host "[$SubscriptionId] Registering resource provider: $provider" + Register-AzResourceProvider -ProviderNamespace $provider -ErrorAction Stop + } + else { + Write-Host "[$SubscriptionId] Resource provider $provider is already registered." + } +} +#> + + +<# +# EXAMPLE: shared resources, e.g. hub networks, bastion host, etc. can be deployed here... +# no resource group is pre-created for this hook, so pick your own name and never use a participant's resource group +$sharedResourceGroup = "shareddeployment" +if(-not (Get-AzResourceGroup -Name $sharedResourceGroup -ErrorAction SilentlyContinue)) { + Write-Host "[$SubscriptionId] Creating shared resource group: $sharedResourceGroup" + New-AzResourceGroup -Name $sharedResourceGroup -Location $PreferredLocation[0] -ErrorAction Stop +} +else { + Write-Host "[$SubscriptionId] Shared resource group $sharedResourceGroup already exists." +} + +# deploy shared resources in the shared resource group (do not forget to assign the correct rbac roles to the allowed Entra users) +# Invoke-MhhDeploymentWithRegionFallback creates/recreates the resource group, re-grants Owner and falls back to the next region + +# $template = Join-Path $scriptPath "template-shared.bicep" +# $template = Join-Path $scriptPath "template-shared.json" +$result = Invoke-MhhDeploymentWithRegionFallback ` + -PreferredLocations $PreferredLocation ` + -ResourceGroupName $sharedResourceGroup ` + -RgOwnerEntraObjectIds $AllowedEntraUserIds ` + -TemplateFile $template ` + -TemplateParameterObject @{ + userIds = $AllowedEntraUserIds + } +#> + +# You can send back information to the hackbox console (credentials) - Simply return a hashtable like this: +# Note: everything returned here is shown to EVERY participant in this subscription, so never emit per-participant secrets. +# @{"HackboxCredential" = @{ name = "AdminPassword" ; value = "TopSecret"; note = "Useful info here" }}