ConfigurationMixedElevationTests.cs (15553B)
1 // ----------------------------------------------------------------------------- 2 // <copyright file="ConfigurationMixedElevationTests.cs" company="Microsoft Corporation"> 3 // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 4 // </copyright> 5 // ----------------------------------------------------------------------------- 6 7 namespace Microsoft.Management.Configuration.UnitTests.Tests 8 { 9 using System; 10 using System.IO; 11 using System.Threading.Tasks; 12 using Microsoft.Management.Configuration.UnitTests.Fixtures; 13 using Microsoft.Management.Configuration.UnitTests.Helpers; 14 using Xunit; 15 using Xunit.Abstractions; 16 17 /// <summary> 18 /// Unit tests for verifying the processor behavior for handling mixed elevation scenarios. 19 /// </summary> 20 [Collection("UnitTestCollection")] 21 [OutOfProc] 22 public class ConfigurationMixedElevationTests : ConfigurationProcessorTestBase 23 { 24 private readonly UnitTestFixture fixture; 25 private readonly ITestOutputHelper log; 26 27 /// <summary> 28 /// Initializes a new instance of the <see cref="ConfigurationMixedElevationTests"/> class. 29 /// </summary> 30 /// <param name="fixture">Unit test fixture.</param> 31 /// <param name="log">Log helper.</param> 32 public ConfigurationMixedElevationTests(UnitTestFixture fixture, ITestOutputHelper log) 33 : base(fixture, log) 34 { 35 this.fixture = fixture; 36 this.log = log; 37 } 38 39 /// <summary> 40 /// Verifies that applying units of mixed elevation is successful. Also verifies that the elevated processor has a different process id. 41 /// </summary> 42 /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns> 43 [Fact] 44 public async Task ApplyMixedElevationUnits() 45 { 46 string resourceName = "E2ETestResourcePID"; 47 string moduleName = "xE2ETestResource"; 48 Version version = new Version("0.0.0.1"); 49 50 string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); 51 Directory.CreateDirectory(tempDirectory); 52 53 ConfigurationSet configurationSet = this.ConfigurationSet(); 54 configurationSet.SchemaVersion = "0.2"; 55 configurationSet.Metadata.Add(Helpers.Constants.EnableDynamicFactoryTestMode, true); 56 57 ConfigurationUnit unit = this.ConfigurationUnit(); 58 unit.Metadata.Add("version", version.ToString()); 59 unit.Metadata.Add("module", moduleName); 60 unit.Settings.Add("directoryPath", tempDirectory); 61 unit.Type = resourceName; 62 unit.Intent = ConfigurationUnitIntent.Apply; 63 64 ConfigurationUnit elevatedUnit = this.ConfigurationUnit(); 65 elevatedUnit.Metadata.Add("version", version.ToString()); 66 elevatedUnit.Metadata.Add("module", moduleName); 67 elevatedUnit.Environment.Context = SecurityContext.Elevated; 68 elevatedUnit.Settings.Add("directoryPath", tempDirectory); 69 elevatedUnit.Type = resourceName; 70 elevatedUnit.Intent = ConfigurationUnitIntent.Apply; 71 72 configurationSet.Units = new ConfigurationUnit[] { unit, elevatedUnit }; 73 74 IConfigurationSetProcessorFactory dynamicFactory = await this.fixture.ConfigurationStatics.CreateConfigurationSetProcessorFactoryAsync(Helpers.Constants.DynamicRuntimeHandlerIdentifier); 75 76 ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(dynamicFactory); 77 78 ApplyConfigurationSetResult result = processor.ApplySet(configurationSet, ApplyConfigurationSetFlags.None); 79 80 // Get the number of unique PIDs from temp directory. 81 int pidCount = Directory.GetFiles(tempDirectory).Length; 82 83 // Clean up temp directory folder. 84 Directory.Delete(tempDirectory, true); 85 86 Assert.NotNull(result); 87 Assert.Null(result.ResultCode); 88 Assert.Equal(2, result.UnitResults.Count); 89 90 foreach (var unitResult in result.UnitResults) 91 { 92 Assert.NotNull(unitResult); 93 Assert.False(unitResult.PreviouslyInDesiredState); 94 Assert.False(unitResult.RebootRequired); 95 Assert.NotNull(unitResult.ResultInformation); 96 Assert.Null(unitResult.ResultInformation.ResultCode); 97 Assert.Equal(ConfigurationUnitResultSource.None, unitResult.ResultInformation.ResultSource); 98 } 99 100 // There should be exactly 2 unique PIDs, one for each integrity level. 101 Assert.Equal(2, pidCount); 102 } 103 104 /// <summary> 105 /// Verifies that applying units of mixed elevation is successful. Also verifies that the elevated processor has a different process id. 106 /// </summary> 107 /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns> 108 [Fact] 109 public async Task ApplyMixedElevationUnits_Schema_0_3() 110 { 111 string resourceName = "xE2ETestResource/E2ETestResourcePID"; 112 Version version = new Version("0.0.0.1"); 113 114 string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); 115 Directory.CreateDirectory(tempDirectory); 116 117 ConfigurationSet configurationSet = this.ConfigurationSet(); 118 configurationSet.SchemaVersion = "0.3"; 119 configurationSet.Metadata.Add(Helpers.Constants.EnableDynamicFactoryTestMode, true); 120 121 ConfigurationUnit unit = this.ConfigurationUnit(); 122 unit.Metadata.Add("version", version.ToString()); 123 unit.Settings.Add("directoryPath", tempDirectory); 124 unit.Type = resourceName; 125 unit.Identifier = "current"; 126 127 ConfigurationUnit elevatedUnit = this.ConfigurationUnit(); 128 elevatedUnit.Intent = ConfigurationUnitIntent.Unknown; 129 elevatedUnit.Metadata.Add("version", version.ToString()); 130 elevatedUnit.Environment.Context = SecurityContext.Elevated; 131 elevatedUnit.Settings.Add("directoryPath", tempDirectory); 132 elevatedUnit.Type = resourceName; 133 elevatedUnit.Identifier = "elevated"; 134 135 configurationSet.Units = new ConfigurationUnit[] { unit, elevatedUnit }; 136 137 IConfigurationSetProcessorFactory dynamicFactory = await this.fixture.ConfigurationStatics.CreateConfigurationSetProcessorFactoryAsync(Helpers.Constants.DynamicRuntimeHandlerIdentifier); 138 139 ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(dynamicFactory); 140 141 ApplyConfigurationSetResult result = processor.ApplySet(configurationSet, ApplyConfigurationSetFlags.None); 142 143 // Get the number of unique PIDs from temp directory. 144 int pidCount = Directory.GetFiles(tempDirectory).Length; 145 146 // Clean up temp directory folder. 147 Directory.Delete(tempDirectory, true); 148 149 Assert.NotNull(result); 150 Assert.Null(result.ResultCode); 151 Assert.Equal(2, result.UnitResults.Count); 152 153 foreach (var unitResult in result.UnitResults) 154 { 155 Assert.NotNull(unitResult); 156 Assert.False(unitResult.PreviouslyInDesiredState); 157 Assert.False(unitResult.RebootRequired); 158 Assert.NotNull(unitResult.ResultInformation); 159 Assert.Null(unitResult.ResultInformation.ResultCode); 160 Assert.Equal(ConfigurationUnitResultSource.None, unitResult.ResultInformation.ResultSource); 161 } 162 163 // There should be exactly 2 unique PIDs, one for each integrity level. 164 Assert.Equal(2, pidCount); 165 } 166 167 /// <summary> 168 /// Verifies that creating a high integrity unit processor for a non elevated unit should return an invalid operation result. 169 /// </summary> 170 /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns> 171 [Fact] 172 public async Task ApplyUnitNotInLimitationSet() 173 { 174 string resourceName = "E2ETestResource"; 175 string moduleName = "xE2ETestResource"; 176 Version version = new Version("0.0.0.1"); 177 178 ConfigurationSet configurationSet = this.ConfigurationSet(); 179 configurationSet.SchemaVersion = "0.2"; 180 configurationSet.Metadata.Add(Helpers.Constants.EnableDynamicFactoryTestMode, true); 181 configurationSet.Metadata.Add(Helpers.Constants.ForceHighIntegrityLevelUnitsTestGuid, true); 182 configurationSet.Metadata.Add(Helpers.Constants.EnableRestrictedIntegrityLevelTestGuid, true); 183 184 ConfigurationUnit unit = this.ConfigurationUnit(); 185 unit.Metadata.Add("version", version.ToString()); 186 unit.Metadata.Add("module", moduleName); 187 unit.Metadata.Add("unique", "value"); 188 unit.Type = resourceName; 189 unit.Intent = ConfigurationUnitIntent.Apply; 190 191 ConfigurationUnit elevatedUnit = this.ConfigurationUnit(); 192 elevatedUnit.Metadata.Add("version", version.ToString()); 193 elevatedUnit.Metadata.Add("module", moduleName); 194 elevatedUnit.Environment.Context = SecurityContext.Elevated; 195 elevatedUnit.Type = resourceName; 196 elevatedUnit.Intent = ConfigurationUnitIntent.Apply; 197 198 configurationSet.Units = new ConfigurationUnit[] { unit, elevatedUnit }; 199 200 IConfigurationSetProcessorFactory dynamicFactory = await this.fixture.ConfigurationStatics.CreateConfigurationSetProcessorFactoryAsync(Helpers.Constants.DynamicRuntimeHandlerIdentifier); 201 202 ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(dynamicFactory); 203 204 ApplyConfigurationSetResult result = processor.ApplySet(configurationSet, ApplyConfigurationSetFlags.None); 205 Assert.NotNull(result); 206 Assert.NotNull(result.ResultCode); 207 Assert.Equal(Errors.WINGET_CONFIG_ERROR_SET_APPLY_FAILED, result.ResultCode.HResult); 208 Assert.Equal(2, result.UnitResults.Count); 209 210 ApplyConfigurationUnitResult unitResult = result.UnitResults[0]; 211 Assert.NotNull(unitResult); 212 Assert.False(unitResult.PreviouslyInDesiredState); 213 Assert.False(unitResult.RebootRequired); 214 Assert.NotNull(unitResult.ResultInformation); 215 Assert.NotNull(unitResult.ResultInformation.ResultCode); 216 Assert.Equal(Errors.CORE_INVALID_OPERATION, unitResult.ResultInformation.ResultCode.HResult); 217 Assert.Equal(ConfigurationUnitResultSource.Internal, unitResult.ResultInformation.ResultSource); 218 219 // Elevated unit should still succeed when applied. 220 ApplyConfigurationUnitResult elevatedUnitResult = result.UnitResults[1]; 221 Assert.NotNull(elevatedUnitResult); 222 Assert.False(elevatedUnitResult.PreviouslyInDesiredState); 223 Assert.False(elevatedUnitResult.RebootRequired); 224 Assert.NotNull(elevatedUnitResult.ResultInformation); 225 Assert.Null(elevatedUnitResult.ResultInformation.ResultCode); 226 Assert.Equal(ConfigurationUnitResultSource.None, elevatedUnitResult.ResultInformation.ResultSource); 227 } 228 229 /// <summary> 230 /// Verifies that attempting to pass a secure parameter across the integrity boundary fails. 231 /// </summary> 232 /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns> 233 [Fact] 234 public async Task SecureParameterAcrossIntegrityBoundaryFails() 235 { 236 string resourceName = "E2ETestResourcePID"; 237 string moduleName = "xE2ETestResource"; 238 Version version = new Version("0.0.0.1"); 239 240 string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); 241 Directory.CreateDirectory(tempDirectory); 242 243 ConfigurationSet configurationSet = this.ConfigurationSet(); 244 configurationSet.Metadata.Add(Helpers.Constants.EnableDynamicFactoryTestMode, true); 245 246 ConfigurationUnit elevatedUnit = this.ConfigurationUnit(); 247 elevatedUnit.Metadata.Add("version", version.ToString()); 248 elevatedUnit.Metadata.Add("module", moduleName); 249 elevatedUnit.Environment.Context = SecurityContext.Elevated; 250 elevatedUnit.Settings.Add("directoryPath", tempDirectory); 251 elevatedUnit.Type = resourceName; 252 elevatedUnit.Intent = ConfigurationUnitIntent.Apply; 253 254 configurationSet.Units = new ConfigurationUnit[] { elevatedUnit }; 255 256 ConfigurationParameter parameter = this.ConfigurationParameter(); 257 parameter.Name = "param"; 258 parameter.Type = Windows.Foundation.PropertyType.String; 259 parameter.IsSecure = true; 260 parameter.ProvidedValue = "secrets"; 261 262 configurationSet.Parameters = new ConfigurationParameter[] { parameter }; 263 264 IConfigurationSetProcessorFactory dynamicFactory = await this.fixture.ConfigurationStatics.CreateConfigurationSetProcessorFactoryAsync(Helpers.Constants.DynamicRuntimeHandlerIdentifier); 265 266 ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(dynamicFactory); 267 268 // While parameters are not supported, we expect to get a not implemented exception. 269 // Once they are implemented, swap to the appropriate error mechanism for the parameter integrity boundary. 270 Assert.Throws<NotImplementedException>(() => processor.ApplySet(configurationSet, ApplyConfigurationSetFlags.None)); 271 } 272 273 /// <summary> 274 /// Verifies that DynamicFactoryProcessors do not break on empty set when working with only units. 275 /// </summary> 276 /// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns> 277 [Fact] 278 public async Task CreateDynamicFactoryProcessorsWithEmptyConfigurationSet() 279 { 280 string resourceName = "E2ETestResourcePID"; 281 string moduleName = "xE2ETestResource"; 282 Version version = new Version("0.0.0.1"); 283 284 string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); 285 Directory.CreateDirectory(tempDirectory); 286 287 ConfigurationUnit unit = this.ConfigurationUnit(); 288 unit.Metadata.Add("version", version.ToString()); 289 unit.Metadata.Add("module", moduleName); 290 unit.Settings.Add("directoryPath", tempDirectory); 291 unit.Type = resourceName; 292 unit.Intent = ConfigurationUnitIntent.Inform; 293 294 IConfigurationSetProcessorFactory dynamicFactory = await this.fixture.ConfigurationStatics.CreateConfigurationSetProcessorFactoryAsync(Helpers.Constants.DynamicRuntimeHandlerIdentifier); 295 296 ConfigurationProcessor processor = this.CreateConfigurationProcessorWithDiagnostics(dynamicFactory); 297 298 var result = await processor.GetUnitSettingsAsync(unit); 299 300 Assert.NotNull(result); 301 } 302 } 303 }