From 59872467aeaaa42f53e1ebe553db23222a9db8e6 Mon Sep 17 00:00:00 2001 From: "Zhidong Peng (HE/HIM)" Date: Thu, 8 Jan 2026 13:02:06 -0800 Subject: [PATCH 1/7] E2E Daily Test Updates --- .../GuestProxyAgentTest.csproj | 4 +- .../LinuxScripts/GuestProxyAgentValidation.sh | 40 ++++++++++++++- .../GuestProxyAgentExtensionValidation.ps1 | 2 +- .../Scripts/GuestProxyAgentValidation.ps1 | 50 +++++++++++++++++-- .../TestCases/EnableProxyAgentCase.cs | 28 ++++++++--- .../GuestProxyAgentValidationCase.cs | 8 +++ .../TestMap/AzureLinux3-Arm64-TestGroup.yml | 4 +- .../TestMap/AzureLinux3-Fips-TestGroup.yml | 4 +- .../TestMap/Test-Map-Linux.yml | 1 - .../TestMap/Ubuntu24-Arm64-TestGroup.yml | 4 +- .../TestMap/Ubuntu24-TestGroup.yml | 4 +- .../TestScenarios/BVTScenario.cs | 1 + .../TestScenarios/LinuxImplicitExtension.cs | 31 ++++++++++++ .../TestScenarios/LinuxPackageScenario.cs | 1 + .../TestScenarios/ProxyAgentExtension.cs | 2 - .../Utilities/VMBuilder.cs | 6 +++ 16 files changed, 170 insertions(+), 20 deletions(-) create mode 100644 e2etest/GuestProxyAgentTest/TestScenarios/LinuxImplicitExtension.cs diff --git a/e2etest/GuestProxyAgentTest/GuestProxyAgentTest.csproj b/e2etest/GuestProxyAgentTest/GuestProxyAgentTest.csproj index 1e27c879..6bb6fd98 100644 --- a/e2etest/GuestProxyAgentTest/GuestProxyAgentTest.csproj +++ b/e2etest/GuestProxyAgentTest/GuestProxyAgentTest.csproj @@ -13,8 +13,8 @@ - - + + diff --git a/e2etest/GuestProxyAgentTest/LinuxScripts/GuestProxyAgentValidation.sh b/e2etest/GuestProxyAgentTest/LinuxScripts/GuestProxyAgentValidation.sh index 4b5d05fa..8713162c 100755 --- a/e2etest/GuestProxyAgentTest/LinuxScripts/GuestProxyAgentValidation.sh +++ b/e2etest/GuestProxyAgentTest/LinuxScripts/GuestProxyAgentValidation.sh @@ -4,8 +4,11 @@ # SPDX-License-Identifier: MIT customOutputJsonUrl=$(echo $customOutputJsonSAS | base64 -d) +expectedSecureChannelState=$(echo $expectedSecureChannelState) echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - Start Guest Proxy Agent Validation" +echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - expectedSecureChannelState=$expectedSecureChannelState" + currentDir=$(pwd) customOutputJsonPath=$currentDir/proxyagentvalidation.json @@ -47,12 +50,47 @@ else echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - logdir does not exist" fi +# check status.json file Content +## check timestamp of last entry in status.json file +## check the secure channel status +timeout=300 +elapsed=0 +statusFile=$logdir/status.json +secureChannelState="" + +# Current UTC time in epoch seconds +currentUtcTime=$(date -u +%s) +echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - Checking GPA status file $statusFile with 5 minute timeout" +while :; do + timestamp=$(cat "$statusFile" | jq -r '.timestamp') + # Convert timestamp to epoch seconds + timestampEpoch=$(date -u -d "$timestamp" +%s) + if ((timestampEpoch > currentUtcTime)); then + echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - The last entry timestamp '$timestamp' is valid." + ## check secure channel status + secureChannelState=$(cat "$statusFile" | jq -r '.proxyAgentStatus.keyLatchStatus.states.secureChannelState') + if [[ "$secureChannelState" == "$expectedSecureChannelState" ]]; then + echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - The secure channel status '$secureChannelState' matches the expected state: '$expectedSecureChannelState'." + break + else + echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - The secure channel status '$secureChannelState' does not match the expected state: '$expectedSecureChannelState'." + fi + fi + ((elapsed += 3)) + if [[ $elapsed -ge $timeout ]]; then + echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - Timeout reached. Error, The secureChannelState is '$secureChannelState'." + break + fi + sleep 3 +done + echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - guestProxyAgentServiceExist=$guestProxyAgentServiceExist" echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - guestProxyAgentServiceStatus=$guestProxyAgentServiceStatus" echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - guestProxyProcessStarted=$guestProxyProcessStarted" echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - guestProxyAgentLogGenerated=$guestProxyAgentLogGenerated" +echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - secureChannelState=$secureChannelState" -jsonString='{"guestProxyAgentServiceInstalled": "'$guestProxyAgentServiceExist'", "guestProxyAgentServiceStatus": "'$guestProxyAgentServiceStatus'", "guestProxyProcessStarted": "'$guestProxyProcessStarted'", "guestProxyAgentLogGenerated": "'$guestProxyAgentLogGenerated'"}' +jsonString='{"guestProxyAgentServiceInstalled": "'$guestProxyAgentServiceExist'", "guestProxyAgentServiceStatus": "'$guestProxyAgentServiceStatus'", "guestProxyProcessStarted": "'$guestProxyProcessStarted'", "secureChannelState": "'$secureChannelState'", "guestProxyAgentLogGenerated": "'$guestProxyAgentLogGenerated'"}' echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - $jsonString" # write to $customOutputJsonPath diff --git a/e2etest/GuestProxyAgentTest/Scripts/GuestProxyAgentExtensionValidation.ps1 b/e2etest/GuestProxyAgentTest/Scripts/GuestProxyAgentExtensionValidation.ps1 index e3f7c474..e2362587 100644 --- a/e2etest/GuestProxyAgentTest/Scripts/GuestProxyAgentExtensionValidation.ps1 +++ b/e2etest/GuestProxyAgentTest/Scripts/GuestProxyAgentExtensionValidation.ps1 @@ -3,7 +3,7 @@ param ( [Parameter(Mandatory=$true, Position=0)] - [string]$customOutputJsonSAS, + [string]$customOutputJsonSAS, [string]$expectedProxyAgentVersion ) Write-Output "$((Get-Date).ToUniversalTime()) - expectedProxyAgentVersion=$expectedProxyAgentVersion" diff --git a/e2etest/GuestProxyAgentTest/Scripts/GuestProxyAgentValidation.ps1 b/e2etest/GuestProxyAgentTest/Scripts/GuestProxyAgentValidation.ps1 index a8037d01..edf23e99 100644 --- a/e2etest/GuestProxyAgentTest/Scripts/GuestProxyAgentValidation.ps1 +++ b/e2etest/GuestProxyAgentTest/Scripts/GuestProxyAgentValidation.ps1 @@ -3,13 +3,15 @@ param ( [Parameter(Mandatory=$true, Position=0)] - [string]$customOutputJsonSAS + [string]$customOutputJsonSAS, + [string]$expectedSecureChannelState ) $decodedUrlBytes = [System.Convert]::FromBase64String($customOutputJsonSAS) $decodedUrlString = [System.Text.Encoding]::UTF8.GetString($decodedUrlBytes) Write-Output "$((Get-Date).ToUniversalTime()) - Start Guest Proxy Agent Validation" +Write-Output "$((Get-Date).ToUniversalTime()) - expectedSecureChannelState=$expectedSecureChannelState" $currentFolder = $PWD.Path $customOutputJsonPath = $currentFolder + "\proxyagentvalidation.json"; @@ -21,7 +23,7 @@ $guestProxyAgentServiceExist = $true $guestProxyAgentServiceStatus = "" $guestProxyAgentProcessExist = $true -if ($service -ne $null) { +if ($null -ne $service) { Write-Output "$((Get-Date).ToUniversalTime()) - The service $serviceName exists." $guestProxyAgentServiceStatus = $service.Status } else { @@ -34,7 +36,7 @@ $processName = "GuestProxyAgent" $process = Get-Process -Name $processName -ErrorAction SilentlyContinue -if ($process -ne $null) { +if ($null -ne $process) { Write-Output "$((Get-Date).ToUniversalTime()) - The process $processName exists." } else { $guestProxyAgentProcessExist = $false @@ -57,10 +59,52 @@ if (Test-Path -Path $folderPath -PathType Container) { Write-Output "$((Get-Date).ToUniversalTime()) - The folder $folderPath does not exist." } +# check status.json file Content +## check timestamp of last entry in status.json file +## check the secure channel status +$timeoutInSeconds = 300 +$statusFilePath = [IO.Path]::Combine($folderPath, "status.json") +Write-Output "$((Get-Date).ToUniversalTime()) - Checking GPA status file $statusFilePath with 5 minute timeout" +$secureChannelState = "" +$stopwatch = [System.Diagnostics.Stopwatch]::StartNew() +$currentUtcTime = (Get-Date).ToUniversalTime() +do { + $boolStatus = Test-Path -Path $statusFilePath + if ($boolStatus) { + $json = Get-Content $statusFilePath | Out-String | ConvertFrom-Json + $timestamp = $json.timestamp + if ($null -ne $timestamp -and $timestamp -ne "") { + Write-Output "$((Get-Date).ToUniversalTime()) - The status.json file contains a valid timestamp: $timestamp" + # parse the timestamp to UTC DateTime object, if must later than $currentUtcTime + $timestampDateTime = [DateTime]::Parse($timestamp).ToUniversalTime() + if ($timestampDateTime -gt $currentUtcTime) { + Write-Output "$((Get-Date).ToUniversalTime()) - The status.json timestamp $timestampDateTime is later than $currentUtcTime." + ## check secure channel status + $secureChannelState = $json.proxyAgentStatus.keyLatchStatus.states.secureChannelState + Write-Output "$((Get-Date).ToUniversalTime()) - The secure channel status is $secureChannelState." + if ($secureChannelState -eq $expectedSecureChannelState) { + Write-Output "$((Get-Date).ToUniversalTime()) - The secure channel status '$secureChannelState' matches the expected state: '$expectedSecureChannelState'." + # break + } else { + Write-Output "$((Get-Date).ToUniversalTime()) - The secure channel status '$secureChannelState' does not match the expected state: '$expectedSecureChannelState'." + } + + if ($stopwatch.Elapsed.TotalSeconds -ge $timeoutInSeconds) { + Write-Output "$((Get-Date).ToUniversalTime()) - Timeout reached. Error, The secureChannelState is '$secureChannelState'." + break + } + } + } else { + Write-Output "$((Get-Date).ToUniversalTime()) - The status.json file does not contain a valid timestamp yet." + } + } + start-sleep -Seconds 3 +} until ($false) $jsonString = '{"guestProxyAgentServiceInstalled": ' + $guestProxyAgentServiceExist.ToString().ToLower() ` + ', "guestProxyProcessStarted": ' + $guestProxyAgentProcessExist.ToString().ToLower() ` + ', "guestProxyAgentServiceStatus": "' + $guestProxyAgentServiceStatus ` + + ', "secureChannelState": "' + $secureChannelState ` + '", "guestProxyAgentLogGenerated": ' + $guestProxyAgentLogGenerated.ToString().ToLower() + '}' Write-Output "$((Get-Date).ToUniversalTime()) - $jsonString" diff --git a/e2etest/GuestProxyAgentTest/TestCases/EnableProxyAgentCase.cs b/e2etest/GuestProxyAgentTest/TestCases/EnableProxyAgentCase.cs index 87fb512e..de1479bc 100644 --- a/e2etest/GuestProxyAgentTest/TestCases/EnableProxyAgentCase.cs +++ b/e2etest/GuestProxyAgentTest/TestCases/EnableProxyAgentCase.cs @@ -1,25 +1,33 @@ -using Azure.ResourceManager.Compute.Models; +// Copyright (c) Microsoft Corporation +// SPDX-License-Identifier: MIT +// +using Azure.ResourceManager.Compute.Models; using GuestProxyAgentTest.Models; using GuestProxyAgentTest.Settings; using GuestProxyAgentTest.TestScenarios; +using GuestProxyAgentTest.Utilities; using Newtonsoft.Json; +using System.Xml.Linq; namespace GuestProxyAgentTest.TestCases { internal class EnableProxyAgentCase : TestCaseBase { - public EnableProxyAgentCase() : this("EnableProxyAgentCase", true) + public EnableProxyAgentCase() : this("EnableProxyAgentCase", true, false) { } - public EnableProxyAgentCase(string testCaseName) : this(testCaseName, true) + public EnableProxyAgentCase(string testCaseName) : this(testCaseName, true, false) { } - public EnableProxyAgentCase(string testCaseName, bool enableProxyAgent) : base(testCaseName) + public EnableProxyAgentCase(string testCaseName, bool enableProxyAgent, bool addProxyAgentExtensionForLinuxVM) : base(testCaseName) { EnableProxyAgent = enableProxyAgent; + AddProxyAgentVMExtension = addProxyAgentExtensionForLinuxVM; } internal bool EnableProxyAgent { get; set; } + internal bool AddProxyAgentVMExtension { get; set; } = false; + public override async Task StartAsync(TestCaseExecutionContext context) { var vmr = context.VirtualMachineResource; @@ -34,16 +42,24 @@ public override async Task StartAsync(TestCaseExecutionContext context) } } }; + // Only Linux VMs support flag 'AddProxyAgentExtension', + // Windows VMs always have the GPA VM Extension installed when ProxyAgentSettings.Enabled is true. + if (!Constants.IS_WINDOWS()) + { + patch.SecurityProfile.ProxyAgentSettings.AddProxyAgentExtension = AddProxyAgentVMExtension; + } if (EnableProxyAgent) { patch.SecurityProfile.ProxyAgentSettings.WireServer = new HostEndpointSettings { - InVmAccessControlProfileReferenceId = TestSetting.Instance.InVmWireServerAccessControlProfileReferenceId + InVmAccessControlProfileReferenceId = TestSetting.Instance.InVmWireServerAccessControlProfileReferenceId, + Mode = HostEndpointSettingsMode.Enforce }; patch.SecurityProfile.ProxyAgentSettings.Imds = new HostEndpointSettings { - InVmAccessControlProfileReferenceId = TestSetting.Instance.InVmIMDSAccessControlProfileReferenceId + InVmAccessControlProfileReferenceId = TestSetting.Instance.InVmIMDSAccessControlProfileReferenceId, + Mode = HostEndpointSettingsMode.Audit }; } diff --git a/e2etest/GuestProxyAgentTest/TestCases/GuestProxyAgentValidationCase.cs b/e2etest/GuestProxyAgentTest/TestCases/GuestProxyAgentValidationCase.cs index 40e02aac..fd204809 100644 --- a/e2etest/GuestProxyAgentTest/TestCases/GuestProxyAgentValidationCase.cs +++ b/e2etest/GuestProxyAgentTest/TestCases/GuestProxyAgentValidationCase.cs @@ -14,6 +14,7 @@ public class GuestProxyAgentValidationCase : TestCaseBase { private static readonly string EXPECTED_GUEST_PROXY_AGENT_SERVICE_STATUS; + private string expectedSecureChannelState = "disabled"; static GuestProxyAgentValidationCase() { if (Constants.IS_WINDOWS()) @@ -28,8 +29,15 @@ static GuestProxyAgentValidationCase() public GuestProxyAgentValidationCase() : base("GuestProxyAgentValidationCase") { } + public GuestProxyAgentValidationCase(string testCaseName, string expectedSecureChannelState) : base(testCaseName) + { + this.expectedSecureChannelState = expectedSecureChannelState; + } + public override async Task StartAsync(TestCaseExecutionContext context) { + List<(string, string)> parameterList = new List<(string, string)>(); + parameterList.Add(("expectedSecureChannelState", expectedSecureChannelState)); context.TestResultDetails = (await RunScriptViaRunCommandV2Async(context, Constants.GUEST_PROXY_AGENT_VALIDATION_SCRIPT_NAME, null!)).ToTestResultDetails(ConsoleLog); if (context.TestResultDetails.Succeed && context.TestResultDetails.CustomOut != null) { diff --git a/e2etest/GuestProxyAgentTest/TestMap/AzureLinux3-Arm64-TestGroup.yml b/e2etest/GuestProxyAgentTest/TestMap/AzureLinux3-Arm64-TestGroup.yml index d5dfdccb..c68fd4df 100644 --- a/e2etest/GuestProxyAgentTest/TestMap/AzureLinux3-Arm64-TestGroup.yml +++ b/e2etest/GuestProxyAgentTest/TestMap/AzureLinux3-Arm64-TestGroup.yml @@ -9,4 +9,6 @@ scenarios: - name: LinuxPackageScenario className: GuestProxyAgentTest.TestScenarios.LinuxPackageScenario - name: ProxyAgentExtension - className: GuestProxyAgentTest.TestScenarios.ProxyAgentExtension \ No newline at end of file + className: GuestProxyAgentTest.TestScenarios.ProxyAgentExtension + - name: LinuxImplicitExtension + className: GuestProxyAgentTest.TestScenarios.LinuxImplicitExtension \ No newline at end of file diff --git a/e2etest/GuestProxyAgentTest/TestMap/AzureLinux3-Fips-TestGroup.yml b/e2etest/GuestProxyAgentTest/TestMap/AzureLinux3-Fips-TestGroup.yml index ad34139f..68dfb487 100644 --- a/e2etest/GuestProxyAgentTest/TestMap/AzureLinux3-Fips-TestGroup.yml +++ b/e2etest/GuestProxyAgentTest/TestMap/AzureLinux3-Fips-TestGroup.yml @@ -9,4 +9,6 @@ scenarios: - name: LinuxPackageScenario className: GuestProxyAgentTest.TestScenarios.LinuxPackageScenario - name: ProxyAgentExtension - className: GuestProxyAgentTest.TestScenarios.ProxyAgentExtension \ No newline at end of file + className: GuestProxyAgentTest.TestScenarios.ProxyAgentExtension + - name: LinuxImplicitExtension + className: GuestProxyAgentTest.TestScenarios.LinuxImplicitExtension \ No newline at end of file diff --git a/e2etest/GuestProxyAgentTest/TestMap/Test-Map-Linux.yml b/e2etest/GuestProxyAgentTest/TestMap/Test-Map-Linux.yml index 0a0d1e6b..3cd46b95 100644 --- a/e2etest/GuestProxyAgentTest/TestMap/Test-Map-Linux.yml +++ b/e2etest/GuestProxyAgentTest/TestMap/Test-Map-Linux.yml @@ -1,6 +1,5 @@ testGroupList: - include: AzureLinux3-Fips-TestGroup.yml - - include: Mariner2-Fips-TestGroup.yml - include: Ubuntu24-TestGroup.yml - include: Ubuntu22-TestGroup.yml - include: Ubuntu20-TestGroup.yml diff --git a/e2etest/GuestProxyAgentTest/TestMap/Ubuntu24-Arm64-TestGroup.yml b/e2etest/GuestProxyAgentTest/TestMap/Ubuntu24-Arm64-TestGroup.yml index e10e26b1..5664d9f6 100644 --- a/e2etest/GuestProxyAgentTest/TestMap/Ubuntu24-Arm64-TestGroup.yml +++ b/e2etest/GuestProxyAgentTest/TestMap/Ubuntu24-Arm64-TestGroup.yml @@ -9,4 +9,6 @@ scenarios: - name: LinuxPackageScenario className: GuestProxyAgentTest.TestScenarios.LinuxPackageScenario - name: ProxyAgentExtension - className: GuestProxyAgentTest.TestScenarios.ProxyAgentExtension \ No newline at end of file + className: GuestProxyAgentTest.TestScenarios.ProxyAgentExtension + - name: LinuxImplicitExtension + className: GuestProxyAgentTest.TestScenarios.LinuxImplicitExtension \ No newline at end of file diff --git a/e2etest/GuestProxyAgentTest/TestMap/Ubuntu24-TestGroup.yml b/e2etest/GuestProxyAgentTest/TestMap/Ubuntu24-TestGroup.yml index 24c28233..bda47658 100644 --- a/e2etest/GuestProxyAgentTest/TestMap/Ubuntu24-TestGroup.yml +++ b/e2etest/GuestProxyAgentTest/TestMap/Ubuntu24-TestGroup.yml @@ -9,4 +9,6 @@ scenarios: - name: LinuxPackageScenario className: GuestProxyAgentTest.TestScenarios.LinuxPackageScenario - name: ProxyAgentExtension - className: GuestProxyAgentTest.TestScenarios.ProxyAgentExtension \ No newline at end of file + className: GuestProxyAgentTest.TestScenarios.ProxyAgentExtension + - name: LinuxImplicitExtension + className: GuestProxyAgentTest.TestScenarios.LinuxImplicitExtension \ No newline at end of file diff --git a/e2etest/GuestProxyAgentTest/TestScenarios/BVTScenario.cs b/e2etest/GuestProxyAgentTest/TestScenarios/BVTScenario.cs index 4226d896..af421971 100644 --- a/e2etest/GuestProxyAgentTest/TestScenarios/BVTScenario.cs +++ b/e2etest/GuestProxyAgentTest/TestScenarios/BVTScenario.cs @@ -27,6 +27,7 @@ public override void TestScenarioSetup() // it will add GPA VM Extension and overwrite the private GPA package AddTestCase(new EnableProxyAgentCase()); secureChannelEnabled = true; + AddTestCase(new GuestProxyAgentValidationCase("GuestProxyAgentValidationWithSecureChannelEnabled", "WireServer Enforce - IMDS Audit - HostGA Enforce")); } AddTestCase(new IMDSPingTestCase("IMDSPingTestBeforeReboot", secureChannelEnabled)); diff --git a/e2etest/GuestProxyAgentTest/TestScenarios/LinuxImplicitExtension.cs b/e2etest/GuestProxyAgentTest/TestScenarios/LinuxImplicitExtension.cs new file mode 100644 index 00000000..c535c097 --- /dev/null +++ b/e2etest/GuestProxyAgentTest/TestScenarios/LinuxImplicitExtension.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation +// SPDX-License-Identifier: MIT +using GuestProxyAgentTest.TestCases; +using GuestProxyAgentTest.Utilities; + +namespace GuestProxyAgentTest.TestScenarios +{ + public class LinuxImplicitExtension : TestScenarioBase + { + public override void TestScenarioSetup() + { + if (Constants.IS_WINDOWS()) + { + throw new InvalidOperationException("LinuxImplicitExtension scenario can only run on Linux VMs."); + } + + // Passing in 0 version number for the first validation case + string proxyAgentVersionBeforeUpdate = "0"; + string proxyAgentVersion = Settings.TestSetting.Instance.proxyAgentVersion; + ConsoleLog(string.Format("Received ProxyAgent Version:{0}", proxyAgentVersion)); + // implicitly enable the Guest Proxy Agent extension by setting EnableProxyAgent to true and AddProxyAgentVMExtension to true + AddTestCase(new EnableProxyAgentCase("EnableProxyAgentCase", true, true)); + AddTestCase(new GuestProxyAgentExtensionValidationCase("GuestProxyAgentExtensionValidationCaseBeforeUpdate", proxyAgentVersionBeforeUpdate)); + AddTestCase(new InstallOrUpdateGuestProxyAgentExtensionCase()); + AddTestCase(new GuestProxyAgentExtensionValidationCase("GuestProxyAgentExtensionValidationCaseAfterUpdate", proxyAgentVersion)); + AddTestCase(new IMDSPingTestCase("IMDSPingTestBeforeReboot", true)); + AddTestCase(new RebootVMCase("RebootVMCaseAfterUpdateGuestProxyAgentExtension")); + AddTestCase(new IMDSPingTestCase("IMDSPingTestAfterReboot", true)); + } + } +} diff --git a/e2etest/GuestProxyAgentTest/TestScenarios/LinuxPackageScenario.cs b/e2etest/GuestProxyAgentTest/TestScenarios/LinuxPackageScenario.cs index 82661abe..1f67065b 100644 --- a/e2etest/GuestProxyAgentTest/TestScenarios/LinuxPackageScenario.cs +++ b/e2etest/GuestProxyAgentTest/TestScenarios/LinuxPackageScenario.cs @@ -13,6 +13,7 @@ public override void TestScenarioSetup() AddTestCase(new InstallOrUpdateGuestProxyAgentPackageCase()); AddTestCase(new GuestProxyAgentValidationCase()); AddTestCase(new EnableProxyAgentCase()); + AddTestCase(new GuestProxyAgentValidationCase("GuestProxyAgentValidationWithSecureChannelEnabled", "WireServer Enforce - IMDS Audit - HostGA Enforce")); AddTestCase(new IMDSPingTestCase("IMDSPingTestBeforeReboot", true)); AddTestCase(new RebootVMCase("RebootVMCaseAfterInstallOrUpdateGuestProxyAgent")); AddTestCase(new IMDSPingTestCase("IMDSPingTestAfterReboot", true)); diff --git a/e2etest/GuestProxyAgentTest/TestScenarios/ProxyAgentExtension.cs b/e2etest/GuestProxyAgentTest/TestScenarios/ProxyAgentExtension.cs index 5be330e7..7b5ae1c2 100644 --- a/e2etest/GuestProxyAgentTest/TestScenarios/ProxyAgentExtension.cs +++ b/e2etest/GuestProxyAgentTest/TestScenarios/ProxyAgentExtension.cs @@ -2,8 +2,6 @@ // SPDX-License-Identifier: MIT using GuestProxyAgentTest.TestCases; using GuestProxyAgentTest.Utilities; -using System.Diagnostics; -using System.IO.Compression; namespace GuestProxyAgentTest.TestScenarios { diff --git a/e2etest/GuestProxyAgentTest/Utilities/VMBuilder.cs b/e2etest/GuestProxyAgentTest/Utilities/VMBuilder.cs index 7dc8b460..f96d2518 100644 --- a/e2etest/GuestProxyAgentTest/Utilities/VMBuilder.cs +++ b/e2etest/GuestProxyAgentTest/Utilities/VMBuilder.cs @@ -140,6 +140,12 @@ private async Task DoCreateVMData(ResourceGroupResource rgr, }, } }; + if (!Constants.IS_WINDOWS()) + { + // Only Linux VMs support flag 'AddProxyAgentExtension', + // Windows VMs always have the GPA VM Extension installed when ProxyAgentSettings.Enabled is true. + vmData.SecurityProfile.ProxyAgentSettings.AddProxyAgentExtension = true; + } } if (Constants.IS_WINDOWS()) From 02c31054856059e6db53a909f4ddd0d13a50e5d7 Mon Sep 17 00:00:00 2001 From: "Zhidong Peng (HE/HIM)" Date: Thu, 8 Jan 2026 14:15:41 -0800 Subject: [PATCH 2/7] Fix --- .../GuestProxyAgentTest/Scripts/GuestProxyAgentValidation.ps1 | 2 +- e2etest/GuestProxyAgentTest/TestCases/EnableProxyAgentCase.cs | 3 +-- .../TestCases/GuestProxyAgentValidationCase.cs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/e2etest/GuestProxyAgentTest/Scripts/GuestProxyAgentValidation.ps1 b/e2etest/GuestProxyAgentTest/Scripts/GuestProxyAgentValidation.ps1 index edf23e99..22c9c90b 100644 --- a/e2etest/GuestProxyAgentTest/Scripts/GuestProxyAgentValidation.ps1 +++ b/e2etest/GuestProxyAgentTest/Scripts/GuestProxyAgentValidation.ps1 @@ -104,7 +104,7 @@ do { $jsonString = '{"guestProxyAgentServiceInstalled": ' + $guestProxyAgentServiceExist.ToString().ToLower() ` + ', "guestProxyProcessStarted": ' + $guestProxyAgentProcessExist.ToString().ToLower() ` + ', "guestProxyAgentServiceStatus": "' + $guestProxyAgentServiceStatus ` - + ', "secureChannelState": "' + $secureChannelState ` + + '", "secureChannelState": "' + $secureChannelState ` + '", "guestProxyAgentLogGenerated": ' + $guestProxyAgentLogGenerated.ToString().ToLower() + '}' Write-Output "$((Get-Date).ToUniversalTime()) - $jsonString" diff --git a/e2etest/GuestProxyAgentTest/TestCases/EnableProxyAgentCase.cs b/e2etest/GuestProxyAgentTest/TestCases/EnableProxyAgentCase.cs index de1479bc..1373465e 100644 --- a/e2etest/GuestProxyAgentTest/TestCases/EnableProxyAgentCase.cs +++ b/e2etest/GuestProxyAgentTest/TestCases/EnableProxyAgentCase.cs @@ -51,15 +51,14 @@ public override async Task StartAsync(TestCaseExecutionContext context) if (EnableProxyAgent) { + // property 'inVMAccessControlProfileReferenceId' cannot be used together with property 'mode' patch.SecurityProfile.ProxyAgentSettings.WireServer = new HostEndpointSettings { InVmAccessControlProfileReferenceId = TestSetting.Instance.InVmWireServerAccessControlProfileReferenceId, - Mode = HostEndpointSettingsMode.Enforce }; patch.SecurityProfile.ProxyAgentSettings.Imds = new HostEndpointSettings { InVmAccessControlProfileReferenceId = TestSetting.Instance.InVmIMDSAccessControlProfileReferenceId, - Mode = HostEndpointSettingsMode.Audit }; } diff --git a/e2etest/GuestProxyAgentTest/TestCases/GuestProxyAgentValidationCase.cs b/e2etest/GuestProxyAgentTest/TestCases/GuestProxyAgentValidationCase.cs index fd204809..ad84b086 100644 --- a/e2etest/GuestProxyAgentTest/TestCases/GuestProxyAgentValidationCase.cs +++ b/e2etest/GuestProxyAgentTest/TestCases/GuestProxyAgentValidationCase.cs @@ -38,7 +38,7 @@ public override async Task StartAsync(TestCaseExecutionContext context) { List<(string, string)> parameterList = new List<(string, string)>(); parameterList.Add(("expectedSecureChannelState", expectedSecureChannelState)); - context.TestResultDetails = (await RunScriptViaRunCommandV2Async(context, Constants.GUEST_PROXY_AGENT_VALIDATION_SCRIPT_NAME, null!)).ToTestResultDetails(ConsoleLog); + context.TestResultDetails = (await RunScriptViaRunCommandV2Async(context, Constants.GUEST_PROXY_AGENT_VALIDATION_SCRIPT_NAME, parameterList)).ToTestResultDetails(ConsoleLog); if (context.TestResultDetails.Succeed && context.TestResultDetails.CustomOut != null) { var validationDetails = context.TestResultDetails.SafeDeserializedCustomOutAs(); From 5e6a16c6fadfd6185045b345eb7ae7d8dc512316 Mon Sep 17 00:00:00 2001 From: "Zhidong Peng (HE/HIM)" Date: Fri, 9 Jan 2026 08:50:43 -0800 Subject: [PATCH 3/7] Enforce SecureChannelState check --- e2etest/GuestProxyAgentTest/Settings/TestSetting.cs | 3 --- .../TestCases/GuestProxyAgentValidationCase.cs | 4 +++- e2etest/GuestProxyAgentTest/TestScenarios/BVTScenario.cs | 2 +- .../GuestProxyAgentTest/TestScenarios/LinuxPackageScenario.cs | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/e2etest/GuestProxyAgentTest/Settings/TestSetting.cs b/e2etest/GuestProxyAgentTest/Settings/TestSetting.cs index 19e2e066..8c17594a 100644 --- a/e2etest/GuestProxyAgentTest/Settings/TestSetting.cs +++ b/e2etest/GuestProxyAgentTest/Settings/TestSetting.cs @@ -3,10 +3,7 @@ using Azure.Core; using GuestProxyAgentTest.Models; using GuestProxyAgentTest.Utilities; -using Newtonsoft.Json; using System.Reflection; -using System.Runtime.Serialization; -using System.Text.Json.Serialization; namespace GuestProxyAgentTest.Settings { diff --git a/e2etest/GuestProxyAgentTest/TestCases/GuestProxyAgentValidationCase.cs b/e2etest/GuestProxyAgentTest/TestCases/GuestProxyAgentValidationCase.cs index ad84b086..acd55770 100644 --- a/e2etest/GuestProxyAgentTest/TestCases/GuestProxyAgentValidationCase.cs +++ b/e2etest/GuestProxyAgentTest/TestCases/GuestProxyAgentValidationCase.cs @@ -48,7 +48,8 @@ public override async Task StartAsync(TestCaseExecutionContext context) && validationDetails.GuestProxyAgentServiceInstalled && validationDetails.GuestProxyAgentServiceStatus.Equals(EXPECTED_GUEST_PROXY_AGENT_SERVICE_STATUS, StringComparison.OrdinalIgnoreCase) && validationDetails.GuestProxyProcessStarted - && validationDetails.GuestProxyAgentLogGenerated) + && validationDetails.GuestProxyAgentLogGenerated + && validationDetails.SecureChannelState.Equals(expectedSecureChannelState, StringComparison.OrdinalIgnoreCase)) { context.TestResultDetails.Succeed = true; } @@ -66,5 +67,6 @@ class GuestProxyAgentValidationDetails public bool GuestProxyProcessStarted { get; set; } public bool GuestProxyAgentLogGenerated { get; set; } public string GuestProxyAgentServiceStatus { get; set; } = null!; + public string SecureChannelState { get; set; } = null!; } } diff --git a/e2etest/GuestProxyAgentTest/TestScenarios/BVTScenario.cs b/e2etest/GuestProxyAgentTest/TestScenarios/BVTScenario.cs index af421971..3bcc2c9b 100644 --- a/e2etest/GuestProxyAgentTest/TestScenarios/BVTScenario.cs +++ b/e2etest/GuestProxyAgentTest/TestScenarios/BVTScenario.cs @@ -27,7 +27,7 @@ public override void TestScenarioSetup() // it will add GPA VM Extension and overwrite the private GPA package AddTestCase(new EnableProxyAgentCase()); secureChannelEnabled = true; - AddTestCase(new GuestProxyAgentValidationCase("GuestProxyAgentValidationWithSecureChannelEnabled", "WireServer Enforce - IMDS Audit - HostGA Enforce")); + AddTestCase(new GuestProxyAgentValidationCase("GuestProxyAgentValidationWithSecureChannelEnabled", "WireServer Enforce - IMDS Enforce - HostGA Enforce")); } AddTestCase(new IMDSPingTestCase("IMDSPingTestBeforeReboot", secureChannelEnabled)); diff --git a/e2etest/GuestProxyAgentTest/TestScenarios/LinuxPackageScenario.cs b/e2etest/GuestProxyAgentTest/TestScenarios/LinuxPackageScenario.cs index 1f67065b..15ba7bc8 100644 --- a/e2etest/GuestProxyAgentTest/TestScenarios/LinuxPackageScenario.cs +++ b/e2etest/GuestProxyAgentTest/TestScenarios/LinuxPackageScenario.cs @@ -13,7 +13,7 @@ public override void TestScenarioSetup() AddTestCase(new InstallOrUpdateGuestProxyAgentPackageCase()); AddTestCase(new GuestProxyAgentValidationCase()); AddTestCase(new EnableProxyAgentCase()); - AddTestCase(new GuestProxyAgentValidationCase("GuestProxyAgentValidationWithSecureChannelEnabled", "WireServer Enforce - IMDS Audit - HostGA Enforce")); + AddTestCase(new GuestProxyAgentValidationCase("GuestProxyAgentValidationWithSecureChannelEnabled", "WireServer Enforce - IMDS Enforce - HostGA Enforce")); AddTestCase(new IMDSPingTestCase("IMDSPingTestBeforeReboot", true)); AddTestCase(new RebootVMCase("RebootVMCaseAfterInstallOrUpdateGuestProxyAgent")); AddTestCase(new IMDSPingTestCase("IMDSPingTestAfterReboot", true)); From 5491fdf6e11f0083b569dc8f42e7b924696f01dd Mon Sep 17 00:00:00 2001 From: "Zhidong Peng (HE/HIM)" Date: Fri, 9 Jan 2026 10:29:28 -0800 Subject: [PATCH 4/7] detecting os and installing jq --- .../LinuxScripts/GuestProxyAgentValidation.sh | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/e2etest/GuestProxyAgentTest/LinuxScripts/GuestProxyAgentValidation.sh b/e2etest/GuestProxyAgentTest/LinuxScripts/GuestProxyAgentValidation.sh index 8713162c..df150a0a 100755 --- a/e2etest/GuestProxyAgentTest/LinuxScripts/GuestProxyAgentValidation.sh +++ b/e2etest/GuestProxyAgentTest/LinuxScripts/GuestProxyAgentValidation.sh @@ -50,6 +50,36 @@ else echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - logdir does not exist" fi +echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - detecting os and installing jq" +os=$(hostnamectl | grep "Operating System") +echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - os=$os" +if [[ $os == *"Ubuntu"* ]]; then + for i in {1..3}; do + echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - start installing jq via apt-get $i" + sudo apt update + sudo apt-get install -y jq + sleep 10 + install=$(apt list --installed jq) + echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - install=$install" + if [[ $install == *"jq"* ]]; then + echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - jq installed successfully" + break + fi + done +else + for i in {1..3}; do + echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - start installing jq via dnf $i" + sudo dnf -y install jq + sleep 10 + install=$(dnf list --installed jq) + echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - install=$install" + if [[ $install == *"jq"* ]]; then + echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - jq installed successfully" + break + fi + done +fi + # check status.json file Content ## check timestamp of last entry in status.json file ## check the secure channel status From 2a331892446eb2e585a1b1e2d17d5be30475fa5e Mon Sep 17 00:00:00 2001 From: "Zhidong Peng (HE/HIM)" Date: Fri, 9 Jan 2026 12:13:47 -0800 Subject: [PATCH 5/7] download & install jq for suse --- .../LinuxScripts/GuestProxyAgentValidation.sh | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/e2etest/GuestProxyAgentTest/LinuxScripts/GuestProxyAgentValidation.sh b/e2etest/GuestProxyAgentTest/LinuxScripts/GuestProxyAgentValidation.sh index df150a0a..4a8bc9d6 100755 --- a/e2etest/GuestProxyAgentTest/LinuxScripts/GuestProxyAgentValidation.sh +++ b/e2etest/GuestProxyAgentTest/LinuxScripts/GuestProxyAgentValidation.sh @@ -66,6 +66,33 @@ if [[ $os == *"Ubuntu"* ]]; then break fi done +elif [[ $os == *"SUSE"* ]]; then + # SUSE repo does not have jq package, so we download jq binary directly + # Detect architecture + arch=$(uname -m) + echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - detected architecture: $arch" + if [[ $arch == "x86_64" ]]; then + jq_binary="jq-linux64" + elif [[ $arch == "aarch64" ]] || [[ $arch == "arm64" ]]; then + jq_binary="jq-linux-arm64" + else + echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - unsupported architecture: $arch" + jq_binary="jq-linux64" + fi + # Download jq binary directly from GitHub + for i in {1..3}; do + echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - downloading $jq_binary binary (attempt $i)" + sudo curl -L https://github.com/jqlang/jq/releases/download/jq-1.6/$jq_binary -o /usr/local/bin/jq + if [ $? -eq 0 ]; then + sudo chmod +x /usr/local/bin/jq + if command -v jq &> /dev/null; then + echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - jq installed successfully" + jq --version + break + fi + fi + sleep 5 + done else for i in {1..3}; do echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - start installing jq via dnf $i" From c2555a526a34352f537e41cba3bdda16a4eee601 Mon Sep 17 00:00:00 2001 From: "Zhidong Peng (HE/HIM)" Date: Fri, 9 Jan 2026 13:16:02 -0800 Subject: [PATCH 6/7] use jq-1.8.1 --- .../LinuxScripts/GuestProxyAgentValidation.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2etest/GuestProxyAgentTest/LinuxScripts/GuestProxyAgentValidation.sh b/e2etest/GuestProxyAgentTest/LinuxScripts/GuestProxyAgentValidation.sh index 4a8bc9d6..1ea12b8d 100755 --- a/e2etest/GuestProxyAgentTest/LinuxScripts/GuestProxyAgentValidation.sh +++ b/e2etest/GuestProxyAgentTest/LinuxScripts/GuestProxyAgentValidation.sh @@ -72,7 +72,7 @@ elif [[ $os == *"SUSE"* ]]; then arch=$(uname -m) echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - detected architecture: $arch" if [[ $arch == "x86_64" ]]; then - jq_binary="jq-linux64" + jq_binary="jq-linux-amd64" elif [[ $arch == "aarch64" ]] || [[ $arch == "arm64" ]]; then jq_binary="jq-linux-arm64" else @@ -82,7 +82,7 @@ elif [[ $os == *"SUSE"* ]]; then # Download jq binary directly from GitHub for i in {1..3}; do echo "$(date -u +"%Y-%m-%dT%H:%M:%SZ") - downloading $jq_binary binary (attempt $i)" - sudo curl -L https://github.com/jqlang/jq/releases/download/jq-1.6/$jq_binary -o /usr/local/bin/jq + sudo curl -L https://github.com/jqlang/jq/releases/download/jq-1.8.1/$jq_binary -o /usr/local/bin/jq if [ $? -eq 0 ]; then sudo chmod +x /usr/local/bin/jq if command -v jq &> /dev/null; then From 86cb46bb8fc3f787b0221835d369c56d5d5d74a2 Mon Sep 17 00:00:00 2001 From: "Zhidong Peng (HE/HIM)" Date: Fri, 9 Jan 2026 14:35:35 -0800 Subject: [PATCH 7/7] fix spell --- .github/actions/spelling/expect.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index 35213d2f..c8a46ad2 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -146,6 +146,7 @@ INVM Ioctl iusr jetbrains +jqlang JOBOBJECT jobsjob joutvhu