diff --git a/src/Microsoft.PowerApps.TestEngine.Tests/Modules/TestEngineExtensionCheckerTests.cs b/src/Microsoft.PowerApps.TestEngine.Tests/Modules/TestEngineExtensionCheckerTests.cs index 310b108b..589a4bd7 100644 --- a/src/Microsoft.PowerApps.TestEngine.Tests/Modules/TestEngineExtensionCheckerTests.cs +++ b/src/Microsoft.PowerApps.TestEngine.Tests/Modules/TestEngineExtensionCheckerTests.cs @@ -207,9 +207,19 @@ public void IsValid(string usingStatements, string script, bool useTemplate, str var settings = new TestSettingExtensions() { Enable = true, +#if RELEASE +#else AllowNamespaces = new List() { allow }, +#endif DenyNamespaces = new List() { deny } }; +#if RELEASE + if (!string.IsNullOrWhiteSpace(allow) && !settings.AllowNamespaces.Contains(allow)) + { + //not a valid scenario since it cant be assigned if not already present or blank + return; + } +#endif var result = checker.Validate(settings, "testengine.module.test.dll"); @@ -369,10 +379,18 @@ public void Verify(bool checkCertificates, bool sign, bool allowUntrustedRoot, s { settings.Parameters.Add("TrustedSource", trustedSource); } +#if RELEASE + if (allowUntrustedRoot) + { + //not a valid scenario since it cant be assigned + return; + } +#else if (allowUntrustedRoot) { settings.Parameters.Add("AllowUntrustedRoot", "True"); } +#endif var valid = false; try diff --git a/src/Microsoft.PowerApps.TestEngine.Tests/Modules/TestEngineModuleMEFLoaderTests.cs b/src/Microsoft.PowerApps.TestEngine.Tests/Modules/TestEngineModuleMEFLoaderTests.cs index 2c87876f..615f0c0e 100644 --- a/src/Microsoft.PowerApps.TestEngine.Tests/Modules/TestEngineModuleMEFLoaderTests.cs +++ b/src/Microsoft.PowerApps.TestEngine.Tests/Modules/TestEngineModuleMEFLoaderTests.cs @@ -3,11 +3,13 @@ using System.Collections.Generic; using System.ComponentModel.Composition.Hosting; +using System.IO; using System.Linq; using System.Text.RegularExpressions; using Microsoft.Extensions.Logging; using Microsoft.PowerApps.TestEngine.Config; using Microsoft.PowerApps.TestEngine.Modules; +using Microsoft.VisualStudio.TestPlatform.Common.Utilities; using Moq; using Xunit; @@ -44,10 +46,20 @@ public void DisabledEmptyCatalog() [InlineData(true, true, "*", "", "testengine.module.foo.dll", "AssemblyCatalog,AssemblyCatalog")] public void ModuleMatch(bool checkAssemblies, bool checkResult, string allow, string deny, string files, string expected) { +#if RELEASE + if (!checkAssemblies) + { + //not a valid scenario since it cant be assigned + return; + } +#endif var setting = new TestSettingExtensions() { Enable = true, +#if RELEASE +#else CheckAssemblies = checkAssemblies +#endif }; Mock mockChecker = new Mock(); @@ -83,24 +95,27 @@ public void ModuleMatch(bool checkAssemblies, bool checkResult, string allow, st } [Theory] - [InlineData("provider", true, true)] - [InlineData("provider", true, false)] - [InlineData("provider", false, false)] - [InlineData("user", true, true)] - [InlineData("user", true, false)] - [InlineData("user", false, false)] - [InlineData("auth", true, true)] - [InlineData("auth", true, false)] - [InlineData("auth", false, false)] - public void ProviderMatch(string providerType, bool verify, bool valid) + [InlineData("provider", "mda", true, true)] + [InlineData("provider", "test", true, false)] + [InlineData("provider", "test", false, false)] + [InlineData("user", "storagestate", true, true)] + [InlineData("user", "test", true, false)] + [InlineData("user", "test", false, false)] + [InlineData("auth", "certstore", true, true, Skip = "No auth providers whitelisted for releases")] + [InlineData("auth", "test", true, false)] + [InlineData("auth", "test", false, false)] + public void ProviderMatch(string providerType, string specificName, bool verify, bool valid) { // Arrange - var assemblyName = $"testengine.{providerType}.test.dll"; + var assemblyName = $"testengine.{providerType}.{specificName}.dll"; var setting = new TestSettingExtensions() { Enable = true, +#if RELEASE +#else CheckAssemblies = true +#endif }; Mock mockChecker = new Mock(); @@ -108,11 +123,11 @@ public void ProviderMatch(string providerType, bool verify, bool valid) loader.DirectoryGetFiles = (location, pattern) => { var searchPattern = Regex.Escape(pattern).Replace(@"\*", ".*?"); - return pattern.Contains(providerType) ? new List() { assemblyName }.ToArray() : new string[] { }; + return pattern.Contains(providerType) ? new List() { Path.Combine(location, assemblyName) }.ToArray() : new string[] { }; }; - mockChecker.Setup(m => m.ValidateProvider(setting, assemblyName)).Returns(verify); - mockChecker.Setup(m => m.Verify(setting, assemblyName)).Returns(valid); + mockChecker.Setup(m => m.ValidateProvider(setting, It.Is(p => p.Contains(assemblyName)))).Returns(verify); + mockChecker.Setup(m => m.Verify(setting, It.Is(p => p.Contains(assemblyName)))).Returns(valid); if (valid) { diff --git a/src/Microsoft.PowerApps.TestEngine/Config/TestSettingExtensionSource.cs b/src/Microsoft.PowerApps.TestEngine/Config/TestSettingExtensionSource.cs index e793bd8a..492b0f76 100644 --- a/src/Microsoft.PowerApps.TestEngine/Config/TestSettingExtensionSource.cs +++ b/src/Microsoft.PowerApps.TestEngine/Config/TestSettingExtensionSource.cs @@ -8,14 +8,20 @@ public class TestSettingExtensionSource { public TestSettingExtensionSource() { - EnableFileSystem = true; + EnableFileSystem = false; InstallSource.Add(Path.GetDirectoryName(this.GetType().Assembly.Location)); } +#if RELEASE + public bool EnableNuGet { get; } = false; + public bool EnableFileSystem { get; } = false; + public List InstallSource { get; } = new List(); +#else public bool EnableNuGet { get; set; } = false; public bool EnableFileSystem { get; set; } = false; public List InstallSource { get; set; } = new List(); +#endif } } diff --git a/src/Microsoft.PowerApps.TestEngine/Config/TestSettingExtensions.cs b/src/Microsoft.PowerApps.TestEngine/Config/TestSettingExtensions.cs index 0405931e..c4fd8ef9 100644 --- a/src/Microsoft.PowerApps.TestEngine/Config/TestSettingExtensions.cs +++ b/src/Microsoft.PowerApps.TestEngine/Config/TestSettingExtensions.cs @@ -18,12 +18,21 @@ public class TestSettingExtensions /// /// Determine if extension modules should be checks for Namespace rules /// +#if RELEASE + public bool CheckAssemblies { get; } = true; +#else public bool CheckAssemblies { get; set; } = true; +#endif /// /// List of allowed Test Engine Modules that can be referenced. /// +#if RELEASE + //restricting for current milestone 1 + public List AllowModule { get; } = new List(); +#else public List AllowModule { get; set; } = new List(); +#endif /// /// List of allowed Test Engine Modules cannot be loaded unless there is an explict allow @@ -33,7 +42,12 @@ public class TestSettingExtensions /// /// List of allowed .Net Namespaces that can be referenced in a Test Engine Module /// +#if RELEASE + //restricting for current milestone 1 + public List AllowNamespaces { get; } = new List(); +#else public List AllowNamespaces { get; set; } = new List(); +#endif /// /// List of allowed .Net Namespaces that deney load unless explict allow is defined diff --git a/src/Microsoft.PowerApps.TestEngine/Modules/TestEngineExtensionChecker.cs b/src/Microsoft.PowerApps.TestEngine/Modules/TestEngineExtensionChecker.cs index eae69fda..14bfa614 100644 --- a/src/Microsoft.PowerApps.TestEngine/Modules/TestEngineExtensionChecker.cs +++ b/src/Microsoft.PowerApps.TestEngine/Modules/TestEngineExtensionChecker.cs @@ -87,10 +87,14 @@ public virtual bool Verify(TestSettingExtensions settings, string file) var sources = GetTrustedSources(settings); var allowUntrustedRoot = false; +#if RELEASE + //dont allow untrusted +#else if (settings.Parameters.ContainsKey("AllowUntrustedRoot")) { allowUntrustedRoot = bool.Parse(settings.Parameters["AllowUntrustedRoot"]); } +#endif foreach (var elem in chain.ChainElements) { @@ -241,19 +245,23 @@ public virtual bool ValidateProvider(TestSettingExtensions settings, string file /// True if the assembly meets the test setting requirements, False if not public virtual bool Validate(TestSettingExtensions settings, string file) { - var contents = GetExtentionContents(file); - - var allowList = new List(settings.AllowNamespaces); - // Add minimum namespaces for a MEF plugin used by TestEngine - allowList.Add("System.Threading.Tasks"); - allowList.Add("Microsoft.PowerFx"); - allowList.Add("System.ComponentModel.Composition"); - allowList.Add("Microsoft.Extensions.Logging"); - allowList.Add("Microsoft.PowerApps.TestEngine."); - allowList.Add("Microsoft.Playwright"); - - var denyList = new List(settings.DenyNamespaces); + var allowList = new List(settings.AllowNamespaces) + { + // Add minimum namespaces for a MEF plugin used by TestEngine + "System.Threading.Tasks", + "Microsoft.PowerFx", + "System.ComponentModel.Composition", + "Microsoft.Extensions.Logging", + "Microsoft.PowerApps.TestEngine.", + "Microsoft.Playwright" + }; + + var denyList = new List(settings.DenyNamespaces) + { + "Microsoft.PowerApps.TestEngine.Modules.", + }; + byte[] contents = GetExtentionContents(file); var found = LoadTypes(contents); var valid = true; diff --git a/src/Microsoft.PowerApps.TestEngine/Modules/TestEngineModuleMEFLoader.cs b/src/Microsoft.PowerApps.TestEngine/Modules/TestEngineModuleMEFLoader.cs index cd49aa19..04c1550b 100644 --- a/src/Microsoft.PowerApps.TestEngine/Modules/TestEngineModuleMEFLoader.cs +++ b/src/Microsoft.PowerApps.TestEngine/Modules/TestEngineModuleMEFLoader.cs @@ -88,6 +88,11 @@ public AggregateCatalog LoadModules(TestSettingExtensions settings) } var possibleUserManager = DirectoryGetFiles(location, "testengine.user.*.dll"); +#if RELEASE + //temporarily limiting to a fixed set of providers, move to allow deny list later #410 + var allowedUserManager = new string[] { Path.Combine(location, "testengine.user.storagestate.dll") }; + possibleUserManager = possibleUserManager.Where(file => allowedUserManager.Contains(file)).ToArray(); +#endif foreach (var possibleModule in possibleUserManager) { if (!Checker.ValidateProvider(settings, possibleModule)) @@ -103,6 +108,11 @@ public AggregateCatalog LoadModules(TestSettingExtensions settings) } var possibleWebProviderModule = DirectoryGetFiles(location, "testengine.provider.*.dll"); +#if RELEASE + //temporarily limiting to a fixed set of providers, move to allow deny list later #410 + var allowedProviderManager = new string[] { Path.Combine(location, "testengine.provider.canvas.dll"), Path.Combine(location, "testengine.provider.mda.dll"), Path.Combine(location, "testengine.provider.powerapps.portal.dll") }; + possibleWebProviderModule = possibleWebProviderModule.Where(file => allowedProviderManager.Contains(file)).ToArray(); +#endif foreach (var possibleModule in possibleWebProviderModule) { if (!Checker.ValidateProvider(settings, possibleModule)) @@ -118,6 +128,11 @@ public AggregateCatalog LoadModules(TestSettingExtensions settings) } var possibleAuthTypeProviderModule = DirectoryGetFiles(location, "testengine.auth.*.dll"); +#if RELEASE + //temporarily limiting to a fixed set of providers for milestone 2, move to allow deny list later #410 + var allowedAuthTypeManager = new string[] { }; + possibleAuthTypeProviderModule = possibleAuthTypeProviderModule.Where(file => allowedAuthTypeManager.Contains(file)).ToArray(); +#endif foreach (var possibleModule in possibleAuthTypeProviderModule) { if (!Checker.ValidateProvider(settings, possibleModule)) diff --git a/src/Microsoft.PowerApps.TestEngine/System/FileSystem.cs b/src/Microsoft.PowerApps.TestEngine/System/FileSystem.cs index 8b798d26..42effb51 100644 --- a/src/Microsoft.PowerApps.TestEngine/System/FileSystem.cs +++ b/src/Microsoft.PowerApps.TestEngine/System/FileSystem.cs @@ -1,20 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -using System; -using System.Collections.Generic; -using System.ComponentModel; using System.ComponentModel.Composition; -using System.Drawing; -using System.IO; using System.Runtime.InteropServices; -using System.Text.RegularExpressions; -using ICSharpCode.Decompiler.CSharp; -using ICSharpCode.Decompiler.IL; -using ICSharpCode.Decompiler.Metadata; -using Microsoft.Playwright; -using Microsoft.PowerApps.TestEngine.Config; -using static System.Net.Mime.MediaTypeNames; namespace Microsoft.PowerApps.TestEngine.System { @@ -284,6 +272,11 @@ public bool WindowsReservedLocationExistsInPath(string fullPath) public bool LinuxReservedLocationExistsInPath(string fullPath) { fullPath = Path.GetFullPath(fullPath); + + if (fullPath.Equals("/")) + { + return true; + } //check if its a network path if so fail var fullPathUri = new Uri(fullPath.StartsWith(@"\\?\") ? fullPath.Replace(@"\\?\", "") : fullPath, UriKind.Absolute); if (fullPathUri.IsUnc) diff --git a/src/Microsoft.PowerApps.TestEngine/Users/IUserManager.cs b/src/Microsoft.PowerApps.TestEngine/Users/IUserManager.cs index f013d432..b80d3572 100644 --- a/src/Microsoft.PowerApps.TestEngine/Users/IUserManager.cs +++ b/src/Microsoft.PowerApps.TestEngine/Users/IUserManager.cs @@ -39,7 +39,7 @@ public interface IUserManager /// The location to use for this user session /// /// Path or resource where the user session should be located - public string Location { get; set; } + public string Location { get; } /// /// Log in as user for currently running test diff --git a/src/PowerAppsTestEngine/Program.cs b/src/PowerAppsTestEngine/Program.cs index f9a955dd..69e99c7a 100644 --- a/src/PowerAppsTestEngine/Program.cs +++ b/src/PowerAppsTestEngine/Program.cs @@ -144,7 +144,7 @@ logLevel = LogLevel.Information; } - var userAuth = "browser"; // Default to brower authentication + var userAuth = "storagestate"; // Default to storage state if (!string.IsNullOrEmpty(inputOptions.UserAuth)) { userAuth = inputOptions.UserAuth; @@ -156,7 +156,7 @@ provider = inputOptions.Provider; } - var auth = "localcert"; + var auth = "default"; if (!string.IsNullOrEmpty(inputOptions.UserAuthType)) { auth = inputOptions.UserAuthType; diff --git a/src/testengine.provider.mda/ModelDrivenApplicationProvider.cs b/src/testengine.provider.mda/ModelDrivenApplicationProvider.cs index d6ed4143..929a9b0c 100644 --- a/src/testengine.provider.mda/ModelDrivenApplicationProvider.cs +++ b/src/testengine.provider.mda/ModelDrivenApplicationProvider.cs @@ -19,7 +19,6 @@ using Newtonsoft.Json.Linq; using testengine.provider.mda; -[assembly: InternalsVisibleTo("testengine.provider.mda.tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b5fc90e7027f67871e773a8fde8938c81dd402ba65b9201d60593e96c492651e889cc13f1415ebb53fac1131ae0bd333c5ee6021672d9718ea31a8aebd0da0072f25d87dba6fc90ffd598ed4da35e44c398c454307e8e33b8426143daec9f596836f97c8f74750e5975c64e2189f45def46b2a2b1247adc3652bf5c308055da9")] namespace Microsoft.PowerApps.TestEngine.Providers { /// diff --git a/src/testengine.user.storagestate.tests/StorageStateUserManagerModuleTests.cs b/src/testengine.user.storagestate.tests/StorageStateUserManagerModuleTests.cs index e2b6c59c..c3749497 100644 --- a/src/testengine.user.storagestate.tests/StorageStateUserManagerModuleTests.cs +++ b/src/testengine.user.storagestate.tests/StorageStateUserManagerModuleTests.cs @@ -91,6 +91,7 @@ public async Task LoadState(string? emailKey, string? emailValue, bool exists, s MockEnvironmentVariable.Setup(x => x.GetVariable(emailKey)).Returns(emailValue); LoggingTestHelper.SetupMock(MockLogger); + MockFileSystem.Setup(x => x.GetDefaultRootTestEngine()).Returns(""); MockFileSystem.Setup(x => x.Exists(".storage-state-user1")).Returns(exists); if (content != null) { @@ -130,6 +131,7 @@ public async Task ValidLogin(string emailKey, string emailValue, string desiredU MockTestState.Setup(x => x.GetUserConfiguration(It.IsAny())).Returns(userConfiguration); MockSingleTestInstanceState.Setup(x => x.GetLogger()).Returns(MockLogger.Object); MockEnvironmentVariable.Setup(x => x.GetVariable(emailKey)).Returns(emailValue); + MockFileSystem.Setup(x => x.GetDefaultRootTestEngine()).Returns(""); MockFileSystem.Setup(x => x.Exists(".storage-state-user1")).Returns(true); MockBrowserContext.Setup(x => x.Pages).Returns(new List() { MockPage.Object }); MockPage.SetupGet(x => x.Url).Returns(pageUrl); @@ -173,6 +175,7 @@ public async Task ErrorLogin(string emailKey, string emailValue, string desiredU MockTestState.Setup(x => x.GetUserConfiguration(It.IsAny())).Returns(userConfiguration); MockSingleTestInstanceState.Setup(x => x.GetLogger()).Returns(MockLogger.Object); MockEnvironmentVariable.Setup(x => x.GetVariable(emailKey)).Returns(emailValue); + MockFileSystem.Setup(x => x.GetDefaultRootTestEngine()).Returns(""); MockFileSystem.Setup(x => x.Exists(".storage-state-user1")).Returns(true); MockBrowserContext.Setup(x => x.Pages).Returns(new List() { MockPage.Object }); MockPage.SetupGet(x => x.Url).Returns(pageUrl); diff --git a/src/testengine.user.storagestate/StorageStateUserManagerModule.cs b/src/testengine.user.storagestate/StorageStateUserManagerModule.cs index 144210a8..00a88515 100644 --- a/src/testengine.user.storagestate/StorageStateUserManagerModule.cs +++ b/src/testengine.user.storagestate/StorageStateUserManagerModule.cs @@ -60,6 +60,7 @@ private Func