From 8b03d25f2df3ca65356b28b186a2704426adc60b Mon Sep 17 00:00:00 2001 From: haofan-ms <56602314+haofan-ms@users.noreply.github.com> Date: Mon, 4 Apr 2022 10:55:44 -0700 Subject: [PATCH] fix: correctly handle multiple root certificates on Azure Stack Hub windows nodes (#4866) --- parts/k8s/kuberneteswindowssetup.ps1 | 27 ++++++++++++++++++++------- pkg/engine/templates_generated.go | 27 ++++++++++++++++++++------- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/parts/k8s/kuberneteswindowssetup.ps1 b/parts/k8s/kuberneteswindowssetup.ps1 index 010a56a35..7f3f90da9 100644 --- a/parts/k8s/kuberneteswindowssetup.ps1 +++ b/parts/k8s/kuberneteswindowssetup.ps1 @@ -450,20 +450,33 @@ try {{if IsAzureStackCloud}} {{if UseCloudControllerManager}} - # Export the Azure Stack root cert for use in cloud node manager container setup. + # Retrieve SSL cert of ARM Endpoint and find unique Azure Stack root cert $azsConfigFile = [io.path]::Combine($global:KubeDir, "azurestackcloud.json") if (-not (Test-Path -Path $azsConfigFile)) { - throw "$azsConfigFile does not exist, cannot export Azure Stack root cert" + throw "$azsConfigFile does not exist" } $azsJson = Get-Content -Raw -Path $azsConfigFile | ConvertFrom-Json - if ([string]::IsNullOrEmpty($azsJson.managementPortalURL)) { - throw "managementPortalURL is empty, cannot get Azure Stack ARM uri" + if ([string]::IsNullOrEmpty($azsJson.resourceManagerEndpoint)) { + throw "resourceManagerEndpoint is empty, cannot get Azure Stack ARM uri" } - $azsARMUri = [System.Uri]$azsJson.managementPortalURL - $azsRootCert = Get-ChildItem -Path Cert:\LocalMachine\Root | Where-Object {$_.DnsNameList.Unicode -contains $azsARMUri.Host.Substring($azsARMUri.Host.IndexOf(".")).TrimStart(".")} + $azsARMUri = [System.Uri]$azsJson.resourceManagerEndpoint + $webRequest = [Net.WebRequest]::Create($azsARMUri.AbsoluteUri) + try { $webRequest.GetResponse() } catch {} + if (($null -eq $webRequest.ServicePoint) -Or ($null -eq $webRequest.ServicePoint.Certificate)) { + throw "SSL Certificate of ARM endpoint is null" + } + $sslCert = $webRequest.ServicePoint.Certificate + $sslCertChain = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Chain + $sslCertChain.build($sslCert) + $sslRootCert = @($sslCertChain.ChainElements.Certificate)[-1] + $azsRootCert = Get-ChildItem -Path Cert:\LocalMachine\Root | Where-Object {$_.Thumbprint -eq $sslRootCert.Thumbprint} if ($null -eq $azsRootCert) { - throw "$azsRootCert is null, cannot export Azure Stack root cert" + throw "azsRootCert is null, cannot find Azure Stack root cert" + } elseif ($azsRootCert.Count -ne 1) { + throw "azsRootCert is not unique, cannot find Azure Stack root cert" } + + # Export the Azure Stack root cert for use in cloud node manager container setup. $azsRootCertFilePath = [io.path]::Combine($global:KubeDir, "azsroot.cer") Export-Certificate -Cert $azsRootCert -FilePath $azsRootCertFilePath -Type CERT diff --git a/pkg/engine/templates_generated.go b/pkg/engine/templates_generated.go index c8e56a1c7..3f423da1a 100644 --- a/pkg/engine/templates_generated.go +++ b/pkg/engine/templates_generated.go @@ -22146,20 +22146,33 @@ try {{if IsAzureStackCloud}} {{if UseCloudControllerManager}} - # Export the Azure Stack root cert for use in cloud node manager container setup. + # Retrieve SSL cert of ARM Endpoint and find unique Azure Stack root cert $azsConfigFile = [io.path]::Combine($global:KubeDir, "azurestackcloud.json") if (-not (Test-Path -Path $azsConfigFile)) { - throw "$azsConfigFile does not exist, cannot export Azure Stack root cert" + throw "$azsConfigFile does not exist" } $azsJson = Get-Content -Raw -Path $azsConfigFile | ConvertFrom-Json - if ([string]::IsNullOrEmpty($azsJson.managementPortalURL)) { - throw "managementPortalURL is empty, cannot get Azure Stack ARM uri" + if ([string]::IsNullOrEmpty($azsJson.resourceManagerEndpoint)) { + throw "resourceManagerEndpoint is empty, cannot get Azure Stack ARM uri" } - $azsARMUri = [System.Uri]$azsJson.managementPortalURL - $azsRootCert = Get-ChildItem -Path Cert:\LocalMachine\Root | Where-Object {$_.DnsNameList.Unicode -contains $azsARMUri.Host.Substring($azsARMUri.Host.IndexOf(".")).TrimStart(".")} + $azsARMUri = [System.Uri]$azsJson.resourceManagerEndpoint + $webRequest = [Net.WebRequest]::Create($azsARMUri.AbsoluteUri) + try { $webRequest.GetResponse() } catch {} + if (($null -eq $webRequest.ServicePoint) -Or ($null -eq $webRequest.ServicePoint.Certificate)) { + throw "SSL Certificate of ARM endpoint is null" + } + $sslCert = $webRequest.ServicePoint.Certificate + $sslCertChain = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Chain + $sslCertChain.build($sslCert) + $sslRootCert = @($sslCertChain.ChainElements.Certificate)[-1] + $azsRootCert = Get-ChildItem -Path Cert:\LocalMachine\Root | Where-Object {$_.Thumbprint -eq $sslRootCert.Thumbprint} if ($null -eq $azsRootCert) { - throw "$azsRootCert is null, cannot export Azure Stack root cert" + throw "azsRootCert is null, cannot find Azure Stack root cert" + } elseif ($azsRootCert.Count -ne 1) { + throw "azsRootCert is not unique, cannot find Azure Stack root cert" } + + # Export the Azure Stack root cert for use in cloud node manager container setup. $azsRootCertFilePath = [io.path]::Combine($global:KubeDir, "azsroot.cer") Export-Certificate -Cert $azsRootCert -FilePath $azsRootCertFilePath -Type CERT