Skip to content

Commit

Permalink
Support for deploying image build resources in different subscription
Browse files Browse the repository at this point in the history
Register ContainerInstance in subscription for image building
  • Loading branch information
SvenAelterman committed Aug 16, 2024
1 parent 7333bfb commit eb69c10
Show file tree
Hide file tree
Showing 5 changed files with 243 additions and 179 deletions.
21 changes: 17 additions & 4 deletions research-hub/deploy.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,35 @@ param (
Location = $Location
}

Write-Verbose "Using template parameter file '$TemplateParameterFile'"
[string]$TemplateParameterJsonFile = [System.IO.Path]::ChangeExtension($TemplateParameterFile, 'json')
bicep build-params $TemplateParameterFile --outfile $TemplateParameterJsonFile

# Read the values from the parameters file, to use when generating the $DeploymentName value
$ParameterFileContents = (Get-Content $TemplateParameterJsonFile | ConvertFrom-Json)
$WorkloadName = $ParameterFileContents.parameters.workloadName.value
$ImagingSubscriptionId = $ParameterFileContents.parameters.imageBuildSubscriptionId.value

# Import the Azure subscription management module
Import-Module ..\scripts\PowerShell\Modules\AzSubscriptionManagement.psm1

# Determine if a cloud context switch is required for configuring the image build subscription, which could be different from the hub subscription
Set-AzContextWrapper -SubscriptionId $ImagingSubscriptionId -Environment $Environment

# LATER: Run provider and feature registrations in parallel
Register-AzResourceProviderWrapper -ProviderNamespace "Microsoft.Storage"
Register-AzResourceProviderWrapper -ProviderNamespace "Microsoft.ContainerInstance" # For image builder

# Determine if a cloud context switch is required
Set-AzContextWrapper -SubscriptionId $TargetSubscriptionId -Environment $Environment

# Ensure the EncryptionAtHost feature is registered for the current subscription
# LATER: Do this with a deployment script in Bicep
Register-AzProviderFeatureWrapper -ProviderNamespace "Microsoft.Compute" -FeatureName "EncryptionAtHost"
# LATER: Run provider and feature registrations in parallel
Register-AzResourceProviderWrapper -ProviderNamespace "Microsoft.Storage"

# Remove the module from the session (always, even in WhatIf mode)
Remove-Module AzSubscriptionManagement -WhatIf:$false

[string]$DeploymentName = "ResearchHub-$(Get-Date -Format 'yyyyMMddThhmmssZ' -AsUTC)"
[string]$DeploymentName = "$WorkloadName-$(Get-Date -Format 'yyyyMMddThhmmssZ' -AsUTC)"
$CmdLetParameters.Add('Name', $DeploymentName)

$DeploymentResults = New-AzDeployment @CmdLetParameters
Expand Down
195 changes: 195 additions & 0 deletions research-hub/hub-modules/imaging/aib-resources.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
param location string = resourceGroup().location
param tags object
param deploymentNameStructure string
param environment string
param namingConvention string
param sequence int
param workloadName string
param imageReference object
param namingStructure string

param enableAvmTelemetry bool
param sampleImageName string

var customRoleName = 'Azure Image Builder Service Image Creation'
var customRoleGuid = guid(resourceGroup().id, customRoleName)

// Create a custom role that's allowed to create images
resource aibRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' = {
name: customRoleGuid
properties: {
roleName: '${customRoleName} (${customRoleGuid})'
description: 'Image Builder access to create resources for the image build'
assignableScopes: [resourceGroup().id]
permissions: [
{
actions: [
'Microsoft.Compute/galleries/read'
'Microsoft.Compute/galleries/images/read'
'Microsoft.Compute/galleries/images/versions/read'
'Microsoft.Compute/galleries/images/versions/write'

'Microsoft.Compute/images/write'
'Microsoft.Compute/images/read'
'Microsoft.Compute/images/delete'

'Microsoft.Network/virtualNetworks/read'
'Microsoft.Network/virtualNetworks/subnets/join/action'
]
}
]
}
}

// Create dedicated UAMI for image building
module aibUamiModule '../../../shared-modules/security/uami.bicep' = {
name: take(replace(deploymentNameStructure, '{rtype}', 'uami-aib'), 64)
params: {
location: location
tags: tags
uamiName: replace(namingStructure, '{rtype}', 'uami-aib')
}
}

