From 4e12b5870bae100922cb0ced1df3935b1afda17e Mon Sep 17 00:00:00 2001 From: Ramkumar Chinchani Date: Wed, 25 Feb 2026 17:08:29 -0800 Subject: [PATCH 1/7] feat(linux): gate custom cloud cert pull on RCV 1P opt-in - add opt-in check via acms/isOptedInForRootCerts before certificate retrieval - use operation-request endpoints for RCV 1P root/intermediate certificate pull - keep fallback to legacy cacertificates flow when not opted in - harden opt-in detection with curl --fail and JSON boolean match - normalize Flatcar cert installation by converting .crt artifacts to .pem during copy --- .../artifacts/init-aks-custom-cloud.sh | 122 ++++++++++++++++-- 1 file changed, 110 insertions(+), 12 deletions(-) diff --git a/parts/linux/cloud-init/artifacts/init-aks-custom-cloud.sh b/parts/linux/cloud-init/artifacts/init-aks-custom-cloud.sh index e63ac62df6f..1379a1150d4 100644 --- a/parts/linux/cloud-init/artifacts/init-aks-custom-cloud.sh +++ b/parts/linux/cloud-init/artifacts/init-aks-custom-cloud.sh @@ -24,29 +24,127 @@ fi echo "distribution is $distribution" echo "Running on $NAME" -# http://168.63.129.16 is a constant for the host's wireserver endpoint -certs=$(curl "http://168.63.129.16/machine?comp=acmspackage&type=cacertificates&ext=json") +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +# Below code calls the wireserver to get the list of CA certs for this cloud and saves them to /root/AzureCACertificates. Then it copies them to the appropriate location based on distro and updates the CA bundle. + +# Function to process certificate operations from a given endpoint +process_cert_operations() { + local endpoint_type="$1" + local operation_response + + echo "Retrieving certificate operations for type: $endpoint_type" + operation_response=$(make_request_with_retry "${WIRESERVER_ENDPOINT}/machine?comp=acmspackage&type=$endpoint_type&ext=json") + local request_status=$? + if [ -z "$operation_response" ] || [ $request_status -ne 0 ]; then + echo "Warning: No response received or request failed for: ${WIRESERVER_ENDPOINT}/machine?comp=acmspackage&type=$endpoint_type&ext=json" + return + fi + + # Extract ResourceFileName values from the JSON response + local cert_filenames + mapfile -t cert_filenames < <(echo "$operation_response" | grep -oP '(?<="ResouceFileName": ")[^"]*') + + if [ ${#cert_filenames[@]} -eq 0 ]; then + echo "No certificate filenames found in response for $endpoint_type" + return + fi + + # Process each certificate file + for cert_filename in "${cert_filenames[@]}"; do + echo "Processing certificate file: $cert_filename" + + # Extract filename and extension + local filename="${cert_filename%.*}" + local extension="${cert_filename##*.}" + + echo "Downloading certificate: filename=$filename, extension=$extension" + + # Retrieve the actual certificate content with retry logic + local cert_content + cert_content=$(make_request_with_retry "${WIRESERVER_ENDPOINT}/machine?comp=acmspackage&type=$filename&ext=$extension") + local request_status=$? + if [ -z "$cert_content" ] || [ $request_status -ne 0 ]; then + echo "Warning: No response received or request failed for: ${WIRESERVER_ENDPOINT}/machine?comp=acmspackage&type=$filename&ext=$extension" + continue + fi + + if [ -n "$cert_content" ]; then + # Save the certificate to the appropriate location + echo "$cert_content" > "/root/AzureCACertificates/$cert_filename" + echo "Successfully saved certificate: $cert_filename" + else + echo "Warning: Failed to retrieve certificate content for $cert_filename" + fi + done +} + IFS_backup=$IFS IFS=$'\r\n' -certNames=($(echo $certs | grep -oP '(?<=Name\": \")[^\"]*')) -certBodies=($(echo $certs | grep -oP '(?<=CertBody\": \")[^\"]*')) -ext=".crt" -if [ "$IS_FLATCAR" -eq 1 ]; then - ext=".pem" + +# First check via curl "http://168.63.129.16/acms/isOptedInForRootCerts" and JSON response for +# {"IsOptedInForRootCerts":true}. The value captured in optInCheck indicates whether THIS VM +# is opted in for the RCV 1P PKI setup described above. If not opted in, skip the RCV 1P pull +# path and use the default cert retrieval flow instead. This check can be removed if you want to +# attempt to pull certs regardless of opt-in status, but it may result in errors in the logs if +# not opted in. +# https://eng.ms/docs/products/onecert-certificates-key-vault-and-dsms/onecert-customer-guide/autorotationandecr/rcv1ptsg + +optInCheck="" +if optInCheck=$(curl -sS --fail "http://168.63.129.16/acms/isOptedInForRootCerts"); then + : +else + echo "Warning: failed to query root cert opt-in status; defaulting to non-opt-in flow" +fi + +if echo "$optInCheck" | grep -Eq '"IsOptedInForRootCerts"[[:space:]]*:[[:space:]]*true'; then + echo "Opted in for root certs, proceeding with CA cert pull and install" + # Process root certificates + process_cert_operations "operationrequestsroot" + + # Process intermediate certificates + process_cert_operations "operationrequestsintermediate" + echo "successfully pulled in root certs" +else + echo "Not opted in for root certs, skipping CA cert pull and install" + # http://168.63.129.16 is a constant for the host's wireserver endpoint + certs=$(curl "http://168.63.129.16/machine?comp=acmspackage&type=cacertificates&ext=json") + certNames=($(echo $certs | grep -oP '(?<=Name\": \")[^\"]*')) + certBodies=($(echo $certs | grep -oP '(?<=CertBody\": \")[^\"]*')) + ext=".crt" + if [ "$IS_FLATCAR" -eq 1 ]; then + ext=".pem" + fi + for i in ${!certBodies[@]}; do + echo ${certBodies[$i]} | sed 's/\\r\\n/\n/g' | sed 's/\\//g' > "/root/AzureCACertificates/$(echo ${certNames[$i]} | sed "s/.cer/.${ext}/g")" + done + echo "successfully pulled in default certs" fi -for i in ${!certBodies[@]}; do - echo ${certBodies[$i]} | sed 's/\\r\\n/\n/g' | sed 's/\\//g' > "/root/AzureCACertificates/$(echo ${certNames[$i]} | sed "s/.cer/.${ext}/g")" -done + IFS=$IFS_backup -if [ "$IS_FLATCAR" -eq 0 ]; then +if [ "${IS_FLATCAR}" -eq 0 ]; then + # Copy all certificate files to the system certificate directory cp /root/AzureCACertificates/*.crt /usr/local/share/ca-certificates/ + + # Update the system certificate store update-ca-certificates # This copies the updated bundle to the location used by OpenSSL which is commonly used cp /etc/ssl/certs/ca-certificates.crt /usr/lib/ssl/cert.pem else - cp /root/AzureCACertificates/*.pem /etc/ssl/certs/ + for cert in /root/AzureCACertificates/*.crt; do + destcert="${cert##*/}" + destcert="${destcert%.*}.pem" + cp "$cert" /etc/ssl/certs/"$destcert" + done update-ca-certificates fi From 2277404c092de0e2588182f96aeb7d5ce298a2f6 Mon Sep 17 00:00:00 2001 From: Ramkumar Chinchani Date: Wed, 25 Feb 2026 18:18:16 -0800 Subject: [PATCH 2/7] feat(windows): add RCV 1P cert refresh flow with scheduled self-refresh - add a dedicated CARefresh parameter set with -CARefreshOnly mode for certificate-only execution - implement RCV 1P cert retrieval from WireServer, including opt-in detection via isOptedInForRootCerts - add operation-request certificate download path (operationrequestsroot/operationrequestsintermediate) - keep backward-compatible fallback to legacy cacertificates endpoint when VM is not opted in - add retry/backoff wrapper for WireServer calls and structured RCV1P logging helper - install downloaded certs into LocalMachine certificate stores (Root for self-signed, CA for intermediates) - register a daily SYSTEM scheduled task (aks-rcv1p-cert-refresh) to rerun cert refresh via this script - wire AKS custom cloud base-prep flow to run RCV 1P refresh and task registration - document RCV 1P intent with inline comment block for maintainability --- parts/windows/kuberneteswindowssetup.ps1 | 228 ++++++++++++++++++++++- 1 file changed, 223 insertions(+), 5 deletions(-) diff --git a/parts/windows/kuberneteswindowssetup.ps1 b/parts/windows/kuberneteswindowssetup.ps1 index 33e663a8edc..00423632698 100644 --- a/parts/windows/kuberneteswindowssetup.ps1 +++ b/parts/windows/kuberneteswindowssetup.ps1 @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -224,6 +228,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="{{GetBootstrapProfileContainerRegistryServer}}" $global:MCR_REPOSITORY_BASE="{{GetMCRRepositoryBase}}" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { @@ -385,7 +602,8 @@ function BasePrep { $envJSON = "{{ GetBase64EncodedEnvironmentJSON }}" [io.file]::WriteAllBytes($azureStackConfigFile, [System.Convert]::FromBase64String($envJSON)) - Get-CACertificates + Invoke-RCV1PCertificateRefresh + Register-RCV1PCertificateRefreshTask {{end}} Write-CACert -CACertificate $global:CACertificate ` From 31145fe345ef88661d15a35a05f4cfe4363326d6 Mon Sep 17 00:00:00 2001 From: Ramkumar Chinchani Date: Tue, 3 Mar 2026 13:43:46 -0800 Subject: [PATCH 3/7] fix: update testdata --- .../CustomData | 2 +- .../CustomData | 2 +- .../CustomData | 228 +++++++++++++++++- .../AKSWindows2019+CustomCloud/CustomData | 228 +++++++++++++++++- .../AKSWindows2019+CustomVnet/CustomData | 225 ++++++++++++++++- .../CustomData | 225 ++++++++++++++++- .../testdata/AKSWindows2019+K8S116/CustomData | 225 ++++++++++++++++- .../testdata/AKSWindows2019+K8S117/CustomData | 225 ++++++++++++++++- .../testdata/AKSWindows2019+K8S118/CustomData | 225 ++++++++++++++++- .../AKSWindows2019+K8S119+CSI/CustomData | 225 ++++++++++++++++- .../AKSWindows2019+K8S119+FIPS/CustomData | 225 ++++++++++++++++- .../testdata/AKSWindows2019+K8S119/CustomData | 225 ++++++++++++++++- .../CustomData | 225 ++++++++++++++++- .../CustomData | 225 ++++++++++++++++- .../AKSWindows2019+ManagedIdentity/CustomData | 225 ++++++++++++++++- .../AKSWindows2019+SecurityProfile/CustomData | 225 ++++++++++++++++- .../CustomData | 225 ++++++++++++++++- .../CustomData | 225 ++++++++++++++++- .../CustomData | 225 ++++++++++++++++- .../CustomData | 225 ++++++++++++++++- .../Flatcar+CustomCloud+USSec/CustomData | 2 +- .../CustomData.inner | 2 +- 22 files changed, 3986 insertions(+), 78 deletions(-) diff --git a/pkg/agent/testdata/AKSUbuntu2204+CustomCloud+USNat/CustomData b/pkg/agent/testdata/AKSUbuntu2204+CustomCloud+USNat/CustomData index 873ef4e0b66..e6ed96a6cd2 100644 --- a/pkg/agent/testdata/AKSUbuntu2204+CustomCloud+USNat/CustomData +++ b/pkg/agent/testdata/AKSUbuntu2204+CustomCloud+USNat/CustomData @@ -91,7 +91,7 @@ write_files: encoding: gzip owner: root content: !!binary | - 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 - path: /opt/azure/containers/reconcilePrivateHosts.sh permissions: "0744" diff --git a/pkg/agent/testdata/AKSUbuntu2204+CustomCloud+USSec/CustomData b/pkg/agent/testdata/AKSUbuntu2204+CustomCloud+USSec/CustomData index 873ef4e0b66..e6ed96a6cd2 100644 --- a/pkg/agent/testdata/AKSUbuntu2204+CustomCloud+USSec/CustomData +++ b/pkg/agent/testdata/AKSUbuntu2204+CustomCloud+USSec/CustomData @@ -91,7 +91,7 @@ write_files: encoding: gzip owner: root content: !!binary | - H4sIAAAAAAAC/6xZ6XPbNhb/zr/iheHGx4ai5GYyW7dM6vjY9Uwae3zsfrBdDQQ+SahIgAVA2aqt/30HAC9JtOt21/2gEngX3vHDw8vbN9GI8WhE1NRTqCF88LJZwiSEOURSCB0d/F5IPDw4RKnZmFGiUXne6eXw5OvB1eHBRdw3H9dfrr9dXcd9j43h5gbCMUSoaSRUKDFFohDu7n4APUXuAQD01rftquMNvh38fAxxDLv+9ajguvB3V5nNX6NyYNcwLZlPjxzrOCWaEvkMb2V7xVwaYD/oVIB/zWdc3HP4ynjxAAlTWrJRoZngfkP5wDQ4CWPm1UIqAarIcyE1JiBylEQzPgG1UBozJ6JkHzPPcyxtLcAUBKtqHdFFwbmRJLhzlO95FKVWcbBNC5mCP9U634+iwcd/9D5+1xvsfd8bfIwyQqeM42cqsjwmNFM5oTMywXd6kWNMCW0F9x0+6PhXJbi/452eXA5HhM6KPA5OTy7Ndxxs3cpbvmXVfiMZqng72LbGBdYSeIKJxBxCcQ5b259/jA3Rrb8Pt/7OzS+3/t3u1s6O5f4iEvbH7IeOcrEhwtjp96jUvs068IMmsj6E+BsMoB17R58b/4+ZNxYSGDAOweObxpibn+6WP0AimkgGj63dgN0tAZ5AYQJbKrq9lbe3PLrl0WSrvRqZ70/gP1tAUXXkx9qLTrYT4quoR1FGveARH/Qymvg7vpcIji4ATVS8507eXzk5faGWo13jQogKJaNUUJJGakokRpSE7ayIrKAiT4jGcG3Pq5WYolYqjWwk10W09LBRTWYC0hTPH1iaY7au5CW7TG0RasonDh4H+yHjTC8rl7kNH2LwKQkljiWqqb+WMUxbIeOCU1eWnOlhYWFpmBHGhxJzMUwwFxoeLY/1IZhluzpEnuSCcR37wcAVfoOv5iQk19EMF5LxSelIV+iHIl+YQndHS2BU8CRF0ALOcuSXl1/BemPMUuz1ev7/HIIWdK1qpCJnmPR87xnjXSZGNYIb8PfrXSUKSVH1Uqb0qnOttDl0UnZLHzP3IySUxENzfFPEnVJ6SbRbF/OKeUGbf9Os0rR1sk6jWobZCn3hfiO5vrQCT1iKsf+czS69euVq6XdKNPz44/HZCXyC1zF63tUiR7UPCY6864tTtQ/B42ZeLks277JgGi3Rv48vLk/Pvg0Pz46OzR2z7FoLXWKqzj3jIHP5de8qpIVkeuEdiiwXHLlW+2CqCQrO5igVgkRz9VGThlmRarfqXbIJxyT8sth3SeyQqqqe8iAhkXTK5hiW671JPvGOz06cHx3NtUzjF53RrkM+NxXEJ3B98VXZG2MlkKYkLzAXRxYEDE1djwbLQwa+em9uZXX7eT+Keje/wN3u+6A25P3EX5PY0k5yXea6006dNZi8B4UIHO8tAsAIU3G/77c42/8fmj+/zqNntbXoKiHLFvjRKdLZ0HQZbagrjC8HbY8ZMgtdMt2HoJBplcOFTIcGU4dUJFh1LKGCMJwiSSAMJf5WoNLwz+Mry7jT7gs/Q8jR3Gx38PRU6gpWZfp193AM/of+B/gmNJyIgie+qZsE5xEv0nSt3J2o44uLswtnr+m+uNBA5oSlZJRiD85dF5sRXpA0XThfGMv0FKFkmZOUJTDCsZAmg0NZ9mqKSpbr5xrHtofvJdM41GK4gm9tb1cbpuSHid2vvN8mGBaSxcGey8IpG2vYa9HMcDHMiZ6qeNsPfvJ3XHjaOu328xAVPHbYsWwgq6m0I6Z0HGynajSsXgIhhScg9zPYeswl4xqCveVWaYNGhJBAsGGLA78uTGsO3EBYo3sDY7wDSaf7QLLk44c2oASPtVdudu+WFjHaoSFJMjQUTvRKTMwyJ5kNhF22dDKN/W6MmeFCRU6fYVuWlVlXV1Dyt2rqIElMJgUVj1FhgKfCuApxzH5CNImD7fuJec6dQVjL26lJbHSD7QQlm+OwPngjf6elO6iE2urKJxCGCRKZCQlPNmBBJaBdY+sCaqtJkmDStn0VZDZs6vJ0nbidOV3mkukTas2Mg9+43Pb5/kpvUPP/Pd72NzqzdrjMhVKqbm788qSrSeRvZFCmzMmqQ63E9mdGpVBirMFSrAXXNRCrOZhVHD2iaCeBEjlyjXRqKVaMyfUE9dBd4ivmkFyHJnXsVju33DYXGk395ciT8iE6FfcGGBcVgsCUzM2VhLwK9pQpyMgCNJkhEKCiyFOEjPHCNKWVAjaGFeVYo/lv62j+EoKvyRgTlrqEGzOeAElrEK1R3QK3oTVgXh1CSJCYCXMSktSrYykyWIiibkGB8AS0XACZEMZ7nSjfMWBYM9I8zFPU+Mbvuhbar448o3/l0bGSauaY5QRA9ZosoiIDN3IJSwS9QCe1ScGa+tzxuz4i9oNN5VFNW3ZVUSM1yqVINnCvW7il6r4Za4bQyHtOAHQg3UrtrBXKzqs1hhqVbQ3/r5rLZ5ir4e3GaTs2Fq6meh1hfSakBk78Gh4qBOoImMm5Zp7g5mtdgxTXz5zbO6RfVS4VWWZKIZyDRJKkjM/gU30bwN6nd4O1om2J8YPtmsm+z/o+7LW4n57Atgpj2Pqb2rL7O3WlVBa8ASoF12QEYbrK3aDIrR80am99aL3816yzArefkfhDy5xbvgV+Hwbfw6797wUVO/DU2Njx5nTRPKkBi3GlDV41Iiw7/CpGMGekkuXDp3d764/RyjE0FUViJx+gNNGF6bbvCdN2Uwqh67fLcQMa29V1dnF8fjY8Oj4/uxoefzs6Pzv9drX0W6OuqrKjrZ1213eB6XrTVw+Cu3q/v9Iv2iC9MI4JHjtPt9xgXEPUF/lWh7CrIO5Xj/zmYvXcXPoPR5MuYcqme7MWSt+qOS1bcjdHTsrfiPxeSDv9KrOkp1DOGS0t0pl8JZtmGcrWwOGTH6g59cve++aaM33nHaGzlgkeX5RZaad1cFgoLTI4NBkHhwewMos7GGuUMUd9L+QsFDxlHHuayAlq7z+Ea/XMnndz6Q5zZ3v/WHBUU6G94wekl5pIHQct77VKpXnzl0fRmXzhKEeEpQuoykyMX3Mm7+bKeOzOO+OHJEWeEBkPvt/v971zlIopjVzHWhboXRCeiIz9jskRpmRxiTT+rt/3vJtTV+J31geYfFnENgiqOn59CBczqlNICGaCm3oSJFnbQ26eqxCGXNxDd3ztQJNOpeCLIRV8XOaGWyl/embDf91lUOtWWuTlZxIaVWrB6bqBCVPWwk26ZoD4BkI0T/vGxs0R3WrpbSzXyGllQLho/pnmVQUpM1N7wWPLhqVznMklaNtWvUzfem9zIVLgOu+Vkzhz+1bXyaiQSkNGHqq+8UNJ36+ozVfPcAs56aAflPSDP0m/90r6Pc+b4cI2OR0JYXoGz0skG2tHMiduiLxKZgk8720qJqAlcXOgDIkqJGbmEW4vIaY0o8rzUjFJmCxliUkpxPMy8lBOF2d4D4N+v9f3PKmpSRTPkzimqaAzOP/XoXtv5jrvQy7SFL6DxP6GeyDGY4Ua+l5GZqg05jDo9SEcuJL6c6ktURmoKdPp1aj+DH9iM+mtseO/AQAA//81fYCEfx0AAA== + H4sIAAAAAAAC/8Q6a1PjRrbf9StOhDY87siySSp144xnloC5l6oEKDNsPgDraqQju9dSt6a7ZXDA//1Wd+tpy4TsTdXOfMBWn/erzzny3jfBI2XBI5FzR6IC/9lJFxEV4GcQCM5VcPJ7LvD05BSFojENiULpOBc30/NfTr6cnkxGff3l9ufbyy+3o75DY7i7Az+GAFUYcOkLTJBIhIeHn0DNkTkAAL3NY/PU4nqXJ7+OYTSCI/f2MWcqd4/ayPpfzXJgnmFSIF+cWdQ4ISokYgduKXuJXAhgvoRzDu4tWzD+xOAXyvJniKhUgj7minLm1pDPVIGlEFOnIlISkHmWcaEwAp6hIIqyGciVVJhaEgV6TB3HojS5AJXgtdlaoEnOmKbEmTWU6ziOkwkeopTTEIWaFtw4kweH8GJYJTwkCSCLMk6ZmqpVhiPXG7iNwwprKlBmnEl0GtpMUAmKS804rOOgRpIQcwGa7hC8Fh/LY5v6yDtIyQKnAr/mKNX0iar5VKASK3C9l98uJuOb8eQf48l0fHl2fXVx+WUdpCScU4afQ55mIxKmMiPhgszwW6NPm+23+KxG/5KcuYcNJUtmUhGVy5H3uQo78H8H19sW04UHeH2FO/DauOAzhD5shpa11m9EaB8N4ZJDSQgEhkiXOhpEKQfEhCYYadsN4S9VuhJIoMoFK2O0YQoTKjFNkJEUpTlISaYfgK82TuEjfDywqnWa6BVmAjPw+TXsH3z+OHInKHke4jlN8JKk6A7BPbz7p/twtH/o1Cb3XvbafO7+/rAGH7/uNOwlb4VfLWDMcxYBZbW5dTx2ReIOo2jwljCamOu9bAvo/gQR35Dr2ubfZnpovCF4LRquU+FaR5QHo01uf+sdrd0NYHxWyCTlbAt6b++ot24Qt4Kd8SeWcBJtSDasuXrlpw8N4l71cUtcwzTkTCFT1VHz4V+f2KWEJrwboh1uiNad3e0Mb0r6J3P7P5Lfu3RvSaX1oSyv77Ayqmvd2bbuO9XbAPwE7s5GINgM7m1qN3mocyPOk2QFkmgLtSJxF4XWpdxh+3NrW6VdYC4nbOVeIb6tAztYxNR8jDhDZ+04F+c300cSLvJs5F2c3+jvI2//XtyzfcdxeKYu2Okcw8XIdXWb03jgHYS5SMCXN+D72ungzpXKhkEw+OG/ez981xsc/9gb/BBo/wZUXmUKowt2zsWEc6XtKd3DhjuGm81EpXRcKf01R7EC7RejtpbGpwxsBP8EEcYkT0zPoTgwzvwCIE74k2uaDhpDVdNLTepaPv4K++5Fp6h3d0MdpTh8eDgaNr8okeN+Qw9L3pDQ5VS7ohJYfgDTtaCpTbpIwOmJVSXLkwSIqedSkSSxDtvR44BbfS6yTmoeRd16PxJlCkWKESWqiBArvWyGr5bM6lLr4W4665Ibb3TrLBc0y7TGbytroMuw6o6ltwtHSBrJIDe7IX2mL2Y5OvDsxW5SRG7d5Bro3h3Cvb6/780FXlP4mUf0j0mcWshVJxktl9sLhXLrtsD16gbdNe3AYLsdMHhZ2UoXiayNTbXVvZdvagH1pb19Z9vrs4Dw6MMa4BUkRrAvg/t7cX/PgnsWzPabTwP9/e1yeNAgbixsaVsirgx6IYqg573gs1oHM/fQrSvQH8ZckdNl2OkcNiWqrlsmqbUFX2oTrt2Olip8Y7gLjrRDIMilCMzFGsg5ERiExG/GVGAzLM8iotDfOHQqLnrMkzIJjNCbNBqM6GMFpv1aJ1XZmWkL/IHMLS9HKJXGKzulvb2joNFPNY/Lz7rjqoOq0MBeh+6mJq5XYm24cIdBtLdIqEx39TIY+pRRtS7dZQ9cGIEbEl9gLFDO21e0nhYNkThnoZ0QGVXT3EzI05RQ3ZBnfBphxlVr7NOPzdNp2Q7Xs1896mvtSKaCBa4EZTPZnP5OebbSNcuqFsFjzqIE9cVylSG7ufkFtNVMT9nr9dz/t+8bU3SbY8gzilGvKO7bwtssCBpTXQxudSp5LkKUvYTKjv4nXUInZDf1RsUpgE1/YYK0i0ovCo5a4VmJ5zXxu9uydLkF1inUZk/zxqqFZOrGENQz2sjdJbMNr17xtLB7SBR8/Di+OodP8D5Ex/myylAOIcJH53ZyIXU7vB2X6wLNucmpQgP0j/Hk5uLqcnp6dTa+PPl1vO565tvAlJ1n2kAZ1zdT16nEMBdUrZxTnmacIVNyCDqbIGd0icI09lIJGuowTHVLZZ46N3TGMPJ/Xg1tENsaWWZPoYhPRDinS/SL571ZNnPGV+dF6TQwtyIZvWmMZh6ypc4gNoPbyS/S3HQtR+qUnGDGz0wR0DBVPur7x6fgyg+6m5D3n4dB0Lv7JzwcffAqQT7M3A2KDe4kU0WsW+6hlQajDyARgeGTqQDwiAl/GjZ7qOZnX/9zqzjaya0BVxJZN4pfqLvVqe6OmqUu17YcNC2mwUzpEskQvFwkZQznIpnqmjoNeYR1Aw++P0cSge+XM9z/jL8YxMPmivJzOSOaCbIcm1o0G600uN/3vwfdF57znEV6pAoiXAYsT5LOPcd4MrmaWHmBSmBcAVkSmpDHBHtwbReqKWE50R2CsYWWTM0RCpQlSWgEjxhzoSPYF8XaUIaCZmrXDrNp4SdBFU4Vn7bqW9Pa5YFO+WlkzkvrNwGmuaAj79hG4ZzGCo4bMAtcTTOi5nJ04Hp/d4v9UJOnOd5doryXDjnWdcmqM+2MSjXyDhL5OC2X0n4Ir0CeFrD/kgnKFHjH63JHpRDBJ+BtyWKLX1dNqxWuS1jNe6vGOCcinA+BpNEP3zcLivdSWeXu6GFtKkbTNSSKphrCkm75RD+2e52B1cLAiUS3OV01ZoErGVh+Gq1okOrs8gr8Rk6dRGZk80oczUIXnrLGlRVHn0dEkZF38DRDBf4V+BW9wwrEeNc7iFDQJU4rxWv6hw3eXknUZFc2A9+PkIiUC3g1DvNKAs0c2yRQSU2iyE7TpeztIrMlU5elq8DtjOnDer1YcbabxQp/e6lY4f/X6MDd6sya7tIXSsG6vvELTdtB5G5FUCq1ZqVSLd/+SkPBJY8VGIgN59oGoh2DaYnRIzLsBJA8Q6YwnBuIljCZmqGa2ku8JQ7JlK9Dxxw1Y8seM65Q51+GLCreicz5ky6Mq7KCwJws9ZWErHT2nEpIyQoUWSAQCHmeJQgpZbluSksGNIYWc6yq+dfNav5WBd+gUa9vYsoiIElVRKuqbgq3htXFvFTCrBRTrjUhUfU0FjyFFc+rFtTsEZRYAZkRynqdVb7jXdeGkCFPswQVfuN2XQvNqSNLw39n6GiFmlaz2FzIXh1FIU/Bvv3ziwo6QUu1DsEK+tri2z5i5HrbzIMKtuiqgppqkAkebdW9buIGqvtmrBB8TW8XAeiodK3c2UiUw3dz9BVK0xr+pZyLMczm8EFttEPjC5tTvQ637nCpLiduVR7KCtThMB1z9TbIvurtWgbZfuba3CH9MnNDnqY6FfwlCCRRQtkCPlW3ARx/+nawkbQNMq53UCGZ+azvwnED+/UVTKsQw/7f5L45P3Rb75JoDN9AKDhT5BH8pI1dV5F716vZ3rvQmPw3pDMED3ZQ/Kkhzj3bB7cPgx/hyPx/g8UhvNYy7nwVUC/Zi/Vkg4RBh3/xR1hSUtJy4dO3x5vDaGmYMOF5ZDYfUL5p8Z8Ite+RBOeqml3GddEoXzy+TMbXV9Oz8fXVl/r1idtYz5WZHewfNru+CSabTV/1m4Su3u/f6ReNk95Yx3gvndqttxA3KuqbeO3fA7SLuFsO+fXF6tifSPzhetUGTNF0b+dCYVu5DIuW3P6kISr+BuT3XJjtVxElPYliScNCIpWKd6IpmqJoLBw+uZ5chm7Re9/dMqoenDO00lLORpMiKs12EE5zqXgKpzriyl17tYs7iRWKEUP1xMXC5yyhDHuKiBkq5zfClNxx5tzdWGUeTO8/4gzlnCtn/IzhjSJCjbyG9RqpUs/8hSoqFW+ockZosoIyzXj8Hp2cuy/aYg/OFTslCbKIiNHgx2G/71yjkFSaV7NK5OhMCIt4Sn/H6AwTsrrBcPRdv+84dxc2xR+MDTD6eTUyTpCl+pUS1mehSiAimHKm84mTaOMMmR5XwfcZf4Ju/5qFZjgXnK2mIWdxERv2SfGnpw/c910GFW+peFZ8jXzNSq5YuClgRKWRcBuuXiB+Az7q0b6WcXtF1069rcdV5TQ0wF/Vvxh6V0KKVOee99KQYW0Np2MJmrKVk+mes5dxngBTWa/YxOnbt7xOHnMhFaTkuewbvy/g+yW0/tbT2FzMOuAHBfzgT8IfvxP+2HEWuDJNTkdA6J7BcSJBY2VBlsQukdtgBsBx9hI+AyWI3QOlSGQuMNVDuLmEqFQ0lI6T8FlERUGLzwoijpOS52K7uMAnGPT7vb7jCBXqQHEcgXGY8HAB1/97aufNTGV9yHiSwHcQmb/+MfA4lqig76RkgVJhBoNeH/yBTak/F9oCpS41RTi9u6rvwI9MJO1pOf4vAAD//5Uc1ZUKKAAA - path: /opt/azure/containers/reconcilePrivateHosts.sh permissions: "0744" diff --git a/pkg/agent/testdata/AKSWindows2019+CustomCloud+ootcredentialprovider/CustomData b/pkg/agent/testdata/AKSWindows2019+CustomCloud+ootcredentialprovider/CustomData index 6a9621ed8eb..ec80cc5b830 100644 --- a/pkg/agent/testdata/AKSWindows2019+CustomCloud+ootcredentialprovider/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+CustomCloud+ootcredentialprovider/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { @@ -379,7 +596,8 @@ function BasePrep { $envJSON = "eyJuYW1lIjoiQXp1cmVTdGFja0Nsb3VkIiwiTmFtZSI6IkF6dXJlU3RhY2tDbG91ZCIsIm1jclVSTCI6Im1jci5taWNyb3NvZnQuZmFrZWN1c3RvbWNsb3VkIiwicmVwb0RlcG90RW5kcG9pbnQiOiJodHRwczovL3JlcG9kZXBvdC5henVyZS5taWNyb3NvZnQuZmFrZWN1c3RvbWNsb3VkL3VidW50dSIsIm1hbmFnZW1lbnRQb3J0YWxVUkwiOiJodHRwczovL3BvcnRhbC5henVyZS5taWNyb3NvZnQuZmFrZWN1c3RvbWNsb3VkLyIsInNlcnZpY2VNYW5hZ2VtZW50RW5kcG9pbnQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS5taWNyb3NvZnQuZmFrZWN1c3RvbWNsb3VkLyIsInJlc291cmNlTWFuYWdlckVuZHBvaW50IjoiaHR0cHM6Ly9tYW5hZ2VtZW50LmF6dXJlLm1pY3Jvc29mdC5mYWtlY3VzdG9tY2xvdWQvIiwiYWN0aXZlRGlyZWN0b3J5RW5kcG9pbnQiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5taWNyb3NvZnQuZmFrZWN1c3RvbWNsb3VkLyIsImtleVZhdWx0RW5kcG9pbnQiOiJodHRwczovL3ZhdWx0LmNsb3VkYXBpLm1pY3Jvc29mdC5mYWtlY3VzdG9tY2xvdWQvIiwiZ3JhcGhFbmRwb2ludCI6Imh0dHBzOi8vZ3JhcGguY2xvdWRhcGkubWljcm9zb2Z0LmZha2VjdXN0b21jbG91ZC8iLCJzdG9yYWdlRW5kcG9pbnRTdWZmaXgiOiJjb3JlLm1pY3Jvc29mdC5mYWtlY3VzdG9tY2xvdWQiLCJzcWxEYXRhYmFzZUROU1N1ZmZpeCI6ImRhdGFiYXNlLmNsb3VkYXBpLm1pY3Jvc29mdC5mYWtlY3VzdG9tY2xvdWQiLCJrZXlWYXVsdEROU1N1ZmZpeCI6InZhdWx0LmNsb3VkYXBpLm1pY3Jvc29mdC5mYWtlY3VzdG9tY2xvdWQiLCJyZXNvdXJjZU1hbmFnZXJWTUROU1N1ZmZpeCI6ImNsb3VkYXBwLmF6dXJlLm1pY3Jvc29mdC5mYWtlY3VzdG9tY2xvdWQvIiwiY29udGFpbmVyUmVnaXN0cnlETlNTdWZmaXgiOiIuYXp1cmVjci5taWNyb3NvZnQuZmFrZWN1c3RvbWNsb3VkIiwiY29zbW9zREJETlNTdWZmaXgiOiJkb2N1bWVudHMuY29yZS5taWNyb3NvZnQuZmFrZWN1c3RvbWNsb3VkLyIsInRva2VuQXVkaWVuY2UiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS5taWNyb3NvZnQuZmFrZWN1c3RvbWNsb3VkLyIsInJlc291cmNlSWRlbnRpZmllcnMiOnt9fQ==" [io.file]::WriteAllBytes($azureStackConfigFile, [System.Convert]::FromBase64String($envJSON)) - Get-CACertificates + Invoke-RCV1PCertificateRefresh + Register-RCV1PCertificateRefreshTask Write-CACert -CACertificate $global:CACertificate ` diff --git a/pkg/agent/testdata/AKSWindows2019+CustomCloud/CustomData b/pkg/agent/testdata/AKSWindows2019+CustomCloud/CustomData index d3af76406b4..7cfb48c7c21 100644 --- a/pkg/agent/testdata/AKSWindows2019+CustomCloud/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+CustomCloud/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { @@ -379,7 +596,8 @@ function BasePrep { $envJSON = "eyJuYW1lIjoiQXp1cmVTdGFja0Nsb3VkIiwiTmFtZSI6IkF6dXJlU3RhY2tDbG91ZCIsIm1jclVSTCI6Im1jci5taWNyb3NvZnQuZmFrZWN1c3RvbWNsb3VkIiwicmVwb0RlcG90RW5kcG9pbnQiOiJodHRwczovL3JlcG9kZXBvdC5henVyZS5taWNyb3NvZnQuZmFrZWN1c3RvbWNsb3VkL3VidW50dSIsIm1hbmFnZW1lbnRQb3J0YWxVUkwiOiJodHRwczovL3BvcnRhbC5henVyZS5taWNyb3NvZnQuZmFrZWN1c3RvbWNsb3VkLyIsInNlcnZpY2VNYW5hZ2VtZW50RW5kcG9pbnQiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS5taWNyb3NvZnQuZmFrZWN1c3RvbWNsb3VkLyIsInJlc291cmNlTWFuYWdlckVuZHBvaW50IjoiaHR0cHM6Ly9tYW5hZ2VtZW50LmF6dXJlLm1pY3Jvc29mdC5mYWtlY3VzdG9tY2xvdWQvIiwiYWN0aXZlRGlyZWN0b3J5RW5kcG9pbnQiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5taWNyb3NvZnQuZmFrZWN1c3RvbWNsb3VkLyIsImtleVZhdWx0RW5kcG9pbnQiOiJodHRwczovL3ZhdWx0LmNsb3VkYXBpLm1pY3Jvc29mdC5mYWtlY3VzdG9tY2xvdWQvIiwiZ3JhcGhFbmRwb2ludCI6Imh0dHBzOi8vZ3JhcGguY2xvdWRhcGkubWljcm9zb2Z0LmZha2VjdXN0b21jbG91ZC8iLCJzdG9yYWdlRW5kcG9pbnRTdWZmaXgiOiJjb3JlLm1pY3Jvc29mdC5mYWtlY3VzdG9tY2xvdWQiLCJzcWxEYXRhYmFzZUROU1N1ZmZpeCI6ImRhdGFiYXNlLmNsb3VkYXBpLm1pY3Jvc29mdC5mYWtlY3VzdG9tY2xvdWQiLCJrZXlWYXVsdEROU1N1ZmZpeCI6InZhdWx0LmNsb3VkYXBpLm1pY3Jvc29mdC5mYWtlY3VzdG9tY2xvdWQiLCJyZXNvdXJjZU1hbmFnZXJWTUROU1N1ZmZpeCI6ImNsb3VkYXBwLmF6dXJlLm1pY3Jvc29mdC5mYWtlY3VzdG9tY2xvdWQvIiwiY29udGFpbmVyUmVnaXN0cnlETlNTdWZmaXgiOiIuYXp1cmVjci5taWNyb3NvZnQuZmFrZWN1c3RvbWNsb3VkIiwiY29zbW9zREJETlNTdWZmaXgiOiJkb2N1bWVudHMuY29yZS5taWNyb3NvZnQuZmFrZWN1c3RvbWNsb3VkLyIsInRva2VuQXVkaWVuY2UiOiJodHRwczovL21hbmFnZW1lbnQuY29yZS5taWNyb3NvZnQuZmFrZWN1c3RvbWNsb3VkLyIsInJlc291cmNlSWRlbnRpZmllcnMiOnt9fQ==" [io.file]::WriteAllBytes($azureStackConfigFile, [System.Convert]::FromBase64String($envJSON)) - Get-CACertificates + Invoke-RCV1PCertificateRefresh + Register-RCV1PCertificateRefreshTask Write-CACert -CACertificate $global:CACertificate ` diff --git a/pkg/agent/testdata/AKSWindows2019+CustomVnet/CustomData b/pkg/agent/testdata/AKSWindows2019+CustomVnet/CustomData index 92c55d606cb..0f0d9908d6d 100644 --- a/pkg/agent/testdata/AKSWindows2019+CustomVnet/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+CustomVnet/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { diff --git a/pkg/agent/testdata/AKSWindows2019+EnablePrivateClusterHostsConfigAgent/CustomData b/pkg/agent/testdata/AKSWindows2019+EnablePrivateClusterHostsConfigAgent/CustomData index 8f4612558ae..71e224676e0 100644 --- a/pkg/agent/testdata/AKSWindows2019+EnablePrivateClusterHostsConfigAgent/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+EnablePrivateClusterHostsConfigAgent/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { diff --git a/pkg/agent/testdata/AKSWindows2019+K8S116/CustomData b/pkg/agent/testdata/AKSWindows2019+K8S116/CustomData index f44eb7ee18c..901496f3da6 100644 --- a/pkg/agent/testdata/AKSWindows2019+K8S116/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+K8S116/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { diff --git a/pkg/agent/testdata/AKSWindows2019+K8S117/CustomData b/pkg/agent/testdata/AKSWindows2019+K8S117/CustomData index bb35b7fb83c..acaee7f8611 100644 --- a/pkg/agent/testdata/AKSWindows2019+K8S117/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+K8S117/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { diff --git a/pkg/agent/testdata/AKSWindows2019+K8S118/CustomData b/pkg/agent/testdata/AKSWindows2019+K8S118/CustomData index 70ccb178f33..29263c15b49 100644 --- a/pkg/agent/testdata/AKSWindows2019+K8S118/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+K8S118/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { diff --git a/pkg/agent/testdata/AKSWindows2019+K8S119+CSI/CustomData b/pkg/agent/testdata/AKSWindows2019+K8S119+CSI/CustomData index 38b0ae757bb..622b4178cee 100644 --- a/pkg/agent/testdata/AKSWindows2019+K8S119+CSI/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+K8S119+CSI/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { diff --git a/pkg/agent/testdata/AKSWindows2019+K8S119+FIPS/CustomData b/pkg/agent/testdata/AKSWindows2019+K8S119+FIPS/CustomData index cac650ff3fe..3dc61a88b3d 100644 --- a/pkg/agent/testdata/AKSWindows2019+K8S119+FIPS/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+K8S119+FIPS/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { diff --git a/pkg/agent/testdata/AKSWindows2019+K8S119/CustomData b/pkg/agent/testdata/AKSWindows2019+K8S119/CustomData index ab6f71f13c3..d94878e7e19 100644 --- a/pkg/agent/testdata/AKSWindows2019+K8S119/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+K8S119/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { diff --git a/pkg/agent/testdata/AKSWindows2019+KubeletClientTLSBootstrapping/CustomData b/pkg/agent/testdata/AKSWindows2019+KubeletClientTLSBootstrapping/CustomData index b085f129e04..df358754cc9 100644 --- a/pkg/agent/testdata/AKSWindows2019+KubeletClientTLSBootstrapping/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+KubeletClientTLSBootstrapping/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { diff --git a/pkg/agent/testdata/AKSWindows2019+KubeletServingCertificateRotation/CustomData b/pkg/agent/testdata/AKSWindows2019+KubeletServingCertificateRotation/CustomData index 5d54a1ac5ec..e5deb0c4687 100644 --- a/pkg/agent/testdata/AKSWindows2019+KubeletServingCertificateRotation/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+KubeletServingCertificateRotation/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { diff --git a/pkg/agent/testdata/AKSWindows2019+ManagedIdentity/CustomData b/pkg/agent/testdata/AKSWindows2019+ManagedIdentity/CustomData index 4d9e63f67e3..7ee609f4b1b 100644 --- a/pkg/agent/testdata/AKSWindows2019+ManagedIdentity/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+ManagedIdentity/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -220,6 +224,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { diff --git a/pkg/agent/testdata/AKSWindows2019+SecurityProfile/CustomData b/pkg/agent/testdata/AKSWindows2019+SecurityProfile/CustomData index a9d154ecfc8..85829d0154a 100644 --- a/pkg/agent/testdata/AKSWindows2019+SecurityProfile/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+SecurityProfile/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { diff --git a/pkg/agent/testdata/AKSWindows2019+ootcredentialprovider/CustomData b/pkg/agent/testdata/AKSWindows2019+ootcredentialprovider/CustomData index 0cff8e5da6e..48cd52f1344 100644 --- a/pkg/agent/testdata/AKSWindows2019+ootcredentialprovider/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+ootcredentialprovider/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { diff --git a/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworking/CustomData b/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworking/CustomData index bdb7b04c2fa..9139b6061de 100644 --- a/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworking/CustomData +++ b/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworking/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { diff --git a/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworkingDisabled/CustomData b/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworkingDisabled/CustomData index 703a36e22ec..dbecac5a366 100644 --- a/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworkingDisabled/CustomData +++ b/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworkingDisabled/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { diff --git a/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworkingNoConfig/CustomData b/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworkingNoConfig/CustomData index c6451db3d31..8c979b28a47 100644 --- a/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworkingNoConfig/CustomData +++ b/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworkingNoConfig/CustomData @@ -19,11 +19,11 @@ #> [CmdletBinding(DefaultParameterSetName="Standard")] param( - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AgentKey, - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] $AADClientSecret, # base64 @@ -31,9 +31,13 @@ param( # MUST keep generating this file when CSE is done and do not change the name # - It is used to avoid running CSE multiple times # - Some customers use this file to check if CSE is done - [parameter(Mandatory=$true)] + [parameter(Mandatory=$true, ParameterSetName="Standard")] [ValidateNotNullOrEmpty()] - $CSEResultFilePath + $CSEResultFilePath, + + [parameter(Mandatory=$true, ParameterSetName="CARefresh")] + [switch] + $CARefreshOnly ) # In an ideal world, all these values would be passed to this script in parameters. However, we don't live in an ideal world. @@ -218,6 +222,219 @@ $global:WindowsCiliumInstallPath = Join-Path -Path $global:WindowsCiliumNetworki $global:BOOTSTRAP_PROFILE_CONTAINER_REGISTRY_SERVER="" $global:MCR_REPOSITORY_BASE="mcr.microsoft.com/" +# The purpose of RCV 1P is to reliably distribute root and intermediate certificates at scale to +# only Microsoft 1st party (1P) virtual machines (VM) and virtual machine scale sets (VMSS). +# This is critical for initiatives such as Microsoft PKI. RCV 1P ensures that these certificates +# are installed on the node at creation time. This eliminates the need for your VM to be connected +# to the internet and ping an endpoint to receive certificate packages. The feature also eliminates +# the dependency on updates to AzSecPack to receive the latest root and intermediate certs. +# RCV 1P is designed to work completely autonomously from the user perspective on all Azure 1st +# party VMs. + +$global:WireServerEndpoint = "http://168.63.129.16" +$global:RCV1PCertificatesDirectory = "C:\AzureData\RCV1PCertificates" +$global:RCV1PCertificateRefreshTaskName = "aks-rcv1p-cert-refresh" + +function Write-RCV1PLog { + Param( + [Parameter(Mandatory=$true)][string] + $Message + ) + + if (Get-Command -Name Write-Log -ErrorAction SilentlyContinue) { + Write-Log $Message + } else { + Write-Output $Message + } +} + +function Invoke-RCV1PWithRetry { + Param( + [Parameter(Mandatory=$true)][scriptblock] + $Script, + [Parameter(Mandatory=$false)][int] + $MaxRetryCount = 5, + [Parameter(Mandatory=$false)][int] + $InitialDelaySeconds = 3 + ) + + $attempt = 1 + $delaySeconds = $InitialDelaySeconds + while ($attempt -le $MaxRetryCount) { + try { + return & $Script + } catch { + if ($attempt -ge $MaxRetryCount) { + throw + } + + Write-RCV1PLog "RCV1P retry [$attempt/$MaxRetryCount] failed: $($_.Exception.Message). Retrying in $delaySeconds seconds." + Start-Sleep -Seconds $delaySeconds + $delaySeconds = [Math]::Min($delaySeconds * 2, 60) + $attempt++ + } + } +} + +function Get-RCV1POptInStatus { + $optInUri = "$($global:WireServerEndpoint)/acms/isOptedInForRootCerts" + + try { + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $optInUri -UseBasicParsing -ErrorAction Stop + } + + $body = "$($response.Content)" + if ([string]::IsNullOrEmpty($body)) { + Write-RCV1PLog "RCV1P opt-in response is empty, defaulting to not opted in" + return $false + } + + try { + $json = $body | ConvertFrom-Json -ErrorAction Stop + return ($json.IsOptedInForRootCerts -eq $true) + } catch { + return ($body -match '"IsOptedInForRootCerts"\s*:\s*true') + } + } catch { + Write-RCV1PLog "Failed to query RCV1P opt-in endpoint: $($_.Exception.Message). Defaulting to non-opt-in flow." + return $false + } +} + +function Get-RCV1POperationCertificates { + Param( + [Parameter(Mandatory=$true)][string] + $OperationType + ) + + $listUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$OperationType&ext=json" + $listResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $listUri -UseBasicParsing -ErrorAction Stop + } + + $operationData = $listResponse.Content | ConvertFrom-Json -ErrorAction Stop + $certFileNames = @() + foreach ($entry in $operationData) { + $candidate = $entry.ResouceFileName + if ([string]::IsNullOrEmpty($candidate)) { + $candidate = $entry.ResourceFileName + } + + if (-not [string]::IsNullOrEmpty($candidate)) { + $certFileNames += $candidate + } + } + + $certificates = @() + foreach ($certFileName in $certFileNames) { + $nameWithoutExtension = [System.IO.Path]::GetFileNameWithoutExtension($certFileName) + $extension = [System.IO.Path]::GetExtension($certFileName).TrimStart('.') + $contentUri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=$nameWithoutExtension&ext=$extension" + + $certContentResponse = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $contentUri -UseBasicParsing -ErrorAction Stop + } + + $certificates += [PSCustomObject]@{ + Name = $certFileName + CertBody = $certContentResponse.Content + } + } + + return $certificates +} + +function Get-LegacyCACertificates { + $uri = "$($global:WireServerEndpoint)/machine?comp=acmspackage&type=cacertificates&ext=json" + $response = Invoke-RCV1PWithRetry -Script { + Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop + } + + $caCerts = $response.Content | ConvertFrom-Json -ErrorAction Stop + return $caCerts.Certificates +} + +function Install-RCV1PCertificateFile { + Param( + [Parameter(Mandatory=$true)][string] + $CertificatePath + ) + + $certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertificatePath) + $storeLocation = if ($certificate.Subject -eq $certificate.Issuer) { "Cert:\LocalMachine\Root" } else { "Cert:\LocalMachine\CA" } + Import-Certificate -FilePath $CertificatePath -CertStoreLocation $storeLocation -ErrorAction Stop | Out-Null +} + +function Invoke-RCV1PCertificateRefresh { + try { + Write-RCV1PLog "Starting RCV1P certificate refresh" + Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + + $certificates = @() + if (Get-RCV1POptInStatus) { + Write-RCV1PLog "VM is opted in for RCV1P PKI setup. Pulling operation-request certificates." + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsroot" + $certificates += Get-RCV1POperationCertificates -OperationType "operationrequestsintermediate" + } else { + Write-RCV1PLog "VM is not opted in for RCV1P PKI setup. Pulling legacy certificate package." + $certificates += Get-LegacyCACertificates + } + + if ($null -eq $certificates -or $certificates.Count -eq 0) { + throw "No certificates received from WireServer" + } + + foreach ($cert in $certificates) { + if ([string]::IsNullOrEmpty($cert.Name) -or [string]::IsNullOrEmpty($cert.CertBody)) { + continue + } + + $certPath = Join-Path $global:RCV1PCertificatesDirectory $cert.Name + [System.IO.File]::WriteAllText($certPath, $cert.CertBody) + Install-RCV1PCertificateFile -CertificatePath $certPath + Write-RCV1PLog "Installed certificate $($cert.Name)" + } + + Write-RCV1PLog "RCV1P certificate refresh completed successfully" + } catch { + Write-RCV1PLog "RCV1P certificate refresh failed: $($_.Exception.Message)" + throw + } +} + +function Register-RCV1PCertificateRefreshTask { + $scriptPath = $MyInvocation.MyCommand.Path + if ([string]::IsNullOrEmpty($scriptPath)) { + $scriptPath = $PSCommandPath + } + + if ([string]::IsNullOrEmpty($scriptPath)) { + Write-RCV1PLog "Unable to determine script path. Skipping registration of RCV1P refresh scheduled task." + return + } + + if (Get-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -ErrorAction SilentlyContinue) { + Write-RCV1PLog "Scheduled task $($global:RCV1PCertificateRefreshTaskName) already exists" + return + } + + $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`" -CARefreshOnly" + $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + $trigger = New-ScheduledTaskTrigger -Daily -At (Get-Date "19:00") + $trigger.RandomDelay = "00:05:00" + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $definition = New-ScheduledTask -Action $action -Principal $principal -Trigger $trigger -Settings $settings -Description "Refresh RCV1P certificates daily" + Register-ScheduledTask -TaskName $global:RCV1PCertificateRefreshTaskName -InputObject $definition | Out-Null + + Write-RCV1PLog "Registered scheduled task $($global:RCV1PCertificateRefreshTaskName)" +} + +if ($CARefreshOnly) { + Invoke-RCV1PCertificateRefresh + exit 0 +} + # Extract cse helper script from ZIP [io.file]::WriteAllBytes("scripts.zip", [System.Convert]::FromBase64String($zippedFiles)) try { diff --git a/pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData b/pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData index b15f72a112a..c29274be7f0 100644 --- a/pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData +++ b/pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData @@ -1 +1 @@ -{"ignition":{"config":{"replace":{"verification":{}}},"proxy":{},"security":{"tls":{}},"timeouts":{},"version":"3.4.0"},"kernelArguments":{},"passwd":{},"storage":{"files":[{"group":{},"overwrite":true,"path":"/var/lib/ignition/ignition-files.tar","user":{},"contents":{"compression":"gzip","source":"data:;base64,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","verification":{}},"mode":384}]},"systemd":{"units":[{"contents":"[Unit]\nDescription=Ignition Early Boot Commands\nDefaultDependencies=no\nAfter=local-fs.target\nBefore=sysinit.target\nConditionPathExists=/etc/ignition-bootcmds.sh\n\n[Service]\nType=oneshot\nExecStart=-/etc/ignition-bootcmds.sh\n\n[Install]\nWantedBy=sysinit.target\n","enabled":true,"name":"ignition-bootcmds.service"},{"contents":"[Unit]\nDescription=Extract Ignition file payload\nDefaultDependencies=no\nAfter=local-fs.target\nBefore=sysinit.target ignition-bootcmds.service\nConditionPathExists=/var/lib/ignition/ignition-files.tar\n\n[Service]\nType=oneshot\nExecStart=tar -xvf /var/lib/ignition/ignition-files.tar -C /\nExecStart=rm -f /var/lib/ignition/ignition-files.tar\nExecStart=systemctl daemon-reload\nRemainAfterExit=yes\n\n[Install]\nWantedBy=sysinit.target\n","enabled":true,"name":"ignition-file-extract.service"}]}} \ No newline at end of file +{"ignition":{"config":{"replace":{"verification":{}}},"proxy":{},"security":{"tls":{}},"timeouts":{},"version":"3.4.0"},"kernelArguments":{},"passwd":{},"storage":{"files":[{"group":{},"overwrite":true,"path":"/var/lib/ignition/ignition-files.tar","user":{},"contents":{"compression":"gzip","source":"data:;base64,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","verification":{}},"mode":384}]},"systemd":{"units":[{"contents":"[Unit]\nDescription=Ignition Early Boot Commands\nDefaultDependencies=no\nAfter=local-fs.target\nBefore=sysinit.target\nConditionPathExists=/etc/ignition-bootcmds.sh\n\n[Service]\nType=oneshot\nExecStart=-/etc/ignition-bootcmds.sh\n\n[Install]\nWantedBy=sysinit.target\n","enabled":true,"name":"ignition-bootcmds.service"},{"contents":"[Unit]\nDescription=Extract Ignition file payload\nDefaultDependencies=no\nAfter=local-fs.target\nBefore=sysinit.target ignition-bootcmds.service\nConditionPathExists=/var/lib/ignition/ignition-files.tar\n\n[Service]\nType=oneshot\nExecStart=tar -xvf /var/lib/ignition/ignition-files.tar -C /\nExecStart=rm -f /var/lib/ignition/ignition-files.tar\nExecStart=systemctl daemon-reload\nRemainAfterExit=yes\n\n[Install]\nWantedBy=sysinit.target\n","enabled":true,"name":"ignition-file-extract.service"}]}} \ No newline at end of file diff --git a/pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData.inner b/pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData.inner index 5ab49bba925..cbf397734b0 100644 --- a/pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData.inner +++ b/pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData.inner @@ -100,7 +100,7 @@ { "contents": { "compression": "gzip", - "source": "data:;base64,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" + "source": "data:;base64,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" }, "mode": 484, "overwrite": true, From 9ede6e07367df01fa70985ff900519f82028f2e9 Mon Sep 17 00:00:00 2001 From: Ramkumar Chinchani Date: Tue, 3 Mar 2026 14:06:17 -0800 Subject: [PATCH 4/7] feat: implement retry logic for HTTP requests in RCV 1P cert retrieval --- .../artifacts/init-aks-custom-cloud.sh | 42 ++++++++++++++++--- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/parts/linux/cloud-init/artifacts/init-aks-custom-cloud.sh b/parts/linux/cloud-init/artifacts/init-aks-custom-cloud.sh index 1379a1150d4..a3daa6404d9 100644 --- a/parts/linux/cloud-init/artifacts/init-aks-custom-cloud.sh +++ b/parts/linux/cloud-init/artifacts/init-aks-custom-cloud.sh @@ -35,6 +35,38 @@ echo "Running on $NAME" # Below code calls the wireserver to get the list of CA certs for this cloud and saves them to /root/AzureCACertificates. Then it copies them to the appropriate location based on distro and updates the CA bundle. +# http://168.63.129.16 is a constant for the host's wireserver endpoint +WIRESERVER_ENDPOINT="http://168.63.129.16" + +# Function to make HTTP request with retry logic for rate limiting +make_request_with_retry() { + local url="$1" + local max_retries=10 + local retry_delay=3 + local attempt=1 + + local response + while [ $attempt -le $max_retries ]; do + response=$(curl -f --no-progress-meter "$url") + local request_status=$? + + if echo "$response" | grep -q "RequestRateLimitExceeded"; then + sleep $retry_delay + retry_delay=$((retry_delay * 2)) + attempt=$((attempt + 1)) + elif [ $request_status -ne 0 ]; then + sleep $retry_delay + attempt=$((attempt + 1)) + else + echo "$response" + return 0 + fi + done + + echo "exhausted all retries, last response: $response" + return 1 +} + # Function to process certificate operations from a given endpoint process_cert_operations() { local endpoint_type="$1" @@ -97,11 +129,11 @@ IFS=$'\r\n' # not opted in. # https://eng.ms/docs/products/onecert-certificates-key-vault-and-dsms/onecert-customer-guide/autorotationandecr/rcv1ptsg -optInCheck="" -if optInCheck=$(curl -sS --fail "http://168.63.129.16/acms/isOptedInForRootCerts"); then - : -else - echo "Warning: failed to query root cert opt-in status; defaulting to non-opt-in flow" +optInCurlStatus=0 +optInCheck=$(curl -sS --fail "http://168.63.129.16/acms/isOptedInForRootCerts" 2>/dev/null) || optInCurlStatus=$? +if [ "$optInCurlStatus" -ne 0 ]; then + echo "Warning: failed to query root cert opt-in status (curl exit code $optInCurlStatus); defaulting to non-opt-in flow" + optInCheck="" fi if echo "$optInCheck" | grep -Eq '"IsOptedInForRootCerts"[[:space:]]*:[[:space:]]*true'; then From 0b5c7670587b6de1bf695001b7988f72a70d6691 Mon Sep 17 00:00:00 2001 From: Ramkumar Chinchani Date: Tue, 3 Mar 2026 14:06:41 -0800 Subject: [PATCH 5/7] feat: add directory creation for RCV1P certificates if it doesn't exist --- parts/windows/kuberneteswindowssetup.ps1 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/parts/windows/kuberneteswindowssetup.ps1 b/parts/windows/kuberneteswindowssetup.ps1 index 00423632698..af8bf2c8d99 100644 --- a/parts/windows/kuberneteswindowssetup.ps1 +++ b/parts/windows/kuberneteswindowssetup.ps1 @@ -375,7 +375,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { From 172daf9463214390b500e6f6552709fd661ad970 Mon Sep 17 00:00:00 2001 From: Ramkumar Chinchani Date: Tue, 3 Mar 2026 14:08:47 -0800 Subject: [PATCH 6/7] fix: update Go version to 1.25 in validate-components workflow --- .github/workflows/validate-components.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate-components.yml b/.github/workflows/validate-components.yml index 7a6ca8414b4..0fe8571e375 100644 --- a/.github/workflows/validate-components.yml +++ b/.github/workflows/validate-components.yml @@ -9,7 +9,7 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: - go-version: '1.24' + go-version: '1.25' - name: Install cue run: | go version From aa1496398c1f8b0a38d02ebf2fd95cc2ea97996f Mon Sep 17 00:00:00 2001 From: Ramkumar Chinchani Date: Tue, 3 Mar 2026 14:17:33 -0800 Subject: [PATCH 7/7] fix: update testdata --- .../testdata/AKSUbuntu2204+CustomCloud+USNat/CustomData | 2 +- .../testdata/AKSUbuntu2204+CustomCloud+USSec/CustomData | 2 +- .../CustomData | 5 ++++- pkg/agent/testdata/AKSWindows2019+CustomCloud/CustomData | 5 ++++- pkg/agent/testdata/AKSWindows2019+CustomVnet/CustomData | 5 ++++- .../CustomData | 5 ++++- pkg/agent/testdata/AKSWindows2019+K8S116/CustomData | 5 ++++- pkg/agent/testdata/AKSWindows2019+K8S117/CustomData | 5 ++++- pkg/agent/testdata/AKSWindows2019+K8S118/CustomData | 5 ++++- pkg/agent/testdata/AKSWindows2019+K8S119+CSI/CustomData | 5 ++++- pkg/agent/testdata/AKSWindows2019+K8S119+FIPS/CustomData | 5 ++++- pkg/agent/testdata/AKSWindows2019+K8S119/CustomData | 5 ++++- .../AKSWindows2019+KubeletClientTLSBootstrapping/CustomData | 5 ++++- .../CustomData | 5 ++++- pkg/agent/testdata/AKSWindows2019+ManagedIdentity/CustomData | 5 ++++- pkg/agent/testdata/AKSWindows2019+SecurityProfile/CustomData | 5 ++++- .../testdata/AKSWindows2019+ootcredentialprovider/CustomData | 5 ++++- .../testdata/AKSWindows23H2Gen2+NextGenNetworking/CustomData | 5 ++++- .../AKSWindows23H2Gen2+NextGenNetworkingDisabled/CustomData | 5 ++++- .../AKSWindows23H2Gen2+NextGenNetworkingNoConfig/CustomData | 5 ++++- pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData | 2 +- .../testdata/Flatcar+CustomCloud+USSec/CustomData.inner | 2 +- 22 files changed, 76 insertions(+), 22 deletions(-) diff --git a/pkg/agent/testdata/AKSUbuntu2204+CustomCloud+USNat/CustomData b/pkg/agent/testdata/AKSUbuntu2204+CustomCloud+USNat/CustomData index e6ed96a6cd2..7f57edf7d3c 100644 --- a/pkg/agent/testdata/AKSUbuntu2204+CustomCloud+USNat/CustomData +++ b/pkg/agent/testdata/AKSUbuntu2204+CustomCloud+USNat/CustomData @@ -91,7 +91,7 @@ write_files: encoding: gzip owner: root content: !!binary | - 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 - path: /opt/azure/containers/reconcilePrivateHosts.sh permissions: "0744" diff --git a/pkg/agent/testdata/AKSUbuntu2204+CustomCloud+USSec/CustomData b/pkg/agent/testdata/AKSUbuntu2204+CustomCloud+USSec/CustomData index e6ed96a6cd2..7f57edf7d3c 100644 --- a/pkg/agent/testdata/AKSUbuntu2204+CustomCloud+USSec/CustomData +++ b/pkg/agent/testdata/AKSUbuntu2204+CustomCloud+USSec/CustomData @@ -91,7 +91,7 @@ write_files: encoding: gzip owner: root content: !!binary | - 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 - path: /opt/azure/containers/reconcilePrivateHosts.sh permissions: "0744" diff --git a/pkg/agent/testdata/AKSWindows2019+CustomCloud+ootcredentialprovider/CustomData b/pkg/agent/testdata/AKSWindows2019+CustomCloud+ootcredentialprovider/CustomData index ec80cc5b830..a4bf28a167d 100644 --- a/pkg/agent/testdata/AKSWindows2019+CustomCloud+ootcredentialprovider/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+CustomCloud+ootcredentialprovider/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows2019+CustomCloud/CustomData b/pkg/agent/testdata/AKSWindows2019+CustomCloud/CustomData index 7cfb48c7c21..fc68a59117c 100644 --- a/pkg/agent/testdata/AKSWindows2019+CustomCloud/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+CustomCloud/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows2019+CustomVnet/CustomData b/pkg/agent/testdata/AKSWindows2019+CustomVnet/CustomData index 0f0d9908d6d..1e5dc86a2a9 100644 --- a/pkg/agent/testdata/AKSWindows2019+CustomVnet/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+CustomVnet/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows2019+EnablePrivateClusterHostsConfigAgent/CustomData b/pkg/agent/testdata/AKSWindows2019+EnablePrivateClusterHostsConfigAgent/CustomData index 71e224676e0..cc8db3a603f 100644 --- a/pkg/agent/testdata/AKSWindows2019+EnablePrivateClusterHostsConfigAgent/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+EnablePrivateClusterHostsConfigAgent/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows2019+K8S116/CustomData b/pkg/agent/testdata/AKSWindows2019+K8S116/CustomData index 901496f3da6..a043e3cb4ab 100644 --- a/pkg/agent/testdata/AKSWindows2019+K8S116/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+K8S116/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows2019+K8S117/CustomData b/pkg/agent/testdata/AKSWindows2019+K8S117/CustomData index acaee7f8611..48412c20862 100644 --- a/pkg/agent/testdata/AKSWindows2019+K8S117/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+K8S117/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows2019+K8S118/CustomData b/pkg/agent/testdata/AKSWindows2019+K8S118/CustomData index 29263c15b49..80aa4fb510e 100644 --- a/pkg/agent/testdata/AKSWindows2019+K8S118/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+K8S118/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows2019+K8S119+CSI/CustomData b/pkg/agent/testdata/AKSWindows2019+K8S119+CSI/CustomData index 622b4178cee..f2d75f9b6b7 100644 --- a/pkg/agent/testdata/AKSWindows2019+K8S119+CSI/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+K8S119+CSI/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows2019+K8S119+FIPS/CustomData b/pkg/agent/testdata/AKSWindows2019+K8S119+FIPS/CustomData index 3dc61a88b3d..514284975f7 100644 --- a/pkg/agent/testdata/AKSWindows2019+K8S119+FIPS/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+K8S119+FIPS/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows2019+K8S119/CustomData b/pkg/agent/testdata/AKSWindows2019+K8S119/CustomData index d94878e7e19..04f3903bb50 100644 --- a/pkg/agent/testdata/AKSWindows2019+K8S119/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+K8S119/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows2019+KubeletClientTLSBootstrapping/CustomData b/pkg/agent/testdata/AKSWindows2019+KubeletClientTLSBootstrapping/CustomData index df358754cc9..7f847dc50c4 100644 --- a/pkg/agent/testdata/AKSWindows2019+KubeletClientTLSBootstrapping/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+KubeletClientTLSBootstrapping/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows2019+KubeletServingCertificateRotation/CustomData b/pkg/agent/testdata/AKSWindows2019+KubeletServingCertificateRotation/CustomData index e5deb0c4687..2e97b9a3e9e 100644 --- a/pkg/agent/testdata/AKSWindows2019+KubeletServingCertificateRotation/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+KubeletServingCertificateRotation/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows2019+ManagedIdentity/CustomData b/pkg/agent/testdata/AKSWindows2019+ManagedIdentity/CustomData index 7ee609f4b1b..865e0796313 100644 --- a/pkg/agent/testdata/AKSWindows2019+ManagedIdentity/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+ManagedIdentity/CustomData @@ -371,7 +371,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows2019+SecurityProfile/CustomData b/pkg/agent/testdata/AKSWindows2019+SecurityProfile/CustomData index 85829d0154a..c90c55a8237 100644 --- a/pkg/agent/testdata/AKSWindows2019+SecurityProfile/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+SecurityProfile/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows2019+ootcredentialprovider/CustomData b/pkg/agent/testdata/AKSWindows2019+ootcredentialprovider/CustomData index 48cd52f1344..f275b3cfc79 100644 --- a/pkg/agent/testdata/AKSWindows2019+ootcredentialprovider/CustomData +++ b/pkg/agent/testdata/AKSWindows2019+ootcredentialprovider/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworking/CustomData b/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworking/CustomData index 9139b6061de..a63b2ad7e0d 100644 --- a/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworking/CustomData +++ b/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworking/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworkingDisabled/CustomData b/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworkingDisabled/CustomData index dbecac5a366..2749305f6a8 100644 --- a/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworkingDisabled/CustomData +++ b/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworkingDisabled/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworkingNoConfig/CustomData b/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworkingNoConfig/CustomData index 8c979b28a47..9c15846b100 100644 --- a/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworkingNoConfig/CustomData +++ b/pkg/agent/testdata/AKSWindows23H2Gen2+NextGenNetworkingNoConfig/CustomData @@ -369,7 +369,10 @@ function Install-RCV1PCertificateFile { function Invoke-RCV1PCertificateRefresh { try { Write-RCV1PLog "Starting RCV1P certificate refresh" - Create-Directory -FullPath $global:RCV1PCertificatesDirectory -DirectoryUsage "storing RCV1P certificates" + if (-not (Test-Path -Path $global:RCV1PCertificatesDirectory)) { + Write-RCV1PLog "Creating directory $($global:RCV1PCertificatesDirectory) for storing RCV1P certificates" + New-Item -ItemType Directory -Path $global:RCV1PCertificatesDirectory -Force | Out-Null + } $certificates = @() if (Get-RCV1POptInStatus) { diff --git a/pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData b/pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData index c29274be7f0..0c7c2ed044f 100644 --- a/pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData +++ b/pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData @@ -1 +1 @@ -{"ignition":{"config":{"replace":{"verification":{}}},"proxy":{},"security":{"tls":{}},"timeouts":{},"version":"3.4.0"},"kernelArguments":{},"passwd":{},"storage":{"files":[{"group":{},"overwrite":true,"path":"/var/lib/ignition/ignition-files.tar","user":{},"contents":{"compression":"gzip","source":"data:;base64,H4sIAAAAAAAC/+y9fXvbNrIovv9efQqUYWsrNfVmx0mdKruMRDs6kSVdUUqbk6R8aBKSuKZIlaScuIrOZ/89eCNBEqQkO+2evb/tec7GIoDBYDAYzACDGX8V1c0/1gGsW74XmY4Hg7C+Cvw7J3R8zwj9dWDBWrj42yP+azQajednZ/jfRqOR/rfZbDafNdk38r35vHX2/G+g8be/4L91GJnB3xqP7is7uH+T/558V79xvPqNGS4q2nhs6O/1iXbdmfQNfaKOJ8al2uu3zwAu6/SH067RG/QmxqR3rQ2nk/YzUnLZ62vGL+qk8yYuOSclb4b9rvGL2u8Npr+qV9pg0n5OCsZaX1N1TVDhBamgjiZGb6BP1H4/BvoTKbru6XpvcGV0pl3VGKmdt+qV1m42SGF32HmrjXNNW+ni7vCXQX+odpPyZqr8rfZeUKeVqoMwRPXi4tNUMUfAFqXg9fD1e9ys39MTIrYoFa9142p0VdD1OQchNzZK085wMFF7A23czVehVB1PB518IaXr2xc6qjBAtGVlp42kLIfVKSXa2+lrDfHMYDgxLofTQbd9SknVu74SNDtNmvW1CU+p07P0LF5fGaMph+rps9xQOxNRvfN8vXEP4ZivWkw9zNfcoF7kar7TxnpvODB6g3dqv9dtn1JSdga9/LjPmvFEj8bDrtHVXgsqtfKVRm+vDLXbpauRUm84Vrkp0cbj4bh9RslDljE3ENzwBeOh7mg8fK3RrxTj4XTyGo0SjW5Aip5xc6+Oeoaujd9pY75CU1ihO9CN/nD4djqi1VrCaup/T8davjJjDnWiitfCeYOrkV2E502uMMvo5xSRd2+62bk9zzNWruPnDW4R5Utpz52pPhleG7qmjjtvjO7wWu0NdDK2FxTA1Wiab//ilCsc9xBn8SvjxVm+ODu+F8+4Otq7XkczRv3pVW+QAnSeVOoNLofGeHhtdIbj8XQ00brtF3Q56Fe/FvbzUyNfh+vhJ0oJ9bqrXqu0Bkfrn56lylNM+tN5Iv67aq+fzOxP3MYwHXXViZYUsVWna2jRvOvhNal3xr3RBPc71tRuAqnZaHCdIFE8HV2N1a7G1WgmNUbT8RVdLM1GK15gSJiMNTSF7WaDzl2npxuqrveuBsZ4OJwYo1/azWYzV4Z5b6SN8UY2HLSbTQoWbWZ4hY3e40rtZpOHPBr13xsjVdd/GY7xQr3sXbWbzcyij/efIV1SzSaThkQE5liv2XyeqjAcaWN1gmhIxEqzySTfZCwopNSnMtDo9HvGZDjst5ts02WCPjXTzVZm98iUUpJoA/V1XzOu1YF6pXUx12q/jrRxTxt0tHYTbbqVeFG/nvb6TBY20b5KCPOLOjI6Yw2xDAHOdjW+pDfQp5eXvU5PG2CueGvoIxV1gXY5XHui9bXRcDzppsRuu8nkZFLOhkKKGS+NJ71LtYP2u7GmXqNdlsFpN5mMFFSiwNpNJhoFddQOWmBd7XqYWuvNZ2cU9zeTyQitjV/fGx0Vsc47bTxpN5kspQsKFWnjid5uMjmqax0kpSd93Xg9HE70yRhRrE+IlN58muc/0c66Pf212teM3miCJk9vN5HoZEV4PnX9Tbv5nLH9uHetjt8bg17H6I04SdF8fsp4S9fGE6N33dWNsaZPEJ8iFhxPUTeDyRAxyFVfM3CH7ebzs33bXfb6E20ct6NrqYv4VStod4kkZqa/833bZfpLlI/LHlJMXqPNTJ1O3lAKvQAJd481NAXGWPu/095Y67ZbTI4NhkwN1inhWkyA6QN1pL8ZxiKT10qRMGP0f4cK0QaNdA3Eti0m09BHnp9bDcZTibFwrepvKVBa1hlrXW0w6al9IpG7QqW7wZYo0peyulSrcc7WNtZ1sNaGsKHYPweZMkGf7VbjBVcNz0ui8jeyEAba5Jfh+C1XpZmtMh2g2RmOe/+NZqDJxoshX2rIBELoobJYblD1hrF+rPZq43fYjNHQeu510AyMhxMiWyfqVbvVPKXU6WvqYDpKlBOjd40mu91qntFlNdCNN5ran7yh1Gk+izvvqP0u00BabCuIP3eGY43pQpR32G4Q19H7vU6u0otMpde9AVrDmEWaTBIIxUfCg9Ox1m61mGzgDExGQ2ZTDd71ur1YlWASscUMK1pcbD4xG4tWxKontjmNsTYakg1Z0IpZXXTzoa21X0fpzarFLDCGZufqmpW8yJdov6JdQhuzKj8Bnk1KNzzCF6eMYpgjR0NEtMuxmuWPZNgJ++rvde1XJgBiDlXf6nj7wBDGw35fG1Oh3jpDfX0AygzUYWTVV4E/c1xYs+srM1rUwgX4BH74AdQKSisVZwZmjmfjcqBE9ysIZicuUDxzCYH0VAmgC80QSkBZBY4XAeX3tROB1qu6De/q3tp1wVcwD+AKKL+Do9rRSxAtoFcBAICh3paPQz+IgBKQ7mNoqI35+RYcLc3IWhzLjRNQ/+24120f155Wq3L9BJhVsAGkx8hfr1YwODY/tD5VXwL4xYnA9qhK+2Bi6cC+YmG2u09gfjjlOgZfQRQAxQZHEoeEOu6pg8mhSJBWxkEDT/cP3RBiJKC18IGU6dXzIzDz154tVWZOpTJ9PR1MpsZQNwbqtdaWyG+pcq2OMVfGBfRDUoLNtWwx+ihVuLWarpUU5CoK6kiVy7466agcFvRDpuXVVB13DY7mEv0mVaim2q77qwifm92ub6AVuRWicrfr6zDA323fuoVBBX5ZodnC5ti7tiRvEuONsdVFeyul6mn6hMBxfct0696dYzsmq5ERg2iRG/oblYGOP/BQRW2QFGHovNsq8qYAcA4KN4DJ+5GWGRP6tKPrtrS0gtrSsQI/9GdRzfKXdfM2RP+vzFfrBJUM2AQoskGI7UokcOe625YsxLIeuH0R1hwfBGsPKEie3DkunEMbKEqwBIriwUhZ+GEEFOWzEy0ULwQrx75AYsuqN+teWF85qPLSX6Plcb+C7RvHs0/CwCJzPl+tT+wwateXHvnhryLH98J2gOqVtTQtXDFpzT6kIMSDpDZcbpyEsUQD9GDUpmNbOTb98w4wtC8YyvFHisAFjw0mlFRBVm9H7bzRjG5v3K7fmUHdMq0FrJuoXWAtnDsY1ivIglUHyBLgKge+H6F6pEFFe6cNJrrRH15dYYOHwXP9Ob14uI55QUW/a9qXCHohwqbWWYeRv9StwFlFdXgHvSisVzrTcd8YTiej6aRdj5arurUOXOMOBjd+CGv+Oqrg3Y6v4QdmmK8x1q56+mT8ninf2ODGAg7Vr1u+N3PmtXtz6YJKBe2QqtqNz65GIyRVpXPbhGet2Qvl7PT8hXJ2/vyF8tPZbKac/nTegK0X8PT8tCFVKtYCWreGFUIjcpbQX0fHVbDBYjVc+GvX7vtztJSaF0oUrOFWwkVL80t3HZhoYnRo+Z4dtp+/aABc5szAB6D8ASR509GpVo/UFqRwDQdd/ULZSuATt1nGjSQ57lICbSChDvNVE4n/ixl4jje/AMJ+APTunMD3ltCLwJ0ZOOaNC4ET4p0hhFFNikHOnPjPAEbrwAONCvcduuYqhDYbqXx8LB/bZgTBj9+HVaAASRYiIFWrFW5saSgSUOYRkOQ8Jb8RcbQg8ANMGrAwQ3ADoYfWJiIYmPkByOADQvLvCYBfLAhtVC1aQOA6SycC/gwIMGVtahJ49UOrhJpNRs1KisTbSsUIYBTcW0vbcLwIBp7pxuyHNxlUOXBg2JabL0G4cGYRV/bZdCLdhXAlLKXs/M50hcUJd4tKraU98cdrr30syf+QqlwJUkX0yIzWYbtBxoOo6QDHA/JxCH8HTSDJFGup+hLYfkwNihGQ5AQ3Ca2Tf2wTXuTgy3+vZHkgKZWAAn8HDSEH3ATQvOXngwfzHcgt+RRzFXIUYiXWwFytAt+0Fo43P8EoI36BZuDeZ5iBm/BWEUZoYA4ZT0I64cAOXAncavgCrXUEbfBRkjdscj88/bT9KAHZwcMKX4K5c4fGsV6BY9cMI6J2hpjcF2niVwXD5Pg+x/vZUYeIbYEkxyxMGMD2PVip7Bopsmr2Y4b9B0+lYWaNpvpA6zVZrjNjZjruOoDxgs2vZSDJTcTgLfQ/pxIbAOL4i7NtGmDouNCLDgE2M92wCJoXur5/u17F8BChjTAWFpSP23LrJYj8yHSN+MvpSxBAyw/stnxG9sHIDCJc3ubkPoG6cFwI0KhSC531DpQYKls4Ckax3QAy6QTNJV6u4OtX8DGGYK2DAHoFvXL8cXzM1wQKh2y1ivYYiKQNP8CyPWOCKsZrPN0OBBCpTfbJQaNDPAJtaefCSK8LOZmtZFnsJEuG2Q9CE22IpbRke530Mtm2jJnjQgPreLndi9+3uH2qxbHe6UuAAIzMaNGWz16CdeC25WcviXgO6fZD2Pt8KwF+kPKGwt9iEIgu8VYpiTclJljTW9IxgHd4aXGdSqCa4sqDJHTZ5Io3n79gv4lPCgSbzjwCzcLNg2NHPebGAnmfLBv6B54UZRbq/Tsg4799ILMZB6+AzJkLoPXqh6YIxb9LQPFgwT6Pl4QZpSAVoUj/xEuJl5RzGBmRGdyYbsK8kRkYWQZmwhNxMKmOORgzLZGTZGZpoXFnuo7dlvDx3EdJpp8/0u0rMgOgRH+kiyRO8gvWFsBVjZj9JE5MSOC8AWJQqGwd4H8ESKV3CtwF6iwePf5SNvzMAl6lFzBHCzwG+MUJozChBGuCSLF7xDwy2SHHeiT6k4HNjZ1DIj3y1dp1jVngL40Azp0QofDZiRYGMjFjYuBK5byAOGjmuzYMshyBtWpwBkBKdPEgt7ukFl85LbqyYomv+SDZtFMiiDenDCC2+s8bABESE5BNieITHk0oJgFFYdRXiFmPSFR4CLBF8/oPCUkP7ighLT04yVFoIaTMXKGIxHKF6+MQQbKTqx4mYMjJwoxf52lhwhW8AskpPaJOhgZZMz/GijHyse0E5B4ghlmNN/ady6dcVJFCxgCEN9IyaWX4lmO45r2/jgTkKyEdEUaniIbzrFBa3tpOABRkd2BJIVYoHqJGHKQikB4vsWYIIp8sE2tF9sjIBxi5Czky58CcRTCI+wRmFMHlKgqF+qS8+9bpmyoEGRFQohE0W414kLFwjgeJREDkK77lKGTCgaIgtsrJhTKxUCoQDlYnRMteSDahKDlA8TBN2zAtC4ahEfm30NuHwzFDnx7CnQEMV74XIouBk85EPbsDSgiUN0C6hpFpm5F5QWxURfH8VeB/uQfS03hLVT4D6aP3/WYRRSvD8m24lRKLTO10NF03JsO32oAd8crHdHkxFCTwFYTQBkeyfZQ0jeGJG0Sm4wLFa2asPwXZ54JeuROCGDBZmK1Go2RFCmGV7xr7W24JxhxO4uOKWSwZyGzeQXC7voEujIBjQy9yonuAuQWgZQJ61139BJMQIKgXIOnhBCzD+QUoHxgvPsS+FKmzYIwiYyM0WnagivCIWW0P7KWKsHfeDyS3XgI4C2C4IIvFmPnB3vuCaQUGWTkvQQQ904sMx8YbBE8ctlPsubDG2uVY099keb5gkf0KRkN9ghdbx/ci6EXK5H4FL5Bx5zoWPlmuf1E+f/6szPxgqawDF3poGm2JOxlB/yk2kOYBGgO+zuIlyA8hDO4cC7ZlOuIfyGjbcjzqH/j67RRzZDtCnBRe1OsMWN0319GiVYdfrIXpzaFoRYqIUrYRiht8q3Un5u6MM1GKz/CNlOvPHe9QvkoNhClte7ISxq0/vOpxfIT3TIwJkNgMIMnM1pGCZ1AJI9vxDtejf/755yzxJbxvVlNn8VQu/110Es+J1lLBmhvcodOb0h/FExzjk9YkTY9OaGggCpqe790v/XXo3h82u5VDJpNNHLla4GbuwClKudp8xeesSR/raIWM8OOswRXAlQ/ccFfHhf1mmWAfc4rMs2kFwAkBR2NyaGreuHD/GUf9oQ7JACXQboOn0tpDgscPnD+gfQHQ32gJEJkJAvj72gmgLT0Fn4qxUztjdvspxPACsC73MppjBiTQ1x78soJWBO1kD8Tbs2kFGch7iyQjvA8juLQil56QhHeW4a8guYTch3+ToxoQt2vLZyC8s5Bx15afJfeAY9RFz5v5bXlzfqHg24XtIVyfOwCM0Qe2CZe+pwTQ9U17nwZyjC6QKbIFNwWYPWUHM2dsKO11+pHR5rM3TjE9dl6yJWiTu7IEZaRFKytzDgOguJlW//TXgWe6qJmyjptUCq2pnacvzMLguQYf4SeXSqUMlbtgos3RzzOJSB8ReMPzjRvXt24f2Q+hFoZU2GUY+auHdoPaEsBpmLYTovX/ULC0eQoyaYuYPbVKuYs+IDeB3ALyaXyPR5oBRSHdp3DUPNSF6tl6aj5jXS91o1dJ8SSbJdBsNMCzZK3JtHGFKLLE8VefqJOpznZ7AV+TNmm+Bq9Axm+I1VNIu5rrzxMjSE53VmCPU82BdWihRYll9w0k91L8rVrWzSK+bBFc1+LTiGeg9YwbHsTkjYd3ACqkpQ1u7hNwxXgVT+nAf51aQeKZfUknwiAn2zZ0zXsjZG45m9MLRWpI24qYAeJl+gBO+EYTB73f13ANyX0jRmq9Sqj1Ldktpy4JPXH+N/DIXz9qupEUs1JMnAQ3J1ToscR+BHBCpC+Y9P4bDw3+y2f6W3a7c/hh5LguMK3IuTMjfG1r+V7keGvHmwPTu/9s3tdqidcJLxq6ZEfBsoHb7lIT4jphpKw9JwqBosyQgaAoZsojX5KbNYpP1qcpvZ8CxuxyExGTDqWZlbn+asXL3Nz+uRcYWtdOjRsu72DQ8Zcrk/OmYV76KjsTRGCBtY7w6cePElBmgP/yP+RLNdX4ddy4tV9j3BqpgZu4/y3W/5IPr7f0gDFlxIQ+2pLi7rjmgG9KPPiP0P999I7AV0DeDLyj3g0LZ76AYfQOBiHW1I97l3o7vqIgfWylGHEZA1FmrWoR3vImDXIrQD1eMNtKZQ6jzmiqBtYinggzsBZt+XhNFNpl4tP5AcgbVHhyskVGmmSiH+dnEpr9TEmwRN/z1hm1G3FxJaeT09KlzUoJv8xhpGPms1N4UrdGqBJ8k5EQjC0zhEDekPItcBIkcAdV0tuXF+fK+Rl4+TIufVpN6E/aSqwYhqaFEHJCdXx9fsYvVOybxKGAeYiSQUiEZsHwG9zAnXBMzfhpkPUTvXE8M7gnhxVNOq30Vi6Ac/ilffTbB1P5o6H89OnH4+OPta/GV8P4qvxYjb9Wnx5/rO+sU316gX6pyn83lJ+MT8nfNUP5tGmcNFvPt/IReAJwr8DyVw7a75ElzA4T5060WN/g5wX+CnpcdBsbIezcrJGerYQraNVvXP+mvjQdr45+1pb2k9XadVMsmIx8C9r/g2xAftwxz4Hc3Sfg1UW2CAAitOvPQyPyDeLXnqF0ZIa3Qp9ZUvvSceHATLlnfX86oJKF8ijSfCa8C5f0/SX4flL7/nRAL1TkzT+2DC+mhNFePLu4Ka73z9D3DERIb96Wj8E/fweKxxnMimIGc4BghJG5XAGAWZuhtJVyVYfM9OnZqCpFQFCRyhj8RWrWWqf5KhMzvEXUAaRbREsBIA1Rsg/voAuAhEzwYIkRMN183WsYhuYckk7RJuLCCNoXQH5aAHfk2Lhuo6B8Iio/2sQEuwBy/PcJT5wLIHO/Thg5LoBM/zqJh49g0D9PuNFeADn5ccKGdgFk+tdJPAJWc+TYJzHa7OPEsbdHGHXKEfHFt7zJP/rYJqdY8objHXynKqovb9Kcvq2hVim33QBG4otWdvYVwIgTbPjOBz+mGXQ041qbqF11otKnK/jth1QXhsNylnZoOF4YmZ4FjSW9wjTwAxeMlVSpzGBkLQzTs8lnQ9yGs7wioHzJ+FvsRFD4aAGtPAhq+7Xf4bCR7If4no3hDxj+AA8OmG4ATfseEH8nYHo20kWp29dhDjB79EZ7uVlHROHH/ZyAAGKaO9480+dyX2pmj7aYGk/3Ot++xz/RH235OHE0TN9kA9FVtkKcX5G2Sv9UsPEDWvFvy/e8AM7WIX69hX5BK2JetOAZUJSl+QX/xl53aF+7qNeb5z/VWs/OavTfOqNVnVHv7+bKUe6oatdqtJpKo6U0mlLqlUyhg0LWawSTGIinJ/2agpw0517B5+0jqucgqiIdk7HvDs7k+CQ++abn7JgfwH/pw8HhGKWQebU/1+xmWxuEa3wDisyme4mqlEQueDD67Ae3ebFAOC9b3KY+m7nv8jGiXgCOarSohn0aZ6YFj/YaS8rbOQs+xnkVOEuk/HiOZTirDLKs0FkxNLkvJQh+aHyqOau7s5qzUm07gGGIvqwCZMjCHvsG6nUgSQ8YTIJEmvR3SyMy58ad6a5hTuWaG/i+QpKbUuY7rk/d1+iveHBkV4/d2AgQCRwh3XO1jmAtMudh3wkj8BUszdVxCF1oRcc13OIriGAYHcvox0sgOVK1WkWEwF3g0dODW1qRXBGQmg8gyyZG/+SEPOZwQnVpq0uTnBTaA9+GIhPDoIMxwts1sTP0yPRsM7CNwXXz3LRD41o9fdbNb1Git368MUiuQozw1lkZ5LGzYQcOkmCi3ZJ/VobbcI8o8W9ilOUnG0j6rbO6Wq27GHgPrdrY3ZAdrCRgJA41epxgUA8TA593eHPDgkHkzBzLjKAR+FH6vqwIZwqMR5t+KsbcvA0VWkmhSCgUCYVDQmFICEfFbhCyNKeWjeVC0+Oe8nw7mr/GHXQI/L0IDpEybhGCG6ulRRQpznW+CDnakMePfipBEdfTSLW36xs4uu6UcQcFmMK3BY2lb90aWHU0kFJiGpbrr+0/BWOtpV371i1+Ld1BfXVQV3sjixe6sTQ9cw5tY75aG/DLCgYO9Cz45+CLe7wmHV6Nplrc3U6cnfDaDJAWPgzwcPuOt/6Skdt+2JY3TUUe6lteavkhOVLLxJ6QwCfw9auwBh9dQlAtH16ivFIG3IFi0QmTAQ/1q7UZ2DvGzb4a+Bm2F7XlTQuVsjgWQuqIB0UdGxNYgsrZMBkPGSKd3L9oQh8xA4dh+FdzyqVrRpZ5IBkz0VAe0u/0Zu1F68O6TYeIObxXeGe6I9O6Neew63/2XN+0p+N+Bgd8QLlpXijbjFssdlTK+VeQ13kBDNcuWjXrwOWeitNDC1JayZi2eadVIrbI/vFfv/OqlOUvl8hUVu6Q0fMDZ/DsQQJnBoSyEEjyUM/evES2NwMUB6Dc4+5+oPj983fw2QxZKT7DwnossxmrgiNycxVhx1gG8hloIpv0AWDjs3U6hchqyxoUpIQdMCdM1Ur9jm8vTtOfY9l3dqF0tUt12p+kxWPf/wyDjhnCtrzxw5OTberQFOKLCKlmx7zVC2uoYtxsW/sooQ+0p22dvmf9KCF1vbQhrZmvZ8OZuXYjVkGq7JrzjR9uc/dtD8D9Dv+itzZ7jOCjJGghb0jXW8Y6GHEiHL4hrgHXc71e2w9dcaMMxuw0gNpzFrmGIRWoB+uGsiUxmtYr24wg5WEKPTFXaChGFuFJbx+zR02mbQaBeQ+UKFcJ/Ax+pgal5MxAja6b8F0LtNsAH4vgC4a4AI3jwye8UFO1yWdiatZcM0qu5U5AbRXAO8dfh33+exVAzwZfQQ23w0pbyMZ9nF6r+F1cNXmkhURgTI/rtRs5amAtchS5nvYnPQPHQy4liqBeli7LbCc5AuVqpCglav9tSdYsIE/JrsWYIY5AOB334/MFfpH0HzhBcxgR/Ee3czqEy8Bfvn3B1kZGCN/GBdnTEMtfrnwPetGAHJW0qLC6fRFem//0g2vH84OkLXtpkwBMLpYVoMyS+/Ea+nXSqlJ48TaAqCDV6BDxK7/O8Ho0HOAbg8teXxupkzf0JFEi85E6YWm3SUQOHu/tx5hGwqWcWvAkOMDpNpHK+EbwSXYFf/jHpy31XsZ307nyxidyUf2z/rY3eiUVXVT3BpfDC5DFmBEExOufrBonBNCJFjAAcLmK7oEf4IhCMycIIwBdiAMzOSEgndYAsshXjjfPd0D3bnyCUJPKH3H2LvU28Qsg7gIZ+rWP4ziF7xCfSgJqPP20ZbGb1h4yN3uXekUkP9vMJyHTCaJn7DlMqQLwK4aC+v/4hPYhzpd4WcKwd/tya9pFOAcStIEsWhtCL9/cyCkW5XGH8o7icgYQEgEz03VvTOt24r9d30ByKNPLnKtQHqNLGyvQEl+QkGnTisuogr/hGhNvFnpUxdk+4jpW5BaG49rob4bTftfQBpfDcYfEzjVG13EOi+1eYbrQiMHouhMrxWjVkGMG+wSEbEkwEoHIx8/JqL9D3AoHMEmPYZfzd3y7F4eMTANQ4p9MpxKPY3l3EIiiuml8rcXSt4H54xdQUD13sRbMiqoqT8EPD7r7G/iMzDH5cURRAbXjVZ4f8V6vKQTmpGnbbwmbDnwb9s0bmPV56auvtb6hT8a9wRUzSpwZdYBzgCTzFdiuzEI845i6uIIu7XfFxZ4xer4NgYvwAake8NsXev+6CmAIvegEeH60wLHkfGDa9g7ZTR2ebBx9TtQD5f40FmHsR5hY08JRZrlXUAnJD8Hn7Ym84RHZCkxREbQU9pyZGcClfwcfM70QSDmcHjHD+5Oinu22zhtXMXKZSid/EXLZbvdC7l+DW33LHzwQZS/Z/2JPN04XT9gbw2dhzafjPnPJTHnICesJV3amFl7Isf8cWAfuCfjsuC5YhxA4EVqFK2rU8JuRlCIKgxc/sUOGgwij/EoiIW+w0x7zmfvwW/3TjzimceDBCIb1uw/YIe9jjf1b+7GO0XBgWK/9eFQRvMwVUU0UPZFcOzFPBemONBwPtIkWx9zeSiAXXwHp3tkusEtePCDx+zz0H+2NBPtYBXDmfBFQ68lTjgSZrUWEurwRwP3++/pTQVsWPi0KTPyM7y5230pDJc6MGcQuQNHMlsaOKGQ/4vKG0EgeFrr3HBsy3iO0iLdfM2RbdhH60o44Fbv4N8kVMBoPcXD+JMhIXJeE4t3W5Q1OXMY+j7XRcMtxsYI2sYvYhZNiuFVcx1t/UeRNZzTFRw4pSZHaOy5dc57ZNi776lX5rsHVyMk+VLa/1MO1eXmHP9QzfRQJYb7OyZ+CSKaPfRD5C/BIS/47GDize5wmYwFNN1ocV/nptP2l6XjE/SOZThphmSssiqbRHegUBjYtkCUujn2RydORUsxsZ04fyni+QaDhEElz8KPnB9ACP4YLZFT/SF7iPgM/skdbz0DtYf5dAQx99w6CwPcjNoCj2tFjcE8jLkCVjoIna3xclYoDkLh5shAAZEzEmiRTk+lW2nvEdLA8FmywNMBJ3O8hxEizBGE1EqcOrMwwhCwuHkbCoFZMSPOsGuugKDLzs0xEZvr8ulkRnx++VnWNyFLWRc28DWvYP6Fm+csD4k4xdzsWOof4QYZA8bnFqnwGUipiD++++Cx2yhcjUzetUFk6QeAHdUKxP1hgAHYKkEJiWxxnh26vYWTeuE64gDagjpXOHQkJkxyN5GjFnXnxRyypLXXPd+Al85GMlRAA2nNY82AqHgAZhQ4jHPamENiO4YARydFBuC/yAfTCdQCB5a7DCAZg5gTws+m6OHK5eGaA7wEnQgan6392nTCFZfocKqN57BHFL/OgnOjmxo0Z8uvA8ZzIMV325KQSs0ThuPGBUAHXU9cGHIQsAUyjPxTOTCbgA4+SJG+4n/V6MZB6McZ4o6JHRbsGVgi/dGgF5DhkYAUgdg2L7A/0TJVHDB++hCEMMvGWcvKPK2Nbc/ZNDAvNYdAsFiyePHHYxFGcVua965s2H/qLA5yc8h7VuKdu5DXX8bG8eZKCsgXfg7NqlX/e1apmOpLkTbpNuy3xL75OdzdIPwHDawXiSE2MGmwsqXZoLGgRnZ8BxeaDu1QrGfs2BS2/cxLaLszQWMFg6YTkZD/uNNP6K709PVqY4bHEtZCqR2ksMie8mQ72Os8dv1Y7NDqZDSNst5wQP3D8Chbw8CppU8QPAOESelWQ5Z38LUGaHqQaize7ixrEN5h2KMnkj2z8q/j5z3GNQ7zGUrLg28kq4lDyJCU8/kABfSoibYbEKZwl8N3OcP4cpSl52BiOKLCjJPUTIiSZixTZRTD3jAJXEu0xvufIxlRH/TMO8D2qbF2gnSsWD4BRlJ6bSnscTXNDAjMHunZmzDWghuF6iZhOjZmSu1JI2nPYSeUH0zhnRxIgjJwqMOdjFpYrIyfjGFK814zlOpCGoOOdZ7jIdKeVjK0TN5FSenbcpEjBjtvhC0hWG5gBjDPBgGESaYw+3Vj5YejcuPAErAKfJURBw02CJ+FDsKwKns2isDMMF2jiYBSUSntaGyXJHtLokTN51/9Mg06YVoAXCu7s6EGDi9WBtPXTLI/mSKEDiBQE4ONr4WhheoCPbBWHdq/lb3nj7tKxHGAEfiTOwDSqH1YRdj5JoqzK4vnhtZF5n9R8Qd4n/YBMImQDtZmtQByUl9CLOEvhB46lE1Yl82l+NtIxB49Lo6CCZ6CJWYIN6DAjVDQNchaHneTNhjTl9JMMqGRPqfGfq5n1m46zGF+8pj+3gYT2i92hQVdmEEI653w8zcMiesbTk1HmjveIupleuCARROl4o4+fO1FAVIoSGXnpiYBoXlmIudzIqVKOF6komtx++Dw0tmomfiTPbzmdmDJc6nuW4zKxHWOWy3w/kOcePVQirQQGRh41KYCmLe11fnYo0+fDfYJTnp+zuBxwiJdQjMCN/My+Q3YDUTjcw5mGeOjwKy7NRzT5AH01wp2C8Y8gEaJzSHWnvZDdVioklOQ6gLr+RieBZnIO58bKDMwl9ViRh/pWyjyIoNczcbXWBXkYwW6ZKmlPdVKRKMoHO6zHUXT4gDNAarVqzYZEH1Xw+EhgX4B8nCQc8gcCRfl97cAIhOGiFvrWLYyKgvCwoDj4ofJnrkESRifJ9BcH02GNkupSFq0kNTDpy6b/1nEbMmM1u95oKARADc1onorLw2GUIU7ub0C6xYG4k4Z23SRvUWF4OOoFIPbAPN1CKosz5YQKi/6V4oeSEFr4SRbSR3X9DQsDV+P1wYIIcggwOMUOjrwASRLBJ6m9c2HydvCvGE+SXzE5vidRBjmsafYCJiaI9UfiRodiaVeGLCe5+D5SUiyAsUyyceyDVKRA3oaD5Jo3l/mHvSsm+TcyDrY2DCPiV5skd2llM0ugSlJyRsWl5ODOpJ7WIjOozf/4+rQWzf9Inw7gbB5f7tLpPJQOA01ilYXmEir+Zw8G2K04BSAVvEgE+rGQWdwjpBsml7lG5Ptu4lie9plizoTY3XHtkRML1D40PfvG/2I4S3MO2c1f6iN9vZj6RvKOxIFAbIOFNcbLPfnOMsVG/tKVsupRCiI9pf0uszmIXB8uFKlRa9Qa0hZIzdrps1oj94Yigz/jNuwfTnBnhwYz15yH+etWaeXbiuPNAlOJR6MQRKv5FZEeSorGu7pOX7amitInFrfwvi23qEc5vEd79S28f6IwX1P28p55lfOQWNYHxQNSWK89VRTceNv+ePzhN/Dp6cdq7Wn9Y7OeeYOMQe5gmQJOyCxo8hGngkqPKj1TEq9ufEeClXBNizTk0jOQLC8Q7ffzLVAuwVH7CJBAPfXfPny4CFemBS8+fXp6nGr0lf6q8lXadTpASnt2joS7XN8c15/UntZPgCTh09dEDMxxYao3qbiexNeT94P341f+h7ARyXF/Z5LjHuLLepShNR+/qHjN7lh4xMdBA0cHkzeLDviaTY0ATcTQzVwBZnQIjsL6bx9+a3962ubh1utHtJD/iuYqLvhNSv6WZO77bjiodlUURSVNtsq28uSN1h9pY10bXlb+9p///jf+Jwx4tQr8OwdbKNQvAYfM82vh4kF9NBqNxvOzM/xvo9HI/ts4a5zGf+Pvrcb5aeNvoPFXEGCNtLe/NR7dV3Zw/yb/PfkO+/LfmOGiUqGKL5pzZBtYITQW0F3BIEw4AB9w0wfnUqUSRuubjDYmby6ngw4ylj80P20BqoG3V9ubUcPX9a3bX1T8llWd8/mIUV18MbyKlmawsw4+NyR+A4XFCHFjvZoHpp2v9OT/95Jp1/pHps1D1/1+6795dvb8WXr9N583m8//s/7/8vXf0TViE0961xqN/VlNfzUuh+NrdTLRuuLYoPDLyg8ikG6ja53hoKuzFooNJLkAqoQzTYNKJR8Ssp2Jl33tWIEf+rOohp/G17QvEfTI1XlnHUb+UrcCZxXVSRzJeiWJT5mHXYmTVt8+w68/EXo0ScqF0ny23EogJhSol68aJCVf5cJ7U7crJanm+nOSQlD7tTcxOsOu1pb/ngTozsQLp9HEma27RweKFUKF5IRJ+kryh+F8dxY4bTQaQNoHWalaeYus1H6KSbh45wv/M6LvW2Sru0ns169MW0V2WaawXa/PJRZdPQ8/z26YeTbZelspxYegWun0h9Nub9Cb9IcdtRRjHKhJcTwnUoi5pqyA9gVa16bj6SxibWYkUlgXV8mMpwiLonEV1S8Z335D+1MGdcB49hrKZW+wz1TNHO9PmqUMAjtHlamfHxrNt9QtGxQ9N1ZoiET7W44s33/RmPI186O5mmr6xFCvtEEp13028dMKE6lttTj5wbcblBCNonEJK+eHxk7GyJGweFxU9P4ZQ8p3Xyj5cjWLBzPW1O77LDSJB3eczg/FNhea32Hg23CMX5rG7pHgCCizpnJaTXdalSrkWL1r6NPra3X8PiafrZie6d7/Abn1pmuGNujuo0/QrRo/AUImRTbgufar1plOesOB0Z2O1Ql+NH98nFSqAgUUqh1E2ahWK5X/0oeD+DlPPpo5lxQTO/RBC0hyvGtLJTX9FZBklp6yBGAApNJyG3eYHWtZk1t84JvZJ8saWGifcBGNCjahnY35tns2m/FtMuK0rCGO0ZGXWaV94YuSDAMUV5+bQJKF0qOsVYjwyiyF0lmiKy45m08Wtrjd0Ub74kQd8kYFWidgiDW8CyD7qxNAL8xkGJxg4dSlV2Lok31CVbNYFF0A+TY8ATh+ZM9zoj7Sf/hSwhNcjVwhLbtEe3KqcHYCBnRH4797qD9dS1UN4Qm4WsMwwpY+XzQ3TwBNw6Gvl0szuL8AchiegNe+H3XNyFz5jheFF2BTNLSDuqLv/VJA6ARtt0egmtgQGX3ZvA3J6YnMSRIcsxcKqnKmAglqT2KWPzD6fJybqMJey4zGmjEaD9/1cI6W4aD/vihMRjIeUd847b+/toosHvxWYxXAFQ517MKIz1WpR+YcgiZgRUCJmT19WYt9ZRFzkhatJNPmvlYU12sngGYEbZBHDSzN4BY/e3HhgZC/OBFoVGZOpfI4eiWgY3pVliTpgiCVBs0WkRP6eZEgyZt8NZzxgsGgOxUo/g/DoNW4psUGWappcTUO1m5jCJTZQOUwS1AU2yHl4AotAVBmAAhhlungHAnLqnHQdii/DNqOavwMl6ie/AyXVBNAE6meeWCiWhhYapOL+fIEaC0Nf8gyu2hnK+bJsh1vN/cV7IalLFa0S+5mJPEuWsYsRRvcDpYQ7n5lsx43wCZCpoFw/nFiMp9IuqNKNS/7yBaa/kyNqaOw/vFjvT4/Sn7/Vvt4XHv6sVqT6x+b9aMqPTQ00Bac1eLz+YgAO+YrWh7i3ERxs5wBk2nE5ynKZCrKZykCQFLf6rWOrtWsEBo0Iy5fm89WhHHAx5ou+pDpmM9VhGum6bkVwKXZivh8RPlcRXzpv2GmoipV0DYJk5QkH8ranSz90Hrl+qZtuP485CPGRDCMgPKlYN83b0PF9eeK5bsutCI/qOXc3fZvCF4JFEorhEq+cnzom3vjNHo/eTMcjNTJm7Z8PHM8m2pDzk39s4kPboCCn8TzV3Afn9bgfB6nEwzega+xgwLndnEfLXzvFMhJH4DhhPALAckk+Sod6iHXvr7ragp6ZB5qq3shMBz4garEnK2e96nm5rQSU4n7CH7Auh9WA3lQlf/n7/8ee/O3z/3fWeP8NHP/33x2/vzZf+7//ur7P208JgLvF3XSecOuv9rnFebWH3tM72ndpFYZsc9UGrouMPEjAOpYm7xIoy7InMn1KNu4UsnFuGi2Gkl4CzKi+MaP+ivFYWUFsauIs9fl7+CI8246KgHwww9cpATuaRALI9FsCV54xOmr8vORF+Yk1kIs9PATWeK4U4xWpkK3p0/GQ1G9Sn8ovH01b0PuRnVDa20rrofoudfdJzvdOvQeM26X8MRTchIiKOFu95DlH9ZW5h20RTXvFqgejvSZcDCrl4ywXqnsu0UF0DatiGSCoS6jaLNiChZBjXxXVma0SDZhXBTndKvzNWvRlygGQahCGnMoZutT1x56o38iHy/8MMKBd06I97qFL8xDfGH+6hUe17KS4REacXUnE+2s1xkOLntXKSbDjjw4YLwRQBy2JPGtDW/YN/yiPuSfvCcvKdIevDdmCEdopTL/XD7VaqJrC/yMJCD4CBa+a4MfKqXA4lcBqr10vGkIAwnkvxEY9FHRWOtrqq5R5/M0AVIBnTbpBuQ4r3leawgy/ZqrSJkjiX0PzHXk0/ck1iLwvfvMe9W/C94J0UT+8bVkhJT7e8+yBY9nPHLaOPz1vfFOHesCcYlTa8hJlczzuMIwSKWUDuOQ5+FrM4Q4NoqUDnycj55SKZ+9/RJ4SmC/ensyChId/xX6Hs8o7Fs5uiSWDzLAO2oHImMx+6W8PRV0OrTWAZz09de+H4VRYK46+FW1BHZU2HMp6Pqb0frmFt6r62jBjTL1HTFRt6err/uaMZq+fqu9N9QpkQupNcDq6PqbsrDP9M2arr/B0iHeSrnmAu9lmnkQwDnOO0hSedJHWMAJwRFi9N47daIZ2tVY03WDMLXa7aJf26P0I0IWt5rIuulYM95MJiPSpgz5PZobHXVX1OuYzqjVCA2lo6aJMR110VA6qtHRxhNdFJ8xBqJFlubdOYHvLdHM58SACN3OVJ8MrxH8yXiqT8oQ3slExJurY3aSVHccKwlKdw81SfVaKGFoUnUJJH/THPx4L8NvgPxQodI6TY5ed0tejy5J9hYup1ZShhUH7ClR9ORjjES3483B0vQU+waLc4X4u4KZa87xXUbq2V7ReMgmcG163Rt1HflTDOPSNeeX+DaktLhI7h8So1P0bJYmUOdDL0ry5rozxhE89d5kOH6PxfeFsrSC2jJ297P85VbaCUj0/Xs+nOs3G0oZFgdAzkSMZRQvm1Y/MMO+P3e82q5wMRLYVQMU0GwrAXmqa2ND1fXe1UDrGr2uNpj0Ju+NXhfIE22gDiboz3jR/X2vJcbENFEzxkQVsCUg/k5FNfEuVWZgDiOavODat6Hq2TS/ZIfp4b0lUg8yrYrzXhL4+tveiIWk7fQ1dTAdteXj4lZER7uc9vux1jvW/u+0N8buLHviCCRZ0K8EJLmnG+/edHHuV+ys2XxYkE+kDEYLGKcxWPo2xA9X6ShAbLwA/HQnzORRlrAYpXhx/Nu7Vq80XRJtCEO9INsbE4NCmj1gk6Bj6sJVGOss6EfeSiZUufJdG3pknC+TME02XEHPhp7lwDCVCEXw8FqQmZGOWOKyLUqHDSDmifHaQxp3PJhsQe4YQZI3E62vjYbjiaENkIbT3T6ckBPoQrRa7JG7njtejEbmezY80HrVGfS6ThD+2XSil2EZ7FJf08pddu0X5ZYl67882UgiC4qgVPdTi+nFmerh5BM4/0lxGRmIhR0b0Kdr03NmMIy6TpDWOt6oOtO7dA0n0eoOr9XeoIwdkEkuaMIfYL0qOOfA066QkwOFpEtTyL4RXzykFTFRR3r++X3yzF0UViHjhFmzpT1Nkc6gx2uNg15GZRu9Oze6U3IJ23n7mKVELLHum87o7pzZZeRXVpjsn9Jxt6VFyDQNYRfPQchbW9myvTZogngsf2w2lORLTiW81nQdWd/DS2PyRjO66vut0MQpGTfZIFhYDtub1ZHWuzQjxxKH36BvYR0ghXW4dCLjzjFBGyz9yOZ/h5Ht+PW5VAQ3m7Nn5x6m2JRBiUKuoA5rdlFMRfM2JIbKtR/ZU5pzLFq08xDqP/2Er/LowkIfM7CIi5EkbwqA5tIOkDw/jefPnh3SCm+YCgQSd0fw0bPMiJAQIYaEw14QObOSPRIU8gofuvRV0o/Q5pyo4yttYmAXCrJMsxmxRbF6zPl1Z0wUr0s/wJWF0Mn6N94M9YnOTiyx78TDTdkROWLokPPtNz4OxllYtNvONiZjdaCP1LE2mBhvpleaMVKvtEeZ2pPA9MKVGUAverOewxF+/15WugeW+i/qCO8nj8JM/2yuiLGa+yTEYaBpXd3oXI2H09G7VlnXEYR7bjX1ZkOx5oG/Xt21SFieVMaCn3/WhpeVDzRK1acKd2jSlphjDMGIpjBQKDjFDpw7GLQpAlIFARLuiZnQI6lnt6iLgTYxJtr1qK9ONPF64uKWoAF6MDIiuFy5ZgSJIKw8gCgxTAX1p8xccy4k0JE2vDzaSSJmYXRjMgVE+VUC+PsahpHCsgk0ny2BwgUvYfWgZ2PP4Pbac75c1Ov1YO1lIrbQP3GMJpD0QCYkbNPx1kLXsWCqPsGdzBEX3ejAiC6t5/mILg8keoz7NyK7MZ4OiGtTX71qC8jbDuDSj2CeTXlNlIHt9vS3xuT9SPt2a/DG8eylv/ai4kU49ZzoU4VGLw7bqIVCmlBIFXUWwUBUkB1UuX6k34dYf+d/pdVe/b3emSAjtz9Uu2WCkuP7ab933ZvoxSQrO7iMeXXqOksn4jXBXFnB3qdPx5oxGBrd6Qi7kl/39M50ONWN1+Ne92F7DCHQwO+uV0NvFPhLJ7TWrwPHRltMSeG3MsB3anVfvx6gj5eNlNzj6Z65Chd+RPShmEFSXwVxoPmJOPSQZNcQi+Kpt2y7acHmc6Xx/CeonDVOLeXm9FlLMZs/tZoQthrPIUSLLLwP6zfrsH63RP9L9qywvrgz1pHj1tceWkz5KDUOkJqnzsdv3tNHjyrzgVXDD3d3UHOjjie9S7UzMfTJWFOve4Orx1t5yYKiH9QgcmamFelRAM2l483ZzOcK0lJCgByd+TIVi2qp2Fe5O9AfNg7zxoXYD7o70BG2/O80kqyfvNH+zW8+8HnHrrsPfIp561i3qKI/m7HKtB6Oux2GwIyY60NikZDzlLIrD+wesg4DbPwsTc++QSMh+NF+Zo5HssyQDlM90XSoJP1U7Jjg+fY+jgn/itto5v6NtkHEtgUFex63vH3B7ztvX4RC80rXOminmfR1I74pGZEEYQ83FViwyvzd9So9sPKKRfdew+nk9XA6QNv29bU66G4LBPEe3hGFHhIZmzmOI+zMjJnpuOsAgvMGaIJnQM6i89DIEOmVzkEdDPByf5k7ef4Wd2f0uRTCF6no/jq68deereCkRQp9Ggay1ZPzSHGDA/Q3vM/T8+MOZoxYYOdKKiXXSd6dYzumQbcqci6e+86OiTOXSum21cqDbnlsGMFg6XgQtSQQAYEYX/yQPsENZG/uJIHH4eBdr9tTje64904bC/egsYbmPL7omplu9v77ajTFSVm3qWQjcRbwYsI8aN270PSmq6vRtEsIKIHcJ+FexWHJIcl2q1Iki1OoFDvaSSSCLpM+aMu6Gk3pHPF5asoZlh9n9ksl50eCx4iPQi7V1+Nex7hWB+oVXoqlHiQHHU7ve3eDiXlp3gSOdY2zOwTJDU6+rFKSBqaoJzJfygzDWbI+pKJoxqLq4LQhpWUhoiFZDno2ZHD2op6R/bp3lWctAdUyS4k8491noGTmr535yAwih2QVyn8T4ii4EkNEMcj4bWO+WhvwywoGDvSsRBWiOzbhny4myuv3xkS94m/FSgDlEj8VSjZRjPuUdKMd4OWTdMCJNxYO++YeK1wr33dBZM4zWYl4vXb4djoyBEPUfh1p45426GhoqKVzXkigtHxhQjBf/eRkF7uUItgmDQ9yIIlVIbLm7KvRVIsJymlKouL0IilFrbKPeNQ8u1g45i7O1KWtLk2ynu2Bb8M9dwt8a0kaS4D7kerhndrvdfHDUkMbj9sN6oiojnpUkyFq0VibjHua3n7W4BJ+yFwtZHfjZB816l7oOt5tTZDyowhys9HIxVHHGbAzneAM2L9ls3Wn/5VLu0VWHer1ffzu45T2/cih7ermnOuGk/L73MN8t0O26m35uNj12wlhcAeDQej6/u16hfOAUDXbo99AE+cI2pQNYCuYDSkdEV2f6G3O1zqXbQyVlxFBn+hlshInWY1RzmMjSqE+1nSShaZ5/qJ2flprtn6qNc+lp6A4eXpmUeBV//aFbnDdqf+NrDlEIipRUxtlYYLyPSCXweQvF7Pgd05/B2fJlEQWVoqS/LLcIr5oAJIJ9w4oimVaMKD3olzuePQxrFtmzQqiOAdufn4uzs5OSSwoNJGHQZX2ALsHeWMrL8uFKYIWSSleUuxeb50HktuzgHL3h0j2pehXWu1B5Eg7iqujHiAjiXML44wT0LplmaPTPaSS+mSKimw7vK2m6x5g09IDG/5NgAujePOU01qnyIA5CuCNj5ORkFAsJ4B8QPsy0qiA44EmWDreOoJHyWlZHCFTsYAULtaR7X/2gBKAJvhBeswxtehNztqjr3LKWPYBfWV2nulAnUy0QVfrGtPR1VjtavouNQ2/8Jmy3arbG7fJ3Za5itD/Y60LO3ogVcq3HSufLZPL9XFsOwF+iy3JmxTUrVTNN4ydQzJVcxWpU8j52dk+tQlXqKPJxcWIIn1xQQ5NFfoWR+k7IeLFpvTyCLx69XConhlF0LOhrUxJ3OaDYCYvmdbe0gxv8Xso23Tc+zhwX/xFoYGh47u/YmDEpPizgCHJFQhA4e8lgNhjLRwq9sb1rds/GygbXJl1vtdqxX5Wh50xfJuVGV9V6MZbdaLu0yThVWJwJCzKOJQmNA3XK2RcE9Pz1oxM6lF9Aj47rourJObpUX49EJo85HrzcajiHgGh/lAHuNO9cRZodOLUY7Y3U2KvO8XzI2d273uMU3cACSN/9TgIVB6kYbAXv2w5Z6/uxamiHtgJWZGP7CJzhlXWE8nUdWBnmcXM/UzuVbeVyhP8f0kSm31DxKUWGXunm8TdoMHjmGN+/JBXEYV0w3eANK11ZeaUB8ATW4vsQq4Qg/jGTgGrACZ3KADxHX5LIZHwICT+HPaDBOQldXw/WJNKHmBDzxY+v/7fEP+fslP4qEAg5fE/nj9vnZ9n4/+ft1r/if/x18f/72ADqNfRjN7AmFyP2uJFbVkKfh8be2U5Hm477LzVJvs2JakRUctBL68qW55T92BUsyVc/ro3oIUIKiq8cTyp8mQy7A5JCu5o4YTAX0fAn+GQk74HIy8kYSEi3/87BsNehesZYMhMcX3TDqVKZ9xD8jF+P85VDBwrcgV108hhxDhXLmGfiSciB248HXSE1YO1Z/EVkbUqqscdEmRqs6fL9Hm8bnTUzhttR9M6PdlT2Pt8Aiu+1B1ro2Fb8sOwjl/FOTDkwEiVXIyDfSM5VCtDvS0fOzPghuT04yl7ZguavK9f69UPTSLKWUiqbPWvYG5+vgVHSzOyFsdy4wTUfzvuddvHtafVqlw/AWYVbGimsMhfr1YwODY/tD5VX5Jdc3v0EswchBDTu/5MxGgXxkEIgq8gCoBigyOJIityqjA6/Z42mIj42rwNlRB7QCiRGyo3zAdCIQnWeVYqgyxYBexdWtcY9adXqDzfe8QelqUXlobfmKp9so13tbF4RUL8eNV08Y5lw2AXkARJFmmFOphysBQGTDAAwSCv1UHvUtMn8ZMpRlYs+pb0sRYWREguXI+Ggzi0XK46lVxeFNIG7950jf7wqqC6KGQNxsjovjbU6WTIHr9f9tUrHgQbPfFjqnPOVVKlMx33DZompB4tV3VrHbjGHQxu/BDW/HVUSZ+itCXyG3U8xm4fcQH9IFU6o6mhjjtvcPLD5EF9HOQlLsevZmlpFamZpU/T4/YkSJS8a+Q4oXSZ41cMkByj7Acw86rX7roIVJhCLpgBuWhTQECyrz3tX5xo0Ym54b9C34vh+WE7DghDSb3NZDBMy968YYtBDPUt94FlpW5L1joIoEfzy6bMO75WPiZN6oQy2eLo8VBbPv7n70CqscgtyJwVLAeadl6qffiEI3260IqOa/j8q90GH6UE7kepKlUzLwwTClOne6M3wMeouRd32JNL30qJd+Lu4wBMNcbkqHKa/MklHW/CP7gjfJnS7w2mvxb3taaPrTBJaVhNHM0sR/4tovfGD9m/bCLJ72R/Y8nQnySseBSCOwbaDALzHjghvne3InI5vzDvIDGHfA8C6MIl9KIaAdObAScCCzMESz+AIFqYHl/rBHyG5JyBOSlFCwhcM4xYDZwufgFJzzX+onXzhEX7oZOtf/jHpy1Q5hFo5q+xaMJtdTzoDa4uOP4EVL3JDrIQ5xqgz/qReViOrpR1mitBG/4OsLkub3LljU9bxP3Sz/rb3uiVVDS43uByuM/I0PQ50QIGAC5X0T3wA4zyzAn4cYSAdFcDsS3MgeYfydekwuT16J/epd6Wjz56R1gZgnaGXdvH8jHRkt6Bn3/+WRKM/+mnrVQld6prL4QRAklS3KLxGKHzB2zLmydC8Ii4/A3M8XHSCCigWa1KQHEjwS0MmlbD8Wz4hd7OpmQhVyqAyY9/lUKoLW/EeMqbBOSW4pwQ/Nr8px9cO54fjJDK+C4WwywXcroXKU7ZogBl1qQXBQm4N3506Xw5CEoIlFmrKmV2ml0Yci4vu6u2gYT0Z2GbFMZ8VeFScLw703VsnmPv4vjDmUEKnCB3bCR0Yg+M6RAH3YpMzzZd30s9rpZKSgEv0MXE26bqpIhFd2ZGmKLIEkAB+WGDNpA3aXqhHaJIY2GxCVL6Spwdm2XPpjPBcdIMSHJOkRa5gJZASjM4p6ggvUMJQI17xAftORR2WZWKIoeIdg7aBz4jn/lrD4lFwFT+E2DDmbl28aUp3iUD2/JtfBrIMRGH8grNJ484XZT5Ue1a3kYAyQneAVDK1nYaNeH6zFYpW8sxeoevY24ZCwZUvpTZUyo+kuq/dCmnaZZewjGNHr18C/uTROuYgssk9S3tN//WFfeb/7yVMmteaABgH+x//g6OYltBaAtwpoBUPQI/AxE0/m2okMFoFxnLgl4q4LjBAqicwrOH4Vb5P/8nnbJ/Z++2D8klHUZjBxY7BTE3y5fOF2h3Bj0+dj29vymcDLx6sTyggnTveaEZDR1vrqxwaJ4QGWwA1yyasGqRJIjlr+eDkh5AfIQCVgEMsYkxo7r6jWndIklseQ6tnp/HQa8P56Z1n9FouYsvUcyhND2TbC703IjYevjMRvBYiMAjwSsGvbRUQvsdc8Ix6BDbx9INfTcrLfyQpi2VgOT6/gqNMXE/JABM12VtDcxRxNEcd+QHgBQhLsMh4NKdIfVZiuNl51gmOZuvy5SkYgeeHArk2QhfJwmTzZEAR7PmKJsDhEmLgRVxztCDyMTBthwbHugMeoCxTGr75sf0kk0O4p4ZWjupdp+daOGvIxI+EVXBCGFOowfiOf5iCzBhL3I4JMmb3AXFxd+36VeE7HCzE59VjuhRZXKQVnZyOh3326ijHXUu2ik5jdliVxvB0y4LcRHdaoyZHxh+YIbtWB3ZBVFiWSgVfwSO7j7aPx5/rH20f6w+5VPA3NXrR0kaCtCsZtzksL6I2ZlSylgHbltuZcaXq5Ifzk7K5oHs5bLn+vMunVc+kPFO8uw33fIxOSIy8O35OnB3Q65mQo7Iu07jSf0D3gEeGBhTxI+Pe3WY8AVZRsmssSWGSJUw7YEd1uVN7qJsS47sFdMKFMFdw8WdvBEumK2CH0or8oadkXM+b6KZmVz9N75/3WPRPnnytL6VwBMwDSHAfps3awfZK+BJ/unpHEZGZAY3SADPAn9pxMFCcThRhCvOZfBs19rGe0UJ5vhAcu+52WYeaw3Hqm6Mpv2+IehCtKlTn6sxHc00cPeTd4UsFRtw30jUZWTbznkv5bM8NylpxtvWIjOozf+Q/tUcsMeO87iJZ4L5T15E+/DALoKAWq2275Ygmq5vNS07Uchcx5TVTqUzYbk7KbsCptcAtuahzXLFzNaue5+yXHPa0GXgL6eByx1AlRv3RQBqxQqXBIrL6CvxKDCtZAb2of2mhPj4nmYXCCkTQFMMkSq3dB+xFthHfwwC348u0P/s1255t3OV4lwkpeJI2tVXvahhJfFhp3ENHw6GXdDuHg3HdsPATK54sfAReCggmcj7JMR1tV8nY7Uz0UhledPcAgEgrMFtWtukiB6ktOXN6Tarp+WQ4J+tcFdWCPP46FLmwcax5PFHJADlTQ4jLPCK5V2p/MmhWKcdEA4X9LYVSPm4XBuPh+NK7iBjRy8FkRQcF4LypplzmZrouFGEYP4R0T6dkSOoOCFWVpzsGCStkOKzOsfuIgj8QWMxkzBTNiOSa7xMLkobkjsn2R0HZkeoBYm4LoFJXwc3fPgW4ITM8Zy5stNUOKIWgDg7EcP9XhACPPEykeTNHn5Q211+VRL3FiI5BNjXd2ubap65dM0c4ycRnsVEzsEX2/O7yR0/u19H+JSO+EJTyjIpCJCa8NnEKVaQDLZP0Ipa0EsSVksqHxyrVsRn+06S9HDypB3r95k2Igy4c5zSVcIdYFBAuT1DkS/2GWQeUnqDaWU3kn2ZMHtOIECTqtiibgUnE/lq1UrqEiLew3YsLoDskwshRInHiOn58kZQE290u/e0/ddsPe4mUeqEPW8fzF2Z+5WNaE72EE3itb+L6CZN7shfngj6p9LYv4PB58CJYHJsuqsDXizjWGsPHF9eoj8CTpJqILtFP44zDmrP6+T7t9rJB4+jTFo9fxgnPmohPGRfrezP72JFCOtB8M506S0Zd7qbcYnAR9Gb5oWyzRxvCg+gSaQ4KYDh2o3a8mYduPzzV3JsTEorQHzekQxN4vchdvUUo8cl9mxeKHLuZoLg+26gTQxURi65dGauXCiyqCjroyqqUyR5RHXjh4wwqgEtk0C24KznwEN4IYolY89vaaJ6dE9DX5P9R1TxMZZWbs7q5IaJ33mEs5Q5wuHAxEc23NkLuy498EL5u73u9+Nr2vARF/ype+MEYnJPHLKL4tw98cIMbBzTwU60V38GmrWzWrMGJgsnZDGnYBD4AcBctTaxDEiHgiRqOD1yvVAKQkEmXvIpN3ipNCSkUCXJr9h6AGeW57DTXT5wSGHOzG2dI1j9Do87eevDlQlOlUntWoT62s1RiR2d20P3GAp/ZVu6/J+Y7mfzPgT/XIcRWIcQfF6Y2NPVdcII4uvfzAsMEPrgMwS27x1FxM858kF471nEE9nynG/s3p4QVeTfPujl/BGpt/agh08nEJoBRCwILDOAwLzx1xF5HIesss+mR322A4jGL/Yf/7xwrAW7Kg+BQ325/9J3B5TV93hxUBJG4E/y8C/2uo/Z4WB3eypIrIXpzTGTcW4P/06+7g/xo805SIsc4FOxO4+dUB1fn59VJZJDPX9bj6RGb0wucfKSygyW52fKncC1Nef9uQvS0i6BlD6MsUv2ZdqFYGd4gpQcy4VmgNhiiYQW9MiS/kw2nzsYgIW5WkGvBswwXC8hcKIQBNA16WrHM+d4WB7cQdA3IxhG4N2bLtvAiGhbQLD2IjM4Ab5rwyBXGM3/qMV4Le+AUDqnx1N/mvKoKfKuRfKLCX3aK7MmbxBSf5BAwDf3IPdETsB1AjGZepuUv/JI4ZhytXGsKLlJeuLMgNzEZ13LVXR/AiLzFuKLg9yr4S0wQ+YBDO5Mdw1rYBgtYPDZCSFt10R1EGFxeepkq+sExDYQA99m9HSuGRFR2LRobR+i9SLrIwGS12nXAc1zR15ET+Z/TJYrYpAIjkzw60EcqKGJlJPzBpB4bOvyhgeD9VJk2WRvEtMkEGii6YkqeFCIsSbbTCxtjkn/QFHYcXfqWTJzNaK1WJ16fX5UzXqlpEEXnqHGx+rZBvjxOumHcX9sY9aSbJWpIaM2kRnMYZQc1wtcb7+vPd3WGiL5RkiL7QINyzgMFok0WsScd/NaXs5XIKX959m2HsNk3RWl001u5PK8LwgUuwqggiPg24x+sU/fRQHdpEz+XnzK3CzOWDb1kITHr6BID44X+QmG6cvRohvg/SgilUAlsosXXKmalE0r6Shfz589K6uY9i7MpPqMl1T69JZQKnkgHV9Mtg7apwVKOmcx7XUjEZtmSDitzMBcwggG2LO1YEj4+gExyNy5g8IdJBkXf6yUj4D/B59+tZu4uRegGj92T70ceQQWyQZQ+tZ+t0TelLbfJs/0kVwQDTg7W3VhvQQOZxVuisfKX7gX8eUjWK0zHePkeTHzHicztGM7yE/lXbIlkOM9mqCQAZcatRdMAjuzXMKwDC5ctrA41SGjopC36FbiclsGyCOZ62eLlJk5fhMfEO3/2A8A/H1tuiDyq2xrQbs/BySDUH5vykxWTbDxHKiVFDNofCiXlkiCaiJtprRB4nJXJErKVg4+TssRi1egv83CKwpTsddyY4+i8GrLbxvfHDyVXPEOXz5+tP75/NKCI+qsdbFLu0/Gp4zpzsiVCoAnwYlK4eeqJTtvujQRabmD90efCfPWaurA9/taNP9jG+s7jzdLv5H5l31NUn5m/emANGwZGteytx2JC1/q6U0+XUJOjduJpuBE8gDbk/b4dn0DX9PD1ok/XEWvneyb2tsXoRHN/zAiZH81MwWxG3KLK3BCg0Z1Ig8hTgvvLjnYaERxwBvwMSaNokSB6YUzP1i2pfBr7enXHxTSkJ12fZWAooQL/3NSE9qKZy5hiAqiwFkpiUHfPuWAcxGpPN+GOEwZDdZTWJbLvfj2hc5LoOwNBRsUa5zBPn79JqjtwihfWxjGuQiPdBL/9MSUPWqK76xTM8Qp8gL+EfBNcqzaJI3TH/mhPbmj8Gnr9Q00iKMUZiJJbknFLCbJp1Km69gh0rDxKcfZhVISwGz7oKu7DJJ0iBnMBepApkq1Il5uWH9GfNyWN5km5Axkx9yKj5/59SyRRyTFkduQqBVhtJUqQumaWdHFWVeoIc2OitMNE8N6twFdOQQuhkldQygHI30046wR0ECj/DJ8CnLr+Gl+o8nQNseHJeTMBeUWNa+kE9xn3pNkeGQrFVLfhhG0oiyrnoA8jBNghoC9wQC4EqbeOoQAP8aIfBIb0aSpJ6l3Y3ridtMlWZUKkrZ7HAM9+NlIhkfzYy5684GWSi6a7YHcH4tsqQC4tHfaifLb2cMGyUd7zF2Y7hom2D1OEXxpdwhgXm8QqSoCHSK7X0ryJi0aUxEJJr7vXgb+MnaOHAU+WpRsZWX2tMj3XYNI5Gbq8TRlNpKzIa0NxSrSKb9/ke6NlRkt2vIZvwHEL9CQ3taWcHQ84Z5F9Wv2mC8y52ht3aXuhpgLdEKP79pAunuaZ84UmLu4Bfq9Td2WivtDP+sf/6eu0MqYUlQK0y16kyETdsyqs7if/BjlTUzo7YUIFVwcEwpt8JK8SRFumwKSf7OSg8B2NO7MbajvPGwbch7rsadQzq+4mbqIdM0I6ajGzEUUVBT2oY1lXp2TeRcIh5MTZN/zuKQyhUQRXK5Y+BcsifmBxxshEoqshJuWLX5fHuME5E0KvYSLvkvEDeqkWMhS8SOgb/yZ7x9/zfS5IwnljkEypCSB57to1ovmio/TzXne4e6hLURA4hOIpwUMznU8his/RoMwZgFWO0jA4tilkMCjZwJp5YMdw30QUdJ3UbwUExvvx8TNg8ezClLtUuROkEov5vjVIfHST+Q3TTvzlqhkB0jynMhuZowPIoqyBu7MD5JNADsfH6Pdl2uASsNqOpgFL+wTCy8voIqYp2hMAl7KyliJKYbp8dCNkUNsW5YMI84EfjkcdzTj7fS1ZoyuO8zczLygOShvZzYDtOrZdDZrhXM8HfeVS9N1cRwSUFYthwZ3QF+aXKJoxd2+CDEDhGS5JW97VmRqYsY6wXnDsSGT8fgTPP8B9hr74+ygczudfLHgYVixrprXsXDkk7LlxDsU0zcsGKvXvYE6fp8P+5Gvwgf7YIZmGQhRHR4GmZl1iEhK1Tpkl1wAcdPUQfkJey9EG+wY0TYV/MigjhaGMzOWTogQ4JKpMgWZfwxVDFd44LK33VnZ81hSOJ01gT4tiZRscXStPagG0mF3SsiXVMQREhIC7pzJ/VM3/7m02IkoSMIgOZU9zgZFAc12HhGKG4kSxiebdn46dqdr/jaRUdIytkvOIl7nJGl8ouCEoGNaC/igo4fElzKez/v43GTcr+QqpxMfTLTrEb5ouBwPr+OxlZtlB6as/lM4UyKfGUvGk4IkqbKVyBIF5Phv12i3aSLhhBgX7KFrtIDA8j3b4VIU+h7ISG/gexYE4xHzPXWw5yA0Q5pHP5Wc6viYRjURD43Fk5RqEo4oCV61QfN5tUp8cAmDZrovYcJ/jdjI4gfykcqEByKcPAXKsoEvT/eVB9l6u4GVSKRsvZT+vtcuBuoLfwnri/sVDNBHJV5C4AekkqClHccb7C3NeRIustPvGZPhMPYQSoRP71q90tiLU6xxIGUoyXScfPtF7U0Mva9pI0PXOsNBV283k1J6RBUXnTcagLcIEXLMWxlnX0PbYh6LLSB6Cn6ZhlGmBreJ84jSVDLyRtTnNpRSB/wxCJbC24oCSeSAkk96yhOB/soPnxZksABWFACF3KatTAsiBbjm+HTQxBQXDJwLlmtDlpeY7vGioRBvub9gNMSt7lC8uaX5zVGyfesWBgeilNIlJBkVFeV5zVVpts72SoePMTqMuU+ILUJT1OIuRRc4uKTYCxItDRvnWWLLrBSLO8fkccjlgN1v4fDoZV4VdCaovyuDn750ismDmLqsJ+I+WdJZ/g5ABKc77LzVSpDOnrCTqAuCU67Dpl8iyVQic/54wT3WJuoV//mUQxX3MccBM8m5phA/7DqbgSPEWsQsJaxSKhIjcy5cxkDOYFIgEst5h7kFP6grjneo0HkIHHL/75o3sHB7Fs0qmfC++lrrG2+192yayYd3an+qpacYd7Bz7ePNVN7EYLdt9gODZLONprGyc+pwlwWU4BDn4Mf8ft0ZYxqEl37QWTieGRODBqaNK7SP5eMyLMg7QRas7+i3pRXUlo4V+KE/i2qWv8SxSHFerw1J2SU3t0fVavbygu+z8PoiEfYzx7PB0goYEjM/AHhkRW8d2Wno0iKzjw9DU71++MenH6Xcp620TR2OpsjXjhV/BnZLvWEViEOx5qmBvuDwXzXLi31jY8BpDqXrmYcub1IIcKYO+94359Cz7h+HH5rhR+LH47FNHd4RS+zxIpcKl2DpiBURlodquiKzmb0cxV68lE5NenW78oOILyF8s/ZoRnuS1oqAG6+91Ko5TDLiFhgOsuZsZHbA5N0N5erswpEuJLmF09uR0Jh3GjMeMwaP/FX4ufahofz06ceCUkX82YhDccobjjJbkmTvCP3fR49jlNymLxrmPhIlKzT+dw+bUwsJfyHV0uCVYI5J4rIiLTg5J4+rZlU4cnKQJW6pF5Ow+lfweUFuAkwbKFSipmReIgLyCzdlK1L46ddIcbRyjkpbfrkps9zCqhSZLvi+ttlqED9fxcq3TFb92/UNHAX+l/vM8i9OO4xzvHeErYnE4cUJkPAxAE7dKu0ADD27AGySLG+MlURoZ7BlYoV6zHf6w2mXXmARH120fXdcf20XHqH+lSJJIzrAx9ox3kW+4r2u+hHtJkeZpQP+QpFxAFqiFf1vv+AEz4vDXAYztpiwopRlLk6ZpssgjRe3vsiyzstUvpSNISMIBGs+VyNPE5E0YctUXCZa3SmRkqtCTvmyQ7dTGS3HOzJaok2EHGBe+zZUqVBYF1KSbCT6296IHb52+po6mI7S9/893Xj3phsHreN933K5UmkqGRb84d2bLrP/ywJKTrFZ8u5NF9hOGAU+DpyBbz3yPYi8YZMrX1Qd38AMhhPjcjgdpJ+hXyLzn3mFj7X/O+2NtW6SmiO+4M+TZPcgWJQWci2DsLyBZLKhDdYrqZJdu0JkELl2P9WciQhT8FYTXyhBG8x914YeO6oMIEtjK+28MxQvSAmIv8fgxMTmLzlzQoPkRBTPeyZDj+nZlDOBE6bZ7QTM1lx6ywD+vg6gLQkOecomYVup+HcwCBwb0sQzHeycwRv2l71Ujl+cRh2JM/K/NWs2r9n1Fw0D7weGB5GqhWCgEkHk6DTA7+tPYwc/nBo3W4EmLDQj8PPP2vASvHolqGKbkRn668CCF7g6FrwXiTG+Wrn3Bk3qQ7G7oPcv2vASUeEJ+vdv//nvG/0nTNKPI7Nit84A2qYVGZiBGLes7g/so9FoNJ6fneF/G41G9t/8363m89PG30DjryDAGunBf2s8uq/s4P7fmP8QeraBJPHhs773/LeenbfS8998/vzs+X/m/6/478l3oL4OA3z9C707sLqPFr53Wqk4S6xFrgPXdW5O459rx2Z/f1m6NRgFENY0Eg5qEkAIzBBok0plEUUr0GbNayPfd69Nz5zD4Lhaqcx90zXCyIyg8WXpgjZA1Wtoa4RhdBxvB0dX2uToJPmJal3U683zF7Xz01qz9VOteV5fmtbC8WD975a/XLURZAyYa7eApg2DsL1JWQ5HX5RlyN74H12Ao1aj2VKaTeW0cfT/sffu7W3byOLw+ffVp0BZtbbTUBfbcRulaleRaEcnuq0ope2Js3xoEpK5pkiWgGyrjt7P/ntwI8GbLk6a7vaxuhtLJDAYAIPBYDCXqCDb1I4khEETaJPKLPQXCIeONz9M9qVCdriKDS3fhocHSzxTfzg4OipFi8twbNAEcZ3KzPFs03UPDyrVSHSJv3Xtg6P3tQ8VDO9xKfRdyJkws3HdDmjsu5BK4Z4Few7CiQfVNrfvpHaO/NfAXECpTRsGrr8is8swT+NQQYHr4MODCq1TKlGlvx9A7/CgemuGVde5qt6Z5hx6uOr6c8t3XWhhP6xSpvKHExw8Bwfh1cERIRzyrBE7+5GhBE36vULOj4c8A3RAjY/J42LKGU23Uk7j5PjF8Vn1dtEi2PX8+aNI5oVae6nW6lLduCQLE6tafkhDcTm+59gHDYBweEgWUoX8c3p4dLShLk2V2AAHrbd6W9dYzIFNbUnI1Sr1Si2/rKAPio5Mm3mlbxd0+lx/rsbUQGsmiCOuuo6/Xvn2qhlN5nO+mkrOTJ7FCiHgJQLNJjiu1RgBULXGYdK6n1WBNqUInuOQHLYOa0clIr7LNQ9i82BWjVbiCg9WZHYwhijwPQQBQ6ABHrJYrYvqkK41Lr1EFXnxK3TxK0cCAMW0flT6r9r/+akFGewoXEHXn3//Pzs7qaflv/r3x0/7/5fZ/+nWf2Wi61IJ4eVVKu8vOZMO2oNWX3tf/7AGpEQidLS+QvAen4f+gscwS+lzEBxkXPIQlC62ko51LOrdifAHLz+w+uusO3jS70nWmh/zoEbUDpUayqiqsPxX2dZFPcjGLSlFn3RSXStAVf0lDpZY9nbpCD8piv5WN6AoKlXUB4BWCMMFgPcYejSODjeQ4ADTjj0KC6US+w3ov+narxPqOrBWilyhoP3o9tel0sLE1jX1h2ITWzSbwIbICaH9jnpUAgRboXUtjAQoq5wB5Rt06YnIETkzGT9Tb8sPMcC18r7y/6sfnikqKUAAryuheaeAjwBRxeY78BFg03GB6tUjpMdw4WNYgDWzctiIdERKyHGhhzkZHXMyok5b2Jyj/WkppphYQX8PlESXq9VK9fKysqYdrzxTzT+ov+FJPAIFvaf6GIgwKD+MuiNNn7QmUxotlcbAot5YCxjO+bigzMAQ2PSBGIzDOcQ6pRObRUykb5kOn2oj6zx4taTBT9OGWN+J8T4BCPbJRMW3+PxBs3yYJjs2aIPIc0omDvaODcpR0jWLjgRzg+awN/jZnyftK1ia+U2LxQ9BAhPWb3elJE2wU72S6VKmhZ16lbIbiTq1xWz/07sWUqzdHHv93ZlTXiCIaKoK94/01LPxamye0c+D2Oekx31p8nNOnjnDUuZEx5t/plnMGzfXAyrykt0DTPccoShxesrIYwZw7cwwOIkNZhgrYuxHRWzoVdXz1RDSvSyEsxCia8krrgODmKsR6SQZEraNRRaOokJZJ4LRzVy+kJb5JxABiBSa5iJjUbRWqj5C1dtj2f1EGNojQUp1OYZSIhQHD2G0L3QLuzL0tPMVn6JIz/PAMXrO665jD4Cc+FzbPDgTSfEf4fO7aR6AUj5WaJ+25vvcNGsbU1DuNdqbc+sWz8F+KTk/JS1n7oxvG4ANYDdnzswjlcJ0qllyyRblq3UfyimkhyT1QA8tQzheelaGFbBr9sGtYzvmGAZ+lqPwy8WL0bQTOrdQikMorsIvRlOjo+kTtpbmwTInkkkUaCAJP+HM/4WvuLac/5mIix537t/p/F8/rZ/VTtP6/9Pai6fz/5c+/w+GHc3oDjrar83YoCs6bVjg+IgVGbT6mlTiqFSKAgW07IXjTREMD48eeLhDcw6BqgG1DtQu/XcBakDtg5fkQ3haq9PvDqa6FickplXcDe8YoD75l3BGukIpCiPmdN52lwjD8I2PcE7EUCqdcCmD/62G0PI9y3Ghyv3WVdI9VEEwvHUsWLGr0t334wDUa+rsd9ujURX4wQ1+BlByAiR29V56r7OSH0qad+uEvreAHm4q1LGxNepy718+jw+pJ2uFXrULOczCrkbTerY8W8dmiEEBeuCklkrW9ps+0frtSc/QJ60xEypL65hWJqHpocAMoYffLOdwJAtp2qRN6p/r9DDNjRnQCs0Q7bOSDrw/eTMyWCrZTqFBfbrUT4BArN6Qvd2tLhZVHCNkXC/nMDDnsMpzmqZg7VapmWnyJ1B+SPZtnR++hVbsaOfj1sWWDkWFduuPDWehOd+vO6xOM93ehs6sJZ7A1QlTBDv+wnS8eEUOtMkvw/FbWWESTzVdEdwUxOazLgaJmj5W/3X5vvOmPbo9vfxQfaARm+qvgAfv8RqQd/xZbQ3IX/Dtt6D6dYxE0/OrB0Ap5+CQFt6oD4GTavA5bQKgNEzp1wqi6gHIayHPT/ChO3p3ZnSmLbpe2m8lsim09coMxdmfPBS5w3H2WYYjx/ct4kAghNRcOTobCrooKheiFXL9eZIO78zg3HGlk+CdGRjI+QMaN1fN8iG8D8hJWv+lNWJWe3r3/zSj/3oNLp+Beq1WO4prub5F7/OaSiI0WY+xYttBN1yqCiEzd1IDM8R5MenZa4NU4RHnDsm5f+FhoHohUH0RgV3VQfkwhKbtOt4NUGdbmjqSQpcT2LMQ8n7aM+q5km5YeMvU7bRt8en64ChjZi0DXSs0EZVSfpCHdKOx8C8iWoRAhGJJlRkEBrW7SyogkuOe24MqKUNqFhtbR8nwl7OZY7HE1KRhZmfteyl8sA8sGhs/xqoB+G0zSHUXkNEAqZF5DsxEFLiZ6bpRtKGhTltJJK1MLQFZ+ycPwDovd5lhQ7LtN7fQie/jTcShjkD1r6EFPh67U8HnmHDSKB02QPO0se/rT595pZQfB4ryl/ZYa02IsK1Pz8+7bZaGtqu/NfRRq61t9gXWBT7MtvcKAmTeUo1hA2SopNC55PgUvADHLyhBktJU4k71620GXkrCk7oSBbRice/ParVM5a24LG7oWD+i0U1QCTCatOLPgMqim8feU3u3IUS5VEXP9zjloTtQAzUqblHRaIaweZXY2DRsSXL+TucdKk9tPdSIUtTtJz63sBmunZ2e7lgpiQ6rZAaY/J+XTuORfFt9+YJCy229oKg0uO+55dmHeBB36qckjb+ZTGg8pV9pSBi9UCSPyzXzKonmYTxdKQDXGAcGxeORAFoWzdrZaFCTpwYFBS5zunCpvIrhbRhvORoUjUolnykvN/f4UtlzyLc0tnF09m4se+giIPVd51lPdFt/zEyjRGf0T5prlJ5s/U+a7Q39/jPme8MYfYYZHwx3mW5RqpmtsH2WPD/qwf6Vc4elEJ3PPf6FqD9m5FMeJnmaL34xFWu6lEhRtlv5ar2mEqKJW1dS+rEDbXh+kK8hI4fDZmY+uN9JtNsSKqSucu1WfJIkwuV9U7FCLOUkjlMRD/WLpRnaQCkPdYX+K/L/pg/YFgyxYUOEuSIkuHGqlqnicIlwlZ1MqqZnXfshigVMnsTCWthNhX1XRR0lDmVSlCR5qG9CYonCKro2Q5hARf1UVM5dE1tmuLV5OunIrZJnW5shhZyZQ6RZqayYnAAuci6t0n2lRh28x4Ugd22e8xtpp5qMp/pE6xjtlohXkdya4/fU5OfeDOfoKCEoFhe+MhE8OwWqDX6iyUhFz9ZsMbZblfIDG4x1Kif7dNQhQmm7ZbS18USn7ZXjTm4uLC+ONg3h2jbb8VDkyKN+gNmEphJlpV6QY6DDAjkj+DuogfLhYRThtN1i3Tfaw+lgsgYqqB8dJWM729ByzRCCWzOkeQHimgRxo/zgrDMa1a944cyAxrhVa4kPeUZAVawQlxIuyVm1lBhSAkYwre0zkYUTJ/ROjn70eOo6Cye6+5DcdKe9br87MTrj4cjoDpieS/IXTPHXuB2JxSKIjSWDHynjmeiuSJGAipuih1Ihxddq+9SiG8GOxXPuRaIVlwGgK2nHeFJevgQBtgkXvsctUUrbZ6X1f9OxZvyvPhzIA5y2JeA5rFtvdUOQZ2847WyqF4VH0AbvuuPhoK8NJmsOJ76II8D/F0n2uJIJwqHtUCKnN2xJNNfKkezlmVcgcQpj81dUJpmqNrcgtz7E4Lv7tGyma+N33bZmjMbdQbs7avWMKJwt6XJWWMtWaPeoakXX2mNt0lTKh/GS/vHHH3dp5CjBybe1kAcvUaJavbysXl5eXq4/GzyFwBNm0cz/FlAH3PwBZ9SgUJdOpZGNtsGcNBQMPdPDXVFEG7QGE6Mbv0fLK2SFToAd3xOl9OlrvT3ujiY08Xpc1jTtNnVPiQoWdSqvkg6tEOItFdloRJWFFvci9JcBqzrW9OF03NaMi/FwOopKCpULK9QbtlsTGkWVv75dTFYBZC/f9Y3JbyNNHgIP4oG5gFH3BxIOCFrL0MErikNcStx/6Fp7Ou5Ofkvhc5sA+a47nkxbPYNXSpQaZ/uYKm4U9Dn0lxhOzCsXxi2Nh9OJZkxar3txB4PQWZjhqnVrOq555bgOXukydqNxt98a/2a03rW6vdbrbo90R5eGgAPQLdOFuTX1dqunJapQuhSGPK9N68afzfq+zetRGo1NlFrtt8Pzc6M/7GgbASg0oHxe3fWGWmOIafTgwsoirOgmINo9S264AYr262g4IMxmA5gO99LbAKYzHTPa3QDmfx2MYbgByP92JxNtnAtibGLYI9t+TvVxa6LRjXRzzX+O9E2VjX+O9M0AXi+tG7gRAeP1tP1W247HL6GD4TZkjF/G3Ym2C0rbwTG8khCXCDLdpN2lJmx4pQmjWQprqmtGvzVoXWgdo0st9Ca/GdqvE22gSxO9RDBsIeTMvRhOt8MWzFTXxkZL17sXAxmGxGeXKHII7UNs2iY2o7ZpKIpBWzP62qTVaU1a64hrmvZr0yWVQv1mKZhnq2O8bvVIjbGhv51GbdgOItxmuMRX/tKz9UFrQttI1uh0dcJ+jOF08no4HXQMUk60CO8td2nDvokwM/DTsenZZmj3XlNQ2q/t3rRDhkufaDxIOkG+0xp3jN7rdcSR2PS9M5euxI/e9vXY8vFda9qbcFsYXm1h3juL5aIndXu8dGHbX/KV3W/92u1P+wbpUdSh8ZRKEtN4aYvm38KVaPzmB6Rk33JreFJAKa25RQ4TlNT7dOzpYp4ImkC5Pc5KSvwOX6luYllVWwHllACxGwTGZgrrZywfksLvJosHSVJMSqmFAnTCpjYhtO5WJSvDbqqXOVDyktrgHS2Xd1DfCRE+8zn2NW9/yLFxy5waJAXK3jq4tGDeGnW5wdho+rrXbdPortm5yitWcKZhB2szcFhqpEqkSEtOchHAnDk+Pd29RnaKN1QrIkUx4QWDE8+6yhyE+dzvgGBy6nMPTEr5gZkLMbFSMyY93YgygYy6g4t1IqUwz8dA7QoSRY3J8K02aKhFOUriFA49emSgwnfxiUwemMJKKUVLLmkw9/bKDVxtCVmXbkUbPxa/ZM09kBSKoGx6iDz2HTUb20PtYvqVor4UlLT6gCeUEYubR/JhOoPMMiuCVchJd6qQWWQ71MpMjTRGRVOzG2RpTeUMH1cnNXe/dIiSmIuQWpGV6qah5e3sOrDZ4lwhVlRuP9vg9Aif91oXelMVfq5bCUkIKan9qT3oxt4ShQ7bxy/AwreD0L+C4Co0PIhnjothmFSP9odE0nmdtp8gS1+upIgluvDtpQuRSuTVil2Vy0j2DBKm3RE9F6N0D8TzTKhScdQe9aYXdMibQKGavfyki1Kqf0I2PDq2781oUE/6Wkxid1xNkQU1qkkVyQDJWGdFGA573fZvPCyq6TqWn8cPhXUn+lpZ0GO3chU69hwq0W/JRFj5en6wB0aJYL4ZtHgirQKMPd+DcjxHUSaWc2W8vnDHpK2oimgopStMyQWoGHgmBqoalWerg5+IuG30GCLfvYVxgE0XAdXFISPikL6V6NXE+S+mr6eDydQYaz2tpWvN8qGLrgyeywmoIVAROP4pZghkZVEGqxwlSDoJhg3uca1SO5XnKLfQ8S6FTlmh3Iv2rjf3Q8ebR4a+IR8Z8PsShisg7kyulpinD3AwAtI4pEwGGdTJtYOAg2hGIOQsAhciDMwgCH3TugbYB3d+eGOG5GgKogYdhJY0fia+9pcYEAbvQgzdFVh6IpijI0mpNBBmNVx60X7BQcnTxAiY+uftUDh3kreSx0YSYdTHfOEygV2j8MtaTxsNx5NtcggDM4EuDPwQ2yW+EDafL/LulKK7nZ0voeA9tAx67ZJ7y5/a6e6hRX1XRj7CTbZCnUCs0BE4H45/aY07oNVua6OJuPpJ2s9JlzvM6W+Wfl7lmyH2F640mBejqTGQmFRmEKNwvejaX7q2gW6cwPCoM6JhM29DJjzGr5vlw+LCicX8s8IiQUicU6pZLGCyhXMBPRia1HbZ8z31YjSVLrn4vkmvackbjxxqeLLUd30aLUMppQ7DUjodxlcHQ4MM0EY5O3+Ik4IBFVh+aU3abxIJdaSr/kyPcnsj2WIXI/1nYUtXT4RyBuFiZL80quwYmqFceAyNhW/d8Aiz1rXjmSx2aAkA7Vjr+9ZNKtR2TMnFlY9KnynBZVFI4TQ7rOTcqAvv4zc+wgrYUqAkZw9KBbPPjWUf7Zj5o1S0Tj+lQz04N61V3/c9y7yBfSss7FluyYgKEnzbwm7Frr58qc780IIqk7DIjzuTY5HHqT2IK05we1pxAoOXBU1Qj59TmzLTdSv8LVkNUoGzjQUYEvyP6s1Uy3RdNeL/pBg7uWw8nLDOAVXlATjSro7tSY/IOcNWZ4PrpLSCd/SWLG2hNL5z99uE9kdDvTsZjn8zXhPxTyk/5DxuNHMiHewF4ZsqrZDlNdHiezPUJ0a/PRZBqCU2Qy1f7Gou4HWV+bkSJqSUCi0WdmiYX9vnWaUUVymllYe71sphPzQA0iE5chygf1T/Ub09rv6jfiBsDvbhYFUqnGcNX4oxyhOFyMBWmDlto1qVE3bJKJOZ/UCGwQzYda9D18d7mlJTec6u1d1bSAuJcOTU9Qo0WS7ltLHkFiYSnXd62kWr/ZuRS4RyliYlmSfpcaRX3FiaAj8DDT6CCh9Hh7Qi32s2jCPLxiXZ1X5GqipufWe62gtmhYVp/UA786t6zng/tMk3Cn/jXCsfBLmy7XLgd5bB0BuF/sJB1vI13S9iE98Cls7qqp6v2stgZ66eOjltbQWLknu20OLpt3UcQnPheCJGzsatDjsLKJm3qervSweSnhKUaDymOwBMK1QXThj6IeUErrm6slVsLZbST+SZAbr2MYYh4WEELDWjNC0elsYKhXJRVRl4VdoiDyi1WmHF8Q/iLjGX460jZl9bwe3ZbsO1u2bSCc4MLjds0Euy7CcjZvwycKzuKBV4zwmaipI6/c0hNri9jOE5luEE7BwXsKB8qXdJm2BykmOt0sMC1KE706k9AA+rRI/C3nyjWW7RlWFJVpCLyyqRWn/LjR5XE/NbvRvIA8qloNGrlt3B0MtBCscPoIeQC+bQC5EJVH+JQXkLquC4dvpDonYIfweqB++Aev+i9hKotrlC4PuTWg2oN3C1HWBus1GfgIqWV/8GSrU9oG4UPIDKWgGqads0XhQpAC3cYhYJzc5AbyRKJq97EzOa0Ufza0AZm+7ggqLTPe+2CeLj4YQbudHMWpvSyIh4Z4i1BiQTdxD6mJokAQcBrs60n4N5fF5F0J2pzCwlF0AUKxwhKe/LHjScjphaS9yR7jIEBk0Y2lRiihNbpL+IA7exhlXLbFossIzyH7wmMqdyPjcGr2Dw7hjSVBhiLikEYYezywDG5/d9msmoqHLzAqbzoNoQw3DheJDU3IkyGWrgCkYECq5WVFEV+L6bUFHJLtq94fDtdGTsMw7GpHWRa9uyD5DtaZ32XY853U1BpNF8KGch8AT8mWvOEc1qxPdnEwGPxhZWMnem7JpQuoWkD6qqShGCKqPQhHcMTXK1uQS1VMhJGP7I6/KcK/Oce1/5Yjn2z9lQKKlW+wj+/Ts4cGagwno06elREDvQZEckilZ+AZboiCoAQQVAzz6IoB9lOiJdXsvxOBnKX5QJZwhq4d8yjbEd5W3enRfLYbAX/q3Y7ga+DXv7wipK7LXrKuJhnJTCLqoqdhGlW5UGZCALhj0TobFu4Iq9orG2E8uroKfnrjkHSgpys1C82AFKGpfmNonmv3HV2dA9rGAXEco8d1x4dJB6wUPDvYWr6PWj1pZp24+nbjKgaT5q2vYnE7l8rUeAtVtkHCLhkEZ+a7fkCFtZ4yUztror0HrIYCL1hmyjQ/3WxoU2OXHdUr6ti1RgXSoVmbJtNs+hbheQEv6V4K1JWx1WArsofs/MdWLvKX6K1GlJmUsHsswd6/G4zRjfClXVZvF3IHXgKeqF1ur0ugOtoSrHixpS1kBVTZNdeS9Da2PdVqsTOXc01HLrrU4f8fXcGo2MbofCExaVNF5gTrA/oKr0jiUOYssGoVnk1JXwzyrAboPReYZFFI2hrCWV3xCMlwiGqskt3lWHm7yrjt0s74+TUuCfnqD8baSYVfZtr5GzBnatZGK2qLaXF6q6qefgD6XXcOaHsJmyYCuyCYsngM1J4ZQopfc81euH0i+mh6H9epVphN+qF2psBv5r17duQN76zapxcjouaXSmY62Ud2hueTYPMJ08NzN65jbYlBHxfKsiq63BgvbzezpWPNo1N5cXlP4AvpL83sVlvP5mOO11DG1wPhy3OaxRvy2SgLIjOpUb6QX+VwDBxS0M2/4iMEOYnxq+odYqtUptrYB65eS0UnsF1gk88gMBCIyGcVp4srMfV2pJc+G9r1+Zp2MyJHlRbtfC+apsikOubI9SnjA9e/wN8udGvijGtQKUveuA/ToG8khnrcijpZQP8SqAQMUbo7QfETqZLT2Lys1/5nCNbuabRmZ0M9/cq8xJYCMoh2X4teHMIaenmR8CfO0gMNTzlAZvf9Cj1L3aeJwRy0a+3fVmoZlMUBzxodGwY3QH5+OWNGXdfutCi3lKpztusmw6gW+rDgEWq8tVmkpZypO0BeqktR1Y4ZsKNkN+Kgp826BlDCmPHCnD1dbI9Owr/549O8oENSysXhiLJ86PEULLn3vOH5AgASgUKb87hZI3UTTRReHA5ATca19D64baGs5AuRBhYLohNO0VywiNRHaYyEbHmQGa1t/Ly+av/h4lB/odKP/aNC7l/MxTPF/+vug9B1FqfHoZV6hS5UnjIc362Nw0c9/8oyFSRe9YISqPzXmTemS7wumIUtKmytVqxp6huh8j5G2bVmgsQzc+gDICAh+BtcRAtatAndWPUlJi+WG3dbuW6Wm0dF0y4FT1Yi7JZGKHeaGzbC4S6UbXUlZg+JZjuObKX2KDVDVoZqp6Dbyg0shueChAKWOTcNGofx93Xxt8kkKgWrezjZ2ftMZroLZ3HyBQ2bBKAE85q6qEomhSTFCOiGsrIun4QjkNYJMm8opgrhvlB2zOWXqfDUwqtQoT+SoZ0tDesCqlnB3k3J/cG7bxR8XxK1boSFemlcDxPGgrQOFfiva9mInykd0FxUex0HAB1HC2x0IRlbbTV1Ll4cKkvqOnTYyOdk59eaneI89/JSdQJi8R7VRJgTtf3laowK2sgVKvHL+s1JQdZaAE9hXEJBCuCOqOzl2yUPOepm8a9sXx5DiL435B1u5MbF3b/nynGGu/8MI6tJpnNSQ7CklsMXmfkLpOoAYokiJSntm1kgOFcXltbOjtN1pn2mu97mlNpqX8aTdISS+UZo5byk/7oUQpV+oY/b0/GHoxTFV/8ihJT3cBKXvzUj2PFEyIluNBlPJlsOIqzS3wtiLGRY18P7hU+ZQSjpSSUwlECag5BVcjfYJKM1/RA0jCnzaThGFH11g2KswhJVZaYP8GeoTHitsUYII8FKT7BSkR07tWr9thet5HuCPGCZtoAjkqXKScEotM2zahEOm5koZtm6sUODfuWktYqW0uvrurYz6ghIp8s4Z8B2ixW/d03GvG1mxp9Wvj9PREiVVj8t5FaG//ic/Ram+Z75z28mc5t+AWx9X8simv1USh/V1Wk4tUOK3Gywtk+ID0TlXzViTYiXXEHq8bhreQPeUP8obiBSEOdqnBB3xD0ZxhNwOHRyFpgNt66cbx7AZoM6bJ7WBQo6QC0tMGO0/yxyUA+DeWkl26X1XJeccPHbxqgE2rjHPl8BaGDbB5/ZSWKIGJMNuJpqwEACnS4Ar6G+g1NjD3EpF/4T2mEPl33g3ep3RfOfjchhlKMfVwgCVrGYbQw+J3XhFBXDniu3S/LxFtCGcwhJ5FU01cQ8CvdOzo2pnFJ5CnQ0nynY27p7Rn7sBStlL6rvS9lar/zrTMZixBwOyRbCzT2C0cBa94A1eN7UE2Hr0IIoyzQ1lI+3mF0mcEOXRGJONPB5NuXxMmAiz2IKfe3MSG0ZZ5XcrZh4rB5dKUnDrva/pf7FPajXxKVRvUz36onJ1U6scvK/UzslqwFQBVtenB+4caUP8NyPb3qOonxy+OzyIIkSARSLbHzfLhbufPlM2yAlIPmKGENtCJfN/td3RjrOmTcbf9SCGVm847CxupIUQ4dKyUmFrAX7agkL2M3Voh58yxWx1OQlsL7y7WiNCIg27bIJP3IM/lOiV9cmvfdLvNyA44/SYNoDvQtfEkizgNXTYZGv3W4KLH40I2yw/7FF9Lgi05U72PrVqokAaaTfBMoTqm3Gy6XMh6Br79ds+aV46n2k6oPAMf8k9qbXH3BOLqIMqHO/NDcOXja7ANN2rvtRUNYUwZQoACaDkzB9rA8ZL2k8qeuiKGQDb1rXDgzL6Rbbr+U+6i/8L76Myd9O5jvy3PsbJbJuTPfC39mfAvvpH+lJzNn+VuOj1q2evpwlTQm6+oP9PQJW6ni7NSb7ih3pDBbCvYXW6rk1r8vKzfkS5ejktQmJfuT7SmSI77pit0BWx6m8b6q232RwtooowBUuB4c9U1MfSsFTipbXFUYOHgtwIS0pCyN47iQHd8mkbl3/4y9EyX+u0tQUrsor57amDOWVgt6rGbY8ggTE+TDnKyLYPOHfumNJ/BVl884QeosvwHFewsYJi16Rq0Rvqb4UTkQMjzZ+w785EZYocsY5FiemNe54Uzp/kwaY3dszkXVavXVPqKcbftqZz3gLO7hHgxmsaRefmaa7JAM+nH61hHVTQ5CRTBSa0mTTONeRBNL49ykFASpOI+vFTZD9W8QfHoFBlVZuDlmFHmlMlxkS4sJqyT4wJFQQMLQWzMApiMCiE53hJBZsCy1DJpMxrGpQ1vTXtBj9WhTyqznBJquHQhkm/EJqEzn0PqmEMqUZ7OM9/ynJUoMi8RUDGrQ1BaXjGs1IWJreumR07Qqkm3wKZp89y5oh6CGFPvXrI4/SVu1iVCePsDajNsR67pQdl4sjzWyAYw1v457Y61jghkMhhGYZw3+AcwIxP53mejGy49BbQnvUQUM643UB1v5icZytsfdHKmH3QHF9F2ti6VWFpPsrP0Tc+ZQYQ7Tpi4Ou63Bt1zTZ90uuPMVcCC10EpQ5BUPdLQXeiwdlIEECusaAPX/gJWy1Gm+2qFtJYqyJZ4omJV0sUl0YiKSEupnIQl5eeIW27EX/MA7VhcAk/z+tRq+cCigIY5VSWfEbYSSqqqppV4st5uu4pOtU1sNsClUua5dbg3xaWSUM9J2HCZJVJlXSplEVz8n53B5S6K4kyVWE+WfKWa9sLxaIGixtJKs0yJhFIzpUcsbG2TXjEeMmlQskMX6xVzK7zVfrtUSgr4qXCm1fvYVrvNhq61xD6yTBeGLduWkti0e1Pai9Z0MqS5I8ZGq9MZDvKv7UxSF1UFhzAjoKoNA9dfke20sjIXbkmOaI4+/si61O389JFbg5U3ZCyJHYk+zhVQ3ohifkM6tHZoiaU4+ZTW0PIq0adkupZPgcyzxUjAo4wxnwI2nMcAk7lM9oIaUVer3W37ngct7KcIq9WmoT4HWnsylE9GerN8SFNfz4DycKlwwrAvFULm36BL5TkQT1memuQbkUUn+TSZOyf5juzPt7DjhBTJlebZge94eBq6rJy4P3D9uePFdo++5zoedVu/VJ5fRvlveObbQigL+p6ug9jvPReRi9AMrkXKGYG0ADMnLyt3jmf7d6jiQcxhoN/dftTCLkhYfghlOI0fTk9POLC56bpww4jw95mOLD4Jg+qlQo0ANzCAja/ZqiVFohVByyfXniyP3oHaUSk3QMUNXIEQmY3T2sszHrHC822IEoErTs5esMAV/hIX3POYFjUaZOuAFK0EcMHCWOxSgTxjNURki+ZUr+qTZrtV7TVvnRAvTVfcGg4zD6bpJ+1B6omSsyTfar81o/Rde3XrrnaUt8S18WQ/gHG378QEJUFu34mSALdtQiG00U8fy4WsiXK+IhSyrHRgLuBPH1N8dC8YZASyCGnjyV5QbuAqA+St9ttmGDEL/4OqelzHWqU4ODU7Y7Z5u0wFgaMGFNC2mQgjtvfTx6rMvFE1vZCricxjqJo73PmYxn28GE07LJZrOrzLUKenqTIPrDzU6dVxTqjxRK7NB3boQ8/nwXK90Qw6ICeq8uBdt9NtGZ1x950wuG3kPYyCXhSd3F6Aeo0K+VcmugaqBZRyezI2Ik1Fr2e0+539GgTzYCniL1ehh8MV5ekVdC20wAknhmb557Q3ewhxUciRXAtp3tjFaApYiN3n9JDpeHK02LQWjfSRoa6nNWmpiOG5XiHhgioVPOsRs7Et2y+7vHlcfmLhXxSTaDy6bJwGNBhxpISd+L5740gx4Kn2iRUakdMcwtCzYN+3YZG1i49AeagDCSuq6UbLgNvXm5ipurGzgJXYoSW9mFKW7PWknfomxQMLsKxGYcDUJVCtlPpyw4QXwz6p1QRwtHA+A8DjF8C1+e3kLtDibNU7J4em6hM2gfpq4TrezcRvuW6HKqQGRB7ZfWCDG8d1gap3L95MR3J41ELcBd8QCp2CDLlELlLJZLlwodoQ0x03UnqvSyVuFguLee2hg1rj/tnpEQuhXd+ivdqqKywgom+/FUZdwZLzF0BWGLSpb06aiPea1btrx7qWCCydL7XfNcaaPu0RSagQ9SSNHmVX6e5gyhRfTZ9Qy5k0UJFjtd8lfZlMdcG7+YTEL4rYNzcziBHilgLezB8P+8BBwPLDcBlgaOcZB2Q5eHdwPjTGw77RHo7H09FE62y4p9uT9+fZ9cUkcOeH1Odw5njxBVGkkP28VBtlkmMamxh9o3tuDDStw6O8sLv/vS7wYkQrGXacoe3ssOwMPLucFZB9JpPZnhLVzpiklrkClKKblzRDOKkpO+8APIuINzP4tmuYC9swF6ZBDrCJfDsORM1y/RW4Mx1sIBfCoFk+fgWEnr988gqga2eGCSdKfsnLwl4HZQ40mWx9POob52N6vdJper7neBiGTIcAbG8WSVHqKjKBFLJEyntTPK7Wz65qpzPze/WHH06gemq+PFV/+ME6Vn+o1X/4oW6efn91/EPVXNiquTBV0m2jXjmp1NTjF7WT49Pj2smJai7ss9NKGCxIn65CaN6QEb5MSoRlhy4V0a9coZC7w9aLlz8dWVCORznxlszUwryBlmldwzQniDLGUy6g3UNrScQaedha/Q5o9VuEf0EQMIMLgjiZRfSK0AKCeBm0FnZrYX4mnrC7TEDvrCViBCc1UKeCPz1muaSiGsLAR2RGMsPLmN+UxZeVJG7aKmDNkgEQ/SaQimTwePW0+p1WvxUJDEXi91ttPNB6whCjWT5c0vtJNQQfAQvgXVWrler8II4T1ep3DAKaM8lRq/2WenYdkhkjyLFkNeoKqKrJkie7ECiCVBmHVymxPlMix28tU+J9TX354bvKM6OcRJLUQdQf9h34CLDpuOQAUT9K5cP7AyjlfFQ3JcKLp2HmeHZEeHxbElNAuAK/kgA35Gjtglt2N7PL4YhPDUdqMJwY58PpoFOQ2q+AtAr6tjt15fbsk+nqMYsC3mPo2dAGrnP1hxM8aoFw/BEI4e9LJ+QmQHl847MtnXQPE3tQ1N29J+Sz4rrLdCxsuujoAUYN3OXc8Sr3P5wZZ6d74956q/OrecAAffZB54oUisjB7aLihcb1cg4DMvfN09rLswOR3kXOx0FmheY3s3yb575TckFS3fJPoBqEPoVQvV1U5SYysQEP48OXg1S+43NF7hFLh0efFUQHzJzcZM/spOGZlDZNf5M1Ouqwd1S88gOA0HVSmhKRWHX9zbaKdnFNOaqUrr8ZLa9u4Kq1xNccIRbgWwTDDehrw1zi66ZSritRAYSujSVKFChJSaNy6hfFWcyB1FQ8X5FTCeWWWbHJpOPLkNL1NyIFgDDjR9fk/7YhPN5E0Ul/VALk36ZSPlzcYLgIjqgzkXl3A9RbYENEeFBTKee0rYAD5rqrXXQH4AE4nsFMVGqvyPbpmha0yXfHQzDE5Ds32q3+q0/KHb5/30CBacHGhw8fy0dVTgl0+A6/EhComkuAOAIPgN7jASWeMinuhiIwllqtR6bCEYL1VwzKK+DBe0ajrMzhV6LMEWm3+i8JxWd5LUrvv4s7sCOK0SDVM4iIbq65s0aHjO+GYdmpRQrtgBzBYwphDvmT/ohOO100Kg07zR6SFfTAAzmwJ69k01N20hxNX7/VfjNa08kbsrheARonJToqLMDZ6SlQfZo3FqhzwFPHUvhJZKKkbBJKEmsh54loYWd5TnbJ5yMYWfVkzXBTNj6xBFYvchfXwtAPG2AjPLGZoyjZmuOSvRFfAxMBM5wvF9DDmag9dfmgyxYsq2+Q+jRji2BHhdZ56QpZ27xsiZKc4+DKoL6Wholx6FwtMUQi6UFUwAzn+Q8N10G4eZjMSynuWFttmlOfa71pLJIdYtHm4hO7hLaip42SiARLjS9bluUvPTyhhZa2Az0LNoAZOI1qtfVW7/Lok68dz3Y84RrJp01PgGiwAM8lkaLRuoaTVQAbIFmMv/fpDZPpJl+2PI8HKH4LVxGqAKggN4Q9zbDB7HMcKeRscpSBoqrOlYo8h0bWaZYfovCYr7uDTndwoRu9YbvVo+tgOCYv9EF3rYAjOfult2WORPCG6N58zfO5yth8F6HD47DE6Df3hv4o9KJr+t3QYxYeO6MnQz/KnY+4iTh4qxPkhG6VARBR3wznwKG9lMG9/8eHtZLQ1EgNNuPCYqtTQfnBDOeSQ0Kkncja/rfe6gaPmknT2+VZ/ncGuqFPz8+7vxYxQmurN5a1RNhfABqpNuP/m2VDWxyAbxI+VBV28VaN3YILeHFJoESXnbCsoyss6/zFOCuRB6gXQrRSVaA8q8R5bZS8x5aX+9iGuY+XSH6875Qw/ROj5TbhSJ1lSNlLAyj12oKHRpMGL+6r6GpFjGc0kJSo0syWERghtXgsMnfzlHH9G/meRJexH/xnczrZle6EsbWDfNfE0AaJ/B9PNJhLg5l4fP+xRBYVUdWQO6rxnFbZJImN8h4kl0u9mduezfRHowPyQaPW+Y4n5wx4IjyZ8P47OBjTYRQ56EZnh80nAiUTmKPYQZlaMyn8diATRS6dlGxho+ESB0uck5mMvDQ4OzQWEJu2iU0eolNU4xFfc4syUcWjbbdsO0SRcB/cnpIHIu5mOYbHEjioITiovK99EBliSWGIEHnCE1t0xTNQrQJF4Yp6vlMI+FyYkzD4rnkovY6wOdsZm7NHYXO2GZszCRv+Opw3y4fdc735HLyKHJqkqu+ffVgrRyAlm0WVC4O4sUQWKrUhpSJmVAVgvyhXSTrrT9IxPw+YfHtNjxFE/GgPx5pIR5EbqoPSpO3FX6hlLsvuH0HRe0TclrJapNzvorrIpX6WIhBbjzzvDPRzx4UoJxNe4iCcxTl7FM4rk+OmVlhMzGpU4EIbaOPWROvQojwGScZnLQ9eUo8RlYjtQqJH2uCdPHbRiMPY2VDZaWAEoGhcogQFOUX4nhS9ed3StbNTQxu0hx2pu83NgxHx1IIBjtsrlf6/bfjHZLRhZuVCm1rOlssMhlwkmaChAyPb0qaYD6AT4i112BbXgQH0bOhZDkRNzxcpHSiBowo2wznEpTHXGjXZOmDkX2rNMAyTj95T2B9Kfbjww1XfvJeHva/1h+PfjF63352sS+3R9J9LH5tyifZoKl5HqVTNKzdaX9HSyl14sqtj1Nk4ZRvPvsRvS4qMKKKKaXfiJOVLajd2dxM3uLQsmpGnksyzyBwX7IvRVLsPYEj1PplsixejKY28mUylGGVzRzdOYDAzD4NdM4rbp/VeXpFsg2ZeCrYxD5bGwgxvYFjEPHlJdR4sVRhhX4nyWeUkjOy3Bq0LrUNtTrRfR9q4qw3a2iY0iyxiEnagfBS1+2B0Mz8P/QUV0eIwCZtLJSZUmLy2L/rikmwrLlS9m26Da9SQApQt7wvb134dDcfUnU6+pcvL5JSfWtK25guVSVgwbCbmZQPDzRJAfmi1vHK721Yh7AfCiilxJyqbMqXuzHKL79eSNV/s0AAptTfcaKR3ayAuHi9JfrdQPLRMvtlITxH3EJSkMZeh3vSiOzCG77TxuNvReJqHHGkmb5DjmAKZrfphazNCYS9YQb97IbhZ4ar/OpMbjjdDKpPj8US7+I0B6Dv30M6/9pULU9Gxqag0IgLCZJuYr8CCVi42t9oOATne3JXCl8vGAPz0vH2EqvVacsDFySov7nUqZsM9tOge1ZS+VpcolI1fE7ABm4JEt9ZAVQMTIVESBdBC+VqFP6dT6WDej+jWph5E8f2iSznbhAvf40ERxI3SBva+lVflm10mUcy3vUwMYdq+ejekUmytABdrvsiiIG84cbPJ/Wd3riEztk1coxi+YBeczjYUJARm3iDVv4Vh6Nhwh9WiY9OzzdDmqgQexyZ6TC9Lo6ebaTDRVcK3WVx/+Wk1ul3ylx6m1snoFqiqyY/uSqP+8rRWU3Kylj2ePot2omKaiHuxkTiS0gjLPm9Y/iJYYmigm2VK0XO7IA/FvStl41+x7Y3G9YtiyPS1SavTmrSMdqv9hp1XinQJpCK70WQ31J6PwcxfenYD7AL0p2+PN15hc4zLh0IDwztXuV3ozh8QVKsALgK8OtipD0epG3oGfZd8Qzh04C0E7/pAfztlKV3jnm/vBj/l8/bIRH1N6Ot//sJP7vHB8RxM1y+7d2MZIivo+pFt1Gq12venp/RvrVZL/T0+rdWPxTP2vP7999/X/wfUvsQALMka/Z/aJ7eV7tx/yUcOYstjccS+o6Hv4yq1MWX5ZEVy7lKpqxPhZNJujZs18oN5TzRrJeaBI3iujwibhCaCSWebSvq1HCR00OprzG9nerX08DLPUydusi7dDb4H5W6HVZ2x2JYFdQXu9aKrmal34/l3HjettR3E7gAc3ytyIoyACACxe6IfRMm4KcvnZzFWncg/rIrcCnAQKCebZYXGS88jkHyPDZRSKpVKQehbECGaat/grfkeSrF9yKMfGHgVwNj8h72MahkhRIHvIShrZ8aM86VzZcdNsXCD1JilnGhHEYEMUtCb5cOFeQONEP6+hIgntKK+Y0S0+KU71ripgzbojIbdwWRdXZjWtePBnwnvb5rWAnHL2m9pf5LNfgvvcfPfyPc4s2edFI0hbOIlSniX0Y0gi2akzCkn6xb4n7HR+sUMyRw1wIDsGQwQCKEFnVtCDaHAA/CIgTM/bIDP2ulNjh3cHIyQCtmqPXPBHTYXZkD3bhWn3oIfwY8iKVreEAkHBn8EDg5//rGp0DAhFjx3XDgwF1BpAOXo/b+UD88O5ASA5Yevk+28/8eHNXVQKRrYgZ8gvxhBKmoAx4uHm+ZRy6HEgkGhRiYyMtySJotg0paGJ3Rj6y+9PEi9BignYEgB99lEiBfNdGvfVJ6tlVRh6ieAHN/LlP7662eVdSZRfYe7UqUwa8StlsW35xLwcvQ1gy5tlMag8mITbfnh51/YAkNK3hJqRynU8ld3coXLmO65tv+S9V3U9wRWpD+Ot4RFbg/8QjDV98LupQr+BJRCQaCaJu4stERGPGSSEUpQYhGEgjC40djniOXy2uPoMz5Q0ITsfbculbrnunFlWjfLoFnunuvkd7N8cBleegelUskPcNejmUDJwcmZAelB+dBahi5QkQ5UlUw6oJGFGtVqInZ/lcxv1UHDAEO765374dj3MRlPpBxJ09FICxNRp+MQs8zDjNpDk94RbFTHA4yCXwl7CJoJxAee76m8wMz17xQqdDgzEPF00RPJGe13cKB0c1GVLdsb8g8cLuGB1A8GnoIg7JRMRYQweg6o1ALtKBNmu8W6QmOQ0MjqcjiPAhkHKNF3vuoQaUMkp925EnVXXUDboUlRYuyRTL4EM9aXuB9KerIGPp2N/D5HsSk2d5aWFmSVT0ubGYdlSosBpaUh8o5szKh5KOwcaIuZnZwUYpGyjt7/65Ju4DGE177tbAfRZiVXuWAIXgpLqiVplGMBvchfldULhCgtXIQiT+WHr2IEyaad3bPZ9slLlJ0PaxC7e15ehpeXXvXSq84P5KdV8nszOzyUgNMRZrAZEAVVKxYMq5XyA7zH6+pcXN4k/X+LaE7YgnGyI2uYsqiYb9FFTXXy8RCulRyRytpwuKs+IxMCqDaNbqxVdG2GsGqZcmxIVOXhY2lEZzX1shS1wpyI3CgfTqKY1JBzFRUj8xovKiGZkRHYgnNilm2IMKknJKWvv35WlY2apdfiO5G4YqLiPWDboZLuiVIWtVJTWDAgZLZ46N3yQ72hOp6D12K62At6Z2KZaghnIUTXyS2anBYpkCiIPYFgLOkJ2ViYDhHIA9+wYeDjxLGPPKZPDSEO57h+0N6ZAa7ewFXoePPE3XzbD1Y0BjHtmg2ulp7NvB+HAfR0vQdoWDQayVo4N37K3Eun6GSLlh849J6+AHm2CqrSqW7GU5qStywuF6q4DsqRfxa3ILdkPnSJ4/DCVL6gRJoHpWJXnyXIM0KvLNfPF8sWt5liuUilZZoNqhYzwDoFSM5oTaUIZ0ZeFf6Uj7tlYqa9F36mWyuWSpNVAFED2PCqNB13ERGHs3S55tVK+tLBkBbiDu9Ge9jRqNND3jMeVh7lviMDFPhkZ8p7i6C1DB28KrX9ReB70MOoAchqAkuPhvOAQGQmgjZYEJGKPi3pztyDtvp61WBEzHikWD28I6oZWtfOLVT588o8mMc3CqzMNHSbGwcjkbXmlqwgbw6m4x6iO11iIsmSHMPA71AmQMpE6zGKZvecRt+4/LlRrVbe/wt8ePa8HCHyfK6kIEqtmwHmtM5atxg20H4OEITAg3dM9X8FXf+uIctQ8neVfGK7qMLWpHICyFpifhaRVg0iHcmsjqZvr+dl7l+GbgOUl6HIK08EK4PwVMPybRgL8EBVr6FpU4Nwdoa70Ca04pGsovxZnBHpCVIcmxIwE3EdTmungMiF5/7SsxP3YPmegePxcMzwFWk9ojASFTBiCtWF6S1NIiHQsSCY4WsIeBUa+gZcUdswEEI15GpDZl1WpMOUR5gaIRvYNxL8TR5t8YIsecOm78XoywWMZeg0y+xihIWXOZbK3MAVtVtHzUOl/A+F64fkNrm3YhGnKT/k4LGOWVa80joOws3yoYuuDKGUVi3wkXosHzwwP9jy8VroqDCEQDVBOYMLv7rM4Wlxh2MWFred4TGlVmhdNwCNUSMzlPJDNCrvn32ITOuiqTFt2yAlGOjEnJDHTK9TZ72g5UKXiDl5POYGrlCVtUez3gvLRrG6yrx+KWM2XBZ1SBPUXpjzOMFxyHvbxGazfHg3hxioQ6BG8I6iInR2y4c2DJ1baEQdj+EfyVdnAihdXcEcqKoNzXDhh+AjnbCyACCvsTSACGvTttlpWuCeZDIZnPJGOiLcXJo+itWLUctMsxjVzyoVo/rfNQ+VjGQmTxfZUHjT8Y4vbIkTRKRkKGiBSM9EpxJz2xeOL4CWSE1uiZu6yTQYu8qYyMotgPwAehha17REApkAzyE22CaeQMcMsEpIh76SaYu99nwMyfoLIHW9Bb4Hrv07whhXgoOAa/OWbEnQE5N97SCwMFcAmzcQmMDyl4ELwcLxlljKpuHMQKJxGHHz39PcfBMHT8GI1Tc0tI7pRkw04uoiZhll5qITVKW48ElPTDt6Sq+fV/4yEkGpHgGHK2DOTcer5HL5nLuuFJKWvwhciOFXSt62IJ86goX1mENHgtRonloeuSbpcAXY7Z/KOegYMqgxCUalef4xJkc0lXK28WpUlktV1RhqNQh9O8P38oHH7jmZnTGqoBJ4RQBADqdLrJ3UQjnauUUVQ0RFw8/aMj+GsTV8GA/aEZ0LtqYqOdNaMKWEnSgRexAcKGfCCM3F2iB21ZunDGLyzIjuITWxci1/sSBLQb0FITRt1/FugJQw5vinb+upRSuBUcqHUSV6PqspiXQzHz8Cng/g4Bt0QN8f5STwskLfw+YVUN1k7ZiLXCrluNlLBUgn/7zoaocFEF9J6Fx6B0CpgfpL8Iz+t6GJI/AxxnGPIMgxCFod/Nu/AreOKWAlbWBSOeOoGQnVfABx06LemTw2cOj7ODq7aDHTEBePD2NtNDQ62mg4ia9PFEk9J1Z29eBIlvrG0E0LfZFNQp7s9xh5kYWIKVbHlB9ye7fOVExx1I31kvYASSYunB6ljbUUJU3crF5lBCNChGTWAh9bdGvlWxuysOoxlSRz3OFFuGM1miJOUjj8pJTRrbXBW2bMqZKFRGuzgAFtQnFC1x7p4pgfDPdQVHnmDO4584vpYVTwTrJWJLJ/0/cguvaxZIJYlkZPWirxmZ93BS/CDV3pmI67AmKZ+bNd+lR6PyEj9qE09NqmCz3bDJv1l41arRQF2cZNGvt4bHq2v3D+gHYHuuZKh1bzpFYrld532RL/QMcA2q9XTToJkVPRVlPI5Dvm1EA9Au9A/vxShaZ1HfreigaY4rTBnvA/PFTZTptB1DaicbwYidGEZmjlWWkEeYytnHIJu0hIjvYxjlkVXXLpZR5HnJPCAOoqthjaaUEy14Pyg4TDmg0c9SuTcRMn069LXwe+7wIPBxWuiSO7bxT7YxkiDBbmvZAbT3n5mihNflVIbT+c55Sv8/L1Pcsf71j+uFS6gSsq5OQQBJEZSiU7dGaYFRH+0MlitECp9LXrzwEOTaYH4jk5F9RMl2xCDsKOhUol15/bTshh+XMOpFRamPdcu3gD70C9VqvUSqUQW4RQSqUQziyakHP0ps3OmwEOaiDwXRecAJv+VY+BP5shiEGttDBvIMIwAPVKDah1tqT2I20RsoojuCtXL6hvU0r6y61Qnz7/Ufa/IbR8z3JcOGIu7W98hNGfZf9bOz6uv0ja/x7X6i/Onux/v7T9LzMA9oHnLz0EsfgZOAGcmY5L3QoSQanUWegvVGzOhakp+SpZw/SA+gYofR4CogGYR1lsz/CycvzitML/VkWoiCrdMT2LkCS18q8SsD+bgaPyEMPN41r9pVo7Uev1b2d+uDBxE8N7TDVhnB3+nHft3T3Xm8orhZ4KgRqaBN+egzD48ccfgVLGUaCDyJJAKT/wMmk1HTbnb+GKdhYD1VYaClBndQKp7BzFZd6Z7hKmSh0nSwlDnDIDGZ0Rnd+B8i/zBrVGXZ2OOAv3ABEq5yqdqJGXaDLX2jEdcJz+iupSFaHe07SRoWvt4aCjN+svRJbN8392Bk2e4d/IRCLjZt9lqTD4qgmeiZgY5ARRSZhic0uHGycAEbcB14TPcJMtCRJyPAsCBx+wq5DWWx1wuHI8JqrkqpH9jEfXiSE0EvCUUunumt6WhUvIZ5S/7o5YDJMCKo/oS/0jgtgdJTdaGgVeKT8kBlLo1WNDPTr0zixWB0jwEsgyCYiOTNq0ik2aHOaVX/JVZQhVW4Yha4iLWvwo7j7iagXqdHE/n5gu7EuDE0WYLRwYprh+EkH+mk/OWTxajypfZeo12//Z4fdxW+NZ8f5fOzmup/b/ev345Gn//xKfXE2K4MfS+qcnLcKZU5w3rRNBziJwYWnMThlN31N5EiDZUVNIHKC6l/iZp6KgJhnqEsGQqymelvSnrn8RDO3R6z13/WfXfST/n3x/mvL/O6vVvn9a/3/R+uchTEpt37Md8mRk4mvt3kEYNemCJctXROnfoC+V0rkJWtqkes0rLnEXwVFM985cIfFTh1bzuKTFAauoPRvz92bmshGm3BFBu3ewzjxE6qcnMVcahXArY4pWxvV+9ViOKBYYT5iTOb6XDyc2a0zF+duprOU5RbipFlCY49Xhwl96WBw0LjMRBS+JDHhnAdU9AqpLDZ0AEz4Ba5ZWV9Urx7MzaGYfvAIzR8nDnoNZmDdQpQZ0WWilZD21ikhNeIXNKxcioGLgmQSG6yCcW9QJ0kW95QKGjiUq7TeV4n5e5fhJ4S/pFiVvc6m1IqWdUlWmHVfZISPxhgbQc80r6CJx4OppExqXxei1Xms9fa0kKtw2j5O/fXe5iCJ72E6YSYHLSrACSKobBfOb9HQjDnfKQvvlFONB8mks1E2FWJDUzg5ljPF0MOn2GbjckjSNbjEk+qK0k6TwdNzI3/+pTSxUsYvUK9/HCIdm8EnCwJb9v14/OUnr/05PXzzt/3/R/t96qwOd0gCY9HTwWtAAaNNI/JvlAvMGqXkExMP4b7xf3XQvW3T3OoYL0/FoTbKzN1cQ5fLgLXhxVqKqtzC88hGMfrOtWzWX+NoPnT+gHb3x4D21vMF+kwBPQI0KEabLYis1M2F743dRcQuGmHHsdOHgxolLsaOXapnqLBJ3MsnrLZO6WIhKrj/npcUVF9vbzBuUv+JdX+BVTm0FT+z1b83/F85cDcwQO0xG/fRT4Db9z2k9ff77vn5ae+L/fxX/DwJ3BfrdCyBiobJsUL4HWGRD0KrXauBiNM07n+VpfKhgnYoQhxYOUBfOHNT30AylSPMasAisUbQnHph/XZqw5LabjFueGFbh/W96mD/D0nhRvP7rx2e1tP7ntP6k//ny979fD4YTrQHaLK+ru3ouFrzrXIVmuAKCMKANDkUW57mDr5dXNKoti0lXjUsdAcv0PB/TbOYgCP0Ahu4KXEHLXCIIfOaz5C8xu0a6GE1FNlZ+01v6ejLsDBtgiqDcuMAH+8D2uQ05J1dgElmQPjOv/FsIHISW5F8wc+6hDUr97oXgE83yQ31dskwEeeRNwT+A47Fw+kq/e1GfS6FGJO5FmJdqzR1Qf/k887+owqtXEaDjrYBOn9P/5VU+2Vb55fPcRk+31XuRV+v7bbVqUi3AxurZUcqxgPqtcVc0MrXiXp8QAgvkn+OgwBGByLRKmYYt50li+wL8/8rxbJVq5z6d+W/n/7Xvj9Py34vv66dP/P8L8X8hmEHvFsRxAH0Aw5BGHdhiFcSjBpa+LpX6NOsdNc1vKtWFh8npUimVhHIu8b78IP1ci4OuEhVmAW1T52ClVJJj1coQlFJJ1waT7kDrbUwsQokbQQ87HnS5YTE3803UTxr6Uh98CTUFKGWp9WTSiCQcamIpYy2BWSulhDJdepvoW6YaKLH0E+Z3d5l3n3j+k1f/Z7kC3Hr//+IkI/+dPN3//1Xnv9eEEBlVipsLmuwpSiqy8HCFvucau/j35vNgnq6uwJFi20EwsUM9He8+q/7HvraC27PPd/2/df1nz38vXpw+2f/+VeufZyOhVPAonXxK/Z5zHU7vPgWd7bp+n0wEv5T8n56gP1v/8309vf8fv3iS//8y+Z+J9DBf0l+WSp03LMn2GTUAYMI2M7m5tgLyD71SO6OeeyWWhLg76E6M9vkFK8fZSZUGXZyZFkQVu/qipsYOwhVrNi+VuJ0+UG1wcAAG2uSX4fgttzqYjluT7nAAfvwRaMM2+PiRmnOXHAIOQHxdA44H8Rkwl9jngdm4DfIL8VNgCtQ6UM+AaolMEdluANWdxbYpqQKktQp1EEZAvWWNC3y0YbtUMm3bcGaG52MD0vvSOC8aM/++PydCfJ3J+cc8hx/3eyZPf/qJv6Ap1kQwKKqbd7w5YAsVsNAI7BBS2JFvvwUZdICCmb4c1GuvFFB+yJnhNal5Gfnup+qXH3JnZ02AJSlAguPMbP/OY+P17bfAmS0D+iPdRXb9IOJSKE8bwZ8r/2Xt8Cp2Fd5Dy2DpTAgZfVb5r/b9Wcr+47hWf5L/voz8l83rNPIRbqaN50bgfDj+pTXugFa7rY0mT4vw77P+rdCxsEtzRf8pbey9/uvH9eOn+78v8gmXHtn7VRF4pwGWnnPfqFar4dKTtoLEruBbN0/r/2+7/3OTN89X7WXwJex/svrf72tnT/Y/f5X+p2XbwIY2EcaZmT0Ily5kfrk3yyvoQQyuQsee01CGQegvHGQt/SUCC98WLh6Fvh8p76JtGmPZy2Nn7XCKgq+fmNW++p/k+H2GpfH9ixdF6//kxXFG/3Ny+nT/86X0P7H9T0n2q5k5Lk2f2QOtt7ra0TrTkToaD/tdvS0HoCttCrjAYwJm6hOGAkw3hKa9AghiKSMa9eCPc1Ky+D+eU/UgrtjVek2NOYtKnpHTKI3Tnm3X8hxuwkjjBiwDsIK4UqmQdhxvDqAZuqtMMjbG2gY0iO6hZeI9UAAfAUtQqVS4c837DzRCnQstfFjBqwCCZhNcKqyNSxqFr8J+KEclzkr7PCL1F2haalE5ipJHSE+Tee0zI8y3gfJDPGhrOtY5G8OGga+JhDQiESkRRaqWayJEel5NwK/yHK174bPj3PPJp2EgnACQlgC69u9SEKPI3j5QHLIdHr6vqS8/PLusHD2crNl3JVEqrwAfcJqX6kE0vN65W7YPWTwMGuLW9IAT3J4CPjhbexr4tr688iBu2Xb4hajNCcxFBdFWk51PIJM7Apa/dG3aWxtiGC4cD7JQvp5vwwMEAt8GBDxg4EFoenPIIuQWd2NHVtBvtcUA7UCWR0J7abJIqFnmJ6Qq69p0PCWX5w5yquUWbOUUVAPQHd2eAhVFFNNvtddA9cEtxNffAVV1AhWFFpDIDqj/FpqdP6Od5AyTxjrj4aigqeF0MppOKEbZUeCj69M00XTuPHjnilje+VsNaigFWxtvSt7PHrMHci5GxMy/g/wX+zl/Nv3PBvmvdnycPv+9OH7K//vl5b+v6X+xzrcb6XxVGySyj5G1j60AqKod+CEGP9SiJf2Y6ifHL47PIghPh7L/jPNfXryCP2P9f1+vZeL/ndWe7n+++PoPQmdhhquBY3VHTaX8MBp3+63xb8ag2za6o4aqKGul5HgIhni8dOHE75ve3IUTst5J+e5A18YTgybgH2v6ZNxtT7rDgTGe9jRjMjT6rcEF+dZ63dMa6sx0EVwrJWZsQiqNY1Ij4LQBKZgBF9csiey7FG0w6LZBd9QAZbkfIm92l6LNsvVLJM1OotgHC9oVQHlXA5QLeimgaSy2cRoaTX6d0xulJEm7CexyRF35PXAQoFbXzwGXVOMUGFL6cLpcU20S3CMzAxaeTyk/FPTr+fO1QgR2cdDLT7/8mqUTYjCI5LXTaD5naRVoms9riK+5c05CBcDMCKK+UZSluB0cnKpHZyoVHNBNJRlB8uQ42lkWmf1pQfMCUHMPVXxTWm91At2cQ7vBRcirFWjNoYdfmzcwBLljS1Whmc7PoImXIVTERnaQTPZWoCJJDnH+iCaHiRyukwPMQjzK1JEM/ih56/AAkFKL+83m1jmKd/06OcyjDMX/x88bNb7ZmDFl94XADxCfayGI88jTQhALITnAf/JCkBvbOkd/u4XAMgHxqPkpgNFOk8q7Jwg9f0jz+VmchOlvsgVIVJ+bWX4TxUdaPjpWWdbv+cCDLEWLDZl5XAHT6pDXxeRNdWV7cfpOROCUvBPU/d9I3J9Cv7mc4e/CubfR754EnGTZn5eA9+LQfzcC5jmzqKCfew7ZJOYXHiLiVNz5rL80e3LK/pvpf3iWlGRAqMDx5qprYuhZq/00QVv0P6entXT8t+PTkyf97xfX/zD/DjnhQ0l7pw0mutEbXlx0BxfUJzsVPyzKFVqhWaoq2j2GHnJ8D1VYwiqdGhZV4S30MKoyZ3AeOHLUmrwRMS6lRw11Q6y0tSJDoE7i5UPbCWlqVeaiLYFSjpRS6ZfWpP3GmHT72nA6iXIblB9ynzfUk1ptDUCpZIXQxPBiCRGmHFsjPYgEXZbnEpvoplmuvwLUTmniLGCzfPwKQM9m309eSYXZEJw7rrAuoPk2v/sGfXMy4Ili/418zyCs1Zs3y4f0ktVLBPc0wzkgoBE2FwEAhNVHTafigpKiwwAy94muzXYFu6DgOxZvhT5R6pXjk2yRiYluCOKANUu6ngOIjlIP3kIXkDMVS8/h+J7pZsv2IULmHLJG29y/wy6AOXJsWq5W8H6S9/7gIRqsBihH35/LA9MAZenXczEUDVDm355HXScw+NfnUk8boBz/eC661QBl/u151ANRcuTYzyO0xcOJY6+ZxCUl3yw/SDSxBj+B8kN2Ua7LD0niWldILSIR3JkOPvfDSU9/LXNyWTX4lZwx0/F87MxWpNqWpJlMKpPLp3OVPwdLpijFPqAFiGAz6ekgsamkwsDUEvK4FDchuewVKUsbzU2YXvkFxywp6mJKm2DiBshA2YQbA3hnYuuaiKXCPpJDxz64goAxERuYOAMb3Dn4GhSwoTUC3CcrTnirT1rjCS0Y8Q7lm3PwzaTyzclAEWko4+lQMSjnAgfq7wuBWnZgwUfA8qMI97tOdwwozYHzbk9LpKoWJkP0NRMvgcIAK+AD+PZb9pqRKHUjoyW2Txb5aIPOlt6m4g3BO3kC4qHPm9dE/VxWT8X3ypgZyFcK1pEClHI8L+SXwDrVxI3juuTQp5bLaR1UnLr7U6jZ8++2U3LiWLXb+GYaujPZMo/GlwbcKqTjeAk9fpR5OL9Ngx2fgcoPhqEPp+O21jGMxndM81fMCUtP9v+p+J/bpf/9fAK22f+/qB+n5P+T+pP9719m/99n858M/kzmH/TY/BdHgH7USXJDbGfmEOD5mdAxnp+Tz0HvXky0cb+0T0DR3fD7+4aXeUySg89r/1Gv10/S679+8hT/4T/h/P8fefyPo5HnwCp8mQM1DgKfgF/qt341xtpk3NX0ZvmhPdY62mDSbfWMd61et0MDGxhSmYZ6UluXyI/fjI7Wa/0mqRjyK+eUbajHAkZWUbEJSkZ98WJNsxkjA/sGG/VCncW1M8P76SdYQUnZUSQ5lh/+wdLUhxA3yz/LrQjdSF7VJyUIV4I0QPnZkyLksylC5HusEOL8myxuI0AKSMcJsRmmVlHMMmi2/2aZXcPwOJA30GuWD9lF38gHyuHPPzbp0wY4qjwrK+BHoJRTIPjKYZUJbZEv1eqlUl0rCYWDQ7PJQ+sGxPsyC7Pr4BUw56bjIQyiFKZgGZKJyWcirVGXZ3KdjnuKvMhDiMOVYflLDzeZ3iOTNZUf67i/Ekv625OIjhLmApRzOVW6nB9nGE2/ugPKNw/XGAeGxXySUu/fAKVlWTDADWAGgetYlISrZOafg2fVZ7kVeEYPkxnuvYZmSE6xdNAz5VXLtGCIgVIwijQrbrvF44YmKytF/Dsx9Osqj3j9M1f7NMsPucO2RoJN0rFfhq7BJuDnUlIrUyaPgTqH4LhWE7oY/tDF4LS2yfzmkM5+sywRwREIoQWdW2jzkM5vJpMRzaG/RJQG2A1sRHYN1piSA12ElYzzpdBhl8nZQayVZPWrEJo3svokt8vwd1Dbv3eUfkOIAt9DkHXIQQzkc/YS3jsY2kxtRx6THorxz+smBU/OTb5nQbDwQ6oInUMMTPbLhth0XGgDGIZ+GDUea/yk3n3FcFDT62ufNfaoxfKYBfPJi+bPWTg5BCG5mBVM8c/JqZWJTjba9S0IqcMX9pl8JIKn7mSKVtpn+TnefgtQTgUesfTy4SGQ4YPvQB0cHaUWlFyArKuyJPduWGCx2l/sntJalw6TQncoN2NiDBcBRsqfOcwsElw5RxCPNbLS3s9TYrZjzBOm1Sz1elZly3juPvpcHpBOYoSpSwpCmY4nSR9ZTW/Cpmbz+KezxMcXHHHX/iheiPIKbqjrok5tryxujqilO7pxmLpJbBNpKcdkNvWfhHqCh+yNe6L2n4n8huNsIcqFdf4cRJnHdrmw1SI0PR/kHcDBzF967L6sECSl8HyGIpH8VtwT956U/e9y4UkLbrrpfOySS4v4EZysuJSBF5XdNBGbLkeSGoPkpUwxF1RA8bsn26r/Kv2vKoKyiqRfUE08/wRn4C32X/UX9Uz8p+9fPMV/+wviv3QHE2183mprTaVcT3itRW/yXNYGPohC+YIg9G8dG9qRy1phoA87G+hjczPdNohLpCyLK0DnO1ol0+Bg2jfao6neLB96RISMQp2IFwo9J58m2uxo561pb2KMfzVeT8/PtbGhd/9Pax7XTn+ITWILCtVrx6e05fZ0PNYG5H2zfAjxNfZ9F6jz5IBKkQQi6/DWKVB4Hi5wbYb2nRlCsnGTAUVRbBHlX+NfG+SXeXcDDh6C0PEwKB+vD45KoosxBiyUC0Etb3BFY+NfwdVyNoMhQM4f7AgcgwCHZLwJiCNJgkimCZz5oTRLmbkY/8qGqJw/dMKpswMxtMhRLJoj0B5NET2JCzwdRFF5HiFAkJEIhJ7iwvtmmbeplKIZuEjOQHgPlKhUHHz5nJ3OyVEDYkDBB2ZoLiCGIcp09L/2/n9JqI/GyajY1ZcvU3yfvvhk1rgx/t9ZTv6XJ/vfL/LRp6/13/SJ1m82FQ9i5TloUS/rZlMxbVt5DrTBu4duxxhoE2PQ6muG3htO1s2mAr3RM+U5GE8H38mZlnYQI8A3N0ppQ7vWtenN4Z/X9JPQl1r/BamjP1sbW/K/Z7/XT0+Oj5/W/19m/4EgXgaqRe/vVQTN0LpWbX9hOt5jzD+Y/L8h/0f9NGP/cVx7iv/619h/3JeQvwwtSFVnuma80XojbaxTNd2oNXmzVlIFOl19Mh7mleOiHAC2hzgZgfJDe6pPhn1D11rj9hujM+y3ugPK39dEkMUQAtUE+6QJYWaLFnZprBozxOC4Bl6Aeg1wAI43p8afxswPDTPAhutbN6hElc7Wguay4AFnSaUXoH5cA2aA1TkZjxVLW+q6IISmu7ABQoj9oxJREgFkLq5M6vLne+xH8lGwwte+d1z5nj92nSsEAtO6MefwxsGSG18OjiIJSHLQxlqr1zdGLV3/ZTju0HGjyIF/+44H1CnIrzDVtfH6H+XDfKCZmQhB1VT/qIJqS/2/6hF4ZL2n7fY/fv935h615qQWkNbCRp8r8Ntu+p/ayVk6/+vJ9y+e9v8vyf/RdZyhlErUV45XIgfcK8cDjgfMG8LBrYyprCourBwVrZDrz1XqDgNDImy7/jz0sYkh+YGhCwM/xDa3HXkPVBg1VS0/XDnemt2YEUHE8ZYwKrREYZXapCSLfvwoF3U9oKKCslEzJXqx97Tqnz5Pn6fP0+d//uf/BQAA//9/np9nACoDAA==","verification":{}},"mode":384}]},"systemd":{"units":[{"contents":"[Unit]\nDescription=Ignition Early Boot Commands\nDefaultDependencies=no\nAfter=local-fs.target\nBefore=sysinit.target\nConditionPathExists=/etc/ignition-bootcmds.sh\n\n[Service]\nType=oneshot\nExecStart=-/etc/ignition-bootcmds.sh\n\n[Install]\nWantedBy=sysinit.target\n","enabled":true,"name":"ignition-bootcmds.service"},{"contents":"[Unit]\nDescription=Extract Ignition file payload\nDefaultDependencies=no\nAfter=local-fs.target\nBefore=sysinit.target ignition-bootcmds.service\nConditionPathExists=/var/lib/ignition/ignition-files.tar\n\n[Service]\nType=oneshot\nExecStart=tar -xvf /var/lib/ignition/ignition-files.tar -C /\nExecStart=rm -f /var/lib/ignition/ignition-files.tar\nExecStart=systemctl daemon-reload\nRemainAfterExit=yes\n\n[Install]\nWantedBy=sysinit.target\n","enabled":true,"name":"ignition-file-extract.service"}]}} \ No newline at end of file +{"ignition":{"config":{"replace":{"verification":{}}},"proxy":{},"security":{"tls":{}},"timeouts":{},"version":"3.4.0"},"kernelArguments":{},"passwd":{},"storage":{"files":[{"group":{},"overwrite":true,"path":"/var/lib/ignition/ignition-files.tar","user":{},"contents":{"compression":"gzip","source":"data:;base64,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","verification":{}},"mode":384}]},"systemd":{"units":[{"contents":"[Unit]\nDescription=Ignition Early Boot Commands\nDefaultDependencies=no\nAfter=local-fs.target\nBefore=sysinit.target\nConditionPathExists=/etc/ignition-bootcmds.sh\n\n[Service]\nType=oneshot\nExecStart=-/etc/ignition-bootcmds.sh\n\n[Install]\nWantedBy=sysinit.target\n","enabled":true,"name":"ignition-bootcmds.service"},{"contents":"[Unit]\nDescription=Extract Ignition file payload\nDefaultDependencies=no\nAfter=local-fs.target\nBefore=sysinit.target ignition-bootcmds.service\nConditionPathExists=/var/lib/ignition/ignition-files.tar\n\n[Service]\nType=oneshot\nExecStart=tar -xvf /var/lib/ignition/ignition-files.tar -C /\nExecStart=rm -f /var/lib/ignition/ignition-files.tar\nExecStart=systemctl daemon-reload\nRemainAfterExit=yes\n\n[Install]\nWantedBy=sysinit.target\n","enabled":true,"name":"ignition-file-extract.service"}]}} \ No newline at end of file diff --git a/pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData.inner b/pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData.inner index cbf397734b0..d105956b0fc 100644 --- a/pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData.inner +++ b/pkg/agent/testdata/Flatcar+CustomCloud+USSec/CustomData.inner @@ -100,7 +100,7 @@ { "contents": { "compression": "gzip", - "source": "data:;base64,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" + "source": "data:;base64,H4sIAAAAAAAC/8Q673PbNrLf+VdsaV4t+UJRcjudVzVKzrWV9zyT2h45uX6wfRqYXEk4kwADgLJVR//7GwD8Lcpx73XmJR8sAfsbu4vdhQ6+C+4pC+6JXDkSFfhPTvIQUQF+CoHgXAUnf2QCT09OUSi6oCFRKB3n/Hr+4ePJp9OT2WSov3z+9fPFp8+ToUMXcHMD/gICVGHApS8wRiIR7u5+AbVC5gAADNrbZtXiehcnv01hMoEj9/N9xlTmHjWR9b+K5cisYZwjn59Z1EVMVEjEHtxC9gI5F8B8CVcc3M/sgfFHBh8py54golIJep8pyplbQT5RBZbCgjolkYKAzNKUC4UR8BQFUZQtQW6kwsSSyNEX1HEsSp0LUAlek60FmmWMaUqcWUO5juM4v5/PptfT2T+ns/n04uzq8vzi08RdKZWOg2D0038NfvphMDr+eTD6yXWchDzgXOCXDKWaP1K1mgtUYtPrw7MRK+YhiSET8cT1Rm5tKSFPBpSinIyGtQ2DP48wJpvJD7V1ohQmqZqMnAawTDnLTfW4ojHCDXg5KPgxgldjBHe/QMRLixfIE68XZiLWbub7jPup4EuBUvoJKhTgepmI3X6JVnC2OktFVCYn3nunBKCL/NS8goMLX2EpMAX/C7gzizkjCj/ShKrpU4gYYeS2HEv/kzFiCl7NJo3tuq28Xq/2FY7guN9vABcG9Hq9wkB/h1ENyHq95lZXDXyGMIS7Py/dKxjWIqVy9spsbWUzwWBYLi6o+Rhxhk4tVvBpRTKpI4XE1p0oyjcQE6nKIx9Di0lOfORsHScVPEQp5yEKNc+jjTPZ8mlkUcopU3O1SbHt3SXWvPTQmoQzI9NaB15Y5cEKScKCC9B0x+A1+Fgeu9QnXm9PJILrPXcE9DZISLiiDN+HPEknJExkSsIHssTvjT5Ntt/jk5r8W3KWh8G+ECjSLvh/gOvtiunCHXz9+mofs9b6nQido8ZwwcvzA4Eh0rXOhqKQAxaExhhp243hL1XaabpgkaNrpjCusqAxMpKgNBsJSfUC+Kq1C2/hbS/39C4TFamCX8Fh7/3biTtDybMQP9AYL0iC7hjc/s2/3Lujw75Tmdx7PmjyufnH3RZ8/LLXsBe84X6VgAuesQgoq8yt/bHLE/cYRYM3hNHEXO95V0C3kZGtXFc2/trhofHG4DVouE4rLRcbkza3vw2Otm4LGJ8UMkk524E+ODgabGvErWBn/JHFnEQtycYVV6/49KZG3Cs/7ohrmIacKWSq3Kov/vWBXUho3Lsm2rcvuNr9lkd4XdI/Gdv/L/G9T/eGVFofyjKs3zMt3dmu7nvVawG+A3dvIRy0nXuX2nUW6thYZHG8AUm0hRqeuI/Cnqu2tP0Ha1vF8wtzjY3Yy8W3eWAPi/p1vHWc8w/X83sSPmTpxDv/cK2/T7zDW3HLDh3H4ak6Z6eZiK+tew3zlRWGD2U9Jq/B9/WpQ2f5GegDDqi8TBVG5+wDFzPOlTaodOH4XRDhOmBZHPe1X7YZeu9Nc2FycGPH7XDYlrEWpbG+ZCg2oM/TmEtz8SmD3POtGqYyD3mE0GbV/wUiXJAsNtW84sA483MSi5g/Frd9aRjXNQV+VWBWe9W9Mf0Ch+55p1VubsY6InB8d3c0rn9RIsPDHYUNCZ269bGXSso3YCokNHlQJyQ4PbHqp1kcAzF3h1Qkjq0Ce+opcMvPeYRLzSPPka9HokyhSDCiROXeaKWX9VDRklldKj3cdpd1wc0JdussH2iaao1fVtZAFx7c7bYvJ6mQ1AJPtisvvaeLADnpebaIMOEod6oGDXTrjuFW1wq3plioKPzKI/ptEqcWctNJRsvlDkKh3KoEcb2qGXZN6THaLT0MXlq0rXnS0Mam2ure83eVgLpA2K0P7FWdQ3j0bgvwFSRGcCiD21txe8uCWxYsD+urgf7+curt1YgbC1valogrg0GIIhh4z/iktsHS7btVtvumz+VRXridjmGTDqsc6RTZ6Lky4dbtKN/CFwYpwZE+EAgyKQJziQdyRQQGIfHrPhXYCMvSiCj0W5tOyQVVGEgZB0boNo0aI3pfgulzrYKqqAK1Bb4hc+OUI5RK4xVV2cHBUVCr3erbxWdd3VVOlWtgr163rYnrFVitI9xjEH1aJFSmknsejX3KqNoWx2U3XJiAGxJf4EKgXDXLAZ3/DZFFxkI7jWFUzTMzjZonhOriP+XzCFOuGi2mXjar86L0rvrMaqymtSOpCh5wIyhbynqnecrTjc5ZVrUI7jMWxaivmssU2fX1R9BWM/XrYDBw/89nX5tYNTmGPKUYDfLkviu8jYKg1kEuwC13Jc9EiHIQU9lRayVr6ITspl7LODmwqWWMk3ZRGUTBUcM9S/G8On53CZisd8A6heocZ3SPNUmqrg1B3Q9O3H0yW/ca5Ku53UOi4O3b6eUHeAevQ3ScT5sU5RgivHc+z86lLr13/XKboznXGVVogP45nV2fX17MTy/Pphcnv023XWu+dUzZuacNlHJ9M3XtSgwzQdXGOeVJyhkyJcegowkyRtcoTBMhlaChdsNEF1lm1bmmS4aR/+tmbJ3Y5sgienJFfCLCFV2jn68PlunSmV5+yFOngfks4smLxqjHIVvrCGJL+Dz7KM1N1zhIHZIzTPmZSQIapoxHff/4FFz5RlcT8vb9OAgGN/+Cu6M3XinIm6XboljjTlKV+7rlHlppMHoDEhEYPpoMAPcY88dxvYaqf/b1P7f0o73canAFkW0t+YW6Wp3r6qg9IfZGdYtpMJO6RDwGM4LNfTgT8Vzn1LmuqateAXx/hSQC3y/6xf+efjKI/fpzwPuivDfdatGiNWjWSmlwfxz+CLou/MAzFun2rWwrOmcq09nscmblBSqBcQVkTWhM7mMcwJV9vEgIy4iuEIwttGRqhZCjrElMI7jHBRfag32Rj+hlKGiq9r0X1C38KKjCueLzRn6rW7vY0CE/j8x+Yf06wDwTdOIdWy9c0YWC4xrMA27mKVErOem53j/cfBZV52m296co77lDjm2VsqpIO6NSTbxeLO/nxQOQH8JXII8PcPicCsoUeMfbYh6mEMEn4O3IYpNfV06rFK5SWMV7J8c4JyJcjYEk0U8/1hOK91xa5ebobmsyRv1oSBTNNYQl3TgTvWxnSPkLh4EzDyedOeYBNzKw/DRaXiBV0eXl+LWYOolMy+YVOJqFTjxFjisyjt6PiCITr/e4RAX+JfglvX4JYk7X60Uo6BrnpeIV/X6Nt1cQNdGVLsH3IyQi4QK+mgPzCgL1GGsTKKUmUWQ78EL2ZpLZkanL0qXjdvp0vxpllpztFLPE3x1glvh/n/Tcncqsflz6QslZtx8wWk7k7nhQIrVmhVKNs/2NhoJLvlBgIFqHawuIpg8mBcaAyLATQPIUmcJwZSAawqRqiWpuL/GGOCRVvnYds1X3LbvNuEIdfymyKH9/XPFHnRg3RQaBFVnrKwlZcdgrKiEhG1DkAYFAyLM0Rkgoy3RRWjCgC2gwx/rbWzObv5TBWzSqkc+CMvuyVGSzIqubxK1hdTIvlDDjy4RrTUhUri4ET2DDs7IENXMEJTZAloSyQWeW73hXbgkZ8iSNUeF3bte1UO860iT8T5qOhqtpNfPJhRxUXhTyBOxLu59n0BlaqpULltBXFt/WERPX22UelLB5VRVUVINU8Ggn73UTty/EnTdjieBrevsIQEema8ROK1D6r+boK5SmNPxLOedtmI3hXmW0vjkLG1ODjmPdc6Q6nbhleigyUMeBaZ+rpkH2ZxVdwyBbz1yZO2RYRG7Ik0SHgr8GgSSKKXuAapALx+++H7WCtkbG9XolkunPho0xsK73TKmwgMO/yUOz33cb71Z0Ad9BKDhT5B78uIldZZFb16vY3rpQ6/xb0hmCvT0Uf6mJc8sOwR3C6Gc4Mv9fYNGHr5WMe58dqoF+Pp6skTDo8G9+D2tKClouvPv+uN2MFoYJY55FZvJRzLZ9/5FQ+2YlOFdl7zKtkkbxyPk8m15dzs+mV5efqqcatzaeKyI7OOzXq74Zxu2ir/z9T1ft95/Ui+aQXhjHeM+d2m13EFsZ9UW85m9vmkncLZr86mJ18h9mfGu8ah0mL7p3YyG3rVyHeUlufz4U5X8D8kcmzPQr95KBRLGmYS6RSsQr0RRNUNQGDu9cT65DN6+9bz4zqu6cM7TSUs4ms9wrzXQQTjOpeAKn2uOKWXs5iztZKBQThuqRiwefs5gyHCgilqic3wlTcs+ec3Ntlbkztf+EM5QrrpzpE4bXigg18WrWq4VK1fPnqqhEvKDKGaHxBoow44vX6OTcfNIWu3Mu2SmJkUVETEY/j4dD5wqFpNI8AyuRoTMjLOIJ/QOjM4zJ5hrDyQ/DoePcnNsQvzM2wOjXzcQcgizUL5WwZxaqGCKCCWc6njiJWnvIdLtqfgz1CN3nawaa4UpwtpmHnC1y37Ar+Z+B3nBfdxmUvKXiaf418jUruWFhW8CISiPhLlw1QPwOfNStfSXj7oiuGXo7y2XmNDTA31S/zntVQIpEx573XJNhaw2nfQnqshWd6YFzkHIeA1PpIJ/E6du3uE7uMyEVJOSpqBt/zOGHBbT+NtDYXCw74Ec5/OhPwh+/Ev7YcR5wY4qcDofQNYPjRIIulAVZEztEboIZAMc5iPkSlCB2DpQgkZnARDfh5hKiUtFQOk7MlxEVOS2+zIk4TkKe8uniAz7CaDgcDB1HqFA7iuMIXIQxDx/g6n9Obb+ZqnQIKY9j+AEi89c/Br5YSFQwND90lApTGA2G4I9sSP051xYodarJ3enVWX0PfmQ86UDL8b8BAAD//69FBJV2KwAA" }, "mode": 484, "overwrite": true,