Move group policy settings and enable policy controlled logging in PowerShell Core (#5791)

Make PowerShell Core reads group policy settings from different registry keys (Windows only) and the configuration files (both Windows and Unix).
- On Windows, move to different GPO registry keys.
- On both Windows and Unix, read GPO related settings from the configuration file `powershell.config.json`.
- On Windows, the policy settings in registry take precedence over the configuration file.
- Enable policy controlled logging and transcription on Unix.
This commit is contained in:
Dongbo Wang authored and GitHub committed 2018-01-08 12:03:23 -08:00
commit d261e1f166
31 files changed
+1503 -787

No files matched your search

+13 -12
View File
@@ -1364,7 +1364,8 @@ function Test-PSPesterResults
function Start-PSxUnit {
[CmdletBinding()]param(
[string] $TestResultsFile = "XUnitResults.xml"
[string] $SequentialTestResultsFile = "SequentialXUnitResults.xml",
[string] $ParallelTestResultsFile = "ParallelXUnitResults.xml"
)
# Add .NET CLI tools to PATH
@@ -1375,9 +1376,11 @@ function Start-PSxUnit {
throw "PowerShell must be built before running tests!"
}
if(Test-Path $TestResultsFile)
{
Remove-Item $TestResultsFile -Force -ErrorAction SilentlyContinue
if (Test-Path $SequentialTestResultsFile) {
Remove-Item $SequentialTestResultsFile -Force -ErrorAction SilentlyContinue
}
if (Test-Path $ParallelTestResultsFile) {
Remove-Item $ParallelTestResultsFile -Force -ErrorAction SilentlyContinue
}
try {
@@ -1386,12 +1389,7 @@ function Start-PSxUnit {
# Path manipulation to obtain test project output directory
dotnet restore
# --fx-version workaround required due to https://github.com/dotnet/cli/issues/7901#issuecomment-343323674
if($Environment.IsWindows)
{
dotnet xunit --fx-version 2.0.0 -xml $TestResultsFile
}
else
if(-not $Environment.IsWindows)
{
if($Environment.IsMacOS)
{
@@ -1419,9 +1417,12 @@ function Start-PSxUnit {
{
throw "Dependencies $requiredDependencies not met."
}
dotnet xunit --fx-version 2.0.0 -configuration $Options.configuration -xml $TestResultsFile
}
# '-fxversion' workaround required due to https://github.com/dotnet/cli/issues/7901#issuecomment-343323674
# Run sequential tests first, and then run the tests that can execute in parallel
dotnet xunit -fxversion 2.0.0 -configuration $Options.configuration -xml $SequentialTestResultsFile -namespace "PSTests.Sequential" -parallel none
dotnet xunit -fxversion 2.0.0 -configuration $Options.configuration -xml $ParallelTestResultsFile -namespace "PSTests.Parallel" -nobuild
}
finally {
Pop-Location
@@ -10,6 +10,7 @@ using System.Globalization;
using System.IO;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Configuration;
using System.Management.Automation.Runspaces;
using System.Management.Automation.Internal;
using System.Diagnostics;
@@ -463,29 +464,17 @@ namespace Microsoft.PowerShell
}
}
private static string s_groupPolicyBase = @"Software\Policies\Microsoft\Windows\PowerShell";
private static string s_consoleSessionConfigurationKey = "ConsoleSessionConfiguration";
private static string s_enableConsoleSessionConfiguration = "EnableConsoleSessionConfiguration";
private static string s_consoleSessionConfigurationName = "ConsoleSessionConfigurationName";
private static string GetConfigurationNameFromGroupPolicy()
{
// Current user policy takes precedence.
var groupPolicySettings = Utils.GetGroupPolicySetting(s_groupPolicyBase, s_consoleSessionConfigurationKey, Utils.RegCurrentUserThenLocalMachine);
if (groupPolicySettings != null)
var consoleSessionSetting = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.CurrentUserThenSystemWideConfig);
if (consoleSessionSetting != null)
{
object keyValue;
if (groupPolicySettings.TryGetValue(s_enableConsoleSessionConfiguration, out keyValue))
if (consoleSessionSetting.EnableConsoleSessionConfiguration == true)
{
if (String.Equals(keyValue.ToString(), "1", StringComparison.OrdinalIgnoreCase))
if (!string.IsNullOrEmpty(consoleSessionSetting.ConsoleSessionConfigurationName))
{
if (groupPolicySettings.TryGetValue(s_consoleSessionConfigurationName, out keyValue))
{
string consoleSessionConfigurationName = keyValue.ToString();
if (!string.IsNullOrEmpty(consoleSessionConfigurationName))
{
return consoleSessionConfigurationName;
}
}
return consoleSessionSetting.ConsoleSessionConfigurationName;
}
}
}
@@ -1643,59 +1643,6 @@ namespace System.Management.Automation
internal ExecutionContext Context { get; }
/// <summary>
/// Reads the path for the appropriate shellID from the registry.
/// </summary>
///
/// <param name="shellID">
/// The ID of the shell to retrieve the path for.
/// </param>
///
/// <returns>
/// The path to the shell represented by the shellID.
/// </returns>
///
/// <remarks>
/// The shellID must be registered in the Windows Registry in either
/// the HKEY_CURRENT_USER or HKEY_LOCAL_MACHINE hive under
/// Software/Microsoft/MSH/&lt;ShellID&gt; and are searched in that order.
/// </remarks>
///
internal static string GetShellPathFromRegistry(string shellID)
{
string result = null;
#if !UNIX
try
{
RegistryKey shellKey = Registry.LocalMachine.OpenSubKey(Utils.GetRegistryConfigurationPath(shellID));
if (shellKey != null)
{
// verify the value kind as a string
RegistryValueKind kind = shellKey.GetValueKind("path");
if (kind == RegistryValueKind.ExpandString ||
kind == RegistryValueKind.String)
{
result = shellKey.GetValue("path") as string;
}
}
}
// Ignore these exceptions and return an empty or null result
catch (SecurityException)
{
}
catch (IOException)
{
}
catch (ArgumentException)
{
}
#endif
return result;
}
internal static PSModuleAutoLoadingPreference GetCommandDiscoveryPreference(ExecutionContext context, VariablePath variablePath, string environmentVariable)
{
Dbg.Assert(context != null, "context cannot be Null");
@@ -11,6 +11,7 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Configuration;
using System.Management.Automation.Internal;
using System.Management.Automation.Runspaces;
using System.Management.Automation.Security;
@@ -4749,28 +4750,18 @@ namespace Microsoft.PowerShell.Commands
{
moduleNames = null;
ModuleLoggingGroupPolicyStatus status = ModuleLoggingGroupPolicyStatus.Undefined;
Dictionary<string, object> groupPolicySettings = Utils.GetGroupPolicySetting("ModuleLogging", Utils.RegLocalMachineThenCurrentUser);
if (groupPolicySettings != null)
var moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.SystemWideThenCurrentUserConfig);
if (moduleLogging != null)
{
object enableModuleLoggingValue = null;
if (groupPolicySettings.TryGetValue("EnableModuleLogging", out enableModuleLoggingValue))
if (moduleLogging.EnableModuleLogging == false)
{
if (String.Equals(enableModuleLoggingValue.ToString(), "0", StringComparison.OrdinalIgnoreCase))
{
return ModuleLoggingGroupPolicyStatus.Disabled;
}
if (String.Equals(enableModuleLoggingValue.ToString(), "1", StringComparison.OrdinalIgnoreCase))
{
status = ModuleLoggingGroupPolicyStatus.Enabled;
object moduleNamesValue = null;
if (groupPolicySettings.TryGetValue("ModuleNames", out moduleNamesValue))
{
moduleNames = new List<String>((string[])moduleNamesValue);
}
}
status = ModuleLoggingGroupPolicyStatus.Disabled;
}
else if (moduleLogging.EnableModuleLogging == true)
{
status = ModuleLoggingGroupPolicyStatus.Enabled;
moduleNames = moduleLogging.ModuleNames;
}
}
@@ -4,6 +4,7 @@ Copyright (c) Microsoft Corporation. All rights reserved.
using System.Collections.Generic;
using System.IO;
using System.Management.Automation.Configuration;
using System.Management.Automation.Internal;
using System.Management.Automation.Language;
using Microsoft.PowerShell.Commands;
@@ -977,8 +978,8 @@ namespace System.Management.Automation
internal static string SetModulePath()
{
string currentModulePath = GetExpandedEnvironmentVariable(Constants.PSModulePathEnvVar, EnvironmentVariableTarget.Process);
string systemWideModulePath = ConfigPropertyAccessor.Instance.GetModulePath(ConfigPropertyAccessor.PropertyScope.SystemWide);
string personalModulePath = ConfigPropertyAccessor.Instance.GetModulePath(ConfigPropertyAccessor.PropertyScope.CurrentUser);
string systemWideModulePath = PowerShellConfig.Instance.GetModulePath(ConfigScope.SystemWide);
string personalModulePath = PowerShellConfig.Instance.GetModulePath(ConfigScope.CurrentUser);
string newModulePathString = GetModulePath(currentModulePath, systemWideModulePath, personalModulePath);
@@ -1,206 +1,65 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Xml;
using System.IO;
using System.Text;
using System.Reflection;
using System.Globalization;
using System.Threading;
using System.Management.Automation;
using System.Management.Automation.Internal;
using Microsoft.Win32;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Management.Automation.Internal;
namespace System.Management.Automation
namespace System.Management.Automation.Configuration
{
/// <summary>
/// Leverages the strategy pattern to abstract away the details of gathering properties from outside sources.
/// Note: This is a class so that it can be internal.
/// </summary>
internal abstract class ConfigPropertyAccessor
internal enum ConfigScope
{
#region Statics
/// <summary>
/// Static constructor to instantiate an instance
/// </summary>
static ConfigPropertyAccessor()
{
Instance = new JsonConfigFileAccessor();
}
/// <summary>
/// The instance of the ConfigPropertyAccessor to use to interact with properties.
/// Derived classes should not be directly instantiated.
/// </summary>
internal static readonly ConfigPropertyAccessor Instance;
// SystemWide configuration applies to all users.
SystemWide = 0,
#endregion // Statics
#region Enums
/// <summary>
/// Describes the scope of the property query.
/// SystemWide properties apply to all users.
/// CurrentUser properties apply to the current user that is impersonated.
/// </summary>
internal enum PropertyScope
{
SystemWide = 0,
CurrentUser = 1
}
#endregion // Enums
#region Interface Methods
/// <summary>
/// Existing Key = HKLM:\System\CurrentControlSet\Control\Session Manager\Environment
/// Proposed value = %ProgramFiles%\PowerShell\Modules by default
///
/// Note: There is no setter because this value is immutable.
/// </summary>
/// <returns>Module path values from the config file.</returns>
internal abstract string GetModulePath(PropertyScope scope);
/// <summary>
/// Existing Key = HKCU and HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell
/// Proposed value = Existing default execution policy if not already specified
/// </summary>
/// <param name="scope">Where it should check for the value.</param>
/// <param name="shellId">The shell associated with this policy. Typically, it is "Microsoft.PowerShell"</param>
/// <returns></returns>
internal abstract string GetExecutionPolicy(PropertyScope scope, string shellId);
internal abstract void RemoveExecutionPolicy(PropertyScope scope, string shellId);
internal abstract void SetExecutionPolicy(PropertyScope scope, string shellId, string executionPolicy);
/// <summary>
/// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds
/// Proposed value = existing default. Probably "1"
/// </summary>
/// <returns>Whether console prompting should happen.</returns>
internal abstract bool GetConsolePrompting();
internal abstract void SetConsolePrompting(bool shouldPrompt);
/// <summary>
/// Existing Key = HKLM\SOFTWARE\Microsoft\PowerShell
/// Proposed value = Existing default. Probably "0"
/// </summary>
/// <returns>Boolean indicating whether Update-Help should prompt</returns>
internal abstract bool GetDisablePromptToUpdateHelp();
internal abstract void SetDisablePromptToUpdateHelp(bool prompt);
/// <summary>
/// Existing Key = HKCU and HKLM\Software\Policies\Microsoft\Windows\PowerShell\UpdatableHelp
/// Proposed value = blank.This should be supported though
/// </summary>
/// <returns></returns>
internal abstract string GetDefaultSourcePath();
internal abstract void SetDefaultSourcePath(string defaultPath);
#if UNIX
/// <summary>
/// Gets the application identity (name) to use for writing to syslog.
/// </summary>
/// <returns>
/// The string identity to use for writing to syslog.
/// <para>
/// The default value is 'powershell'
/// </para>
/// </returns>
internal abstract string GetSysLogIdentity();
/// <summary>
/// Gets the log level filter.
/// </summary>
/// <returns>One of the PSLevel values indicating the level to log.
/// <para>
/// The default value is PSLevel.Informational
/// </para>
/// </returns>
internal abstract PSLevel GetLogLevel();
/// <summary>
/// Gets the bitmask of the PSChannel values to log.
/// </summary>
/// <returns>
/// A bitmask of PSChannel.Operational and/or PSChannel.Analytic
/// <para>
/// The default value is PSChannel.Operational
/// </para>
/// </returns>
internal abstract PSChannel GetLogChannels();
/// <summary>
/// Gets the bitmask of keywords to log.
/// </summary>
/// <returns>
/// A bitmask of PSKeyword values.
/// <para>
/// The default value is all keywords other than UseAlwaysAnalytic
/// </para>
/// </returns>
internal abstract PSKeyword GetLogKeywords();
#endif // UNIX
#endregion // Interface Methods
// CurrentUser configuration applies to the current user.
CurrentUser = 1
}
/// <summary>
/// JSON configuration file accessor
///
/// Reads from and writes to configuration files. The values stored were
/// originally stored in the Windows registry.
/// Reads from and writes to the JSON configuration files.
/// The config values were originally stored in the Windows registry.
/// </summary>
internal class JsonConfigFileAccessor : ConfigPropertyAccessor
internal sealed class PowerShellConfig
{
// Provide a singleton
private static readonly PowerShellConfig s_instance = new PowerShellConfig();
internal static PowerShellConfig Instance => s_instance;
private string psHomeConfigDirectory;
private string appDataConfigDirectory;
private const string configFileName = "PowerShellProperties.json";
private const string configFileName = "powershell.config.json";
/// <summary>
/// Lock used to enable multiple concurrent readers and singular write locks within a
/// single process.
/// TODO: This solution only works for IO from a single process. A more robust solution is needed to enable ReaderWriterLockSlim behavior between processes.
/// Lock used to enable multiple concurrent readers and singular write locks within a single process.
/// TODO: This solution only works for IO from a single process.
/// A more robust solution is needed to enable ReaderWriterLockSlim behavior between processes.
/// </summary>
private ReaderWriterLockSlim fileLock = new ReaderWriterLockSlim();
internal JsonConfigFileAccessor()
private PowerShellConfig()
{
//
// Sets the system-wide configuration directory
//
Assembly assembly = typeof(PSObject).GetTypeInfo().Assembly;
psHomeConfigDirectory = Path.GetDirectoryName(assembly.Location);
psHomeConfigDirectory = Utils.DefaultPowerShellAppBase;
//
// Sets the per-user configuration directory
// Note: This directory may or may not exist depending upon the
// execution scenario. Writes will attempt to create the directory
// if it does not already exist.
//
appDataConfigDirectory = Utils.GetUserConfigurationDirectory();
}
/// <summary>
/// This value is not writable via the API and must be set using a text editor.
/// Existing Key = HKLM:\System\CurrentControlSet\Control\Session Manager\Environment
/// Proposed value = %ProgramFiles%\PowerShell\Modules by default
/// Note: There is no setter because this value is immutable.
/// </summary>
/// <param name="scope"></param>
/// <param name="scope">Whether this is a system-wide or per-user setting.</param>
/// <returns>Value if found, null otherwise. The behavior matches ModuleIntrinsics.GetExpandedEnvironmentVariable().</returns>
internal override string GetModulePath(PropertyScope scope)
internal string GetModulePath(ConfigScope scope)
{
string scopeDirectory = psHomeConfigDirectory;
// Defaults to system wide.
if (PropertyScope.CurrentUser == scope)
{
scopeDirectory = appDataConfigDirectory;
}
string scopeDirectory = scope == ConfigScope.SystemWide ? psHomeConfigDirectory : appDataConfigDirectory;
string fileName = Path.Combine(scopeDirectory, configFileName);
string modulePath = ReadValueFromFile<string>(fileName, Constants.PSModulePathEnvVar);
@@ -217,7 +76,7 @@ namespace System.Management.Automation
///
/// Schema:
/// {
/// "shell ID string","ExecutionPolicy" : "execution policy string"
/// "shell-ID-string:ExecutionPolicy" : "execution policy string"
/// }
///
/// TODO: In a single config file, it might be better to nest this. It is unnecessary complexity until a need arises for more nested values.
@@ -225,13 +84,13 @@ namespace System.Management.Automation
/// <param name="scope">Whether this is a system-wide or per-user setting.</param>
/// <param name="shellId">The shell associated with this policy. Typically, it is "Microsoft.PowerShell"</param>
/// <returns>The execution policy if found. Null otherwise.</returns>
internal override string GetExecutionPolicy(PropertyScope scope, string shellId)
internal string GetExecutionPolicy(ConfigScope scope, string shellId)
{
string execPolicy = null;
string scopeDirectory = psHomeConfigDirectory;
// Defaults to system wide.
if(PropertyScope.CurrentUser == scope)
if(ConfigScope.CurrentUser == scope)
{
scopeDirectory = appDataConfigDirectory;
}
@@ -247,12 +106,12 @@ namespace System.Management.Automation
return execPolicy;
}
internal override void RemoveExecutionPolicy(PropertyScope scope, string shellId)
internal void RemoveExecutionPolicy(ConfigScope scope, string shellId)
{
string scopeDirectory = psHomeConfigDirectory;
// Defaults to system wide.
if (PropertyScope.CurrentUser == scope)
if (ConfigScope.CurrentUser == scope)
{
scopeDirectory = appDataConfigDirectory;
}
@@ -262,12 +121,12 @@ namespace System.Management.Automation
RemoveValueFromFile<string>(fileName, valueName);
}
internal override void SetExecutionPolicy(PropertyScope scope, string shellId, string executionPolicy)
internal void SetExecutionPolicy(ConfigScope scope, string shellId, string executionPolicy)
{
string scopeDirectory = psHomeConfigDirectory;
// Defaults to system wide.
if (PropertyScope.CurrentUser == scope)
if (ConfigScope.CurrentUser == scope)
{
// Exceptions are not caught so that they will propagate to the
// host for display to the user.
@@ -292,13 +151,13 @@ namespace System.Management.Automation
/// }
/// </summary>
/// <returns>Whether console prompting should happen. If the value cannot be read it defaults to false.</returns>
internal override bool GetConsolePrompting()
internal bool GetConsolePrompting()
{
string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
return ReadValueFromFile<bool>(fileName, "ConsolePrompting");
}
internal override void SetConsolePrompting(bool shouldPrompt)
internal void SetConsolePrompting(bool shouldPrompt)
{
string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
WriteValueToFile<bool>(fileName, "ConsolePrompting", shouldPrompt);
@@ -314,46 +173,26 @@ namespace System.Management.Automation
/// }
/// </summary>
/// <returns>Boolean indicating whether Update-Help should prompt. If the value cannot be read, it defaults to false.</returns>
internal override bool GetDisablePromptToUpdateHelp()
internal bool GetDisablePromptToUpdateHelp()
{
string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
return ReadValueFromFile<bool>(fileName, "DisablePromptToUpdateHelp");
}
internal override void SetDisablePromptToUpdateHelp(bool prompt)
internal void SetDisablePromptToUpdateHelp(bool prompt)
{
string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
WriteValueToFile<bool>(fileName, "DisablePromptToUpdateHelp", prompt);
}
/// <summary>
/// Existing Key = HKCU and HKLM\Software\Policies\Microsoft\Windows\PowerShell\UpdatableHelp
/// Proposed value = blank.This should be supported though
///
/// Schema:
/// {
/// "DefaultSourcePath" : "path to local updatable help location"
/// }
/// Corresponding settings of the original Group Policies
/// </summary>
/// <returns>The source path if found, null otherwise.</returns>
internal override string GetDefaultSourcePath()
internal PowerShellPolicies GetPowerShellPolicies(ConfigScope scope)
{
string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
string rawExecPolicy = ReadValueFromFile<string>(fileName, "DefaultSourcePath");
if (!String.IsNullOrEmpty(rawExecPolicy))
{
return rawExecPolicy;
}
return null;
}
internal override void SetDefaultSourcePath(string defaultPath)
{
string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
WriteValueToFile<string>(fileName, "DefaultSourcePath", defaultPath);
string scopeDirectory = (scope == ConfigScope.SystemWide) ? psHomeConfigDirectory : appDataConfigDirectory;
string fileName = Path.Combine(scopeDirectory, configFileName);
return ReadValueFromFile<PowerShellPolicies>(fileName, nameof(PowerShellPolicies));
}
#if UNIX
@@ -361,12 +200,9 @@ namespace System.Management.Automation
/// Gets the identity name to use for writing to syslog.
/// </summary>
/// <returns>
/// The string identity to use for writing to syslog.
/// <para>
/// The default value is 'powershell'.
/// </para>
/// The string identity to use for writing to syslog. The default value is 'powershell'.
/// </returns>
internal override string GetSysLogIdentity()
internal string GetSysLogIdentity()
{
string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
string identity = ReadValueFromFile<string>(fileName, "LogIdentity");
@@ -382,12 +218,10 @@ namespace System.Management.Automation
/// <summary>
/// Gets the log level filter.
/// </summary>
/// <returns>One of the PSLevel values indicating the level to log.
/// <para>
/// The default value is PSLevel.Informational.
/// </para>
/// <returns>
/// One of the PSLevel values indicating the level to log. The default value is PSLevel.Informational.
/// </returns>
internal override PSLevel GetLogLevel()
internal PSLevel GetLogLevel()
{
string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
string levelName = ReadValueFromFile<string>(fileName, "LogLevel");
@@ -418,12 +252,9 @@ namespace System.Management.Automation
/// Gets the bitmask of the PSChannel values to log.
/// </summary>
/// <returns>
/// A bitmask of PSChannel.Operational and/or PSChannel.Analytic.
/// <para>
/// The default value is PSChannel.Operational.
/// </para>
/// A bitmask of PSChannel.Operational and/or PSChannel.Analytic. The default value is PSChannel.Operational.
/// </returns>
internal override PSChannel GetLogChannels()
internal PSChannel GetLogChannels()
{
string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
string values = ReadValueFromFile<string>(fileName, "LogChannels");
@@ -464,12 +295,9 @@ namespace System.Management.Automation
/// Gets the bitmask of keywords to log.
/// </summary>
/// <returns>
/// A bitmask of PSKeyword values.
/// <para>
/// The default value is all keywords other than UseAlwaysAnalytic.
/// </para>
/// A bitmask of PSKeyword values. The default value is all keywords other than UseAlwaysAnalytic.
/// </returns>
internal override PSKeyword GetLogKeywords()
internal PSKeyword GetLogKeywords()
{
string fileName = Path.Combine(psHomeConfigDirectory, configFileName);
string values = ReadValueFromFile<string>(fileName, "LogKeywords");
@@ -502,48 +330,36 @@ namespace System.Management.Automation
return result;
}
#endif // UNIX
private T ReadValueFromFile<T>(string fileName, string key)
private T ReadValueFromFile<T>(string fileName, string key, T defaultValue = default(T),
Func<JToken, JsonSerializer, T, T> readImpl = null)
{
if (!File.Exists(fileName)) { return defaultValue; }
// Open file for reading, but allow multiple readers
fileLock.EnterReadLock();
try
{
// Open file for reading, but allow multiple readers
using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
using (StreamReader streamRdr = new StreamReader(fs))
using (JsonTextReader jsonReader = new JsonTextReader(streamRdr))
using (var streamReader = new StreamReader(fileName))
using (var jsonReader = new JsonTextReader(streamReader))
{
// Safely determines whether there is content to read from the file
bool isReadSuccess = jsonReader.Read();
if (isReadSuccess)
var settings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.None, MaxDepth = 10 };
var serializer = JsonSerializer.Create(settings);
var configData = serializer.Deserialize<JObject>(jsonReader);
if (configData != null && configData.TryGetValue(key, StringComparison.OrdinalIgnoreCase, out JToken jToken))
{
JObject jsonObject = (JObject) JToken.ReadFrom(jsonReader);
JToken value = jsonObject.GetValue(key);
if (null != value)
{
return value.ToObject<T>();
}
return readImpl != null ? readImpl(jToken, serializer, defaultValue) : jToken.ToObject<T>(serializer);
}
}
}
catch (FileNotFoundException)
{
// The file doesn't exist. Treat this the same way as if the
// key was not present in the file.
}
catch (DirectoryNotFoundException)
{
// A directory in the path does not exist. Treat this as if the
// key is not present in the file.
}
finally
{
fileLock.ExitReadLock();
}
return default(T);
return defaultValue;
}
/// <summary>
@@ -677,5 +493,129 @@ namespace System.Management.Automation
}
}
}
} // Namespace System.Management.Automation
#region GroupPolicy Configs
/// <summary>
/// The GroupPolicy related settings used in PowerShell are as follows in Registry:
/// - Software\Policies\Microsoft\PowerShellCore -- { EnableScripts (0 or 1); ExecutionPolicy (string) }
/// SubKeys Name-Value-Pairs
/// - ScriptBlockLogging { EnableScriptBlockLogging (0 or 1); EnableScriptBlockInvocationLogging (0 or 1) }
/// - ModuleLogging { EnableModuleLogging (0 or 1); ModuleNames (string[]) }
/// - Transcription { EnableTranscripting (0 or 1); OutputDirectory (string); EnableInvocationHeader (0 or 1) }
/// - UpdatableHelp { DefaultSourcePath (string) }
/// - ConsoleSessionConfiguration { EnableConsoleSessionConfiguration (0 or 1); ConsoleSessionConfigurationName (string) }
/// - Software\Policies\Microsoft\Windows\EventLog
/// SubKeys Name-Value-Pairs
/// - ProtectedEventLogging { EnableProtectedEventLogging (0 or 1); EncryptionCertificate (string[]) }
///
/// The JSON representation is in sync with the 'PowerShellPolicies' type. Here is an example:
/// {
/// "PowerShellPolicies": {
/// "ScriptExecution": {
/// "ExecutionPolicy": "RemoteSigned"
/// },
/// "ScriptBlockLogging": {
/// "EnableScriptBlockInvocationLogging": true,
/// "EnableScriptBlockLogging": false
/// },
/// "ProtectedEventLogging": {
/// "EnableProtectedEventLogging": false,
/// "EncryptionCertificate": [
/// "Joe"
/// ]
/// },
/// "Transcription": {
/// "EnableTranscripting": true,
/// "EnableInvocationHeader": true,
/// "OutputDirectory": "c:\\tmp"
/// },
/// "UpdatableHelp": {
/// "DefaultSourcePath": "f:\\temp"
/// },
/// "ConsoleSessionConfiguration": {
/// "EnableConsoleSessionConfiguration": true,
/// "ConsoleSessionConfigurationName": "name"
/// }
/// }
/// }
/// </summary>
internal sealed class PowerShellPolicies
{
public ScriptExecution ScriptExecution { get; set; }
public ScriptBlockLogging ScriptBlockLogging { get; set; }
public ModuleLogging ModuleLogging { get; set; }
public ProtectedEventLogging ProtectedEventLogging { get; set; }
public Transcription Transcription { get; set; }
public UpdatableHelp UpdatableHelp { get; set; }
public ConsoleSessionConfiguration ConsoleSessionConfiguration { get; set; }
}
internal abstract class PolicyBase { }
/// <summary>
/// Setting about ScriptExecution
/// </summary>
internal sealed class ScriptExecution : PolicyBase
{
public string ExecutionPolicy { get; set; }
public bool? EnableScripts { get; set; }
}
/// <summary>
/// Setting about ScriptBlockLogging
/// </summary>
internal sealed class ScriptBlockLogging : PolicyBase
{
public bool? EnableScriptBlockInvocationLogging { get; set; }
public bool? EnableScriptBlockLogging { get; set; }
}
/// <summary>
/// Setting about ModuleLogging
/// </summary>
internal sealed class ModuleLogging : PolicyBase
{
public bool? EnableModuleLogging { get; set; }
public string[] ModuleNames { get; set; }
}
/// <summary>
/// Setting about Transcription
/// </summary>
internal sealed class Transcription : PolicyBase
{
public bool? EnableTranscripting { get; set; }
public bool? EnableInvocationHeader { get; set; }
public string OutputDirectory { get; set; }
}
/// <summary>
/// Setting about UpdatableHelp
/// </summary>
internal sealed class UpdatableHelp : PolicyBase
{
public bool? EnableUpdateHelpDefaultSourcePath { get; set; }
public string DefaultSourcePath { get; set; }
}
/// <summary>
/// Setting about ConsoleSessionConfiguration
/// </summary>
internal sealed class ConsoleSessionConfiguration : PolicyBase
{
public bool? EnableConsoleSessionConfiguration { get; set; }
public string ConsoleSessionConfigurationName { get; set; }
}
/// <summary>
/// Setting about ProtectedEventLogging
/// </summary>
internal sealed class ProtectedEventLogging : PolicyBase
{
public bool? EnableProtectedEventLogging { get; set; }
public string[] EncryptionCertificate { get; set; }
}
#endregion
}
+186 -101
View File
@@ -5,6 +5,7 @@ Copyright (c) Microsoft Corporation. All rights reserved.
using System.Security;
using System.Runtime.InteropServices;
using System.Diagnostics.CodeAnalysis;
using System.Management.Automation.Configuration;
using System.Management.Automation.Internal;
using System.Management.Automation.Security;
using System.Reflection;
@@ -233,12 +234,11 @@ namespace System.Management.Automation
}
#endif
internal static string DefaultPowerShellAppBase { get; } = GetApplicationBase(DefaultPowerShellShellID);
internal static string DefaultPowerShellAppBase => GetApplicationBase(DefaultPowerShellShellID);
internal static string GetApplicationBase(string shellId)
{
// Use the location of SMA.dll as the application base.
Assembly assembly = typeof(PSObject).GetTypeInfo().Assembly;
Assembly assembly = typeof(PSObject).Assembly;
return Path.GetDirectoryName(assembly.Location);
}
@@ -497,125 +497,210 @@ namespace System.Management.Automation
/// </summary>
internal static string ModuleDirectory = Path.Combine(ProductNameForDirectory, "Modules");
internal static string GetRegistryConfigurationPrefix()
{
// For 3.0 PowerShell, we still use "1" as the registry version key for
// Snapin and Custom shell lookup/discovery.
// For 3.0 PowerShell, we use "3" as the registry version key only for Engine
// related data like ApplicationBase etc.
return "SOFTWARE\\Microsoft\\PowerShell\\" + PSVersionInfo.RegistryVersion1Key + "\\ShellIds";
}
internal readonly static ConfigScope[] SystemWideOnlyConfig = new[] { ConfigScope.SystemWide };
internal readonly static ConfigScope[] CurrentUserOnlyConfig = new[] { ConfigScope.CurrentUser };
internal readonly static ConfigScope[] SystemWideThenCurrentUserConfig = new[] { ConfigScope.SystemWide, ConfigScope.CurrentUser };
internal readonly static ConfigScope[] CurrentUserThenSystemWideConfig = new[] { ConfigScope.CurrentUser, ConfigScope.SystemWide };
internal static string GetRegistryConfigurationPath(string shellID)
internal static T GetPolicySetting<T>(ConfigScope[] preferenceOrder) where T : PolicyBase, new()
{
return GetRegistryConfigurationPrefix() + "\\" + shellID;
}
// Calling static members of 'Registry' on UNIX will raise 'PlatformNotSupportedException'
#if UNIX
internal static RegistryKey[] RegLocalMachine = null;
internal static RegistryKey[] RegCurrentUser = null;
internal static RegistryKey[] RegLocalMachineThenCurrentUser = null;
internal static RegistryKey[] RegCurrentUserThenLocalMachine = null;
#else
internal static RegistryKey[] RegLocalMachine = new[] { Registry.LocalMachine };
internal static RegistryKey[] RegCurrentUser = new[] { Registry.CurrentUser };
internal static RegistryKey[] RegLocalMachineThenCurrentUser = new[] { Registry.LocalMachine, Registry.CurrentUser };
internal static RegistryKey[] RegCurrentUserThenLocalMachine = new[] { Registry.CurrentUser, Registry.LocalMachine };
T policy = null;
#if !UNIX
// On Windows, group policy settings from registry take precedence.
// If the requested policy is not defined in registry, we query the configuration file.
policy = GetPolicySettingFromGPO<T>(preferenceOrder);
if (policy != null) { return policy; }
#endif
internal static Dictionary<string, object> GetGroupPolicySetting(string settingName, RegistryKey[] preferenceOrder)
{
string groupPolicyBase = "Software\\Policies\\Microsoft\\Windows\\PowerShell";
return GetGroupPolicySetting(groupPolicyBase, settingName, preferenceOrder);
policy = GetPolicySettingFromConfigFile<T>(preferenceOrder);
return policy;
}
// We use a static to avoid creating "extra garbage."
private static Dictionary<string, object> s_emptyDictionary = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
private readonly static ConcurrentDictionary<ConfigScope, PowerShellPolicies> s_cachedPoliciesFromConfigFile =
new ConcurrentDictionary<ConfigScope, PowerShellPolicies>();
internal static Dictionary<string, object> GetGroupPolicySetting(string groupPolicyBase, string settingName, RegistryKey[] preferenceOrder)
/// <summary>
/// Get a specific kind of policy setting from the configuration file.
/// </summary>
private static T GetPolicySettingFromConfigFile<T>(ConfigScope[] preferenceOrder) where T : PolicyBase, new()
{
#if UNIX
return s_emptyDictionary;
#else
lock (s_cachedGroupPolicySettings)
foreach (ConfigScope scope in preferenceOrder)
{
// Return cached information, if we have it
Dictionary<string, object> settings;
if ((s_cachedGroupPolicySettings.TryGetValue(settingName, out settings)) &&
!InternalTestHooks.BypassGroupPolicyCaching)
PowerShellPolicies policies;
if (InternalTestHooks.BypassGroupPolicyCaching)
{
return settings;
policies = PowerShellConfig.Instance.GetPowerShellPolicies(scope);
}
if (!String.Equals(".", settingName, StringComparison.OrdinalIgnoreCase))
else if (!s_cachedPoliciesFromConfigFile.TryGetValue(scope, out policies))
{
groupPolicyBase += "\\" + settingName;
}
settings = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
foreach (RegistryKey searchKey in preferenceOrder)
{
try
// Use lock here to reduce the contention on accessing the configuration file
lock (s_cachedPoliciesFromConfigFile)
{
// Look up the machine-wide group policy
using (RegistryKey key = searchKey.OpenSubKey(groupPolicyBase))
policies = s_cachedPoliciesFromConfigFile.GetOrAdd(scope, PowerShellConfig.Instance.GetPowerShellPolicies);
}
}
if (policies != null)
{
PolicyBase result = null;
switch (typeof(T).Name)
{
case nameof(ScriptExecution): result = policies.ScriptExecution; break;
case nameof(ScriptBlockLogging): result = policies.ScriptBlockLogging; break;
case nameof(ModuleLogging): result = policies.ModuleLogging; break;
case nameof(ProtectedEventLogging): result = policies.ProtectedEventLogging; break;
case nameof(Transcription): result = policies.Transcription; break;
case nameof(UpdatableHelp): result = policies.UpdatableHelp; break;
case nameof(ConsoleSessionConfiguration): result = policies.ConsoleSessionConfiguration; break;
default: Diagnostics.Assert(false, "Should be unreachable code. Update this switch block when new PowerShell policy types are added."); break;
}
if (result != null) { return (T) result; }
}
}
return null;
}
#if !UNIX
private static readonly Dictionary<string, string> GroupPolicyKeys = new Dictionary<string, string>
{
{nameof(ScriptExecution), @"Software\Policies\Microsoft\PowerShellCore"},
{nameof(ScriptBlockLogging), @"Software\Policies\Microsoft\PowerShellCore\ScriptBlockLogging"},
{nameof(ModuleLogging), @"Software\Policies\Microsoft\PowerShellCore\ModuleLogging"},
{nameof(ProtectedEventLogging), @"Software\Policies\Microsoft\Windows\EventLog\ProtectedEventLogging"},
{nameof(Transcription), @"Software\Policies\Microsoft\PowerShellCore\Transcription"},
{nameof(UpdatableHelp), @"Software\Policies\Microsoft\PowerShellCore\UpdatableHelp"},
{nameof(ConsoleSessionConfiguration), @"Software\Policies\Microsoft\PowerShellCore\ConsoleSessionConfiguration"}
};
private readonly static ConcurrentDictionary<Tuple<ConfigScope, string>, PolicyBase> s_cachedPoliciesFromRegistry =
new ConcurrentDictionary<Tuple<ConfigScope, string>, PolicyBase>();
/// <summary>
/// The implementation of fetching a specific kind of policy setting from the given configuration scope.
/// </summary>
private static T GetPolicySettingFromGPOImpl<T>(ConfigScope scope) where T : PolicyBase, new()
{
Type tType = typeof(T);
// SystemWide scope means 'LocalMachine' root key when query from registry
RegistryKey rootKey = (scope == ConfigScope.SystemWide) ? Registry.LocalMachine : Registry.CurrentUser;
GroupPolicyKeys.TryGetValue(tType.Name, out string gpoKeyPath);
Diagnostics.Assert(gpoKeyPath != null, StringUtil.Format("The GPO registry key path should be pre-defined for {0}", tType.Name));
using (RegistryKey gpoKey = rootKey.OpenSubKey(gpoKeyPath))
{
// If the corresponding GPO key doesn't exist, return null
if (gpoKey == null) { return null; }
// The corresponding GPO key exists, then create an instance of T
// and populate its properties with the settings
object tInstance = Activator.CreateInstance(tType, nonPublic: true);
var properties = tType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
bool isAnyPropertySet = false;
string[] valueNames = gpoKey.GetValueNames();
string[] subKeyNames = gpoKey.GetSubKeyNames();
var valueNameSet = valueNames.Length > 0 ? new HashSet<string>(valueNames, StringComparer.OrdinalIgnoreCase) : null;
var subKeyNameSet = subKeyNames.Length > 0 ? new HashSet<string>(subKeyNames, StringComparer.OrdinalIgnoreCase) : null;
foreach (var property in properties)
{
string settingName = property.Name;
object rawRegistryValue = null;
// Get the raw value from registry.
if (valueNameSet != null && valueNameSet.Contains(settingName))
{
rawRegistryValue = gpoKey.GetValue(settingName);
}
else if (subKeyNameSet != null && subKeyNameSet.Contains(settingName))
{
using (RegistryKey subKey = gpoKey.OpenSubKey(settingName))
{
if (key != null)
{
foreach (string subkeyName in key.GetValueNames())
{
// A null or empty subkey name string corresponds to a (Default) key.
// If it is null, make it an empty string which the Dictionary can handle.
string keyName = subkeyName ?? string.Empty;
settings[keyName] = key.GetValue(keyName);
}
foreach (string subkeyName in key.GetSubKeyNames())
{
// A null or empty subkey name string corresponds to a (Default) key.
// If it is null, make it an empty string which the Dictionary can handle.
string keyName = subkeyName ?? string.Empty;
using (RegistryKey subkey = key.OpenSubKey(keyName))
{
if (subkey != null)
{
settings[keyName] = subkey.GetValueNames();
}
}
}
break;
}
if (subKey != null) { rawRegistryValue = subKey.GetValueNames(); }
}
}
catch (System.Security.SecurityException)
// Get the actual property value based on the property type.
// If the final property value is not null, then set the property.
if (rawRegistryValue != null)
{
// User doesn't have access to open group policy key
Type propertyType = property.PropertyType;
object propertyValue = null;
switch (propertyType)
{
case var _ when propertyType == typeof(bool?):
if (rawRegistryValue is int rawIntValue)
{
if (rawIntValue == 1) { propertyValue = true; }
else if (rawIntValue == 0) { propertyValue = false; }
}
break;
case var _ when propertyType == typeof(string):
if (rawRegistryValue is string rawStringValue)
{
propertyValue = rawStringValue;
}
break;
case var _ when propertyType == typeof(string[]):
if (rawRegistryValue is string[] rawStringArrayValue)
{
propertyValue = rawStringArrayValue;
}
else if (rawRegistryValue is string stringValue)
{
propertyValue = new string[] { stringValue };
}
break;
default:
Diagnostics.Assert(false, "Should be unreachable code. Update this switch block when properties of new types are added to PowerShell policy types.");
break;
}
// Set the property if the value is not null
if (propertyValue != null)
{
property.SetValue(tInstance, propertyValue);
isAnyPropertySet = true;
}
}
}
// No group policy settings, then return null
if (settings.Count == 0)
{
settings = null;
}
// Cache the data
if (!InternalTestHooks.BypassGroupPolicyCaching)
{
s_cachedGroupPolicySettings[settingName] = settings;
}
return settings;
// If no property is set, then we consider this policy as undefined
return isAnyPropertySet ? (T) tInstance : null;
}
#endif
}
private static ConcurrentDictionary<string, Dictionary<string, object>> s_cachedGroupPolicySettings =
new ConcurrentDictionary<string, Dictionary<string, object>>();
/// <summary>
/// Get a specific kind of policy setting from the group policy registry key.
/// </summary>
private static T GetPolicySettingFromGPO<T>(ConfigScope[] preferenceOrder) where T : PolicyBase, new()
{
PolicyBase policy = null;
foreach (ConfigScope scope in preferenceOrder)
{
if (InternalTestHooks.BypassGroupPolicyCaching)
{
policy = GetPolicySettingFromGPOImpl<T>(scope);
}
else
{
var key = Tuple.Create(scope, typeof(T).Name);
if (!s_cachedPoliciesFromRegistry.TryGetValue(key, out policy))
{
lock (s_cachedPoliciesFromRegistry)
{
policy = s_cachedPoliciesFromRegistry.GetOrAdd(key, tuple => GetPolicySettingFromGPOImpl<T>(tuple.Item1));
}
}
}
if (policy != null) { return (T) policy; }
}
return null;
}
#endif
/// <summary>
/// Scheduled job module name.
@@ -269,7 +269,7 @@ namespace System.Management.Automation.Runspaces
RegistryKey key;
try
{
key = Registry.LocalMachine.OpenSubKey(Utils.GetRegistryConfigurationPrefix());
key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\PowerShell\\1\\ShellIds");
}
catch (System.Security.SecurityException)
{
@@ -9,6 +9,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Security;
using System.Globalization;
using System.Management.Automation.Configuration;
using System.Management.Automation.Runspaces;
using Microsoft.PowerShell.Commands;
using System.Threading;
@@ -909,9 +910,8 @@ namespace System.Management.Automation.Host
/// </summary>
internal static TranscriptionOption GetSystemTranscriptOption(TranscriptionOption currentTranscript)
{
Dictionary<string, object> groupPolicySettings = Utils.GetGroupPolicySetting("Transcription", Utils.RegLocalMachineThenCurrentUser);
if (groupPolicySettings != null)
var transcription = Utils.GetPolicySetting<Transcription>(Utils.SystemWideThenCurrentUserConfig);
if (transcription != null)
{
// If we have an existing system transcript for this process, use that.
// Otherwise, populate the static variable with the result of the group policy setting.
@@ -921,7 +921,7 @@ namespace System.Management.Automation.Host
{
if (systemTranscript == null)
{
systemTranscript = PSHostUserInterface.GetTranscriptOptionFromSettings(groupPolicySettings, currentTranscript);
systemTranscript = PSHostUserInterface.GetTranscriptOptionFromSettings(transcription, currentTranscript);
}
}
}
@@ -931,44 +931,31 @@ namespace System.Management.Automation.Host
internal static TranscriptionOption systemTranscript = null;
private static Object s_systemTranscriptLock = new Object();
private static TranscriptionOption GetTranscriptOptionFromSettings(Dictionary<string, object> settings, TranscriptionOption currentTranscript)
private static TranscriptionOption GetTranscriptOptionFromSettings(Transcription transcriptConfig, TranscriptionOption currentTranscript)
{
TranscriptionOption transcript = null;
object keyValue = null;
if (settings.TryGetValue("EnableTranscripting", out keyValue))
if (transcriptConfig.EnableTranscripting == true)
{
if (String.Equals(keyValue.ToString(), "1", StringComparison.OrdinalIgnoreCase))
if (currentTranscript != null)
{
if (currentTranscript != null)
{
return currentTranscript;
}
transcript = new TranscriptionOption();
// Pull out the transcript path
object outputDirectoryValue = null;
if (settings.TryGetValue("OutputDirectory", out outputDirectoryValue))
{
string outputDirectoryString = outputDirectoryValue as string;
transcript.Path = GetTranscriptPath(outputDirectoryString, true);
}
else
{
transcript.Path = GetTranscriptPath();
}
// Pull out the "enable invocation header"
object enableInvocationHeaderValue = null;
if (settings.TryGetValue("EnableInvocationHeader", out enableInvocationHeaderValue))
{
if (String.Equals("1", enableInvocationHeaderValue.ToString(), StringComparison.OrdinalIgnoreCase))
{
transcript.IncludeInvocationHeader = true;
}
}
return currentTranscript;
}
transcript = new TranscriptionOption();
// Pull out the transcript path
if (transcriptConfig.OutputDirectory != null)
{
transcript.Path = GetTranscriptPath(transcriptConfig.OutputDirectory, true);
}
else
{
transcript.Path = GetTranscriptPath();
}
// Pull out the "enable invocation header"
transcript.IncludeInvocationHeader = transcriptConfig.EnableInvocationHeader == true;
}
return transcript;
@@ -7,6 +7,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management.Automation.Configuration;
using System.Management.Automation.Internal;
using System.Management.Automation.Language;
using System.Management.Automation.Runspaces;
@@ -1234,13 +1235,14 @@ namespace System.Management.Automation
internal static void LogScriptBlockCreation(ScriptBlock scriptBlock, bool force)
{
if (force || ShouldLogScriptBlockActivity("EnableScriptBlockLogging"))
ScriptBlockLogging logSetting = GetScriptBlockLoggingSetting();
if (force || logSetting?.EnableScriptBlockLogging == true)
{
if (!scriptBlock.HasLogged || InternalTestHooks.ForceScriptBlockLogging)
{
// If script block logging is explicitly disabled, or it's from a trusted
// file or internal, skip logging.
if (ScriptBlockLoggingExplicitlyDisabled() ||
if (logSetting?.EnableScriptBlockLogging == false ||
scriptBlock.ScriptBlockData.IsProductCode)
{
return;
@@ -1284,18 +1286,17 @@ namespace System.Management.Automation
private static bool WriteScriptBlockToLog(ScriptBlock scriptBlock, int segment, int segments, string textToLog)
{
// See if we need to encrypt the event log message. This info is all cached by Utils.GetGroupPolicySetting(),
// so we're not hitting the registry for every script block we compile.
Dictionary<string, object> protectedEventLoggingSettings = Utils.GetGroupPolicySetting(
"Software\\Policies\\Microsoft\\Windows\\EventLog", "ProtectedEventLogging", Utils.RegLocalMachine);
if (protectedEventLoggingSettings != null)
// See if we need to encrypt the event log message. This info is all cached by Utils.GetPolicySetting(),
// so we're not hitting the configuration file for every script block we compile.
ProtectedEventLogging logSetting = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.SystemWideOnlyConfig);
if (logSetting != null)
{
lock (s_syncObject)
{
// Populates the encryptionRecipients list from the Group Policy, if possible. If not possible,
// does all appropriate logging and encryptionRecipients is 'null'. 'CouldLog' being false
// implies the engine wasn't ready for logging yet.
bool couldLog = GetAndValidateEncryptionRecipients(scriptBlock);
bool couldLog = GetAndValidateEncryptionRecipients(scriptBlock, logSetting);
if (!couldLog)
{
return false;
@@ -1345,109 +1346,92 @@ namespace System.Management.Automation
return true;
}
private static bool GetAndValidateEncryptionRecipients(ScriptBlock scriptBlock)
private static bool GetAndValidateEncryptionRecipients(ScriptBlock scriptBlock, ProtectedEventLogging logSetting)
{
Dictionary<string, object> protectedEventLoggingSettings = Utils.GetGroupPolicySetting(
"Software\\Policies\\Microsoft\\Windows\\EventLog", "ProtectedEventLogging", Utils.RegLocalMachine);
// See if protected event logging is enabled
object enableProtectedEventLogging = null;
if (protectedEventLoggingSettings.TryGetValue("EnableProtectedEventLogging", out enableProtectedEventLogging))
if (logSetting.EnableProtectedEventLogging == true)
{
if (String.Equals("1", enableProtectedEventLogging.ToString(), StringComparison.OrdinalIgnoreCase))
// Get the encryption certificate
if (logSetting.EncryptionCertificate != null)
{
// Get the encryption certificate
object encryptionCertificate = null;
if (protectedEventLoggingSettings.TryGetValue("EncryptionCertificate", out encryptionCertificate))
ErrorRecord error = null;
ExecutionContext executionContext = LocalPipeline.GetExecutionContextFromTLS();
SessionState sessionState = null;
// Use the session state from the current pipeline, if it exists.
if (executionContext != null)
{
ErrorRecord error = null;
ExecutionContext executionContext = LocalPipeline.GetExecutionContextFromTLS();
SessionState sessionState = null;
sessionState = executionContext.SessionState;
}
// Use the session state from the current pipeline, if it exists.
if (executionContext != null)
// If the engine hasn't started up yet, then we're just compiling script
// blocks. We'll have to log them when they are used and we have an engine
// to work with.
if (sessionState == null)
{
return false;
}
string fullCertificateContent = String.Join(Environment.NewLine, logSetting.EncryptionCertificate);
// If the certificate has changed, drop all of our cached information
ResetCertificateCacheIfNeeded(fullCertificateContent);
// If we have valid recipients, no need for further analysis.
if (s_encryptionRecipients != null)
{
return true;
}
// If we've already verified all of the properties of the cert we care about (even if it
// didn't result in a valid cert), return now.
if (s_hasProcessedCertificate)
{
return true;
}
// Resolve the certificate to a recipient
CmsMessageRecipient recipient = new CmsMessageRecipient(fullCertificateContent);
recipient.Resolve(sessionState, ResolutionPurpose.Encryption, out error);
s_hasProcessedCertificate = true;
// If there's an error that we haven't already reported, report it in the event log.
// We only do this once, as the error will always be the same for a given certificate.
if (error != null)
{
// If we got an error resolving the encryption certificate, log a warning and continue
// logging the (unencrypted) message anyways. Logging trumps protected logging -
// being able to detect that an attacker has compromised a box outweighs the danger of the
// attacker seeing potentially sensitive data. Because if they aren't detected, then
// they can just wait on the compromised box and see the sensitive data eventually anyways.
string errorMessage = StringUtil.Format(SecuritySupportStrings.CouldNotUseCertificate, error.ToString());
PSEtwLog.LogOperationalError(PSEventId.ScriptBlock_Compile_Detail, PSOpcode.Create, PSTask.ExecuteCommand, PSKeyword.UseAlwaysAnalytic,
0, 0, errorMessage, scriptBlock.Id.ToString(), scriptBlock.File ?? String.Empty);
return true;
}
// Now, save the certificate. We'll be comfortable using this one from now on.
s_encryptionRecipients = new CmsMessageRecipient[] { recipient };
// Check if the certificate has a private key, and report a warning if so.
// We only do this once, as the error will always be the same for a given certificate.
foreach (X509Certificate2 validationCertificate in recipient.Certificates)
{
if (validationCertificate.HasPrivateKey)
{
sessionState = executionContext.SessionState;
}
// Only log the first line of what we pulled from the configuration. If this is a path, this will have enough information.
// If this is the actual certificate, only include the first line of the certificate content so that we're not permanently keeping the private
// key in the log.
string certificateForLog = fullCertificateContent;
if (logSetting.EncryptionCertificate.Length > 1)
{
certificateForLog = logSetting.EncryptionCertificate[1];
}
// If the engine hasn't started up yet, then we're just compiling script
// blocks. We'll have to log them when they are used and we have an engine
// to work with.
if (sessionState == null)
{
return false;
}
string[] encryptionCertificateContent = encryptionCertificate as string[];
string fullCertificateContent = null;
if (encryptionCertificateContent != null)
{
fullCertificateContent = String.Join(Environment.NewLine, encryptionCertificateContent);
}
else
{
fullCertificateContent = encryptionCertificate as string;
}
// If the certificate has changed, drop all of our cached information
ResetCertificateCacheIfNeeded(fullCertificateContent);
// If we have valid recipients, no need for further analysis.
if (s_encryptionRecipients != null)
{
return true;
}
// If we've already verified all of the properties of the cert we care about (even if it
// didn't result in a valid cert), return now.
if (s_hasProcessedCertificate)
{
return true;
}
// Resolve the certificate to a recipient
CmsMessageRecipient recipient = new CmsMessageRecipient(fullCertificateContent);
recipient.Resolve(sessionState, ResolutionPurpose.Encryption, out error);
s_hasProcessedCertificate = true;
// If there's an error that we haven't already reported, report it in the event log.
// We only do this once, as the error will always be the same for a given certificate.
if (error != null)
{
// If we got an error resolving the encryption certificate, log a warning and continue
// logging the (unencrypted) message anyways. Logging trumps protected logging -
// being able to detect that an attacker has compromised a box outweighs the danger of the
// attacker seeing potentially sensitive data. Because if they aren't detected, then
// they can just wait on the compromised box and see the sensitive data eventually anyways.
string errorMessage = StringUtil.Format(SecuritySupportStrings.CouldNotUseCertificate, error.ToString());
string errorMessage = StringUtil.Format(SecuritySupportStrings.CertificateContainsPrivateKey, certificateForLog);
PSEtwLog.LogOperationalError(PSEventId.ScriptBlock_Compile_Detail, PSOpcode.Create, PSTask.ExecuteCommand, PSKeyword.UseAlwaysAnalytic,
0, 0, errorMessage, scriptBlock.Id.ToString(), scriptBlock.File ?? String.Empty);
return true;
}
// Now, save the certificate. We'll be comfortable using this one from now on.
s_encryptionRecipients = new CmsMessageRecipient[] { recipient };
// Check if the certificate has a private key, and report a warning if so.
// We only do this once, as the error will always be the same for a given certificate.
foreach (X509Certificate2 validationCertificate in recipient.Certificates)
{
if (validationCertificate.HasPrivateKey)
{
// Only log the first line of what we pulled from the registry. If this is a path, this will have enough information.
// If this is the actual certificate, only include the first line of the certificate content so that we're not permanently keeping the private
// key in the log.
string certificateForLog = fullCertificateContent;
if ((encryptionCertificateContent != null) && (encryptionCertificateContent.Length > 1))
{
certificateForLog = encryptionCertificateContent[1];
}
string errorMessage = StringUtil.Format(SecuritySupportStrings.CertificateContainsPrivateKey, certificateForLog);
PSEtwLog.LogOperationalError(PSEventId.ScriptBlock_Compile_Detail, PSOpcode.Create, PSTask.ExecuteCommand, PSKeyword.UseAlwaysAnalytic,
0, 0, errorMessage, scriptBlock.Id.ToString(), scriptBlock.File ?? String.Empty);
}
}
}
}
@@ -1472,23 +1456,9 @@ namespace System.Management.Automation
}
}
private static bool ShouldLogScriptBlockActivity(string activity)
private static ScriptBlockLogging GetScriptBlockLoggingSetting()
{
// If script block logging is turned on, log this one.
Dictionary<string, object> groupPolicySettings = Utils.GetGroupPolicySetting("ScriptBlockLogging", Utils.RegLocalMachineThenCurrentUser);
if (groupPolicySettings != null)
{
object logScriptBlockExecution = null;
if (groupPolicySettings.TryGetValue(activity, out logScriptBlockExecution))
{
if (String.Equals("1", logScriptBlockExecution.ToString(), StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
}
return false;
return Utils.GetPolicySetting<ScriptBlockLogging>(Utils.SystemWideThenCurrentUserConfig);
}
// Quick check for script blocks that may have suspicious content. If this
@@ -1808,27 +1778,6 @@ namespace System.Management.Automation
#endif
}
internal static bool ScriptBlockLoggingExplicitlyDisabled()
{
// Verify they haven't explicitly turned off script block logging.
Dictionary<string, object> groupPolicySettings = Utils.GetGroupPolicySetting("ScriptBlockLogging", Utils.RegLocalMachineThenCurrentUser);
if (groupPolicySettings != null)
{
object logScriptBlockExecution;
if (groupPolicySettings.TryGetValue("EnableScriptBlockLogging", out logScriptBlockExecution))
{
// If it is configured and explicitly disabled, return true.
// (Don't even auto-log ones with suspicious content)
if (String.Equals("0", logScriptBlockExecution.ToString(), StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
}
return false;
}
internal static void LogScriptBlockStart(ScriptBlock scriptBlock, Guid runspaceId)
{
// When invoking, log the creation of the script block if it has suspicious
@@ -1843,7 +1792,7 @@ namespace System.Management.Automation
// properly analyzed the script block's security.
LogScriptBlockCreation(scriptBlock, forceLogCreation);
if (ShouldLogScriptBlockActivity("EnableScriptBlockInvocationLogging"))
if (GetScriptBlockLoggingSetting()?.EnableScriptBlockInvocationLogging == true)
{
PSEtwLog.LogOperationalVerbose(PSEventId.ScriptBlock_Invoke_Start_Detail, PSOpcode.Create, PSTask.CommandStart, PSKeyword.UseAlwaysAnalytic,
scriptBlock.Id.ToString(), runspaceId.ToString());
@@ -1852,7 +1801,7 @@ namespace System.Management.Automation
internal static void LogScriptBlockEnd(ScriptBlock scriptBlock, Guid runspaceId)
{
if (ShouldLogScriptBlockActivity("EnableScriptBlockInvocationLogging"))
if (GetScriptBlockLoggingSetting()?.EnableScriptBlockInvocationLogging == true)
{
PSEtwLog.LogOperationalVerbose(PSEventId.ScriptBlock_Invoke_Complete_Detail, PSOpcode.Create, PSTask.CommandStop, PSKeyword.UseAlwaysAnalytic,
scriptBlock.Id.ToString(), runspaceId.ToString());
@@ -6,6 +6,7 @@ using System.Globalization;
using System.Collections.ObjectModel;
using System.Net;
using System.ComponentModel;
using System.Management.Automation.Configuration;
using System.Management.Automation.Internal;
using System.Diagnostics;
using System.Threading;
@@ -1665,14 +1666,9 @@ namespace System.Management.Automation.Help
/// <returns></returns>
internal string GetDefaultSourcePath()
{
try
{
return ConfigPropertyAccessor.Instance.GetDefaultSourcePath();
}
catch (SecurityException)
{
return null;
}
var updatableHelpSetting = Utils.GetPolicySetting<UpdatableHelp>(Utils.SystemWideOnlyConfig);
string defaultSourcePath = updatableHelpSetting?.DefaultSourcePath;
return String.IsNullOrEmpty(defaultSourcePath) ? null : defaultSourcePath;
}
/// <summary>
@@ -1682,7 +1678,7 @@ namespace System.Management.Automation.Help
{
try
{
ConfigPropertyAccessor.Instance.SetDisablePromptToUpdateHelp(true);
PowerShellConfig.Instance.SetDisablePromptToUpdateHelp(true);
}
catch (UnauthorizedAccessException)
{
@@ -1712,7 +1708,7 @@ namespace System.Management.Automation.Help
return false;
}
return ConfigPropertyAccessor.Instance.GetDisablePromptToUpdateHelp();
return PowerShellConfig.Instance.GetDisablePromptToUpdateHelp();
}
catch (SecurityException)
{
@@ -134,54 +134,23 @@ namespace System.Management.Automation
/// <returns></returns>
private static Collection<LogProvider> CreateLogProvider(string shellId)
{
#if V2
try
{
Assembly crimsonAssembly = Assembly.Load(_crimsonLogProviderAssemblyName);
if (crimsonAssembly != null)
{
LogProvider logProvider = (LogProvider)crimsonAssembly.CreateInstance(_crimsonLogProviderTypeName,
false, // don't ignore case
BindingFlags.CreateInstance,
null, // use default binder
null,
null, // use current culture
null // no special activation attributes
);
System.Diagnostics.Debug.Assert(logProvider != null);
return logProvider;
}
}
catch (FileNotFoundException e)
{
_trace.TraceException(e);
}
catch (BadImageFormatException e)
{
_trace.TraceException(e);
}
catch (SecurityException e)
{
_trace.TraceException(e);
}
catch (TargetInvocationException e)
{
_trace.TraceException(e);
}
#endif
Collection<LogProvider> providers = new Collection<LogProvider>();
// Porting note: Linux does not support ETW
#if !UNIX
try
{
#if !CORECLR //TODO:CORECLR EventLogLogProvider not handled yet
LogProvider eventLogLogProvider = new EventLogLogProvider(shellId);
providers.Add(eventLogLogProvider);
#endif
#if UNIX
LogProvider sysLogProvider = new PSSysLogProvider();
providers.Add(sysLogProvider);
#else
LogProvider etwLogProvider = new PSEtwLogProvider();
providers.Add(etwLogProvider);
#endif
return providers;
}
@@ -198,7 +167,7 @@ namespace System.Management.Automation
// when running as non-admin user. In that case, we will default
// to dummy log.
}
#endif
providers.Add(new DummyLogProvider());
return providers;
}
@@ -11,6 +11,7 @@ using System.IO;
using Microsoft.PowerShell;
using Microsoft.PowerShell.Commands;
using Microsoft.Win32;
using System.Management.Automation.Configuration;
using System.Management.Automation.Internal;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
@@ -141,7 +142,6 @@ namespace System.Management.Automation.Internal
throw new PlatformNotSupportedException();
#else
string executionPolicy = "Restricted";
string preferenceKey = Utils.GetRegistryConfigurationPath(shellId);
switch (policy)
{
@@ -174,12 +174,11 @@ namespace System.Management.Automation.Internal
// They want to remove it
if (policy == ExecutionPolicy.Undefined)
{
ConfigPropertyAccessor.Instance.RemoveExecutionPolicy(ConfigPropertyAccessor.PropertyScope.CurrentUser, shellId);
CleanKeyParents(Registry.CurrentUser, preferenceKey);
PowerShellConfig.Instance.RemoveExecutionPolicy(ConfigScope.CurrentUser, shellId);
}
else
{
ConfigPropertyAccessor.Instance.SetExecutionPolicy(ConfigPropertyAccessor.PropertyScope.CurrentUser, shellId, executionPolicy);
PowerShellConfig.Instance.SetExecutionPolicy(ConfigScope.CurrentUser, shellId, executionPolicy);
}
break;
}
@@ -189,12 +188,11 @@ namespace System.Management.Automation.Internal
// They want to remove it
if (policy == ExecutionPolicy.Undefined)
{
ConfigPropertyAccessor.Instance.RemoveExecutionPolicy(ConfigPropertyAccessor.PropertyScope.SystemWide, shellId);
CleanKeyParents(Registry.LocalMachine, preferenceKey);
PowerShellConfig.Instance.RemoveExecutionPolicy(ConfigScope.SystemWide, shellId);
}
else
{
ConfigPropertyAccessor.Instance.SetExecutionPolicy(ConfigPropertyAccessor.PropertyScope.SystemWide, shellId, executionPolicy);
PowerShellConfig.Instance.SetExecutionPolicy(ConfigScope.SystemWide, shellId, executionPolicy);
}
break;
}
@@ -202,50 +200,6 @@ namespace System.Management.Automation.Internal
#endif
}
// Clean up the parents of a registry key as long as they
// contain at most a single child
private static void CleanKeyParents(RegistryKey baseKey, string keyPath)
{
#if CORECLR
if (!Platform.IsInbox)
return;
#endif
using (RegistryKey key = baseKey.OpenSubKey(keyPath, true))
{
// Verify the child key has no children
if ((key == null) || ((key.ValueCount == 0) && (key.SubKeyCount == 0)))
{
// If so, split the key into its path elements
string[] parentKeys = keyPath.Split(Utils.Separators.Backslash);
// Verify we aren't traveling into SOFTWARE\Microsoft
if (parentKeys.Length <= 2)
return;
string currentItem = parentKeys[parentKeys.Length - 1];
// Figure out the parent key name
string parentKeyPath = keyPath.Remove(keyPath.Length - currentItem.Length - 1);
// Open the parent, and clear the child key
if (key != null)
{
using (RegistryKey parentKey = baseKey.OpenSubKey(parentKeyPath, true))
{
parentKey.DeleteSubKey(currentItem, true);
}
}
// Now, process the parent key
CleanKeyParents(baseKey, parentKeyPath);
}
else
{
return;
}
}
}
internal static ExecutionPolicy GetExecutionPolicy(string shellId)
{
foreach (ExecutionPolicyScope scope in ExecutionPolicyScopePreferences)
@@ -556,41 +510,31 @@ namespace System.Management.Automation.Internal
/// <returns>NULL if it is not defined at this level</returns>
private static string GetGroupPolicyValue(string shellId, ExecutionPolicyScope scope)
{
RegistryKey[] scopeKey = null;
ConfigScope[] scopeKey = null;
switch (scope)
{
case ExecutionPolicyScope.MachinePolicy:
{
scopeKey = Utils.RegLocalMachine;
}; break;
scopeKey = Utils.SystemWideOnlyConfig;
break;
case ExecutionPolicyScope.UserPolicy:
{
scopeKey = Utils.RegCurrentUser;
}; break;
scopeKey = Utils.CurrentUserOnlyConfig;
break;
}
Dictionary<string, object> groupPolicySettings = Utils.GetGroupPolicySetting(".", scopeKey);
if (groupPolicySettings == null)
var scriptExecutionSetting = Utils.GetPolicySetting<ScriptExecution>(scopeKey);
if (scriptExecutionSetting != null)
{
return null;
}
Object enableScriptsValue = null;
if (groupPolicySettings.TryGetValue("EnableScripts", out enableScriptsValue))
{
if (String.Equals(enableScriptsValue.ToString(), "0", StringComparison.OrdinalIgnoreCase))
if (scriptExecutionSetting.EnableScripts == false)
{
// Script execution is explicitly disabled
return "Restricted";
}
else if (String.Equals(enableScriptsValue.ToString(), "1", StringComparison.OrdinalIgnoreCase))
else if (scriptExecutionSetting.EnableScripts == true)
{
Object executionPolicyValue = null;
if (groupPolicySettings.TryGetValue("ExecutionPolicy", out executionPolicyValue))
{
return executionPolicyValue.ToString();
}
// Script execution is explicitly enabled
return scriptExecutionSetting.ExecutionPolicy;
}
}
@@ -608,11 +552,11 @@ namespace System.Management.Automation.Internal
{
// 1: Look up the current-user preference
case ExecutionPolicyScope.CurrentUser:
return ConfigPropertyAccessor.Instance.GetExecutionPolicy(ConfigPropertyAccessor.PropertyScope.CurrentUser, shellId);
return PowerShellConfig.Instance.GetExecutionPolicy(ConfigScope.CurrentUser, shellId);
// 2: Look up the system-wide preference
case ExecutionPolicyScope.LocalMachine:
return ConfigPropertyAccessor.Instance.GetExecutionPolicy(ConfigPropertyAccessor.PropertyScope.SystemWide, shellId);
return PowerShellConfig.Instance.GetExecutionPolicy(ConfigScope.SystemWide, shellId);
}
return null;
@@ -3,6 +3,7 @@
// Copyright (C) Microsoft. All rights reserved.
//
using System.Diagnostics.Eventing;
using System.Management.Automation.Configuration;
using System.Management.Automation.Internal;
using System.Text;
using System.Collections.Generic;
@@ -24,10 +25,10 @@ namespace System.Management.Automation.Tracing
/// </summary>
static PSSysLogProvider()
{
s_provider = new SysLogProvider(ConfigPropertyAccessor.Instance.GetSysLogIdentity(),
ConfigPropertyAccessor.Instance.GetLogLevel(),
ConfigPropertyAccessor.Instance.GetLogKeywords(),
ConfigPropertyAccessor.Instance.GetLogChannels());
s_provider = new SysLogProvider(PowerShellConfig.Instance.GetSysLogIdentity(),
PowerShellConfig.Instance.GetLogLevel(),
PowerShellConfig.Instance.GetLogKeywords(),
PowerShellConfig.Instance.GetLogChannels());
}
/// <summary>
@@ -88,7 +88,7 @@ namespace System.Management.Automation.Tracing
/// Initializes a new instance of this class.
/// </summary>
/// <param name="applicationId">The log identity name used to identify the application in syslog.</param>
/// <param name="level">The trace lavel to enable.</param>
/// <param name="level">The trace level to enable.</param>
/// <param name="keywords">The keywords to enable.</param>
/// <param name="channels">The output channels to enable.</param>
public SysLogProvider(string applicationId, PSLevel level, PSKeyword keywords, PSChannel channels)
@@ -313,6 +313,13 @@ namespace System.Management.Automation.Tracing
/// <param name="args">The payload for the log message.</param>
public void Log(PSEventId eventId, PSChannel channel, PSTask task, PSOpcode opcode, PSLevel level, PSKeyword keyword, params object[] args)
{
if (keyword == PSKeyword.UseAlwaysAnalytic)
{
// Use the 'DefaultKeywords' to work around the default keyword filter.
// Note that the PSKeyword argument is not really used in writing SysLog.
keyword = PSSysLogProvider.DefaultKeywords;
}
if (ShouldLog(level, keyword, channel))
{
int threadId = Thread.CurrentThread.ManagedThreadId;
@@ -10,8 +10,8 @@
<ItemGroup>
<Compile Include="..\powershell\Program.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
<Content Include="..\System.Management.Automation\PowerShellProperties.json">
<Link>PowerShellProperties.json</Link>
<Content Include="..\System.Management.Automation\powershell.config.json">
<Link>powershell.config.json</Link>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="..\Modules\Windows-Core\**\*;..\Modules\Windows-Core+Full\**\*;..\Modules\Shared\**\*">
+1 -1
View File
@@ -2,7 +2,7 @@ using Xunit;
using System;
using System.Management.Automation.Language;
namespace PSTests
namespace PSTests.Parallel
{
public static class PSEnumerableBinderTests
{
+1 -1
View File
@@ -4,7 +4,7 @@ using System.IO;
using System.Diagnostics;
using System.Management.Automation;
namespace PSTests
namespace PSTests.Parallel
{
public static class PlatformTests
{
+1 -1
View File
@@ -2,7 +2,7 @@ using Xunit;
using System;
using System.Management.Automation;
namespace PSTests
namespace PSTests.Parallel
{
public static class PSTypeExtensionsTests
{
+1 -1
View File
@@ -15,7 +15,7 @@ using Microsoft.PowerShell;
using Microsoft.PowerShell.Commands;
using System.Reflection;
namespace PSTests
namespace PSTests.Parallel
{
public class FileSystemProviderTests: IDisposable
{
+1 -1
View File
@@ -2,7 +2,7 @@ using Xunit;
using System;
using System.Management.Automation;
namespace PSTests
namespace PSTests.Parallel
{
// Not static because a test requires non-const variables
public class MshSnapinInfoTests
+900
View File
@@ -0,0 +1,900 @@
using Xunit;
using System;
using System.IO;
using System.Management.Automation;
using System.Management.Automation.Configuration;
using System.Management.Automation.Internal;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace PSTests.Sequential
{
public class PowerShellPolicyFixture : IDisposable
{
private const string configFileName = "powershell.config.json";
private readonly string systemWideConfigFile;
private readonly string currentUserConfigFile;
private readonly string systemWideConfigBackupFile;
private readonly string currentUserConfigBackupFile;
private readonly string systemWideConfigDirectory;
private readonly string currentUserConfigDirectory;
private readonly JsonSerializer serializer;
private readonly PowerShellPolicies systemWidePolicies;
private readonly PowerShellPolicies currentUserPolicies;
private readonly bool originalTestHookValue;
public PowerShellPolicyFixture()
{
systemWideConfigDirectory = Utils.DefaultPowerShellAppBase;
currentUserConfigDirectory = Utils.GetUserConfigurationDirectory();
if (!Directory.Exists(currentUserConfigDirectory))
{
// Create the CurrentUser config directory if it doesn't exist
Directory.CreateDirectory(currentUserConfigDirectory);
}
systemWideConfigFile = Path.Combine(systemWideConfigDirectory, configFileName);
currentUserConfigFile = Path.Combine(currentUserConfigDirectory, configFileName);
if (File.Exists(systemWideConfigFile))
{
systemWideConfigBackupFile = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
File.Move(systemWideConfigFile, systemWideConfigBackupFile);
}
if (File.Exists(currentUserConfigFile))
{
currentUserConfigBackupFile = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
File.Move(currentUserConfigFile, currentUserConfigBackupFile);
}
var settings = new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.None,
MaxDepth = 10,
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore
};
serializer = JsonSerializer.Create(settings);
systemWidePolicies = new PowerShellPolicies()
{
ScriptExecution = new ScriptExecution() { ExecutionPolicy = "RemoteSigned", EnableScripts = true },
ScriptBlockLogging = new ScriptBlockLogging() { EnableScriptBlockInvocationLogging = true, EnableScriptBlockLogging = false },
ModuleLogging = new ModuleLogging() { EnableModuleLogging = false, ModuleNames = new string[] { "PSReadline", "PowerShellGet" } },
ProtectedEventLogging = new ProtectedEventLogging() { EnableProtectedEventLogging = false, EncryptionCertificate = new string[] { "Joe" } },
Transcription = new Transcription() { EnableInvocationHeader = true, EnableTranscripting = true, OutputDirectory = "c:\tmp" },
UpdatableHelp = new UpdatableHelp() { DefaultSourcePath = "f:\temp" },
ConsoleSessionConfiguration = new ConsoleSessionConfiguration() { EnableConsoleSessionConfiguration = true, ConsoleSessionConfigurationName = "name" }
};
currentUserPolicies = new PowerShellPolicies()
{
ScriptExecution = new ScriptExecution() { ExecutionPolicy = "RemoteSigned" },
ScriptBlockLogging = new ScriptBlockLogging() { EnableScriptBlockLogging = false },
ModuleLogging = new ModuleLogging() { EnableModuleLogging = false },
ProtectedEventLogging = new ProtectedEventLogging() { EncryptionCertificate = new string[] { "Joe" } }
};
// Set the test hook to disable policy caching
originalTestHookValue = InternalTestHooks.BypassGroupPolicyCaching;
InternalTestHooks.BypassGroupPolicyCaching = true;
}
public void Dispose()
{
CleanupConfigFiles();
if (systemWideConfigBackupFile != null)
{
File.Move(systemWideConfigBackupFile, systemWideConfigFile);
}
if (currentUserConfigBackupFile != null)
{
File.Move(currentUserConfigBackupFile, currentUserConfigFile);
}
InternalTestHooks.BypassGroupPolicyCaching = originalTestHookValue;
}
internal PowerShellPolicies SystemWidePolicies
{
get { return systemWidePolicies; }
}
internal PowerShellPolicies CurrentUserPolicies
{
get { return currentUserPolicies; }
}
#region Compare_Policy_Settings
internal void CompareScriptExecution(ScriptExecution a, ScriptExecution b)
{
if (a == null)
{
Assert.Null(b);
}
else
{
Assert.Equal(a.EnableScripts, b.EnableScripts);
Assert.Equal(a.ExecutionPolicy, b.ExecutionPolicy);
}
}
internal void CompareScriptBlockLogging(ScriptBlockLogging a, ScriptBlockLogging b)
{
if (a == null)
{
Assert.Null(b);
}
else
{
Assert.Equal(a.EnableScriptBlockInvocationLogging, b.EnableScriptBlockInvocationLogging);
Assert.Equal(a.EnableScriptBlockLogging, b.EnableScriptBlockLogging);
}
}
internal void CompareModuleLogging(ModuleLogging a, ModuleLogging b)
{
if (a == null)
{
Assert.Null(b);
}
else
{
Assert.Equal(a.EnableModuleLogging, b.EnableModuleLogging);
if (a.ModuleNames == null)
{
Assert.Null(b.ModuleNames);
}
else
{
Assert.Equal(a.ModuleNames.Length, b.ModuleNames.Length);
for (int i = 0; i < a.ModuleNames.Length; i++)
{
Assert.Equal(a.ModuleNames[i], b.ModuleNames[i]);
}
}
}
}
internal void CompareProtectedEventLogging(ProtectedEventLogging a, ProtectedEventLogging b)
{
if (a == null)
{
Assert.Null(b);
}
else
{
Assert.Equal(a.EnableProtectedEventLogging, b.EnableProtectedEventLogging);
if (a.EncryptionCertificate == null)
{
Assert.Null(b.EncryptionCertificate);
}
else
{
Assert.Equal(a.EncryptionCertificate.Length, b.EncryptionCertificate.Length);
for (int i = 0; i < a.EncryptionCertificate.Length; i++)
{
Assert.Equal(a.EncryptionCertificate[i], b.EncryptionCertificate[i]);
}
}
}
}
internal void CompareTranscription(Transcription a, Transcription b)
{
if (a == null)
{
Assert.Null(b);
}
else
{
Assert.Equal(a.EnableTranscripting, b.EnableTranscripting);
Assert.Equal(a.EnableInvocationHeader, b.EnableInvocationHeader);
Assert.Equal(a.OutputDirectory, b.OutputDirectory);
}
}
internal void CompareUpdatableHelp(UpdatableHelp a, UpdatableHelp b)
{
if (a == null)
{
Assert.Null(b);
}
else
{
Assert.Equal(a.DefaultSourcePath, b.DefaultSourcePath);
}
}
internal void CompareConsoleSessionConfiguration(ConsoleSessionConfiguration a, ConsoleSessionConfiguration b)
{
if (a == null)
{
Assert.Null(b);
}
else
{
Assert.Equal(a.EnableConsoleSessionConfiguration, b.EnableConsoleSessionConfiguration);
Assert.Equal(a.ConsoleSessionConfigurationName, b.ConsoleSessionConfigurationName);
}
}
internal void CompareTwoPolicies(PowerShellPolicies a, PowerShellPolicies b)
{
// Compare 'ScriptExecution' settings
CompareScriptExecution(a.ScriptExecution, b.ScriptExecution);
// Compare 'ScriptBlockLogging' settings
CompareScriptBlockLogging(a.ScriptBlockLogging, b.ScriptBlockLogging);
// Compare 'ModuleLogging' settings
CompareModuleLogging(a.ModuleLogging, b.ModuleLogging);
// Compare 'ProtectedEventLogging' settings
CompareProtectedEventLogging(a.ProtectedEventLogging, b.ProtectedEventLogging);
// Compare 'Transcription' settings
CompareTranscription(a.Transcription, b.Transcription);
// Compare 'UpdatableHelp' settings
CompareUpdatableHelp(a.UpdatableHelp, b.UpdatableHelp);
// Compare 'ConsoleSessionConfiguration' settings
CompareConsoleSessionConfiguration(a.ConsoleSessionConfiguration, b.ConsoleSessionConfiguration);
}
#endregion
#region Configuration_File_Setup
public void CleanupConfigFiles()
{
if (File.Exists(systemWideConfigFile))
{
File.Delete(systemWideConfigFile);
}
if (File.Exists(currentUserConfigFile))
{
File.Delete(currentUserConfigFile);
}
}
public void SetupConfigFile1()
{
CleanupConfigFiles();
// System wide config file has all policy settings
var systemWideConfig = new { ConsolePrompting = true, PowerShellPolicies = systemWidePolicies };
using (var streamWriter = new StreamWriter(systemWideConfigFile))
{
serializer.Serialize(streamWriter, systemWideConfig);
}
// Current user config file has partial policy settings
var currentUserConfig = new { DisablePromptToUpdateHelp = false, PowerShellPolicies = currentUserPolicies };
using (var streamWriter = new StreamWriter(currentUserConfigFile))
{
serializer.Serialize(streamWriter, currentUserConfig);
}
}
public void SetupConfigFile2()
{
CleanupConfigFiles();
// System wide config file has all policy settings
var systemWideConfig = new { ConsolePrompting = true, PowerShellPolicies = systemWidePolicies };
using (var streamWriter = new StreamWriter(systemWideConfigFile))
{
serializer.Serialize(streamWriter, systemWideConfig);
}
// Current user config file is empty
CreateEmptyFile(currentUserConfigFile);
}
public void SetupConfigFile3()
{
CleanupConfigFiles();
// System wide config file is empty
CreateEmptyFile(systemWideConfigFile);
// Current user config file has partial policy settings
var currentUserConfig = new { DisablePromptToUpdateHelp = false, PowerShellPolicies = currentUserPolicies };
using (var streamWriter = new StreamWriter(currentUserConfigFile))
{
serializer.Serialize(streamWriter, currentUserConfig);
}
}
public void SetupConfigFile4()
{
CleanupConfigFiles();
// System wide config file is empty
CreateEmptyFile(systemWideConfigFile);
// Current user config file is empty
CreateEmptyFile(currentUserConfigFile);
}
private void CreateEmptyFile(string fileName)
{
File.Create(fileName).Dispose();
}
#endregion
}
public class PowerShellPolicyTests : IClassFixture<PowerShellPolicyFixture>
{
PowerShellPolicyFixture fixture;
public PowerShellPolicyTests(PowerShellPolicyFixture fixture)
{
this.fixture = fixture;
}
[Fact]
public void PowerShellConfig_GetPowerShellPolicies_BothConfigFilesNotEmpty()
{
fixture.SetupConfigFile1();
var sysPolicies = PowerShellConfig.Instance.GetPowerShellPolicies(ConfigScope.SystemWide);
var userPolicies = PowerShellConfig.Instance.GetPowerShellPolicies(ConfigScope.CurrentUser);
Assert.NotNull(sysPolicies);
Assert.NotNull(userPolicies);
fixture.CompareTwoPolicies(sysPolicies, fixture.SystemWidePolicies);
fixture.CompareTwoPolicies(userPolicies, fixture.CurrentUserPolicies);
}
[Fact]
public void PowerShellConfig_GetPowerShellPolicies_EmptyUserConfig()
{
fixture.SetupConfigFile2();
var sysPolicies = PowerShellConfig.Instance.GetPowerShellPolicies(ConfigScope.SystemWide);
var userPolicies = PowerShellConfig.Instance.GetPowerShellPolicies(ConfigScope.CurrentUser);
Assert.NotNull(sysPolicies);
Assert.Null(userPolicies);
fixture.CompareTwoPolicies(sysPolicies, fixture.SystemWidePolicies);
}
[Fact]
public void PowerShellConfig_GetPowerShellPolicies_EmptySystemConfig()
{
fixture.SetupConfigFile3();
var sysPolicies = PowerShellConfig.Instance.GetPowerShellPolicies(ConfigScope.SystemWide);
var userPolicies = PowerShellConfig.Instance.GetPowerShellPolicies(ConfigScope.CurrentUser);
Assert.Null(sysPolicies);
Assert.NotNull(userPolicies);
fixture.CompareTwoPolicies(userPolicies, fixture.CurrentUserPolicies);
}
[Fact]
public void PowerShellConfig_GetPowerShellPolicies_BothConfigFilesEmpty()
{
fixture.SetupConfigFile4();
var sysPolicies = PowerShellConfig.Instance.GetPowerShellPolicies(ConfigScope.SystemWide);
var userPolicies = PowerShellConfig.Instance.GetPowerShellPolicies(ConfigScope.CurrentUser);
Assert.Null(sysPolicies);
Assert.Null(userPolicies);
}
[Fact]
public void PowerShellConfig_GetPowerShellPolicies_BothConfigFilesNotExist()
{
fixture.CleanupConfigFiles();
var sysPolicies = PowerShellConfig.Instance.GetPowerShellPolicies(ConfigScope.SystemWide);
var userPolicies = PowerShellConfig.Instance.GetPowerShellPolicies(ConfigScope.CurrentUser);
Assert.Null(sysPolicies);
Assert.Null(userPolicies);
}
[Fact]
public void Utils_GetPolicySetting_BothConfigFilesNotEmpty()
{
fixture.SetupConfigFile1();
ScriptExecution scriptExecution;
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.SystemWideOnlyConfig);
fixture.CompareScriptExecution(scriptExecution, fixture.SystemWidePolicies.ScriptExecution);
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.CurrentUserOnlyConfig);
fixture.CompareScriptExecution(scriptExecution, fixture.CurrentUserPolicies.ScriptExecution);
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareScriptExecution(scriptExecution, fixture.SystemWidePolicies.ScriptExecution);
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareScriptExecution(scriptExecution, fixture.CurrentUserPolicies.ScriptExecution);
ScriptBlockLogging scriptBlockLogging;
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.SystemWideOnlyConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, fixture.SystemWidePolicies.ScriptBlockLogging);
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.CurrentUserOnlyConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, fixture.CurrentUserPolicies.ScriptBlockLogging);
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, fixture.SystemWidePolicies.ScriptBlockLogging);
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, fixture.CurrentUserPolicies.ScriptBlockLogging);
ModuleLogging moduleLogging;
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.SystemWideOnlyConfig);
fixture.CompareModuleLogging(moduleLogging, fixture.SystemWidePolicies.ModuleLogging);
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.CurrentUserOnlyConfig);
fixture.CompareModuleLogging(moduleLogging, fixture.CurrentUserPolicies.ModuleLogging);
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareModuleLogging(moduleLogging, fixture.SystemWidePolicies.ModuleLogging);
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareModuleLogging(moduleLogging, fixture.CurrentUserPolicies.ModuleLogging);
ProtectedEventLogging protectedEventLogging;
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.SystemWideOnlyConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, fixture.SystemWidePolicies.ProtectedEventLogging);
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.CurrentUserOnlyConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, fixture.CurrentUserPolicies.ProtectedEventLogging);
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, fixture.SystemWidePolicies.ProtectedEventLogging);
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, fixture.CurrentUserPolicies.ProtectedEventLogging);
// The CurrentUser config doesn't contain any settings for 'Transcription', 'UpdatableHelp' and 'ConsoleSessionConfiguration'
Transcription transcription;
transcription = Utils.GetPolicySetting<Transcription>(Utils.SystemWideOnlyConfig);
fixture.CompareTranscription(transcription, fixture.SystemWidePolicies.Transcription);
transcription = Utils.GetPolicySetting<Transcription>(Utils.CurrentUserOnlyConfig);
fixture.CompareTranscription(transcription, null);
transcription = Utils.GetPolicySetting<Transcription>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareTranscription(transcription, fixture.SystemWidePolicies.Transcription);
transcription = Utils.GetPolicySetting<Transcription>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareTranscription(transcription, fixture.SystemWidePolicies.Transcription);
UpdatableHelp updatableHelp;
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.SystemWideOnlyConfig);
fixture.CompareUpdatableHelp(updatableHelp, fixture.SystemWidePolicies.UpdatableHelp);
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.CurrentUserOnlyConfig);
fixture.CompareUpdatableHelp(updatableHelp, null);
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareUpdatableHelp(updatableHelp, fixture.SystemWidePolicies.UpdatableHelp);
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareUpdatableHelp(updatableHelp, fixture.SystemWidePolicies.UpdatableHelp);
ConsoleSessionConfiguration consoleSessionConfiguration;
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.SystemWideOnlyConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, fixture.SystemWidePolicies.ConsoleSessionConfiguration);
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.CurrentUserOnlyConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null);
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, fixture.SystemWidePolicies.ConsoleSessionConfiguration);
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, fixture.SystemWidePolicies.ConsoleSessionConfiguration);
}
[Fact]
public void Utils_GetPolicySetting_EmptyUserConfig()
{
fixture.SetupConfigFile2();
// The CurrentUser config is empty
ScriptExecution scriptExecution;
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.SystemWideOnlyConfig);
fixture.CompareScriptExecution(scriptExecution, fixture.SystemWidePolicies.ScriptExecution);
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.CurrentUserOnlyConfig);
fixture.CompareScriptExecution(scriptExecution, null);
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareScriptExecution(scriptExecution, fixture.SystemWidePolicies.ScriptExecution);
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareScriptExecution(scriptExecution, fixture.SystemWidePolicies.ScriptExecution);
ScriptBlockLogging scriptBlockLogging;
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.SystemWideOnlyConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, fixture.SystemWidePolicies.ScriptBlockLogging);
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.CurrentUserOnlyConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, null);
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, fixture.SystemWidePolicies.ScriptBlockLogging);
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, fixture.SystemWidePolicies.ScriptBlockLogging);
ModuleLogging moduleLogging;
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.SystemWideOnlyConfig);
fixture.CompareModuleLogging(moduleLogging, fixture.SystemWidePolicies.ModuleLogging);
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.CurrentUserOnlyConfig);
fixture.CompareModuleLogging(moduleLogging, null);
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareModuleLogging(moduleLogging, fixture.SystemWidePolicies.ModuleLogging);
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareModuleLogging(moduleLogging, fixture.SystemWidePolicies.ModuleLogging);
ProtectedEventLogging protectedEventLogging;
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.SystemWideOnlyConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, fixture.SystemWidePolicies.ProtectedEventLogging);
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.CurrentUserOnlyConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, null);
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, fixture.SystemWidePolicies.ProtectedEventLogging);
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, fixture.SystemWidePolicies.ProtectedEventLogging);
Transcription transcription;
transcription = Utils.GetPolicySetting<Transcription>(Utils.SystemWideOnlyConfig);
fixture.CompareTranscription(transcription, fixture.SystemWidePolicies.Transcription);
transcription = Utils.GetPolicySetting<Transcription>(Utils.CurrentUserOnlyConfig);
fixture.CompareTranscription(transcription, null);
transcription = Utils.GetPolicySetting<Transcription>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareTranscription(transcription, fixture.SystemWidePolicies.Transcription);
transcription = Utils.GetPolicySetting<Transcription>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareTranscription(transcription, fixture.SystemWidePolicies.Transcription);
UpdatableHelp updatableHelp;
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.SystemWideOnlyConfig);
fixture.CompareUpdatableHelp(updatableHelp, fixture.SystemWidePolicies.UpdatableHelp);
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.CurrentUserOnlyConfig);
fixture.CompareUpdatableHelp(updatableHelp, null);
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareUpdatableHelp(updatableHelp, fixture.SystemWidePolicies.UpdatableHelp);
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareUpdatableHelp(updatableHelp, fixture.SystemWidePolicies.UpdatableHelp);
ConsoleSessionConfiguration consoleSessionConfiguration;
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.SystemWideOnlyConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, fixture.SystemWidePolicies.ConsoleSessionConfiguration);
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.CurrentUserOnlyConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null);
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, fixture.SystemWidePolicies.ConsoleSessionConfiguration);
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, fixture.SystemWidePolicies.ConsoleSessionConfiguration);
}
[Fact]
public void Utils_GetPolicySetting_EmptySystemConfig()
{
fixture.SetupConfigFile3();
// The SystemWide config is empty
ScriptExecution scriptExecution;
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.SystemWideOnlyConfig);
fixture.CompareScriptExecution(scriptExecution, null);
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.CurrentUserOnlyConfig);
fixture.CompareScriptExecution(scriptExecution, fixture.CurrentUserPolicies.ScriptExecution);
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareScriptExecution(scriptExecution, fixture.CurrentUserPolicies.ScriptExecution);
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareScriptExecution(scriptExecution, fixture.CurrentUserPolicies.ScriptExecution);
ScriptBlockLogging scriptBlockLogging;
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.SystemWideOnlyConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, null);
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.CurrentUserOnlyConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, fixture.CurrentUserPolicies.ScriptBlockLogging);
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, fixture.CurrentUserPolicies.ScriptBlockLogging);
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, fixture.CurrentUserPolicies.ScriptBlockLogging);
ModuleLogging moduleLogging;
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.SystemWideOnlyConfig);
fixture.CompareModuleLogging(moduleLogging, null);
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.CurrentUserOnlyConfig);
fixture.CompareModuleLogging(moduleLogging, fixture.CurrentUserPolicies.ModuleLogging);
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareModuleLogging(moduleLogging, fixture.CurrentUserPolicies.ModuleLogging);
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareModuleLogging(moduleLogging, fixture.CurrentUserPolicies.ModuleLogging);
ProtectedEventLogging protectedEventLogging;
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.SystemWideOnlyConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, null);
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.CurrentUserOnlyConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, fixture.CurrentUserPolicies.ProtectedEventLogging);
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, fixture.CurrentUserPolicies.ProtectedEventLogging);
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, fixture.CurrentUserPolicies.ProtectedEventLogging);
// The CurrentUser config doesn't contain any settings for 'Transcription', 'UpdatableHelp' and 'ConsoleSessionConfiguration'
Transcription transcription;
transcription = Utils.GetPolicySetting<Transcription>(Utils.SystemWideOnlyConfig);
fixture.CompareTranscription(transcription, null);
transcription = Utils.GetPolicySetting<Transcription>(Utils.CurrentUserOnlyConfig);
fixture.CompareTranscription(transcription, null);
transcription = Utils.GetPolicySetting<Transcription>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareTranscription(transcription, null);
transcription = Utils.GetPolicySetting<Transcription>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareTranscription(transcription, null);
UpdatableHelp updatableHelp;
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.SystemWideOnlyConfig);
fixture.CompareUpdatableHelp(updatableHelp, null);
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.CurrentUserOnlyConfig);
fixture.CompareUpdatableHelp(updatableHelp, null);
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareUpdatableHelp(updatableHelp, null);
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareUpdatableHelp(updatableHelp, null);
ConsoleSessionConfiguration consoleSessionConfiguration;
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.SystemWideOnlyConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null);
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.CurrentUserOnlyConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null);
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null);
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null);
}
[Fact]
public void Utils_GetPolicySetting_BothConfigFilesEmpty()
{
fixture.SetupConfigFile4();
// Both config files are empty
ScriptExecution scriptExecution;
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.SystemWideOnlyConfig);
fixture.CompareScriptExecution(scriptExecution, null);
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.CurrentUserOnlyConfig);
fixture.CompareScriptExecution(scriptExecution, null);
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareScriptExecution(scriptExecution, null);
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareScriptExecution(scriptExecution, null);
ScriptBlockLogging scriptBlockLogging;
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.SystemWideOnlyConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, null);
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.CurrentUserOnlyConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, null);
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, null);
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, null);
ModuleLogging moduleLogging;
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.SystemWideOnlyConfig);
fixture.CompareModuleLogging(moduleLogging, null);
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.CurrentUserOnlyConfig);
fixture.CompareModuleLogging(moduleLogging, null);
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareModuleLogging(moduleLogging, null);
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareModuleLogging(moduleLogging, null);
ProtectedEventLogging protectedEventLogging;
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.SystemWideOnlyConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, null);
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.CurrentUserOnlyConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, null);
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, null);
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, null);
// The CurrentUser config doesn't contain any settings for 'Transcription', 'UpdatableHelp' and 'ConsoleSessionConfiguration'
Transcription transcription;
transcription = Utils.GetPolicySetting<Transcription>(Utils.SystemWideOnlyConfig);
fixture.CompareTranscription(transcription, null);
transcription = Utils.GetPolicySetting<Transcription>(Utils.CurrentUserOnlyConfig);
fixture.CompareTranscription(transcription, null);
transcription = Utils.GetPolicySetting<Transcription>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareTranscription(transcription, null);
transcription = Utils.GetPolicySetting<Transcription>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareTranscription(transcription, null);
UpdatableHelp updatableHelp;
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.SystemWideOnlyConfig);
fixture.CompareUpdatableHelp(updatableHelp, null);
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.CurrentUserOnlyConfig);
fixture.CompareUpdatableHelp(updatableHelp, null);
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareUpdatableHelp(updatableHelp, null);
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareUpdatableHelp(updatableHelp, null);
ConsoleSessionConfiguration consoleSessionConfiguration;
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.SystemWideOnlyConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null);
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.CurrentUserOnlyConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null);
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null);
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null);
}
[Fact]
public void Utils_GetPolicySetting_BothConfigFilesNotExist()
{
fixture.CleanupConfigFiles();
// Both config files don't exist
ScriptExecution scriptExecution;
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.SystemWideOnlyConfig);
fixture.CompareScriptExecution(scriptExecution, null);
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.CurrentUserOnlyConfig);
fixture.CompareScriptExecution(scriptExecution, null);
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareScriptExecution(scriptExecution, null);
scriptExecution = Utils.GetPolicySetting<ScriptExecution>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareScriptExecution(scriptExecution, null);
ScriptBlockLogging scriptBlockLogging;
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.SystemWideOnlyConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, null);
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.CurrentUserOnlyConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, null);
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, null);
scriptBlockLogging = Utils.GetPolicySetting<ScriptBlockLogging>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareScriptBlockLogging(scriptBlockLogging, null);
ModuleLogging moduleLogging;
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.SystemWideOnlyConfig);
fixture.CompareModuleLogging(moduleLogging, null);
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.CurrentUserOnlyConfig);
fixture.CompareModuleLogging(moduleLogging, null);
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareModuleLogging(moduleLogging, null);
moduleLogging = Utils.GetPolicySetting<ModuleLogging>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareModuleLogging(moduleLogging, null);
ProtectedEventLogging protectedEventLogging;
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.SystemWideOnlyConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, null);
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.CurrentUserOnlyConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, null);
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, null);
protectedEventLogging = Utils.GetPolicySetting<ProtectedEventLogging>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareProtectedEventLogging(protectedEventLogging, null);
// The CurrentUser config doesn't contain any settings for 'Transcription', 'UpdatableHelp' and 'ConsoleSessionConfiguration'
Transcription transcription;
transcription = Utils.GetPolicySetting<Transcription>(Utils.SystemWideOnlyConfig);
fixture.CompareTranscription(transcription, null);
transcription = Utils.GetPolicySetting<Transcription>(Utils.CurrentUserOnlyConfig);
fixture.CompareTranscription(transcription, null);
transcription = Utils.GetPolicySetting<Transcription>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareTranscription(transcription, null);
transcription = Utils.GetPolicySetting<Transcription>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareTranscription(transcription, null);
UpdatableHelp updatableHelp;
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.SystemWideOnlyConfig);
fixture.CompareUpdatableHelp(updatableHelp, null);
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.CurrentUserOnlyConfig);
fixture.CompareUpdatableHelp(updatableHelp, null);
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareUpdatableHelp(updatableHelp, null);
updatableHelp = Utils.GetPolicySetting<UpdatableHelp>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareUpdatableHelp(updatableHelp, null);
ConsoleSessionConfiguration consoleSessionConfiguration;
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.SystemWideOnlyConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null);
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.CurrentUserOnlyConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null);
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.SystemWideThenCurrentUserConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null);
consoleSessionConfiguration = Utils.GetPolicySetting<ConsoleSessionConfiguration>(Utils.CurrentUserThenSystemWideConfig);
fixture.CompareConsoleSessionConfiguration(consoleSessionConfiguration, null);
}
}
}
+1 -1
View File
@@ -2,7 +2,7 @@ using Xunit;
using System;
using System.Management.Automation;
namespace PSTests
namespace PSTests.Parallel
{
public static class PSVersionInfoTests
{
+1 -1
View File
@@ -3,7 +3,7 @@ using System;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
namespace PSTests
namespace PSTests.Parallel
{
// NOTE: do not call AddCommand("out-host") after invoking or MergeMyResults,
// otherwise Invoke will not return any objects
+1 -1
View File
@@ -2,7 +2,7 @@ using Xunit;
using System;
using System.Management.Automation;
namespace PSTests
namespace PSTests.Parallel
{
public static class SecuritySupportTests
{
+1 -1
View File
@@ -10,7 +10,7 @@ using System.Management.Automation.Internal.Host;
using System.Management.Automation.Runspaces;
using Microsoft.PowerShell;
namespace PSTests
namespace PSTests.Parallel
{
public class SessionStateTests
{
+1 -1
View File
@@ -3,7 +3,7 @@ using System;
using System.Management.Automation;
using System.Reflection;
namespace PSTests
namespace PSTests.Parallel
{
public static class UtilsTests
{
@@ -1,5 +1,5 @@
#
# Functional tests to verify basic conditions for IO to the PowerShellProperties.json files
# Functional tests to verify basic conditions for IO to the powershell.config.json files
# The properties files are supported on non-Windows OSes, but the tests are specific to
# Windows so that file IO can be verified using supported cmdlets.
#
@@ -14,18 +14,18 @@ try {
$IsNotSkipped = ($IsWindows -and !$IsInbox) # Only execute for PowerShell Core on Windows
$PSDefaultParameterValues["it:skip"] = !$IsNotSkipped
Describe "User-Specific PowerShellProperties.json Modifications" -Tags "CI" {
Describe "User-Specific powershell.config.json Modifications" -Tags "CI" {
BeforeAll {
if ($IsNotSkipped) {
# Discover the user-specific PowerShellProperties.json file
# Discover the user-specific powershell.config.json file
$userSettingsDir = [System.IO.Path]::Combine($env:USERPROFILE, "Documents", $productName)
$userPropertiesFile = Join-Path $userSettingsDir "PowerShellProperties.json"
$userPropertiesFile = Join-Path $userSettingsDir "powershell.config.json"
# Save the file for restoration after the tests are complete
$backupPropertiesFile = ""
if (Test-Path $userPropertiesFile) {
$backupPropertiesFile = Join-Path $userSettingsDir "ORIGINAL_PowerShellProperties.json"
$backupPropertiesFile = Join-Path $userSettingsDir "ORIGINAL_powershell.config.json"
Copy-Item -Path $userPropertiesFile -Destination $backupPropertiesFile -Force -ErrorAction Continue
}
elseif (-not (Test-Path $userSettingsDir)) {
@@ -49,12 +49,12 @@ try {
if ($IsNotSkipped) {
if (-not $backupPropertiesFile)
{
# Remove PowerShellProperties.json if it did not exist before the tests
# Remove powershell.config.json if it did not exist before the tests
Remove-Item -Path $userPropertiesFile -Force -ErrorAction SilentlyContinue
}
else
{
# Restore the original PowerShellProperties.json file if it existed before the test pass.
# Restore the original powershell.config.json file if it existed before the test pass.
Move-Item -Path $backupPropertiesFile -Destination $userPropertiesFile -Force -ErrorAction Continue
}
+11 -4
View File
@@ -325,7 +325,8 @@ function Invoke-AppVeyorTest
Write-Host -Foreground Green 'Run CoreCLR tests'
$testResultsNonAdminFile = "$pwd\TestsResultsNonAdmin.xml"
$testResultsAdminFile = "$pwd\TestsResultsAdmin.xml"
$testResultsXUnitFile = "$pwd\TestResultsXUnit.xml"
$SequentialXUnitTestResultsFile = "$pwd\SequentialXUnitTestResults.xml"
$ParallelXUnitTestResultsFile = "$pwd\ParallelXUnitTestResults.xml"
if(!(Test-Path "$env:CoreOutput\pwsh.exe"))
{
throw "CoreCLR pwsh.exe was not built"
@@ -359,9 +360,10 @@ function Invoke-AppVeyorTest
Write-Host -Foreground Green 'Upload CoreCLR Admin test results'
Update-AppVeyorTestResults -resultsFile $testResultsAdminFile
Start-PSxUnit -TestResultsFile $testResultsXUnitFile
Start-PSxUnit -SequentialTestResultsFile $SequentialXUnitTestResultsFile -ParallelTestResultsFile $ParallelXUnitTestResultsFile
Write-Host -ForegroundColor Green 'Uploading PSxUnit test results'
Update-AppVeyorTestResults -resultsFile $testResultsXUnitFile
Update-AppVeyorTestResults -resultsFile $SequentialXUnitTestResultsFile
Update-AppVeyorTestResults -resultsFile $ParallelXUnitTestResultsFile
#
# Fail the build, if tests failed
@@ -372,7 +374,12 @@ function Invoke-AppVeyorTest
Test-PSPesterResults -TestResultsFile $_
}
$testPassResult = Test-XUnitTestResults -TestResultsFile $testResultsXUnitFile
@(
$SequentialXUnitTestResultsFile,
$ParallelXUnitTestResultsFile
) | ForEach-Object {
Test-XUnitTestResults -TestResultsFile $_
}
Set-BuildVariable -Name TestPassed -Value True
}
+5 -3
View File
@@ -240,10 +240,12 @@ elseif($Stage -eq 'Build')
}
try {
$testResultsXUnitFile = "$pwd/TestResultsXUnit.xml"
Start-PSxUnit -TestResultsFile $testResultsXUnitFile
$SequentialXUnitTestResultsFile = "$pwd/SequentialXUnitTestResults.xml"
$ParallelXUnitTestResultsFile = "$pwd/ParallelXUnitTestResults.xml"
Start-PSxUnit -SequentialTestResultsFile $SequentialXUnitTestResultsFile -ParallelTestResultsFile $ParallelXUnitTestResultsFile
# If there are failures, Test-XUnitTestResults throws
$testPassResult = Test-XUnitTestResults -TestResultsFile $testResultsXUnitFile
$SequentialXUnitTestResultsFile, $ParallelXUnitTestResultsFile | ForEach-Object { Test-XUnitTestResults -TestResultsFile $_ }
}
catch {
$result = "FAIL"