// Assign the new custom role to the UAMI
module uamiImagingRoleAssignmentModule '../../../module-library/roleAssignments/roleAssignment-rg.bicep' = {
name: take(replace(deploymentNameStructure, '{rtype}', 'uami-img-rbac'), 64)
params: {
principalId: aibUamiModule.outputs.principalId
roleDefinitionId: aibRoleDefinition.id
principalType: 'ServicePrincipal'
}
}

var aibNetworkAddressPrefix = '192.168.1.0/24'

module aibNetworkModule '../../../shared-modules/networking/main.bicep' = {
name: take(replace(deploymentNameStructure, '{rtype}', 'network-aib'), 64)
params: {
deploymentNameStructure: deploymentNameStructure
location: location
namingStructure: namingStructure
vnetAddressPrefixes: [aibNetworkAddressPrefix]

subnetDefs: {
ImageBuilderSubnet: {
addressPrefix: cidrSubnet(aibNetworkAddressPrefix, 24, 0)
privateLinkServiceNetworkPolicies: 'Disabled'
// For compliance, all subnets need a NSG
securityRules: []
}
}

tags: tags
}
}

module computeGalleryNameModule '../../../module-library/createValidAzResourceName.bicep' = {
name: take(replace(deploymentNameStructure, '{rtype}', 'galname'), 64)
params: {
environment: environment
location: location
namingConvention: namingConvention
resourceType: 'gal'
sequence: sequence
workloadName: workloadName
subWorkloadName: ''
}
dependsOn: [uamiImagingRoleAssignmentModule]
}

module computeGalleryModule 'br/public:avm/res/compute/gallery:0.3.1' = {
name: take(replace(deploymentNameStructure, '{rtype}', 'gal'), 64)
params: {
name: computeGalleryNameModule.outputs.validName
location: location

images: [
{
hyperVGeneration: 'V2'
name: sampleImageName

// TODO: Customize based on Image Reference
offer: 'WindowsClient'
osType: 'Windows'
publisher: 'Customer'
sku: 'Windows-11-Enterprise-23H2-Gen2'

securityType: 'TrustedLaunch'
isAcceleratedNetworkSupported: true
isHibernateSupported: true
osState: 'Generalized'

// Avoid warnings when using the image from the GUI
maxRecommendedMemory: 4000
maxRecommendedvCPUs: 128
minRecommendedMemory: 4
minRecommendedvCPUs: 2

tags: tags
}
]

tags: tags
enableTelemetry: enableAvmTelemetry
}
}

module imageTemplateModule 'br/public:avm/res/virtual-machine-images/image-template:0.1.1' = {
name: take(replace(deploymentNameStructure, '{rtype}', 'img'), 64)
params: {
name: replace(namingStructure, '{rtype}', 'img')
location: location
imageSource: union(imageReference, { type: 'PlatformImage' })

vmSize: 'Standard_D2as_v5'

// TODO: Load from customizable file
customizationSteps: [
{
type: 'WindowsUpdate'
filters: [
'exclude:$_.Title -like \'*Preview*\''
'include:$true'
]
}
{
type: 'PowerShell'
name: 'Install Microsoft Storage Explorer'
runElevated: true
runAsSystem: true
scriptUri: 'https://raw.githubusercontent.com/SvenAelterman/Azure-HubAndSpokeResearchEnclave/main/scripts/PowerShell/Scripts/AIB/Windows/Install-StorageExplorer.ps1'
sha256Checksum: 'a8122168d9700c8e3b2fe03804e181a88fdc4833bbeee19bd42e58e3d85903c5'
}
{
type: 'PowerShell'
name: 'Install azcopy'
runElevated: true
runAsSystem: true
scriptUri: 'https://raw.githubusercontent.com/SvenAelterman/Azure-HubAndSpokeResearchEnclave/main/scripts/PowerShell/Scripts/AIB/Windows/Install-AzCopy.ps1'
sha256Checksum: '45453a42a0d8d75f4aecb0e83566078373b3320489431b158f8ea4ae08379e59'
}
]

distributions: [
{
type: 'SharedImage'
sharedImageGalleryImageDefinitionResourceId: '${computeGalleryModule.outputs.resourceId}/images/${sampleImageName}'
excludeFromLatest: false
}
]

managedIdentities: {
userAssignedResourceIds: [
aibUamiModule.outputs.id
]
}

subnetResourceId: aibNetworkModule.outputs.createdSubnets.ImageBuilderSubnet.id

enableTelemetry: enableAvmTelemetry
tags: tags
}
}

output imageDefinitionId string = imageTemplateModule.outputs.resourceId
Loading

0 comments on commit eb69c10

Please sign in to comment.