Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions .pipelines/asa-stage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Attack Surface Analyzer (ASA) install-diff stage.
#
# Runs the ASA install-diff on a clean CloudTest VM (the same harness used by the
# nightly TAEF tests). The VM installs the freshly built wsl.msi and uses ASA to
# verify the installer does not weaken the OS security configuration. Findings are
# triaged against tools/devops/asa-expected-findings.json (staged into the build
# drop under testbin\devops). The ASA SARIF and the net-new report are written to
# the CloudTest logging directory and uploaded with the test results.
#
# Introduced as NON-GATING: the runbook is generated with -FailOnNewFindings:$false
# (cloudtest/CMakeLists.txt ASA_FAIL_ON_NEW). Once the allowlist is confirmed
# stable, flip ASA_FAIL_ON_NEW to "$true" in cloudtest/CMakeLists.txt to make it a
# hard gate.

parameters:
- name: pool
type: string
default: ''

# Client image whose generated ASA group is run. Must match the image passed to
# add_asa_group() in cloudtest/CMakeLists.txt.
- name: image
type: string
default: 'wsl-test-image-win11-23h2-ent-2024-11-18'

stages:
- stage: asa
displayName: "Attack Surface Analyzer"
dependsOn: [build_x64]
jobs:
- job: asa_install_diff
displayName: "ASA install-diff (x64)"
dependsOn: []
variables:
ob_outputDirectory: '$(Build.SourcesDirectory)\out'
ob_artifactBaseName: 'drop_wsl'
ob_artifactSuffix: '_asa'
timeoutInMinutes: 180
cancelTimeoutInMinutes: 240
${{ if eq(parameters.pool, '') }}:
pool: {'type': 'cloudtestagentless'}
${{ else }}:
pool: ${{ parameters.pool }}
steps:
- task: CloudTestServerBuildTask@2
inputs:
DisplayName: "ASA install-diff (x64)"
connectedServiceName: "CloudTest-PROD"
cloudTestTenant: "wsl"
testMapLocation: 'testbin\x64\cloudtest\asa-${{ parameters.image }}\TestMap.xml'
pipelineArtifactName: "drop_wsl_build"
pipelineArtifactBuildUrl: '$(System.TaskDefinitionsUri)$(System.TeamProject)/_build/results?buildId=$(Build.BuildId)'
buildDropArtifactName: ""
timeoutInMinutes: 180
sessionTimeout: 180
cancelTimeoutInMinutes: 240
TestTimeout: "0.02:00:00"
parserProperties: "worker:VsTestVersion=V150;session:HoldTrigger=Failure;VstsTestResultAttachmentUploadBehavior=Always"
notificationSubscribers: $(Build.RequestedForEmail)
4 changes: 4 additions & 0 deletions .pipelines/build-job.yml
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,10 @@ jobs:

Move-Item -Path "bin\x64\cloudtest" -Destination "$(ob_outputDirectory)\testbin\x64\cloudtest"

mkdir $(ob_outputDirectory)\testbin\devops
Copy-Item -Path "tools\devops\Run-AsaInstallDiff.ps1" -Destination "$(ob_outputDirectory)\testbin\devops\Run-AsaInstallDiff.ps1"
Copy-Item -Path "tools\devops\asa-expected-findings.json" -Destination "$(ob_outputDirectory)\testbin\devops\asa-expected-findings.json"
Comment on lines +316 to +318

Move-Item -Path "tools\test\test-setup.ps1" -Destination "$(ob_outputDirectory)\testbin\test-setup.ps1"
Move-Item -Path "tools\test\CloudTest-Setup.bat" -Destination "$(ob_outputDirectory)\testbin\CloudTest-Setup.bat"
Move-Item -Path "diagnostics\wsl.wprp" -Destination "$(ob_outputDirectory)\testbin\wsl.wprp"
Expand Down
7 changes: 6 additions & 1 deletion .pipelines/wsl-build-nightly-onebranch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,9 @@ extends:

- template: nuget-stage.yml@self
parameters:
isNightly: true
isNightly: true

- template: asa-stage.yml@self
# Non-gating for now: ASA publishes findings without failing the build
# (controlled by ASA_FAIL_ON_NEW in cloudtest/CMakeLists.txt). Flip that to
# "$true" once the allowlist in tools/devops/asa-expected-findings.json is stable.
28 changes: 28 additions & 0 deletions cloudtest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,38 @@ function(add_test_group image version suffix filter)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/TestGroup.xml.in ${DIR}/TestGroup.xml)
endfunction()

