Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

restrict to specific list of providers and allow settings #498

Merged
merged 6 commits into from
Dec 12, 2024
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -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<string>() { allow },
#endif
DenyNamespaces = new List<string>() { 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");

Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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<TestEngineExtensionChecker> mockChecker = new Mock<TestEngineExtensionChecker>();

Expand Down Expand Up @@ -83,36 +95,39 @@ 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<TestEngineExtensionChecker> mockChecker = new Mock<TestEngineExtensionChecker>();

var loader = new TestEngineModuleMEFLoader(MockLogger.Object);
loader.DirectoryGetFiles = (location, pattern) =>
{
var searchPattern = Regex.Escape(pattern).Replace(@"\*", ".*?");
return pattern.Contains(providerType) ? new List<string>() { assemblyName }.ToArray() : new string[] { };
return pattern.Contains(providerType) ? new List<string>() { 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<string>(p => p.Contains(assemblyName)))).Returns(verify);
mockChecker.Setup(m => m.Verify(setting, It.Is<string>(p => p.Contains(assemblyName)))).Returns(valid);

if (valid)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<string> InstallSource { get; } = new List<string>();
#else
public bool EnableNuGet { get; set; } = false;

public bool EnableFileSystem { get; set; } = false;

public List<string> InstallSource { get; set; } = new List<string>();
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,21 @@ public class TestSettingExtensions
/// <summary>
/// Determine if extension modules should be checks for Namespace rules
/// </summary>
#if RELEASE
public bool CheckAssemblies { get; } = true;
#else
public bool CheckAssemblies { get; set; } = true;
#endif

/// <summary>
/// List of allowed Test Engine Modules that can be referenced.
/// </summary>
#if RELEASE
//restricting for current milestone 1
public List<string> AllowModule { get; } = new List<string>();
#else
public List<string> AllowModule { get; set; } = new List<string>();
#endif

/// <summary>
/// List of allowed Test Engine Modules cannot be loaded unless there is an explict allow
Expand All @@ -33,7 +42,12 @@ public class TestSettingExtensions
/// <summary>
/// List of allowed .Net Namespaces that can be referenced in a Test Engine Module
/// </summary>
#if RELEASE
//restricting for current milestone 1
public List<string> AllowNamespaces { get; } = new List<string>();
#else
public List<string> AllowNamespaces { get; set; } = new List<string>();
#endif

/// <summary>
/// List of allowed .Net Namespaces that deney load unless explict allow is defined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -241,19 +245,23 @@ public virtual bool ValidateProvider(TestSettingExtensions settings, string file
/// <returns><c>True</c> if the assembly meets the test setting requirements, <c>False</c> if not</returns>
public virtual bool Validate(TestSettingExtensions settings, string file)
{
var contents = GetExtentionContents(file);

var allowList = new List<string>(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<string>(settings.DenyNamespaces);
var allowList = new List<string>(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<string>(settings.DenyNamespaces)
{
"Microsoft.PowerApps.TestEngine.Modules.",
};

byte[] contents = GetExtentionContents(file);
var found = LoadTypes(contents);

var valid = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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))
Expand All @@ -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))
Expand Down
17 changes: 5 additions & 12 deletions src/Microsoft.PowerApps.TestEngine/System/FileSystem.cs
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.PowerApps.TestEngine/Users/IUserManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public interface IUserManager
/// The location to use for this user session
/// </summary>
/// <value>Path or resource where the user session should be located</value>
public string Location { get; set; }
public string Location { get; }

/// <summary>
/// Log in as user for currently running test
Expand Down
4 changes: 2 additions & 2 deletions src/PowerAppsTestEngine/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -156,7 +156,7 @@
provider = inputOptions.Provider;
}

var auth = "localcert";
var auth = "default";
if (!string.IsNullOrEmpty(inputOptions.UserAuthType))
{
auth = inputOptions.UserAuthType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -130,6 +131,7 @@ public async Task ValidLogin(string emailKey, string emailValue, string desiredU
MockTestState.Setup(x => x.GetUserConfiguration(It.IsAny<string>())).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<IPage>() { MockPage.Object });
MockPage.SetupGet(x => x.Url).Returns(pageUrl);
Expand Down Expand Up @@ -173,6 +175,7 @@ public async Task ErrorLogin(string emailKey, string emailValue, string desiredU
MockTestState.Setup(x => x.GetUserConfiguration(It.IsAny<string>())).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<IPage>() { MockPage.Object });
MockPage.SetupGet(x => x.Url).Returns(pageUrl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ private Func<IEnvironmentVariable, ISingleTestInstanceState, ITestState, IFileSy
var user = environmentVariable.GetVariable(userConfig.EmailKey);
var userName = GetUserNameFromEmail(user);
Location = !Location.EndsWith($"-{userName}") ? Location += $"-{userName}" : Location;
Location = !Path.IsPathRooted(Location) ? Path.Combine(fileSystem.GetDefaultRootTestEngine(), Location) : Location;
if (!IsValidEmail(user))
{
return String.Empty;
Expand Down Expand Up @@ -151,6 +152,7 @@ public async Task LoginAsUserAsync(

var userName = GetUserNameFromEmail(user);
Location = !Location.EndsWith($"-{userName}") ? Location += $"-{userName}" : Location;
Location = !Path.IsPathRooted(Location) ? Path.Combine(fileSystem.GetDefaultRootTestEngine(), Location) : Location;

if (!fileSystem.Exists(Location))
{
Expand Down
Loading