From 07e94bd8df4ee11bcde1efcebc15fa5db0649580 Mon Sep 17 00:00:00 2001 From: Dinesh Reddy Gottam Date: Tue, 13 Apr 2021 14:56:43 -0700 Subject: [PATCH 1/2] AAD retries and updated HCI mooncake URL Added retries for AAD operations and update HCI mooncake URL --- src/StackHCI/Az.StackHCI.psd1 | 11 +- src/StackHCI/Az.StackHCI.psm1 | 240 ++++++++++++++++++---------------- 2 files changed, 131 insertions(+), 120 deletions(-) diff --git a/src/StackHCI/Az.StackHCI.psd1 b/src/StackHCI/Az.StackHCI.psd1 index d96b6e018c5d..abd9f174a854 100644 --- a/src/StackHCI/Az.StackHCI.psd1 +++ b/src/StackHCI/Az.StackHCI.psd1 @@ -108,13 +108,10 @@ PrivateData = @{ # IconUri = '' # ReleaseNotes of this module - ReleaseNotes = '* Made changes to registration script to register the GA version of On-Premises Azure Stack HCI with Azure. - - Supports registering with user provided certificate thumbprint. - - Supports On-Premises Azure Stack HCI OS changes to use independent certificate on cluster nodes. - - Cleans up resource group during unregistration. - - Improves registration output and logging. -* [Breaking Change] Breaks the public preview registration of On-Premises Azure Stack HCI with Azure. - - To register public preview On-Premises Azure Stack HCi with Azure, use 0.3.1 version of Az.StackHCI.' + ReleaseNotes = '* Made changes to registration script to add retries for AAD operations and to add AzureChinaCloud support. + - Added retries for AAD operations for reliability. + - Supports registration in AzureChinaCloud. + - Supports Tag while resource creation.' # Prerelease string of this module # Prerelease = '' diff --git a/src/StackHCI/Az.StackHCI.psm1 b/src/StackHCI/Az.StackHCI.psm1 index b95b5869d91f..7f4c573ebdc6 100644 --- a/src/StackHCI/Az.StackHCI.psm1 +++ b/src/StackHCI/Az.StackHCI.psm1 @@ -106,31 +106,26 @@ $ServiceEndpointAzureCloud = $ServiceEndpointAzureCloudFrontDoor $AuthorityAzureCloud = "https://login.microsoftonline.com" $BillingServiceApiScopeAzureCloud = "https://azurestackhci-usage.trafficmanager.net/.default" $GraphServiceApiScopeAzureCloud = "https://graph.microsoft.com/.default" -$GraphEndpointResourceIdAzureCloud = "https://graph.windows.net/" $ServiceEndpointAzurePPE = "https://azurestackhci-df.azurefd.net" $AuthorityAzurePPE = "https://login.windows-ppe.net" $BillingServiceApiScopeAzurePPE = "https://azurestackhci-usage-df.azurewebsites.net/.default" $GraphServiceApiScopeAzurePPE = "https://graph.ppe.windows.net/.default" -$GraphEndpointResourceIdAzurePPE = "https://graph.ppe.windows.net/" -$ServiceEndpointAzureChinaCloud = "https://azurestackhci-usage.trafficmanager.cn" -$AuthorityAzureChinaCloud = "https://login.chinacloudapi.cn" -$BillingServiceApiScopeAzureChinaCloud = "https://azurestackhci-usage.azurewebsites.cn/.default" -$GraphServiceApiScopeAzureChinaCloud = "https://graph.chinacloudapi.cn/.default" -$GraphEndpointResourceIdAzureChinaCloud = "https://graph.chinacloudapi.cn/" +$ServiceEndpointAzureChinaCloud = "https://sha-azurestackhci-dp-mc.chinacloudsites.cn" +$AuthorityAzureChinaCloud = "https://login.partner.microsoftonline.cn" +$BillingServiceApiScopeAzureChinaCloud = "$UsageServiceFirstPartyAppId/.default" +$GraphServiceApiScopeAzureChinaCloud = "https://microsoftgraph.chinacloudapi.cn/.default" $ServiceEndpointAzureUSGovernment = "https://azurestackhci-usage.trafficmanager.us" $AuthorityAzureUSGovernment = "https://login.microsoftonline.us" $BillingServiceApiScopeAzureUSGovernment = "https://azurestackhci-usage.azurewebsites.us/.default" $GraphServiceApiScopeAzureUSGovernment = "https://graph.windows.net/.default" -$GraphEndpointResourceIdAzureUSGovernment = "https://graph.windows.net/" $ServiceEndpointAzureGermanCloud = "https://azurestackhci-usage.trafficmanager.de" $AuthorityAzureGermanCloud = "https://login.microsoftonline.de" $BillingServiceApiScopeAzureGermanCloud = "https://azurestackhci-usage.azurewebsites.de/.default" $GraphServiceApiScopeAzureGermanCloud = "https://graph.cloudapi.de/.default" -$GraphEndpointResourceIdAzureGermancloud = "https://graph.cloudapi.de/" $RPAPIVersion = "2020-10-01" @@ -187,6 +182,86 @@ param( Start-Transcript -LiteralPath $LogFileName -Append | out-null } +function Retry-Command { + param ( + [parameter(Mandatory=$true)] + [ValidateNotNullOrEmpty()] + [scriptblock] $ScriptBlock, + [int] $Attempts = 8, + [int] $MinWaitTimeInSeconds = 5, + [int] $MaxWaitTimeInSeconds = 60, + [int] $BaseBackoffTimeInSeconds = 2, + [bool] $RetryIfNullOutput = $true + ) + + $attempt = 0 + $completed = $false + $result = $null + + if($MaxWaitTimeInSeconds -lt $MinWaitTimeInSeconds) + { + throw "MaxWaitTimeInSeconds($MaxWaitTimeInSeconds) is less than MinWaitTimeInSeconds($MinWaitTimeInSeconds)" + } + + while (-not $completed) { + try + { + $attempt = $attempt + 1 + $result = Invoke-Command -ScriptBlock $ScriptBlock + + if($RetryIfNullOutput) + { + if($result -ne $null) + { + Write-Verbose ("Command [{0}] succeeded. Non null result received." -f $ScriptBlock) + $completed = $true + } + else + { + throw "Null result received." + } + } + else + { + Write-Verbose ("Command [{0}] succeeded." -f $ScriptBlock) + $completed = $true + } + } + catch + { + $exception = $_.Exception + + if([int]$exception.ErrorCode -eq [int][system.net.httpstatuscode]::Forbidden) + { + Write-Verbose ("Command [{0}] failed Authorization. Attempt {1}. Exception: {2}" -f $ScriptBlock, $attempt,$exception.Message) + throw + } + else + { + if ($attempt -ge $Attempts) + { + Write-Verbose ("Command [{0}] failed the maximum number of {1} attempts. Exception: {2}" -f $ScriptBlock, $attempt,$exception.Message) + throw + } + else + { + $secondsDelay = $MinWaitTimeInSeconds + [int]([Math]::Pow($BaseBackoffTimeInSeconds,($attempt-1))) + + if($secondsDelay -gt $MaxWaitTimeInSeconds) + { + $secondsDelay = $MaxWaitTimeInSeconds + } + + Write-Verbose ("Command [{0}] failed. Retrying in {1} seconds. Exception: {2}" -f $ScriptBlock, $secondsDelay,$exception.Message) + Start-Sleep $secondsDelay + } + } + } + } + + return $result +} + function Get-PortalDomain{ param( [string] $TenantId, @@ -228,26 +303,7 @@ param( # Below commands ensure there is graph access token in cache Get-AzADApplication -DisplayName SomeApp1 -ErrorAction Ignore | Out-Null - if($EnvironmentName -eq $AzureCloud) - { - $graphTokenItemResource = $GraphEndpointResourceIdAzureCloud - } - elseif($EnvironmentName -eq $AzureChinaCloud) - { - $graphTokenItemResource = $GraphEndpointResourceIdAzureChinaCloud - } - elseif($EnvironmentName -eq $AzureUSGovernment) - { - $graphTokenItemResource = $GraphEndpointResourceIdAzureUSGovernment - } - elseif($EnvironmentName -eq $AzureGermanCloud) - { - $graphTokenItemResource = $GraphEndpointResourceIdAzureGermancloud - } - elseif($EnvironmentName -eq $AzurePPE) - { - $graphTokenItemResource = $GraphEndpointResourceIdAzurePPE - } + $graphTokenItemResource = (Get-AzContext).Environment.GraphUrl $authFactory = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory $azContext = Get-AzContext @@ -363,9 +419,7 @@ param( ) Write-Verbose "Adding the required permissions to AAD Application $AppId if not already added" - $usagesp = Get-AzureADServicePrincipal -Filter "AppId eq '$UsageServiceFirstPartyAppId'" - - $app = Get-AzureADApplication -Filter "AppId eq '$AppId'" + $app = Retry-Command -ScriptBlock { Get-AzureADApplication -Filter "AppId eq '$AppId'"} $shouldAddRequiredPerms = $false if($app.RequiredResourceAccess -eq $Null) @@ -410,7 +464,7 @@ param( if($shouldAddRequiredPerms -eq $true) { $requiredResourcesAccess = Get-RequiredResourceAccess - Set-AzureADApplication -ObjectId $app.ObjectId -RequiredResourceAccess $requiredResourcesAccess | Out-Null + Retry-Command -ScriptBlock { Set-AzureADApplication -ObjectId $app.ObjectId -RequiredResourceAccess $requiredResourcesAccess | Out-Null} -RetryIfNullOutput $false } } @@ -420,42 +474,17 @@ param( ) Write-Verbose "Checking admin consent status for AAD Application $AppId" - $usagesp = Get-AzureADServicePrincipal -Filter "AppId eq '$UsageServiceFirstPartyAppId'" - $appSP = Get-AzureADServicePrincipal -Filter "AppId eq '$AppId'" - $assignedPerms = Get-AzureADServiceAppRoleAssignedTo -ObjectId $appSP.ObjectId + $appSP = Retry-Command -ScriptBlock { Get-AzureADServicePrincipal -Filter "AppId eq '$AppId'"} + + # Try Get-AzureADServiceAppRoleAssignment as well to get app role assignments. WAC token falls under this case. + $assignedPerms = Retry-Command -ScriptBlock { (Get-AzureADServiceAppRoleAssignedTo -ObjectId $appSP.ObjectId) + (Get-AzureADServiceAppRoleAssignment -ObjectId $appSP.ObjectId)} -RetryIfNullOutput $false $clusterRead = $assignedPerms | where { ($_.Id -eq $ClusterReadPermission) } $clusterReadWrite = $assignedPerms | where { ($_.Id -eq $ClusterReadWritePermission) } $clusterNodeRead = $assignedPerms | where { ($_.Id -eq $ClusterNodeReadPermission) } $clusterNodeReadWrite = $assignedPerms | where { ($_.Id -eq $ClusterNodeReadWritePermission) } - if($clusterRead -eq $Null -or $clusterReadWrite -eq $Null -or $clusterNodeRead -eq $Null -or $clusterNodeReadWrite -eq $Null) - { - # Try Get-AzureADServiceAppRoleAssignment as well to get app role assignments. WAC token falls under this case. - $assignedPerms = Get-AzureADServiceAppRoleAssignment -ObjectId $appSP.ObjectId - } - - if($clusterRead -eq $Null) - { - $clusterRead = $assignedPerms | where { ($_.Id -eq $ClusterReadPermission) } - } - - if($clusterReadWrite -eq $Null) - { - $clusterReadWrite = $assignedPerms | where { ($_.Id -eq $ClusterReadWritePermission) } - } - - if($clusterNodeRead -eq $Null) - { - $clusterNodeRead = $assignedPerms | where { ($_.Id -eq $ClusterNodeReadPermission) } - } - - if($clusterNodeReadWrite -eq $Null) - { - $clusterNodeReadWrite = $assignedPerms | where { ($_.Id -eq $ClusterNodeReadWritePermission) } - } - $assignedPermsList = New-Object System.Collections.Generic.List[Microsoft.Open.AzureAD.Model.DirectoryObject] $assignedPermsList.Add($clusterRead) $assignedPermsList.Add($clusterReadWrite) @@ -485,39 +514,14 @@ param( Write-Verbose "Creating AAD Application $AppName" # If the subscription is just registered to have HCI resources, sometimes it may take a while for the billing service principal to propogate - $usagesp = '' - $Stoploop = $false - [int]$Retrycount = "0" - - do { - $usagesp = Get-AzureADServicePrincipal -Filter "AppId eq '$UsageServiceFirstPartyAppId'" - if ($usagesp -eq $Null) - { - if ($Retrycount -gt 5) - { - Write-Error "Could not get service principal of Billing Service." - $Stoploop = $true - } - else - { - $Stoploop = $false - Write-Verbose "Could not get service principal of Billing Service. Retrying in 10 seconds..." - Start-Sleep -Seconds 10 - $Retrycount = $Retrycount + 1 - } - } - else - { - $Stoploop = $true - } - } - While ($Stoploop -eq $false) + + $usagesp = Retry-Command -ScriptBlock { Get-AzureADServicePrincipal -Filter "AppId eq '$UsageServiceFirstPartyAppId'"} $requiredResourcesAccess = Get-RequiredResourceAccess # Create application - $app = New-AzureADApplication -DisplayName $AppName -RequiredResourceAccess $requiredResourcesAccess - $sp = New-AzureADServicePrincipal -AppId $app.AppId + $app = Retry-Command -ScriptBlock { New-AzureADApplication -DisplayName $AppName -RequiredResourceAccess $requiredResourcesAccess } + $sp = Retry-Command -ScriptBlock { New-AzureADServicePrincipal -AppId $app.AppId } Write-Verbose "Created new AAD Application $app.AppId" @@ -530,15 +534,15 @@ param( ) Write-Verbose "Granting admin consent for AAD Application Id $AppId" - $usagesp = Get-AzureADServicePrincipal -Filter "AppId eq '$UsageServiceFirstPartyAppId'" - $appSP = Get-AzureADServicePrincipal -Filter "AppId eq '$AppId'" + $usagesp = Retry-Command -ScriptBlock { Get-AzureADServicePrincipal -Filter "AppId eq '$UsageServiceFirstPartyAppId'"} + $appSP = Retry-Command -ScriptBlock { Get-AzureADServicePrincipal -Filter "AppId eq '$AppId'"} try { - New-AzureADServiceAppRoleAssignment -ObjectId $appSP.ObjectId -PrincipalId $appSP.ObjectId -ResourceId $usagesp.ObjectId -Id $ClusterReadPermission - New-AzureADServiceAppRoleAssignment -ObjectId $appSP.ObjectId -PrincipalId $appSP.ObjectId -ResourceId $usagesp.ObjectId -Id $ClusterReadWritePermission - New-AzureADServiceAppRoleAssignment -ObjectId $appSP.ObjectId -PrincipalId $appSP.ObjectId -ResourceId $usagesp.ObjectId -Id $ClusterNodeReadPermission - New-AzureADServiceAppRoleAssignment -ObjectId $appSP.ObjectId -PrincipalId $appSP.ObjectId -ResourceId $usagesp.ObjectId -Id $ClusterNodeReadWritePermission + Retry-Command -ScriptBlock { New-AzureADServiceAppRoleAssignment -ObjectId $appSP.ObjectId -PrincipalId $appSP.ObjectId -ResourceId $usagesp.ObjectId -Id $ClusterReadPermission} -RetryIfNullOutput $false + Retry-Command -ScriptBlock { New-AzureADServiceAppRoleAssignment -ObjectId $appSP.ObjectId -PrincipalId $appSP.ObjectId -ResourceId $usagesp.ObjectId -Id $ClusterReadWritePermission} -RetryIfNullOutput $false + Retry-Command -ScriptBlock { New-AzureADServiceAppRoleAssignment -ObjectId $appSP.ObjectId -PrincipalId $appSP.ObjectId -ResourceId $usagesp.ObjectId -Id $ClusterNodeReadPermission} -RetryIfNullOutput $false + Retry-Command -ScriptBlock { New-AzureADServiceAppRoleAssignment -ObjectId $appSP.ObjectId -PrincipalId $appSP.ObjectId -ResourceId $usagesp.ObjectId -Id $ClusterNodeReadWritePermission} -RetryIfNullOutput $false } catch { @@ -557,10 +561,10 @@ param( ) Write-Verbose "Removing old scopes on AAD Application with Id $AppId" - $appSP = Get-AzureADServicePrincipal -Filter "AppId eq '$AppId'" + $appSP = Retry-Command -ScriptBlock { Get-AzureADServicePrincipal -Filter "AppId eq '$AppId'"} # Remove AzureStackHCI.Billing.Sync and AzureStackHCI.Census.Sync permissions if present as we dont need them - $assignedPerms = Get-AzureADServiceAppRoleAssignedTo -ObjectId $appSP.ObjectId + $assignedPerms = Retry-Command -ScriptBlock { Get-AzureADServiceAppRoleAssignedTo -ObjectId $appSP.ObjectId} -RetryIfNullOutput $false $billingSync = $assignedPerms | where { ($_.Id -eq $BillingSyncPermission) } $censusSync = $assignedPerms | where { ($_.Id -eq $CensusSyncPermission) } @@ -568,7 +572,7 @@ param( if($billingSync -eq $Null -or $censusSync -eq $Null) { # Try Get-AzureADServiceAppRoleAssignment as well to get app role assignments. WAC token falls under this case. - $assignedPerms = Get-AzureADServiceAppRoleAssignment -ObjectId $appSP.ObjectId + $assignedPerms = Retry-Command -ScriptBlock { Get-AzureADServiceAppRoleAssignment -ObjectId $appSP.ObjectId} -RetryIfNullOutput $false } if($billingSync -eq $Null) @@ -583,12 +587,12 @@ param( if($billingSync -ne $Null) { - Remove-AzureADServiceAppRoleAssignment -ObjectId $appSP.ObjectId -AppRoleAssignmentId $billingSync.ObjectId | Out-Null + Retry-Command -ScriptBlock { Remove-AzureADServiceAppRoleAssignment -ObjectId $appSP.ObjectId -AppRoleAssignmentId $billingSync.ObjectId | Out-Null} -RetryIfNullOutput $false } if($censusSync -ne $Null) { - Remove-AzureADServiceAppRoleAssignment -ObjectId $appSP.ObjectId -AppRoleAssignmentId $censusSync.ObjectId | Out-Null + Retry-Command -ScriptBlock { Remove-AzureADServiceAppRoleAssignment -ObjectId $appSP.ObjectId -AppRoleAssignmentId $censusSync.ObjectId | Out-Null} -RetryIfNullOutput $false } } @@ -883,9 +887,12 @@ param( $AddAppCredentialMessageProgress = $AddAppCredentialMessage -f $ResourceName Write-Progress -activity $RegisterProgressActivityName -status $AddAppCredentialMessageProgress -percentcomplete 80 $now = [System.DateTime]::UtcNow - $appCredential = New-AzureADApplicationKeyCredential -ObjectId $ObjectId -Type AsymmetricX509Cert -Usage Verify -Value $CertBase64 -StartDate $now -EndDate $Cert.NotAfter + $appCredential = Retry-Command -ScriptBlock { New-AzureADApplicationKeyCredential -ObjectId $ObjectId -Type AsymmetricX509Cert -Usage Verify -Value $CertBase64 -StartDate $now -EndDate $Cert.NotAfter} $CertificatesToBeMaintained.Add($appCredential.KeyId, $true) $userProvidedCertAddedToAAD = $true + + # Wait till the credential added is returned in Get to avoid the rush in using this new certificate. Gives more time for AAD replication before using certificate. + $credReturned = Retry-Command -ScriptBlock { Get-AzureADApplicationKeyCredential -ObjectId $ObjectId | where {($_.KeyId -eq $appCredential.KeyId)} } } # Set the certificate - Certificate will be set after testing the certificate by calling cloud service API @@ -945,6 +952,9 @@ enum ConnectionTestResult .PARAMETER ResourceName Specifies the resource name of the resource created in Azure. If not specified, on-premises cluster name is used. + .PARAMETER Tag + Specifies the resource tags for the resource in Azure in the form of key-value pairs in a hash table. For example: @{key0="value0";key1=$null;key2="value2"} + .PARAMETER TenantId Specifies the Azure TenantId. @@ -961,7 +971,7 @@ enum ConnectionTestResult Specifies the ARM access token. Specifying this along with ArmAccessToken and GraphAccessToken will avoid Azure interactive logon. .PARAMETER EnvironmentName - Specifies the Azure Environment. Default is AzureCloud. Valid values are AzureCloud, AzurePPE + Specifies the Azure Environment. Default is AzureCloud. Valid values are AzureCloud, AzurePPE, AzureChinaCloud .PARAMETER ComputerName Specifies the cluster name or one of the cluster node in on-premise cluster that is being registered to Azure. @@ -1028,6 +1038,9 @@ param( [Parameter(Mandatory = $false)] [string] $ResourceName, + [Parameter(Mandatory = $false)] + [System.Collections.Hashtable] $Tag, + [Parameter(Mandatory = $false)] [string] $TenantId, @@ -1322,7 +1335,7 @@ param( $CreatingCloudResourceMessageProgress = $CreatingCloudResourceMessage -f $ResourceName Write-Progress -activity $RegisterProgressActivityName -status $CreatingCloudResourceMessageProgress -percentcomplete 60 $properties = @{"aadClientId"="$appId";"aadTenantId"="$TenantId"} - $resource = New-AzResource -ResourceId $resourceId -Location $Region -ApiVersion $RPAPIVersion -PropertyObject $properties -Force + $resource = New-AzResource -ResourceId $resourceId -Location $Region -ApiVersion $RPAPIVersion -PropertyObject $properties -Tag $Tag -Force # Try Granting admin consent for requested permissions @@ -1373,9 +1386,9 @@ param( $appId = $resource.Properties.aadClientId $cloudId = $resource.Properties.cloudId - $app = Get-AzureADApplication -Filter "AppId eq '$appId'" + $app = Retry-Command -ScriptBlock { Get-AzureADApplication -Filter "AppId eq '$appId'"} $objectId = $app.ObjectId - $appSP = Get-AzureADServicePrincipal -Filter "AppId eq '$appId'" + $appSP = Retry-Command -ScriptBlock { Get-AzureADServicePrincipal -Filter "AppId eq '$appId'"} $spObjectId = $appSP.ObjectId # Add certificate @@ -1453,7 +1466,8 @@ param( # Delete all certificates except certificates which we created in this current registration flow. if(($RepairRegistration -eq $true) -or (-Not ([string]::IsNullOrEmpty($CertificateThumbprint))) ) { - Foreach ($keyCred in (Get-AzureADApplicationKeyCredential -ObjectId $objectId)) + $aadAppKeyCreds = Retry-Command -ScriptBlock {Get-AzureADApplicationKeyCredential -ObjectId $objectId} + Foreach ($keyCred in $aadAppKeyCreds) { if($CertificatesToBeMaintained[$keyCred.KeyId] -eq $true) { @@ -1463,7 +1477,7 @@ param( else { Write-Verbose ($DeletingCertificateFromAADApp -f $keyCred.KeyId) - Remove-AzureADApplicationKeyCredential -ObjectId $objectId -KeyId $keyCred.KeyId + Retry-Command -ScriptBlock { Remove-AzureADApplicationKeyCredential -ObjectId $objectId -KeyId $keyCred.KeyId} -RetryIfNullOutput $false } } } @@ -1536,7 +1550,7 @@ param( Specifies the ARM access token. Specifying this along with ArmAccessToken and GraphAccessToken will avoid Azure interactive logon. .PARAMETER EnvironmentName - Specifies the Azure Environment. Default is AzureCloud. Valid values are AzureCloud, AzurePPE + Specifies the Azure Environment. Default is AzureCloud. Valid values are AzureCloud, AzurePPE, AzureChinaCloud .PARAMETER ComputerName Specifies one of the cluster node in on-premise cluster that is being registered to Azure. @@ -1748,13 +1762,13 @@ param( if($resource -ne $Null) { $appId = $resource.Properties.aadClientId - $app = Get-AzureADApplication -Filter "AppId eq '$appId'" + $app = Retry-Command -ScriptBlock { Get-AzureADApplication -Filter "AppId eq '$appId'"} -RetryIfNullOutput $false if($app -ne $Null) { $DeletingAADApplicationMessageProgress = $DeletingAADApplicationMessage -f $ResourceName Write-Progress -activity $UnregisterProgressActivityName -status $DeletingAADApplicationMessageProgress -percentcomplete 60 - Remove-AzureADApplication -ObjectId $app.ObjectId + Retry-Command -ScriptBlock { Remove-AzureADApplication -ObjectId $app.ObjectId} -RetryIfNullOutput $false } $DeletingCloudResourceMessageProgress = $DeletingCloudResourceMessage -f $ResourceName @@ -1824,7 +1838,7 @@ param( Test-AzStackHCIConnection verifies connectivity from on-premises clustered nodes to the Azure services required by Azure Stack HCI. .PARAMETER EnvironmentName - Specifies the Azure Environment. Default is AzureCloud. Valid values are AzureCloud, AzurePPE + Specifies the Azure Environment. Default is AzureCloud. Valid values are AzureCloud, AzurePPE, AzureChinaCloud .PARAMETER Region Specifies the Region to connect to. Not used unless it is Canary region. From 26c9bf9fad09d444ceb05589f2e438a81051f0ad Mon Sep 17 00:00:00 2001 From: Dinesh Reddy Gottam Date: Tue, 13 Apr 2021 16:26:19 -0700 Subject: [PATCH 2/2] Updated changelog and help Updated change log and help for Register-AzStackHCI --- src/StackHCI/Az.StackHCI.psd1 | 11 +++++--- src/StackHCI/ChangeLog.md | 4 +++ src/StackHCI/help/Register-AzStackHCI.md | 35 +++++++++++++++++------- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/src/StackHCI/Az.StackHCI.psd1 b/src/StackHCI/Az.StackHCI.psd1 index abd9f174a854..d96b6e018c5d 100644 --- a/src/StackHCI/Az.StackHCI.psd1 +++ b/src/StackHCI/Az.StackHCI.psd1 @@ -108,10 +108,13 @@ PrivateData = @{ # IconUri = '' # ReleaseNotes of this module - ReleaseNotes = '* Made changes to registration script to add retries for AAD operations and to add AzureChinaCloud support. - - Added retries for AAD operations for reliability. - - Supports registration in AzureChinaCloud. - - Supports Tag while resource creation.' + ReleaseNotes = '* Made changes to registration script to register the GA version of On-Premises Azure Stack HCI with Azure. + - Supports registering with user provided certificate thumbprint. + - Supports On-Premises Azure Stack HCI OS changes to use independent certificate on cluster nodes. + - Cleans up resource group during unregistration. + - Improves registration output and logging. +* [Breaking Change] Breaks the public preview registration of On-Premises Azure Stack HCI with Azure. + - To register public preview On-Premises Azure Stack HCi with Azure, use 0.3.1 version of Az.StackHCI.' # Prerelease string of this module # Prerelease = '' diff --git a/src/StackHCI/ChangeLog.md b/src/StackHCI/ChangeLog.md index 95d6906f8176..38a7a4ed11dd 100644 --- a/src/StackHCI/ChangeLog.md +++ b/src/StackHCI/ChangeLog.md @@ -18,6 +18,10 @@ - Additional information about change #1 --> ## Upcoming Release +* Made changes to registration script to add retries for AAD operations and to add AzureChinaCloud support. + - Added retries for AAD operations for reliability. + - Supports registration in AzureChinaCloud. + - Supports Tag while resource creation. ## Version 0.4.1 * Fixed an issue blocking user to use cmdlets in Az.StackHCI v0.4.0. diff --git a/src/StackHCI/help/Register-AzStackHCI.md b/src/StackHCI/help/Register-AzStackHCI.md index 498de8830505..b71c10723b21 100644 --- a/src/StackHCI/help/Register-AzStackHCI.md +++ b/src/StackHCI/help/Register-AzStackHCI.md @@ -14,7 +14,7 @@ Register-AzStackHCI creates a Microsoft.AzureStackHCI cloud resource representin ``` Register-AzStackHCI [-SubscriptionId] [[-Region] ] [[-ResourceName] ] - [[-TenantId] ] [[-ResourceGroupName] ] [[-ArmAccessToken] ] + [[-Tag] ] [[-TenantId] ] [[-ResourceGroupName] ] [[-ArmAccessToken] ] [[-GraphAccessToken] ] [[-AccountId] ] [[-EnvironmentName] ] [[-ComputerName] ] [[-CertificateThumbprint] ] [-RepairRegistration] [-UseDeviceAuthentication] [[-Credential] ] [] @@ -81,7 +81,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 8 +Position: 9 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -97,7 +97,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 6 +Position: 7 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -112,7 +112,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 11 +Position: 12 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -127,7 +127,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 10 +Position: 11 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -143,7 +143,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 12 +Position: 13 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -160,7 +160,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 9 +Position: 10 Default value: $AzureCloud Accept pipeline input: False Accept wildcard characters: False @@ -176,7 +176,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 7 +Position: 8 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -223,7 +223,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 5 +Position: 6 Default value: None Accept pipeline input: False Accept wildcard characters: False @@ -261,6 +261,21 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -Tag +Specifies the resource tags for the resource in Azure in the form of key-value pairs in a hash table. For example: @{key0="value0";key1=$null;key2="value2"} + +```yaml +Type: System.Collections.Hashtable +Parameter Sets: (All) +Aliases: + +Required: False +Position: 4 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -TenantId Specifies the Azure TenantId. @@ -270,7 +285,7 @@ Parameter Sets: (All) Aliases: Required: False -Position: 4 +Position: 5 Default value: None Accept pipeline input: False Accept wildcard characters: False