DSCv3AdminSettingsResourceCommand.cs (18214B)
1 // ----------------------------------------------------------------------------- 2 // <copyright file="DSCv3AdminSettingsResourceCommand.cs" company="Microsoft Corporation"> 3 // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 4 // </copyright> 5 // ----------------------------------------------------------------------------- 6 7 namespace AppInstallerCLIE2ETests 8 { 9 using System.Collections.Generic; 10 using System.Text.Json; 11 using System.Text.Json.Nodes; 12 using System.Text.Json.Serialization; 13 using AppInstallerCLIE2ETests.Helpers; 14 using NUnit.Framework; 15 16 /// <summary> 17 /// `Configure` command tests. 18 /// </summary> 19 [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1010:Opening square brackets should be spaced correctly", Justification = "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3687 pending SC 1.2 release")] 20 [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1011:Closing square brackets should be spaced correctly", Justification = "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3687 pending SC 1.2 release")] 21 public class DSCv3AdminSettingsResourceCommand : DSCv3ResourceTestBase 22 { 23 private const string AdminSettingsResource = "admin-settings"; 24 private const string SettingsPropertyName = "settings"; 25 26 // Bool settings 27 private const string BypassCertificatePinningForMicrosoftStore = "BypassCertificatePinningForMicrosoftStore"; 28 private const string InstallerHashOverride = "InstallerHashOverride"; 29 private const string LocalArchiveMalwareScanOverride = "LocalArchiveMalwareScanOverride"; 30 private const string LocalManifestFiles = "LocalManifestFiles"; 31 private const string ProxyCommandLineOptions = "ProxyCommandLineOptions"; 32 33 // String settings 34 private const string DefaultProxy = "DefaultProxy"; 35 36 // Not a setting 37 private const string NotAnAdminSettingName = "NotAnAdminSetting"; 38 39 /// <summary> 40 /// Setup done once before all the tests here. 41 /// </summary> 42 [OneTimeSetUp] 43 public void OneTimeSetup() 44 { 45 EnsureTestResourcePresence(); 46 } 47 48 /// <summary> 49 /// Teardown done once after all the tests here. 50 /// </summary> 51 [OneTimeTearDown] 52 public void OneTimeTeardown() 53 { 54 ResetAllSettings(); 55 GroupPolicyHelper.DeleteExistingPolicies(); 56 } 57 58 /// <summary> 59 /// Set up. 60 /// </summary> 61 [SetUp] 62 public void Setup() 63 { 64 ResetAllSettings(); 65 GroupPolicyHelper.DeleteExistingPolicies(); 66 } 67 68 /// <summary> 69 /// Calls `get` on the `admin-settings` resource with the value not present. 70 /// </summary> 71 /// <param name="function">The resource function to invoke.</param> 72 [TestCase(GetFunction)] 73 [TestCase(ExportFunction)] 74 public void AdminSettings_Get(string function) 75 { 76 var result = RunDSCv3Command(AdminSettingsResource, function, null); 77 AssertSuccessfulResourceRun(ref result); 78 79 AdminSettingsResourceData output = GetSingleOutputLineAs<AdminSettingsResourceData>(result.StdOut); 80 Assert.IsNotNull(output); 81 Assert.IsNotNull(output.Settings); 82 Assert.IsTrue(output.Settings.ContainsKey(LocalManifestFiles)); 83 Assert.IsFalse(output.Settings.ContainsKey(DefaultProxy)); 84 Assert.IsFalse(output.Settings.ContainsKey(NotAnAdminSettingName)); 85 } 86 87 /// <summary> 88 /// Calls `test` on the `admin-settings` resource with a bool setting. 89 /// </summary> 90 /// <param name="settingName">The setting to test.</param> 91 [TestCase(BypassCertificatePinningForMicrosoftStore)] 92 [TestCase(InstallerHashOverride)] 93 [TestCase(LocalArchiveMalwareScanOverride)] 94 [TestCase(LocalManifestFiles)] 95 [TestCase(ProxyCommandLineOptions)] 96 public void AdminSettings_Test_BoolSetting(string settingName) 97 { 98 AdminSettingsResourceData resourceData = new AdminSettingsResourceData() { Settings = new JsonObject() }; 99 100 resourceData.Settings[settingName] = true; 101 var result = RunDSCv3Command(AdminSettingsResource, TestFunction, resourceData); 102 AssertTestOfBoolSetting(ref result, settingName, false, true); 103 104 resourceData.Settings[settingName] = false; 105 result = RunDSCv3Command(AdminSettingsResource, TestFunction, resourceData); 106 AssertTestOfBoolSetting(ref result, settingName, false, false); 107 108 Assert.AreEqual(Constants.ErrorCode.S_OK, TestCommon.RunAICLICommand("settings", $"--enable {settingName}").ExitCode); 109 110 resourceData.Settings[settingName] = false; 111 result = RunDSCv3Command(AdminSettingsResource, TestFunction, resourceData); 112 AssertTestOfBoolSetting(ref result, settingName, true, false); 113 114 resourceData.Settings[settingName] = true; 115 result = RunDSCv3Command(AdminSettingsResource, TestFunction, resourceData); 116 AssertTestOfBoolSetting(ref result, settingName, true, true); 117 } 118 119 /// <summary> 120 /// Calls `test` on the `admin-settings` resource with a string setting. 121 /// </summary> 122 /// <param name="settingName">The setting to test.</param> 123 [TestCase(DefaultProxy)] 124 public void AdminSettings_Test_StringSetting(string settingName) 125 { 126 const string testValue = "A string to test"; 127 const string differentTestValue = "A different value"; 128 129 AdminSettingsResourceData resourceData = new AdminSettingsResourceData() { Settings = new JsonObject() }; 130 131 resourceData.Settings[settingName] = null; 132 var result = RunDSCv3Command(AdminSettingsResource, TestFunction, resourceData); 133 AssertTestOfStringSetting(ref result, settingName, null, null); 134 135 resourceData.Settings[settingName] = testValue; 136 result = RunDSCv3Command(AdminSettingsResource, TestFunction, resourceData); 137 AssertTestOfStringSetting(ref result, settingName, null, testValue); 138 139 Assert.AreEqual(Constants.ErrorCode.S_OK, TestCommon.RunAICLICommand("settings set", $"{settingName} \"{testValue}\"").ExitCode); 140 141 resourceData.Settings[settingName] = null; 142 result = RunDSCv3Command(AdminSettingsResource, TestFunction, resourceData); 143 AssertTestOfStringSetting(ref result, settingName, testValue, null); 144 145 resourceData.Settings[settingName] = testValue; 146 result = RunDSCv3Command(AdminSettingsResource, TestFunction, resourceData); 147 AssertTestOfStringSetting(ref result, settingName, testValue, testValue); 148 149 resourceData.Settings[settingName] = differentTestValue; 150 result = RunDSCv3Command(AdminSettingsResource, TestFunction, resourceData); 151 AssertTestOfStringSetting(ref result, settingName, testValue, differentTestValue); 152 } 153 154 /// <summary> 155 /// Calls `test` on the `admin-settings` resource with a complex input. 156 /// </summary> 157 [Test] 158 public void AdminSettings_Test_Complex() 159 { 160 Assert.AreEqual(Constants.ErrorCode.S_OK, TestCommon.RunAICLICommand("settings", $"--enable {LocalArchiveMalwareScanOverride}").ExitCode); 161 Assert.AreEqual(Constants.ErrorCode.S_OK, TestCommon.RunAICLICommand("settings", $"--enable {LocalManifestFiles}").ExitCode); 162 163 AdminSettingsResourceData resourceData = new AdminSettingsResourceData() { Settings = new JsonObject() }; 164 resourceData.Settings[LocalArchiveMalwareScanOverride] = true; 165 resourceData.Settings[BypassCertificatePinningForMicrosoftStore] = false; 166 resourceData.Settings[DefaultProxy] = null; 167 168 var result = RunDSCv3Command(AdminSettingsResource, TestFunction, resourceData); 169 AssertSuccessfulResourceRun(ref result); 170 171 (AdminSettingsResourceData output, List<string> diff) = GetSingleOutputLineAndDiffAs<AdminSettingsResourceData>(result.StdOut); 172 Assert.IsNotNull(output); 173 Assert.IsTrue(output.InDesiredState); 174 Assert.IsNotNull(output.Settings); 175 176 AssertDiffState(diff, []); 177 } 178 179 /// <summary> 180 /// Calls `set` on the `admin-settings` resource with a bool setting. 181 /// </summary> 182 /// <param name="settingName">The setting to test.</param> 183 [TestCase(BypassCertificatePinningForMicrosoftStore)] 184 [TestCase(InstallerHashOverride)] 185 [TestCase(LocalArchiveMalwareScanOverride)] 186 [TestCase(LocalManifestFiles)] 187 [TestCase(ProxyCommandLineOptions)] 188 public void AdminSettings_Set_BoolSetting(string settingName) 189 { 190 AdminSettingsResourceData resourceData = new AdminSettingsResourceData() { Settings = new JsonObject() }; 191 192 resourceData.Settings[settingName] = true; 193 var result = RunDSCv3Command(AdminSettingsResource, SetFunction, resourceData); 194 AssertSetOfBoolSetting(ref result, settingName, false, true); 195 196 result = RunDSCv3Command(AdminSettingsResource, SetFunction, resourceData); 197 AssertSetOfBoolSetting(ref result, settingName, true, true); 198 199 resourceData.Settings[settingName] = false; 200 result = RunDSCv3Command(AdminSettingsResource, SetFunction, resourceData); 201 AssertSetOfBoolSetting(ref result, settingName, true, false); 202 203 result = RunDSCv3Command(AdminSettingsResource, SetFunction, resourceData); 204 AssertSetOfBoolSetting(ref result, settingName, false, false); 205 } 206 207 /// <summary> 208 /// Calls `set` on the `admin-settings` resource with a string setting. 209 /// </summary> 210 /// <param name="settingName">The setting to test.</param> 211 [TestCase(DefaultProxy)] 212 public void AdminSettings_Set_StringSetting(string settingName) 213 { 214 const string testValue = "A string to test"; 215 const string differentTestValue = "A different value"; 216 217 AdminSettingsResourceData resourceData = new AdminSettingsResourceData() { Settings = new JsonObject() }; 218 219 resourceData.Settings[settingName] = null; 220 var result = RunDSCv3Command(AdminSettingsResource, SetFunction, resourceData); 221 AssertSetOfStringSetting(ref result, settingName, null, null); 222 223 resourceData.Settings[settingName] = testValue; 224 result = RunDSCv3Command(AdminSettingsResource, SetFunction, resourceData); 225 AssertSetOfStringSetting(ref result, settingName, null, testValue); 226 227 resourceData.Settings[settingName] = testValue; 228 result = RunDSCv3Command(AdminSettingsResource, SetFunction, resourceData); 229 AssertSetOfStringSetting(ref result, settingName, testValue, testValue); 230 231 resourceData.Settings[settingName] = differentTestValue; 232 result = RunDSCv3Command(AdminSettingsResource, SetFunction, resourceData); 233 AssertSetOfStringSetting(ref result, settingName, testValue, differentTestValue); 234 235 resourceData.Settings[settingName] = null; 236 result = RunDSCv3Command(AdminSettingsResource, SetFunction, resourceData); 237 AssertSetOfStringSetting(ref result, settingName, differentTestValue, null); 238 } 239 240 /// <summary> 241 /// Calls `set` on the `admin-settings` resource with a complex input. 242 /// </summary> 243 [Test] 244 public void AdminSettings_Set_Complex() 245 { 246 const string testValue = "A string to test"; 247 248 AdminSettingsResourceData resourceData = new AdminSettingsResourceData() { Settings = new JsonObject() }; 249 resourceData.Settings[LocalArchiveMalwareScanOverride] = true; 250 resourceData.Settings[BypassCertificatePinningForMicrosoftStore] = false; 251 resourceData.Settings[DefaultProxy] = testValue; 252 253 var result = RunDSCv3Command(AdminSettingsResource, SetFunction, resourceData); 254 AssertSuccessfulResourceRun(ref result); 255 256 (AdminSettingsResourceData output, List<string> diff) = GetSingleOutputLineAndDiffAs<AdminSettingsResourceData>(result.StdOut); 257 Assert.IsNotNull(output); 258 Assert.IsNotNull(output.Settings); 259 Assert.AreEqual(JsonValueKind.True, output.Settings[LocalArchiveMalwareScanOverride].AsValue().GetValueKind()); 260 Assert.AreEqual(JsonValueKind.False, output.Settings[BypassCertificatePinningForMicrosoftStore].AsValue().GetValueKind()); 261 Assert.AreEqual(testValue, output.Settings[DefaultProxy].AsValue().GetValue<string>()); 262 263 AssertDiffState(diff, [ SettingsPropertyName ]); 264 } 265 266 /// <summary> 267 /// Calls `set` on the `admin-settings` resource attempting to change a setting with group policy enabled. 268 /// </summary> 269 [Test] 270 public void AdminSettings_Set_GroupPolicyBlocked() 271 { 272 GroupPolicyHelper.EnableHashOverride.Disable(); 273 274 AdminSettingsResourceData resourceData = new AdminSettingsResourceData() { Settings = new JsonObject() }; 275 resourceData.Settings[InstallerHashOverride] = true; 276 277 var result = RunDSCv3Command(AdminSettingsResource, SetFunction, resourceData); 278 Assert.AreEqual(Constants.ErrorCode.ERROR_BLOCKED_BY_POLICY, result.ExitCode); 279 } 280 281 private static void ResetAllSettings() 282 { 283 Assert.AreEqual(Constants.ErrorCode.S_OK, TestCommon.RunAICLICommand("settings reset", "--all").ExitCode); 284 } 285 286 private static void AssertTestOfBoolSetting(ref TestCommon.RunCommandResult result, string settingName, bool expectedState, bool testState) 287 { 288 AssertSuccessfulResourceRun(ref result); 289 290 bool inDesiredState = expectedState == testState; 291 292 (AdminSettingsResourceData output, List<string> diff) = GetSingleOutputLineAndDiffAs<AdminSettingsResourceData>(result.StdOut); 293 Assert.IsNotNull(output); 294 Assert.AreEqual(inDesiredState, output.InDesiredState); 295 Assert.IsNotNull(output.Settings); 296 Assert.IsTrue(output.Settings.ContainsKey(settingName)); 297 Assert.AreEqual(expectedState ? JsonValueKind.True : JsonValueKind.False, output.Settings[settingName].AsValue().GetValueKind()); 298 299 AssertDiffState(diff, inDesiredState ? [] : [ SettingsPropertyName ]); 300 } 301 302 private static void AssertSetOfBoolSetting(ref TestCommon.RunCommandResult result, string settingName, bool previousState, bool desiredState) 303 { 304 AssertSuccessfulResourceRun(ref result); 305 306 bool inDesiredState = previousState == desiredState; 307 308 (AdminSettingsResourceData output, List<string> diff) = GetSingleOutputLineAndDiffAs<AdminSettingsResourceData>(result.StdOut); 309 Assert.IsNotNull(output); 310 Assert.IsNotNull(output.Settings); 311 Assert.IsTrue(output.Settings.ContainsKey(settingName)); 312 Assert.AreEqual(desiredState ? JsonValueKind.True : JsonValueKind.False, output.Settings[settingName].AsValue().GetValueKind()); 313 314 AssertDiffState(diff, inDesiredState ? [] : [ SettingsPropertyName ]); 315 } 316 317 private static void AssertTestOfStringSetting(ref TestCommon.RunCommandResult result, string settingName, string expectedState, string testState) 318 { 319 AssertSuccessfulResourceRun(ref result); 320 321 bool inDesiredState = expectedState == testState; 322 323 (AdminSettingsResourceData output, List<string> diff) = GetSingleOutputLineAndDiffAs<AdminSettingsResourceData>(result.StdOut); 324 Assert.IsNotNull(output); 325 Assert.AreEqual(inDesiredState, output.InDesiredState); 326 Assert.IsNotNull(output.Settings); 327 if (expectedState != null) 328 { 329 Assert.IsTrue(output.Settings.ContainsKey(settingName)); 330 Assert.AreEqual(expectedState, output.Settings[settingName].AsValue().GetValue<string>()); 331 } 332 else 333 { 334 Assert.IsFalse(output.Settings.ContainsKey(settingName)); 335 } 336 337 AssertDiffState(diff, inDesiredState ? [] : [SettingsPropertyName]); 338 } 339 340 private static void AssertSetOfStringSetting(ref TestCommon.RunCommandResult result, string settingName, string previousState, string desiredState) 341 { 342 AssertSuccessfulResourceRun(ref result); 343 344 bool inDesiredState = previousState == desiredState; 345 346 (AdminSettingsResourceData output, List<string> diff) = GetSingleOutputLineAndDiffAs<AdminSettingsResourceData>(result.StdOut); 347 Assert.IsNotNull(output); 348 Assert.IsNotNull(output.Settings); 349 if (desiredState != null) 350 { 351 Assert.IsTrue(output.Settings.ContainsKey(settingName)); 352 Assert.AreEqual(desiredState, output.Settings[settingName].AsValue().GetValue<string>()); 353 } 354 else 355 { 356 Assert.IsFalse(output.Settings.ContainsKey(settingName)); 357 } 358 359 AssertDiffState(diff, inDesiredState ? [] : [SettingsPropertyName]); 360 } 361 362 private class AdminSettingsResourceData 363 { 364 [JsonPropertyName(InDesiredStatePropertyName)] 365 public bool? InDesiredState { get; set; } 366 367 public JsonObject Settings { get; set; } 368 } 369 } 370 }