From f8e244c59838ff9e3510d61992b8506e35075594 Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Fri, 21 Feb 2020 09:28:07 -0800 Subject: [PATCH 1/7] Fix how we set execution policy --- .../PowerShellContextService.cs | 91 +++++++++++-------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs index dddbd37bb..d4f6c63f6 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Globalization; using System.IO; using System.Linq; using System.Management.Automation.Host; @@ -23,6 +22,7 @@ namespace Microsoft.PowerShell.EditorServices.Services { using System.Diagnostics.CodeAnalysis; using System.Management.Automation; + using System.Runtime.InteropServices; using Microsoft.PowerShell.EditorServices.Handlers; using Microsoft.PowerShell.EditorServices.Hosting; using Microsoft.PowerShell.EditorServices.Logging; @@ -367,10 +367,10 @@ public void Initialize( powerShellVersion.ToString()); } - if (this.LocalPowerShellVersion.Edition != "Linux") + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { // TODO: Should this be configurable? - this.SetExecutionPolicy(ExecutionPolicy.RemoteSigned); + this.SetExecutionPolicy(); } // Set up the runspace @@ -2086,56 +2086,67 @@ private static string GetStringForPSCommand(PSCommand psCommand) return stringBuilder.ToString(); } - private void SetExecutionPolicy(ExecutionPolicy desiredExecutionPolicy) + private void SetExecutionPolicy() { - var currentPolicy = ExecutionPolicy.Undefined; + // We want to get the list hierarchy of execution policies + // Calling the cmdlet is the simplest way to do that + IEnumerable policies = this.powerShell + .AddCommand("Get-ExecutionPolicy") + .AddParameter("-List") + .Invoke(); - // Get the current execution policy so that we don't set it higher than it already is - this.powerShell.Commands.AddCommand("Get-ExecutionPolicy"); + this.powerShell.Commands.Clear(); - var result = this.powerShell.Invoke(); - if (result.Count > 0) + // The policies come out in the following order: + // - MachinePolicy + // - UserPolicy + // - Process + // - CurrentUser + // - LocalMachine + // This is the order of precedence we want to follow, skipping the Process scope + // + // Get-ExecutionPolicy -List emits PSObjects with Scope and ExecutionPolicy note properties + // set to expected values, so we must sift through those. + ExecutionPolicy policyToSet = ExecutionPolicy.Bypass; + foreach (PSObject policy in policies) { - currentPolicy = result.FirstOrDefault(); + if ((ExecutionPolicyScope)policy.Members["Scope"].Value == ExecutionPolicyScope.Process) + { + continue; + } + + var executionPolicy = (ExecutionPolicy)policy.Members["ExecutionPolicy"].Value; + if (executionPolicy != ExecutionPolicy.Undefined) + { + policyToSet = executionPolicy; + } } - if (desiredExecutionPolicy < currentPolicy || - desiredExecutionPolicy == ExecutionPolicy.Bypass || - currentPolicy == ExecutionPolicy.Undefined) + // If there's nothing to do, save ourselves a PowerShell invocation + if (policyToSet == ExecutionPolicy.Bypass) { - this.logger.LogTrace( - string.Format( - "Setting execution policy:\r\n Current = ExecutionPolicy.{0}\r\n Desired = ExecutionPolicy.{1}", - currentPolicy, - desiredExecutionPolicy)); + this.logger.LogTrace("Execution policy already set to Bypass. Skipping execution policy set"); + return; + } - this.powerShell.Commands.Clear(); + // Finally set the inherited execution policy + this.logger.LogTrace("Setting execution policy to {Policy}", policyToSet); + try + { this.powerShell .AddCommand("Set-ExecutionPolicy") - .AddParameter("ExecutionPolicy", desiredExecutionPolicy) .AddParameter("Scope", ExecutionPolicyScope.Process) - .AddParameter("Force"); - - try - { - this.powerShell.Invoke(); - } - catch (CmdletInvocationException e) - { - this.logger.LogException( - $"An error occurred while calling Set-ExecutionPolicy, the desired policy of {desiredExecutionPolicy} may not be set.", - e); - } - - this.powerShell.Commands.Clear(); + .AddParameter("ExecutionPolicy", policyToSet) + .AddParameter("Force") + .Invoke(); } - else + catch (CmdletInvocationException e) { - this.logger.LogTrace( - string.Format( - "Current execution policy: ExecutionPolicy.{0}", - currentPolicy)); - + this.logger.LogError(e, "Error occurred calling 'Set-ExecutionPolicy -Scope Process -ExecutionPolicy {Policy} -Force'", policyToSet); + } + finally + { + this.powerShell.Commands.Clear(); } } From 15e1bd5a28ba815d443517455c859301da5df7bd Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Tue, 25 Feb 2020 14:47:10 -0800 Subject: [PATCH 2/7] Remove TODO --- .../Services/PowerShellContext/PowerShellContextService.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs index d4f6c63f6..496389d64 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs @@ -369,7 +369,6 @@ public void Initialize( if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - // TODO: Should this be configurable? this.SetExecutionPolicy(); } From 603e289e13ce93121c3ea24ea3f114248ae1490f Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Tue, 25 Feb 2020 14:52:15 -0800 Subject: [PATCH 3/7] Iterate through policies in reverse order --- .../PowerShellContext/PowerShellContextService.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs index 496389d64..12d39e5dd 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs @@ -2089,7 +2089,7 @@ private void SetExecutionPolicy() { // We want to get the list hierarchy of execution policies // Calling the cmdlet is the simplest way to do that - IEnumerable policies = this.powerShell + IReadOnlyList policies = this.powerShell .AddCommand("Get-ExecutionPolicy") .AddParameter("-List") .Invoke(); @@ -2107,17 +2107,20 @@ private void SetExecutionPolicy() // Get-ExecutionPolicy -List emits PSObjects with Scope and ExecutionPolicy note properties // set to expected values, so we must sift through those. ExecutionPolicy policyToSet = ExecutionPolicy.Bypass; - foreach (PSObject policy in policies) + for (int i = policies.Count; i >= 0; i--) { - if ((ExecutionPolicyScope)policy.Members["Scope"].Value == ExecutionPolicyScope.Process) + PSObject policyObject = policies[i]; + + if ((ExecutionPolicyScope)policyObject.Members["Scope"].Value == ExecutionPolicyScope.Process) { continue; } - var executionPolicy = (ExecutionPolicy)policy.Members["ExecutionPolicy"].Value; + var executionPolicy = (ExecutionPolicy)policyObject.Members["ExecutionPolicy"].Value; if (executionPolicy != ExecutionPolicy.Undefined) { policyToSet = executionPolicy; + break; } } From ebc1ce32928081245c3f02c7b16869002790310d Mon Sep 17 00:00:00 2001 From: Robert Holt Date: Tue, 25 Feb 2020 15:48:08 -0800 Subject: [PATCH 4/7] Apply suggestions from code review Co-Authored-By: Tyler James Leonhardt --- .../Services/PowerShellContext/PowerShellContextService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs index 12d39e5dd..03b6af596 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs @@ -2090,7 +2090,7 @@ private void SetExecutionPolicy() // We want to get the list hierarchy of execution policies // Calling the cmdlet is the simplest way to do that IReadOnlyList policies = this.powerShell - .AddCommand("Get-ExecutionPolicy") + .AddCommand("Microsoft.PowerShell.Security\\Get-ExecutionPolicy") .AddParameter("-List") .Invoke(); @@ -2136,7 +2136,7 @@ private void SetExecutionPolicy() try { this.powerShell - .AddCommand("Set-ExecutionPolicy") + .AddCommand("Microsoft.PowerShell.Security\\Set-ExecutionPolicy") .AddParameter("Scope", ExecutionPolicyScope.Process) .AddParameter("ExecutionPolicy", policyToSet) .AddParameter("Force") From aa47bd38611899fc5a8600d60033fb90bd37c9d9 Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Tue, 25 Feb 2020 15:50:08 -0800 Subject: [PATCH 5/7] Use IsWindows util method --- .../Services/PowerShellContext/PowerShellContextService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs index 12d39e5dd..688881070 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs @@ -367,7 +367,7 @@ public void Initialize( powerShellVersion.ToString()); } - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (VersionUtils.IsWindows) { this.SetExecutionPolicy(); } From 069ee0962ba4f244e1eb6bccbc2542c85601970e Mon Sep 17 00:00:00 2001 From: Robert Holt Date: Wed, 26 Feb 2020 11:39:06 -0800 Subject: [PATCH 6/7] Update src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs Co-Authored-By: Patrick Meinecke --- .../Services/PowerShellContext/PowerShellContextService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs index 6da46693c..d7f625b60 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs @@ -2113,7 +2113,7 @@ private void SetExecutionPolicy() if ((ExecutionPolicyScope)policyObject.Members["Scope"].Value == ExecutionPolicyScope.Process) { - continue; + break; } var executionPolicy = (ExecutionPolicy)policyObject.Members["ExecutionPolicy"].Value; From 921eee64705a723dbd4d14cef617c54c827d3786 Mon Sep 17 00:00:00 2001 From: Rob Holt Date: Wed, 26 Feb 2020 11:47:20 -0800 Subject: [PATCH 7/7] Fix indexing --- .../Services/PowerShellContext/PowerShellContextService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs index d7f625b60..8bf56b7a3 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs @@ -2107,7 +2107,7 @@ private void SetExecutionPolicy() // Get-ExecutionPolicy -List emits PSObjects with Scope and ExecutionPolicy note properties // set to expected values, so we must sift through those. ExecutionPolicy policyToSet = ExecutionPolicy.Bypass; - for (int i = policies.Count; i >= 0; i--) + for (int i = policies.Count - 1; i >= 0; i--) { PSObject policyObject = policies[i];