# Attack Surface Analyzer install-diff group. Runs on a single clean client image
# and is generated only for nightly/release builds that publish the wsl.msi bundle.
# Map ALLOW_UNSIGNED_PACKAGE (0/1) straight through; the runbook switches accept 1/0.
# (A literal "$true" cannot be bound to a [switch] when passed on a command line.)
if (ALLOW_UNSIGNED_PACKAGE STREQUAL "1")
set(ASA_ALLOW_UNSIGNED "1")
else()
set(ASA_ALLOW_UNSIGNED "0")
endif()

# Non-gating to start: report net-new findings without failing the run.
# Flip to "1" once the allowlist has been validated against a few nightly runs.
set(ASA_FAIL_ON_NEW "0")

function(add_asa_group image)
set(DIR ${OUT}/asa-${image})
file(MAKE_DIRECTORY ${DIR})

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/TestMapAsa.xml.in ${DIR}/TestMap.xml)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/TestGroupAsa.xml.in ${DIR}/TestGroup.xml)
endfunction()

foreach(image ${CLOUDTEST_IMAGES})
add_test_group("${image}" "1" "wsl1" "not (@TestCategory='WSLC')")
add_test_group("${image}" "2" "wsl2" "not (@TestCategory='WSLC')")
if (NOT "${image}" IN_LIST CLOUDTEST_SERVER_IMAGES)
add_test_group("${image}" "2" "wslc" "@TestCategory='WSLC'")
endif()
endforeach()

# The MSI bundle is only staged for nightly/release builds (INCLUDE_PACKAGE_STAGE),
# so only generate the ASA group when that bundle will be present in drop_wsl_build.
if (INCLUDE_PACKAGE_STAGE AND CLOUDTEST_IMAGES)
add_asa_group("wsl-test-image-win11-23h2-ent-2024-11-18")
endif()
16 changes: 16 additions & 0 deletions cloudtest/TestGroupAsa.xml.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<TestJobGroup EnableProcessJobObjectBreakaway="true">
<ResourceSpec>
<Resource SKU="Standard_D4_v3" Image="${image}"/>
</ResourceSpec>
<Setup TimeoutMins="30">
<BuildFiles>
<Copy Src="[drop]\bundle\wsl.${PACKAGE_VERSION}.${TARGET_PLATFORM}.msi" Dest="[WorkingDirectory]" IsRecursive="false" Writable="true"/>
<Copy Src="[drop]\testbin\devops\*" Dest="[WorkingDirectory]\devops" IsRecursive="true" Writable="true"/>
</BuildFiles>
</Setup>

<TestJob Name="CloudTest.Asa" TimeoutMins="120">
<Execution Type="Exe" Path="C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" Args="-NoProfile -ExecutionPolicy Bypass -File &quot;[WorkingDirectory]\devops\Run-AsaInstallDiff.ps1&quot; -MsiPath &quot;[WorkingDirectory]\wsl.${PACKAGE_VERSION}.${TARGET_PLATFORM}.msi&quot; -ExpectedFindingsPath &quot;[WorkingDirectory]\devops\asa-expected-findings.json&quot; -WorkDir &quot;[LoggingDirectory]\asa&quot; -TrxPath &quot;[WorkingDirectory]\TestResults\asa.trx&quot; -AllowUnsignedWslBinaries ${ASA_ALLOW_UNSIGNED} -FailOnNewFindings ${ASA_FAIL_ON_NEW}" Parser="TRX" />
</TestJob>
</TestJobGroup>
13 changes: 13 additions & 0 deletions cloudtest/TestMapAsa.xml.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<TestMap>
<TestJobGroup Name="AsaTestGroup" TestSystem="Default" ConfigPath="[BuildRoot]\testbin\${TARGET_PLATFORM}\cloudtest\asa-${image}\TestGroup.xml" IsActive="true"/>
<Providers>
<Provider Type="PipelineArtifacts">
<Properties>
<Add Name="CloudTest.ProviderCustomName" Value="[drop]" />
<Add Name="PipelineArtifactBuildUrl" Value="https://${VSO_ORG}.visualstudio.com/${VSO_PROJECT}/_build/results?buildId=${PIPELINE_BUILD_ID}"/>
<Add Name="PipelineArtifactName" Value="drop_wsl_build"/>
</Properties>
</Provider>
</Providers>
</TestMap>
Loading