Skip to content
Open
4 changes: 3 additions & 1 deletion azure_jumpstart_localbox/artifacts/PowerShell/Bootstrap.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ param (
[string]$adminUsername,
[string]$adminPassword,
[string]$spnProviderId,
[string]$azureEnvironment,
[string]$tenantId,
[string]$subscriptionId,
[string]$resourceGroup,
Expand All @@ -24,6 +25,7 @@ Write-Output "Input parameters:"
$PSBoundParameters

[System.Environment]::SetEnvironmentVariable('adminUsername', $adminUsername, [System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('azureEnvironment', $azureEnvironment, [System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('tenantId', $tenantId, [System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('spnProviderId', $spnProviderId, [System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable('subscriptionId', $subscriptionId, [System.EnvironmentVariableTarget]::Machine)
Expand Down Expand Up @@ -153,7 +155,7 @@ Import-Module Az.Accounts -RequiredVersion 5.3.1 -Force
Import-Module Az.KeyVault -RequiredVersion 6.4.1 -Force
Import-Module Az.Resources -RequiredVersion 9.0.0 -Force

Connect-AzAccount -Identity
Connect-AzAccount -Identity -Environment $azureEnvironment

$DeploymentProgressString = "Started bootstrap-script..."

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ $Env:LocalBoxDir = "C:\LocalBox"
$LocalBoxConfig = Import-PowerShellDataFile -Path $Env:LocalBoxConfigFile
Start-Transcript -Path "$($LocalBoxConfig.Paths.LogsDir)\Configure-AKSWorkloadCluster.log"

az cloud set --name $Env:azureEnvironment
az login --identity
az config set extension.use_dynamic_install=yes_without_prompt | Out-Null
az extension add --name customlocation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ if (-not (Test-Path -Path $cliDirPath)) {
}

Write-Header "Az CLI Login"
az cloud set --name $Env:azureEnvironment
az login --use-device-code
az account set -s $env:subscriptionId

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ $Env:LocalBoxDir = "C:\LocalBox"
$LocalBoxConfig = Import-PowerShellDataFile -Path $Env:LocalBoxConfigFile
Start-Transcript -Path "$($LocalBoxConfig.Paths.LogsDir)\Configure-VMLogicalNetwork.log"

az cloud set --name $Env:azureEnvironment
az login --identity
az config set extension.use_dynamic_install=yes_without_prompt | Out-Null
az extension add --name customlocation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ $LocalBoxConfig = Import-PowerShellDataFile -Path $Env:LocalBoxConfigFile
Start-Transcript -Path "$($LocalBoxConfig.Paths.LogsDir)\LocalBoxLogonScript.log"

# Login to Azure PowerShell
Connect-AzAccount -Identity -Tenant $Env:tenantId -Subscription $Env:subscriptionId
Connect-AzAccount -Identity -Tenant $Env:tenantId -Subscription $Env:subscriptionId -Environment $Env:azureEnvironment

#####################################################################
# Add RBAC permissions
Expand Down
150 changes: 149 additions & 1 deletion azure_jumpstart_localbox/artifacts/PowerShell/New-LocalBoxCluster.ps1
Original file line number Diff line number Diff line change
@@ -1,4 +1,152 @@
Start-Transcript -Path $Env:LocalBoxLogsDir\New-LocalBoxCluster.log
###################################################################################
<############# Adding Set-AzLocalDeployPrereqs here, as the one defined in the
SDK (https://github.com/Azure/jumpstart-sdk/blob/main/powershell/modules/Azure.Arc.Jumpstart.LocalBox/source/Public/Set-AzLocalDeployPrereqs.ps1)
is hardcoded to AzureCloud. The one below will use AzureUSGovernment cloud.
Also added ConvertFrom-SecureStringToPlainText function to the top since it is called in the Set-AzLocalDeployPrereqs function.
#>#

function ConvertFrom-SecureStringToPlainText {
param (
[Parameter(Mandatory = $true)]
[System.Security.SecureString]$SecureString
)

$Ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString)
try {
return [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($Ptr)
}
finally {
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($Ptr)
}
}
function Set-AzLocalDeployPrereqs {
param (
$LocalBoxConfig,
[PSCredential]$localCred,
[PSCredential]$domainCred
)
Invoke-Command -VMName $LocalBoxConfig.MgmtHostConfig.Hostname -Credential $localCred -ScriptBlock {
$LocalBoxConfig = $using:LocalBoxConfig
$localCred = $using:localcred
$domainCred = $using:domainCred
Invoke-Command -VMName $LocalBoxConfig.DCName -Credential $domainCred -ArgumentList $LocalBoxConfig -ScriptBlock {
$LocalBoxConfig = $args[0]
$domainCredNoDomain = new-object -typename System.Management.Automation.PSCredential `
-argumentlist ($LocalBoxConfig.LCMDeployUsername), (ConvertTo-SecureString $LocalBoxConfig.SDNAdminPassword -AsPlainText -Force)

Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser
Install-Module AsHciADArtifactsPreCreationTool -Repository PSGallery -Force -Confirm:$false
$domainName = $LocalBoxConfig.SDNDomainFQDN.Split('.')
$ouName = "OU=$($LocalBoxConfig.LCMADOUName)"
foreach ($name in $domainName) {
$ouName += ",DC=$name"
}
$nodes = @()
foreach ($node in $LocalBoxConfig.NodeHostConfig) {
$nodes += $node.Hostname.ToString()
}
Add-KdsRootKey -EffectiveTime ((Get-Date).AddHours(-10))
New-HciAdObjectsPreCreation -AzureStackLCMUserCredential $domainCredNoDomain -AsHciOUName $ouName
}
}

$armtoken = ConvertFrom-SecureStringToPlainText -SecureString ((Get-AzAccessToken -AsSecureString).Token)
$clientId = (Get-AzContext).Account.Id
foreach ($node in $LocalBoxConfig.NodeHostConfig) {
Invoke-Command -VMName $node.Hostname -Credential $localCred -ArgumentList $env:subscriptionId, $env:tenantId, $clientId, $armtoken, $env:resourceGroup, $env:azureLocation -ScriptBlock {
$subId = $args[0]
$tenantId = $args[1]
$clientId = $args[2]
$armtoken = $args[3]
$resourceGroup = $args[4]
$location = $args[5]

function ConvertFrom-SecureStringToPlainText {
param (
[Parameter(Mandatory = $true)]
[System.Security.SecureString]$SecureString
)

$Ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString)
try {
return [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($Ptr)
}
finally {
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($Ptr)
}
}

# Prep nodes for Azure Arc onboarding
#winrm quickconfig -quiet
#netsh advfirewall firewall add rule name="ICMP Allow incoming V4 echo request" protocol=icmpv4:8,any dir=in action=allow

# Register PSGallery as a trusted repo
#Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
#Register-PSRepository -Default -InstallationPolicy Trusted -ErrorAction SilentlyContinue
#Set-PSRepository -Name PSGallery -InstallationPolicy Trusted

#Install Arc registration script from PSGallery
#Install-Module AzsHCI.ARCinstaller -Force # Pre-installed in 24H2 base image, part of module AzureEdgeBootstrap

#Install required PowerShell modules in your node for registration
#Install-Module Az.Accounts -Force # Pre-installed in 24H2 base image
#Install-Module Az.ConnectedMachine -Force
#Install-Module Az.Resources -Force

# Workaround for BITS transfer issue
#Get-NetAdapter StorageA | Disable-NetAdapter -Confirm:$false | Out-Null
#Get-NetAdapter StorageB | Disable-NetAdapter -Confirm:$false | Out-Null

#Invoke the registration script.
Invoke-AzStackHciArcInitialization -SubscriptionID $subId -ResourceGroup $resourceGroup -TenantID $tenantId -Region $location -Cloud "AzureUSGovernment" -ArmAccessToken $armtoken -AccountID $clientId -ErrorAction Continue

#Get-NetAdapter StorageA | Enable-NetAdapter -Confirm:$false | Out-Null
#Get-NetAdapter StorageB | Enable-NetAdapter -Confirm:$false | Out-Null
}
}

<# Not needed in 24H2, extensions are installed by cluster validation stage

Get-AzConnectedMachine -ResourceGroupName $env:resourceGroup | foreach-object {

Write-Host "Checking extension status for $($PSItem.Name)"

$requiredExtensions = @('AzureEdgeTelemetryAndDiagnostics', 'AzureEdgeDeviceManagement', 'AzureEdgeLifecycleManager')
$attempts = 0
$maxAttempts = 90

do {
$attempts++
$extension = Get-AzConnectedMachineExtension -MachineName $PSItem.Name -ResourceGroupName $env:resourceGroup

foreach ($extensionName in $requiredExtensions) {
$extensionTest = $extension | Where-Object { $_.Name -eq $extensionName }
if (!$extensionTest) {
Write-Host "$($PSItem.Name) : Extension $extensionName is missing" -ForegroundColor Yellow
$Wait = $true
} elseif ($extensionTest.ProvisioningState -ne "Succeeded") {
Write-Host "$($PSItem.Name) : Extension $extensionName is in place, but not yet provisioned. Current state: $($extensionTest.ProvisioningState)" -ForegroundColor Yellow
$Wait = $true
} elseif ($extensionTest.ProvisioningState -eq "Succeeded") {
Write-Host "$($PSItem.Name) : Extension $extensionName is in place and provisioned. Current state: $($extensionTest.ProvisioningState)" -ForegroundColor Green
$Wait = $false
}
}

if ($Wait){
Write-Host "Waiting for extension installation to complete, sleeping for 2 minutes. Attempt $attempts of $maxAttempts"
Start-Sleep -Seconds 120
} else {
break
}

} while ($attempts -lt $maxAttempts)

} #>

}
####################################################################################
Start-Transcript -Path $Env:LocalBoxLogsDir\New-LocalBoxCluster.log
$starttime = Get-Date

# Import Configuration data file
Expand Down
2 changes: 1 addition & 1 deletion azure_jumpstart_localbox/artifacts/PowerShell/WinGet.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ $logFilePath = Join-Path -Path $Env:LocalBoxLogsDir -ChildPath ('WinGet-provisio
Start-Transcript -Path $logFilePath -Force -ErrorAction SilentlyContinue

# Login to Azure PowerShell
Connect-AzAccount -Identity -Tenant $Env:tenantId -Subscription $Env:subscriptionId
Connect-AzAccount -Identity -Tenant $Env:tenantId -Subscription $Env:subscriptionId -Environment $Env:azureEnvironment

Update-AzDeploymentProgressTag -ProgressString 'Installing WinGet packages...' -ResourceGroupName $env:resourceGroup -ComputerName $env:computername

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ $logFilePath = 'C:\LocalBox\Logs\New-LocalBoxCluster.log'

Write-Output "Adding Storage Blob Data Contributor role assignment to Managed Identity for allowing upload of Pester test results to Azure Storage"

$null = Connect-AzAccount -Identity -Scope Process
$null = Connect-AzAccount -Identity -Scope Process -Environment $Env:azureEnvironment

Write-Output 'Wait for Azure CLI to become available (installed by WinGet)'

Expand Down Expand Up @@ -53,6 +53,7 @@ $newPath = 'C:\Program Files\Microsoft SDKs\Azure\CLI2\wbin'
$env:Path = $currentPath + ';' + $newPath

Write-Output 'Az CLI Login'
az cloud set --name $Env:azureEnvironment
az login --identity
az account set -s $env:subscriptionId

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ BeforeDiscovery {
$clusters = @($LocalBoxConfig.ClusterName)

# Login to Azure PowerShell
Connect-AzAccount -Identity -Tenant $env:tenantId -Subscription $env:subscriptionId
Connect-AzAccount -Identity -Tenant $env:tenantId -Subscription $env:subscriptionId -Environment $Env:azureEnvironment

}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
BeforeDiscovery {

$null = Connect-AzAccount -Identity -Tenant $env:tenantId -Subscription $env:subscriptionId
$null = Connect-AzAccount -Identity -Tenant $env:tenantId -Subscription $env:subscriptionId -Environment $Env:azureEnvironment

}

Expand Down
12 changes: 6 additions & 6 deletions azure_jumpstart_localbox/artifacts/azlocal.json
Original file line number Diff line number Diff line change
Expand Up @@ -475,10 +475,10 @@
"LocalAdminCredentialSecretName": "[concat( parameters('clusterName'), '-', 'LocalAdminCredential')]",
"domainAdminSecretName": "[concat( parameters('clusterName'), '-', 'AzureStackLCMUserCredential')]",
"storageWitnessNameVar": "WitnessStorageKey",
"secretsLocationVar": "[concat('https://',parameters('keyVaultName'), '.vault.azure.net')]",
"secretsLocationVar": "[concat('https://',parameters('keyVaultName'), '.vault.usgovcloudapi.net')]",
"witnessTypeVar": "[if(equals(parameters('witnessType'), 'No Witness'), '','Cloud')]",
"clusterWitnessStorageAccountNameVar": "[if(equals(parameters('witnessType'), 'No Witness'), '', parameters('clusterWitnessStorageAccountName'))]",
"AzureServiceEndpointVar": "[if(equals(parameters('witnessType'), 'No Witness'), '', 'core.windows.net')]",
"AzureServiceEndpointVar": "[if(equals(parameters('witnessType'), 'No Witness'), '', 'core.usgovcloudapi.net')]",
"localAdminSecretValue": "[base64(concat(parameters('localAdminUserName'),':',parameters('localAdminPassword')))]",
"domainAdminSecretValueVar": "[base64(concat(parameters('AzureStackLCMAdminUsername'),':',parameters('AzureStackLCMAdminPasssword')))]",
"CloudWithnessStorageAccountIdVar": "[resourceId('Microsoft.Storage/storageAccounts', parameters('clusterWitnessStorageAccountName'))]",
Expand All @@ -489,7 +489,7 @@
"input": {
"secretName": "[parameters('partnerCredentialList')[copyIndex('answerfileSBESecrets')].secretName]",
"eceSecretName": "[parameters('partnerCredentialList')[copyIndex('answerfileSBESecrets')].secretName]",
"secretLocation": "[concat('https://', parameters('keyVaultName'), '.vault.azure.net/secrets/', parameters('partnerCredentialList')[copyIndex('answerfileSBESecrets')].secretName)]"
"secretLocation": "[concat('https://', parameters('keyVaultName'), '.vault.usgovcloudapi.net/secrets/', parameters('partnerCredentialList')[copyIndex('answerfileSBESecrets')].secretName)]"
}
},
{
Expand All @@ -502,17 +502,17 @@
{
"secretName": "[variables('storageWitnessSecretName')]",
"eceSecretName" : "[variables('storageWitnessECEName')]",
"secretLocation": "[concat('https://', parameters('keyVaultName'), '.vault.azure.net/secrets/', variables('storageWitnessSecretName'))]"
"secretLocation": "[concat('https://', parameters('keyVaultName'), '.vault.usgovcloudapi.net/secrets/', variables('storageWitnessSecretName'))]"
},
{
"secretName": "[variables('LocalAdminCredentialSecretName')]",
"eceSecretName" : "[variables('LocalAdminCredentialECEName')]",
"secretLocation": "[concat('https://', parameters('keyVaultName'), '.vault.azure.net/secrets/', variables('LocalAdminCredentialSecretName'))]"
"secretLocation": "[concat('https://', parameters('keyVaultName'), '.vault.usgovcloudapi.net/secrets/', variables('LocalAdminCredentialSecretName'))]"
},
{
"secretName": "[variables('domainAdminSecretName')]",
"eceSecretName" : "[variables('domainAdminCredentialECEName')]",
"secretLocation": "[concat('https://', parameters('keyVaultName'), '.vault.azure.net/secrets/', variables('domainAdminSecretName'))]"
"secretLocation": "[concat('https://', parameters('keyVaultName'), '.vault.usgovcloudapi.net/secrets/', variables('domainAdminSecretName'))]"
}

]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"value": "tenantId-stage"
},
"spnAuthority": {
"value": "https://login.microsoftonline.com"
"value": "https://login.microsoftonline.us"
},
"logAnalyticsWorkspaceId": {
"value": "logAnalyticsWorkspaceId-stage"
Expand Down
8 changes: 7 additions & 1 deletion azure_jumpstart_localbox/bicep/host/host.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ param vmName string = 'LocalBox-Client'
@allowed([
'Standard_E32s_v5'
'Standard_E32s_v6'
'Standard_E32as_v5'
'Standard_E32as_v6'
])
param vmSize string = 'Standard_E32s_v5'

Expand Down Expand Up @@ -33,6 +35,7 @@ param location string = resourceGroup().location
'canadacentral'
'japaneast'
'centralindia'
'usgovvirginia'
])
param azureLocalInstanceLocation string = 'australiaeast'

Expand All @@ -41,6 +44,9 @@ param subnetId string

param resourceTags object

@description('Azure environment for your service principal')
param azureEnvironment string

@description('Tenant id of the service principal')
param tenantId string

Expand Down Expand Up @@ -284,7 +290,7 @@ resource vmBootstrap 'Microsoft.Compute/virtualMachines/extensions@2022-03-01' =
fileUris: [
uri(templateBaseUrl, 'artifacts/PowerShell/Bootstrap.ps1')
]
commandToExecute: 'powershell.exe -ExecutionPolicy Bypass -File Bootstrap.ps1 -adminUsername ${windowsAdminUsername} -adminPassword ${encodedPassword} -tenantId ${tenantId} -subscriptionId ${subscription().subscriptionId} -spnProviderId ${spnProviderId} -resourceGroup ${resourceGroup().name} -azureLocation ${azureLocalInstanceLocation} -stagingStorageAccountName ${stagingStorageAccountName} -workspaceName ${workspaceName} -templateBaseUrl ${templateBaseUrl} -registerCluster ${registerCluster} -deployAKSArc ${deployAKSArc} -deployResourceBridge ${deployResourceBridge} -natDNS ${natDNS} -rdpPort ${rdpPort} -autoDeployClusterResource ${autoDeployClusterResource} -autoUpgradeClusterResource ${autoUpgradeClusterResource} -vmAutologon ${vmAutologon}'
commandToExecute: 'powershell.exe -ExecutionPolicy Bypass -File Bootstrap.ps1 -adminUsername ${windowsAdminUsername} -adminPassword ${encodedPassword} -azureEnvironment ${azureEnvironment} -tenantId ${tenantId} -subscriptionId ${subscription().subscriptionId} -spnProviderId ${spnProviderId} -resourceGroup ${resourceGroup().name} -azureLocation ${azureLocalInstanceLocation} -stagingStorageAccountName ${stagingStorageAccountName} -workspaceName ${workspaceName} -templateBaseUrl ${templateBaseUrl} -registerCluster ${registerCluster} -deployAKSArc ${deployAKSArc} -deployResourceBridge ${deployResourceBridge} -natDNS ${natDNS} -rdpPort ${rdpPort} -autoDeployClusterResource ${autoDeployClusterResource} -autoUpgradeClusterResource ${autoUpgradeClusterResource} -vmAutologon ${vmAutologon}'
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion azure_jumpstart_localbox/bicep/main.azd.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ param githubBranch string = 'main'
param deployBastion bool = false

@description('Location to deploy resources')
@allowed(['eastus', 'westeurope', 'australiaeast','canadacentral'])
@allowed(['eastus', 'westeurope', 'australiaeast','canadacentral','usgovvirginia'])
param location string

@description('Override default RDP port using this parameter. Default is 3389.')
Expand Down
7 changes: 7 additions & 0 deletions azure_jumpstart_localbox/bicep/main.bicep
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
@description('Azure environment for your service principal')
param azureEnvironment string

@description('Azure AD tenant id for your service principal')
param tenantId string

Expand Down Expand Up @@ -50,6 +53,8 @@ param natGatewayName string = 'LocalBox-NatGateway'
@allowed([
'Standard_E32s_v5'
'Standard_E32s_v6'
'Standard_E32as_v5'
'Standard_E32as_v6'
])
param vmSize string = 'Standard_E32s_v6'

Expand All @@ -75,6 +80,7 @@ param tags object = {
'canadacentral'
'japaneast'
'centralindia'
'usgovvirginia'
])
param azureLocalInstanceLocation string = 'australiaeast'

Expand Down Expand Up @@ -136,6 +142,7 @@ module hostDeployment 'host/host.bicep' = {
resourceTags: resourceTags
enableAzureSpotPricing: enableAzureSpotPricing
azureLocalInstanceLocation: azureLocalInstanceLocation
azureEnvironment: azureEnvironment
}
}

Expand Down
Loading