mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Implement RoleDefinitions RoleCapabilityFiles keyword (#3067)
* Changes to implement remote endpoint RoleDefinition RoleCapabilityFiles keyword * Fixed spelling error. Added back missing resource string * Updated tests from CR comments * Simplified error tests per Code Review * Test change from Code Review
This commit is contained in:
committed by
Dongbo Wang
parent
a16fead0a5
commit
ca12001c8d
+1
-1
@@ -735,7 +735,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
if (_roleDefinitions == null)
|
||||
{
|
||||
result.Append(SessionConfigurationUtils.ConfigFragment(ConfigFileConstants.RoleDefinitions, RemotingErrorIdStrings.DISCRoleDefinitionsComment,
|
||||
"@{ 'CONTOSO\\SqlAdmins' = @{ RoleCapabilities = 'SqlAdministration' }; 'CONTOSO\\ServerMonitors' = @{ VisibleCmdlets = 'Get-Process' } } ", streamWriter, true));
|
||||
"@{ 'CONTOSO\\SqlAdmins' = @{ RoleCapabilities = 'SqlAdministration' }; 'CONTOSO\\SqlManaged' = @{ RoleCapabilityFiles = 'C:\\RoleCapability\\SqlManaged.psrc' }; 'CONTOSO\\ServerMonitors' = @{ VisibleCmdlets = 'Get-Process' } } ", streamWriter, true));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+43
-4
@@ -947,6 +947,7 @@ namespace System.Management.Automation.Remoting
|
||||
internal static readonly string ScriptsToProcess = "ScriptsToProcess";
|
||||
internal static readonly string SessionType = "SessionType";
|
||||
internal static readonly string RoleCapabilities = "RoleCapabilities";
|
||||
internal static readonly string RoleCapabilityFiles = "RoleCapabilityFiles";
|
||||
internal static readonly string RunAsVirtualAccount = "RunAsVirtualAccount";
|
||||
internal static readonly string RunAsVirtualAccountGroups = "RunAsVirtualAccountGroups";
|
||||
internal static readonly string TranscriptDirectory = "TranscriptDirectory";
|
||||
@@ -981,6 +982,7 @@ namespace System.Management.Automation.Remoting
|
||||
new ConfigTypeEntry(PowerShellVersion, new ConfigTypeEntry.TypeValidationCallback(StringTypeValidationCallback)),
|
||||
new ConfigTypeEntry(RequiredGroups, new ConfigTypeEntry.TypeValidationCallback(HashtableTypeValidationCallback)),
|
||||
new ConfigTypeEntry(RoleCapabilities, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)),
|
||||
new ConfigTypeEntry(RoleCapabilityFiles, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)),
|
||||
new ConfigTypeEntry(RoleDefinitions, new ConfigTypeEntry.TypeValidationCallback(HashtableTypeValidationCallback)),
|
||||
new ConfigTypeEntry(RunAsVirtualAccount, new ConfigTypeEntry.TypeValidationCallback(BooleanTypeValidationCallback)),
|
||||
new ConfigTypeEntry(RunAsVirtualAccountGroups, new ConfigTypeEntry.TypeValidationCallback(StringArrayTypeValidationCallback)),
|
||||
@@ -1391,6 +1393,7 @@ namespace System.Management.Automation.Remoting
|
||||
private static readonly HashSet<string> s_allowedRoleCapabilityKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"RoleCapabilities",
|
||||
"RoleCapabilityFiles",
|
||||
"ModulesToImport",
|
||||
"VisibleAliases",
|
||||
"VisibleCmdlets",
|
||||
@@ -1808,8 +1811,11 @@ namespace System.Management.Automation.Remoting
|
||||
}
|
||||
|
||||
// Takes the "RoleCapabilities" node in the config hash, and merges its values into the base configuration.
|
||||
private const string PSRCExtension = ".psrc";
|
||||
private void MergeRoleCapabilitiesIntoConfigHash()
|
||||
{
|
||||
List<string> psrcFiles = new List<string>();
|
||||
|
||||
if (_configHash.ContainsKey(ConfigFileConstants.RoleCapabilities))
|
||||
{
|
||||
string[] roleCapabilities = TryGetStringArray(_configHash[ConfigFileConstants.RoleCapabilities]);
|
||||
@@ -1821,18 +1827,51 @@ namespace System.Management.Automation.Remoting
|
||||
string roleCapabilityPath = GetRoleCapabilityPath(roleCapability);
|
||||
if (String.IsNullOrEmpty(roleCapabilityPath))
|
||||
{
|
||||
string message = StringUtil.Format(RemotingErrorIdStrings.CouldNotFindRoleCapability, roleCapability, roleCapability + ".psrc");
|
||||
string message = StringUtil.Format(RemotingErrorIdStrings.CouldNotFindRoleCapability, roleCapability, roleCapability + PSRCExtension);
|
||||
PSInvalidOperationException ioe = new PSInvalidOperationException(message);
|
||||
ioe.SetErrorId("CouldNotFindRoleCapability");
|
||||
throw ioe;
|
||||
}
|
||||
|
||||
DISCPowerShellConfiguration roleCapabilityConfiguration = new DISCPowerShellConfiguration(roleCapabilityPath, null);
|
||||
IDictionary roleCapabilityConfigurationItems = roleCapabilityConfiguration.ConfigHash;
|
||||
MergeConfigHashIntoConfigHash(roleCapabilityConfigurationItems);
|
||||
psrcFiles.Add(roleCapabilityPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ConfigHash.ContainsKey(ConfigFileConstants.RoleCapabilityFiles))
|
||||
{
|
||||
string[] roleCapabilityFiles = TryGetStringArray(ConfigHash[ConfigFileConstants.RoleCapabilityFiles]);
|
||||
if (roleCapabilityFiles != null)
|
||||
{
|
||||
foreach (var roleCapabilityFilePath in roleCapabilityFiles)
|
||||
{
|
||||
if (!Path.GetExtension(roleCapabilityFilePath).Equals(PSRCExtension, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string message = StringUtil.Format(RemotingErrorIdStrings.InvalidRoleCapabilityFileExtension, roleCapabilityFilePath);
|
||||
PSInvalidOperationException ioe = new PSInvalidOperationException(message);
|
||||
ioe.SetErrorId("InvalidRoleCapabilityFileExtension");
|
||||
throw ioe;
|
||||
}
|
||||
|
||||
if (!File.Exists(roleCapabilityFilePath))
|
||||
{
|
||||
string message = StringUtil.Format(RemotingErrorIdStrings.CouldNotFindRoleCapabilityFile, roleCapabilityFilePath);
|
||||
PSInvalidOperationException ioe = new PSInvalidOperationException(message);
|
||||
ioe.SetErrorId("CouldNotFindRoleCapabilityFile");
|
||||
throw ioe;
|
||||
}
|
||||
|
||||
psrcFiles.Add(roleCapabilityFilePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var roleCapabilityFile in psrcFiles)
|
||||
{
|
||||
DISCPowerShellConfiguration roleCapabilityConfiguration = new DISCPowerShellConfiguration(roleCapabilityFile, null);
|
||||
IDictionary roleCapabilityConfigurationItems = roleCapabilityConfiguration.ConfigHash;
|
||||
MergeConfigHashIntoConfigHash(roleCapabilityConfigurationItems);
|
||||
}
|
||||
}
|
||||
|
||||
// Merge a role / role capability hashtable into the master configuration hashtable
|
||||
|
||||
@@ -936,7 +936,7 @@ Do you want to continue?</value>
|
||||
<value>{0} may need to restart the WinRM service if a configuration using this name has recently been unregistered, certain system data structures may still be cached. In that case, a restart of WinRM may be required.
|
||||
All WinRM sessions connected to Windows PowerShell session configurations, such as Microsoft.PowerShell and session configurations that are created with the Register-PSSessionConfiguration cmdlet, are disconnected.</value>
|
||||
</data>
|
||||
<data name="WinRMForceRestartWarning" xml:space="preserve">
|
||||
<data name="WinRMForceRestartWarning" xml:space="preserve">
|
||||
<value>You are running in a remote session and have selected the Force option which means the WinRM service may restart.If the WinRM service restarts then this remote session will be terminated and you will need to create a new session to continue</value>
|
||||
</data>
|
||||
<data name="JobSourceAdapterCannotSaveNullJob" xml:space="preserve">
|
||||
@@ -1636,4 +1636,10 @@ All WinRM sessions connected to Windows PowerShell session configurations, such
|
||||
<data name="SSHConnectionDuplicateKeyPath" xml:space="preserve">
|
||||
<value>The provided SSHConnection hashtable contains both a KeyFilePath and IdentityFilePath parameter. Only one can be specified.</value>
|
||||
</data>
|
||||
<data name="CouldNotFindRoleCapabilityFile" xml:space="preserve">
|
||||
<value>Could not find the provided role capability file {0}.</value>
|
||||
</data>
|
||||
<data name="InvalidRoleCapabilityFileExtension" xml:space="preserve">
|
||||
<value>The provided role capability file {0} does not have the required .psrc extension.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -0,0 +1,111 @@
|
||||
##
|
||||
## PowerShell Remoting Endpoint Role Capability Files Tests
|
||||
##
|
||||
|
||||
Describe "Remote session configuration RoleDefintion RoleCapabilityFiles key tests" -Tags "Feature" {
|
||||
|
||||
BeforeAll {
|
||||
|
||||
if (!$IsWindows)
|
||||
{
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
}
|
||||
else
|
||||
{
|
||||
[string] $RoleCapDirectory = (New-Item -Path "$TestDrive\RoleCapability" -ItemType Directory -Force).FullName
|
||||
|
||||
[string] $GoodRoleCapFile = "$RoleCapDirectory\TestGoodRoleCap.psrc"
|
||||
New-PSRoleCapabilityFile -Path $GoodRoleCapFile -VisibleCmdlets 'Get-Command','Get-Process','Clear-Host','Out-Default','Select-Object','Get-FormatData','Get-Help'
|
||||
|
||||
[string] $BadRoleCapFile = "$RoleCapDirectory\TestBadRoleCap.psrc"
|
||||
New-PSRoleCapabilityFile -Path $BadRoleCapFile -VisibleCmdlets *
|
||||
[string] $BadRoleCapFile = $BadRoleCapFile.Replace('.psrc', 'psbad')
|
||||
|
||||
[string] $PSSessionConfigFile = "$RoleCapDirectory\TestConfig.pssc"
|
||||
}
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
|
||||
if (!$IsWindows)
|
||||
{
|
||||
$global:PSDefaultParameterValues = $originalDefaultParameterValues
|
||||
}
|
||||
}
|
||||
|
||||
It "Verifies missing role capability file error" {
|
||||
|
||||
New-PSSessionConfigurationFile -Path $PSSessionConfigFile -RoleDefinitions @{
|
||||
Administrators = @{ RoleCapabilityFiles = "$RoleCapDirectory\NoFile.psrc" }
|
||||
}
|
||||
|
||||
$fullyQualifiedErrorId = ""
|
||||
try
|
||||
{
|
||||
$iss = [initialsessionstate]::CreateFromSessionConfigurationFile($PSSessionConfigFile, { $true })
|
||||
throw 'No Exception!'
|
||||
}
|
||||
catch
|
||||
{
|
||||
$psioe = [System.Management.Automation.PSInvalidOperationException] ($_.Exception).InnerException
|
||||
if ($psioe -ne $null)
|
||||
{
|
||||
$fullyQualifiedErrorId = $psioe.ErrorRecord.FullyQualifiedErrorId
|
||||
}
|
||||
$fullyQualifiedErrorId | Should Be 'CouldNotFindRoleCapabilityFile'
|
||||
}
|
||||
}
|
||||
|
||||
It "Verifies incorrect role capability file extenstion error" {
|
||||
|
||||
New-PSSessionConfigurationFile -Path $PSSessionConfigFile -RoleDefinitions @{
|
||||
Administrators = @{ RoleCapabilityFiles = "$BadRoleCapFile" }
|
||||
}
|
||||
|
||||
$fullyQualifiedErrorId = ""
|
||||
try
|
||||
{
|
||||
$iss = [initialsessionstate]::CreateFromSessionConfigurationFile($PSSessionConfigFile, { $true })
|
||||
throw 'No Exception!'
|
||||
}
|
||||
catch
|
||||
{
|
||||
$psioe = [System.Management.Automation.PSInvalidOperationException] ($_.Exception).InnerException
|
||||
if ($psioe -ne $null)
|
||||
{
|
||||
$fullyQualifiedErrorId = $psioe.ErrorRecord.FullyQualifiedErrorId
|
||||
}
|
||||
$fullyQualifiedErrorId | Should Be 'InvalidRoleCapabilityFileExtension'
|
||||
}
|
||||
}
|
||||
|
||||
It "Verifies restriction on good role capability file" {
|
||||
|
||||
New-PSSessionConfigurationFile -Path $PSSessionConfigFile -RoleDefinitions @{
|
||||
Administrators = @{ RoleCapabilityFiles = "$GoodRoleCapFile" }
|
||||
}
|
||||
|
||||
# 'Get-Service' is not included in the session.
|
||||
$iss = [initialsessionstate]::CreateFromSessionConfigurationFile($PSSessionConfigFile, { $true })
|
||||
[powershell] $ps = [powershell]::Create($iss)
|
||||
$null = $ps.AddCommand('Get-Service')
|
||||
|
||||
$exceptionTypeName = ""
|
||||
try
|
||||
{
|
||||
$ps.Invoke()
|
||||
throw 'No Exception!'
|
||||
}
|
||||
catch
|
||||
{
|
||||
if ($_.Exception.InnerException -ne $null)
|
||||
{
|
||||
$exceptionTypeName = $_.Exception.InnerException.GetType().FullName
|
||||
}
|
||||
$exceptionTypeName | Should Be 'System.Management.Automation.CommandNotFoundException'
|
||||
}
|
||||
|
||||
$ps.Dispose()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user