diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index 5b743c2e8..54faabcd6 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -26,3 +26,8 @@ jobs:
- template: build/template-install-dependencies.yaml
- template: build/template-build.yaml
- template: build/template-run-unit-tests.yaml
+ parameters:
+ # Exclude managed-identity E2E tests: they require an MI assigned to the
+ # host (IMDS), which Microsoft-hosted agents do not have. They still run in
+ # the official OneBranch pipeline on VM-based agents that have the MI.
+ e2eTestFilterCriteria: 'Category!=MI_E2E'
diff --git a/build/template-run-unit-tests.yaml b/build/template-run-unit-tests.yaml
index b60a59bcf..cc7895d7d 100644
--- a/build/template-run-unit-tests.yaml
+++ b/build/template-run-unit-tests.yaml
@@ -1,6 +1,15 @@
# template-run-unit-tests.yaml
# Run all unit tests across the IdWeb project
+parameters:
+# VSTest filter applied to the E2E test run. Empty by default so every consumer
+# (e.g. the release build) runs the full E2E suite. The PR build passes a filter
+# to exclude tests that cannot run on Microsoft-hosted agents (e.g. managed
+# identity tests, which require an MI assigned to the host: Category!=MI_E2E).
+- name: e2eTestFilterCriteria
+ type: string
+ default: ''
+
steps:
- task: VSTest@2
@@ -38,6 +47,7 @@ steps:
tests\E2E Tests\TokenAcquirerTests\bin\**\TokenAcquirerTests.dll
tests\E2E Tests\NET 7 tests\IntegrationTests\bin\**\IntegrationTests.dll
searchFolder: '$(System.DefaultWorkingDirectory)'
+ testFiltercriteria: '${{ parameters.e2eTestFilterCriteria }}'
rerunFailedTests: true
rerunMaxAttempts: '3'
runInParallel: false
diff --git a/tests/E2E Tests/TokenAcquirerTests/TokenAcquirer.cs b/tests/E2E Tests/TokenAcquirerTests/TokenAcquirer.cs
index e5fb1819b..5dd4d1872 100644
--- a/tests/E2E Tests/TokenAcquirerTests/TokenAcquirer.cs
+++ b/tests/E2E Tests/TokenAcquirerTests/TokenAcquirer.cs
@@ -551,6 +551,7 @@ private static async Task CreateGraphClientAndAssertAsync(TokenAcquirerFactory t
}
[Collection(nameof(TokenAcquirerFactorySingletonProtection))]
+ [Trait("Category", TestCategories.ManagedIdentity)]
public class AcquireTokenManagedIdentity
{
[OnlyOnAzureDevopsFact]
diff --git a/tests/Microsoft.Identity.Web.Test.Common/TestCategories.cs b/tests/Microsoft.Identity.Web.Test.Common/TestCategories.cs
new file mode 100644
index 000000000..78274768c
--- /dev/null
+++ b/tests/Microsoft.Identity.Web.Test.Common/TestCategories.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+namespace Microsoft.Identity.Web.Test.Common
+{
+ ///
+ /// Well-known xUnit trait categories (used with [Trait("Category", ...)])
+ /// so that specific groups of tests can be included or excluded from a test run
+ /// via the VSTest testFilterCriteria (for example Category!=MI_E2E).
+ ///
+ public static class TestCategories
+ {
+ ///
+ /// Tests that require a real Azure managed identity to be assigned to the host
+ /// (they call the IMDS endpoint). These pass on the official pipeline, which runs
+ /// on VM-based agents with a managed identity, but cannot run on Microsoft-hosted
+ /// agents that have no managed identity, so they are filtered out there.
+ ///
+ public const string ManagedIdentity = "MI_E2E";
+ }
+}