Merge pull request #1674 from PowerShell/mirichmo/winrm-registration

Delivering a script to register the WinRM endpoint
This commit is contained in:
Travis Plunk 2016-08-08 10:37:18 -07:00 committed by GitHub
commit 76fd51cc69
3 changed files with 222 additions and 30 deletions

View file

@ -115,16 +115,15 @@ function Start-PSBuild {
# Add .NET CLI tools to PATH
Find-Dotnet
# verify we have all tools in place to do the build
$precheck = precheck 'dotnet' "Build dependency 'dotnet' not found in PATH. Run Start-PSBootstrap. Also see: https://dotnet.github.io/getting-started/"
if ($IsWindows) {
# use custom package store - this value is also defined in nuget.config under config/repositoryPath
# dotnet restore uses this value as the target for installing the assemblies for referenced nuget packages.
# dotnet build does not currently consume the config value but will consume env:NUGET_PACKAGES to resolve these dependencies
$env:NUGET_PACKAGES="$PSScriptRoot\Packages"
}
# verify we have all tools in place to do the build
$precheck = precheck 'dotnet' "Build dependency 'dotnet' not found in PATH. Run Start-PSBootstrap. Also see: https://dotnet.github.io/getting-started/"
if ($FullCLR) {
# cmake is needed to build powershell.exe
$precheck = $precheck -and (precheck 'cmake' 'cmake not found. Run Start-PSBootstrap. You can also install it from https://chocolatey.org/packages/cmake.portable')
@ -261,8 +260,8 @@ function Start-PSBuild {
if (-not (Test-Path $Lib)) {
throw "Compilation of $Lib failed"
}
} elseif ($FullCLR -and (-not $SMAOnly)) {
log "Start building native powershell.exe"
} elseif ($IsWindows -and (-not $SMAOnly)) {
log "Start building native Windows binaries"
try {
Push-Location "$PSScriptRoot\src\powershell-native"
@ -280,37 +279,62 @@ cmd.exe /C cd /d "$currentLocation" "&" "$($vcVarsPath)\vcvarsall.bat" "$NativeH
}
}
# Disabling until I figure out if it is necessary
# $overrideFlags = "-DCMAKE_USER_MAKE_RULES_OVERRIDE=$PSScriptRoot\src\powershell-native\windows-compiler-override.txt"
$overrideFlags = ""
$location = Get-Location
#
# BUILD_ONECORE
#
function Build-NativeWindowsBinaries {
param(
# Describes wither it should build the CoreCLR or FullCLR version
[ValidateSet("ON", "OFF")]
[string]$OneCoreValue,
# Array of file names to copy from the local build directory to the packaging directory
[string[]]$FilesToCopy
)
# Disabling until I figure out if it is necessary
# $overrideFlags = "-DCMAKE_USER_MAKE_RULES_OVERRIDE=$PSScriptRoot\src\powershell-native\windows-compiler-override.txt"
$overrideFlags = ""
$location = Get-Location
$BuildOneCoreValues = @("ON","OFF")
foreach ($oneCoreValue in $BuildOneCoreValues) {
$command = @"
cmd.exe /C cd /d "$location" "&" "$($vcVarsPath)\vcvarsall.bat" "$NativeHostArch" "&" cmake "$overrideFlags" -DBUILD_ONECORE=$oneCoreValue -G "$cmakeGenerator" . "&" msbuild ALL_BUILD.vcxproj "/p:Configuration=$msbuildConfiguration"
cmd.exe /C cd /d "$location" "&" "$($vcVarsPath)\vcvarsall.bat" "$NativeHostArch" "&" cmake "$overrideFlags" -DBUILD_ONECORE=$OneCoreValue -G "$cmakeGenerator" . "&" msbuild ALL_BUILD.vcxproj "/p:Configuration=$msbuildConfiguration"
"@
log " Executing Build Command: $command"
Start-NativeExecution { Invoke-Expression -Command:$command }
$clrTarget = "FullClr"
if ($OneCoreValue -eq "ON")
{
$clrTarget = "CoreClr"
}
# Copy the binaries from the local build directory to the packaging directory
$dstPath = ($script:Options).Top
$FilesToCopy | % {
$srcPath = Join-Path (Join-Path (Join-Path (Get-Location) "bin") $msbuildConfiguration) "$clrTarget/$_"
log " Copying $srcPath to $dstPath"
Copy-Item $srcPath $dstPath
}
}
if ($FullCLR) {
$fullBinaries = @(
'powershell.exe',
'powershell.pdb',
'pwrshplugin.dll',
'pwrshplugin.pdb'
)
Build-NativeWindowsBinaries "OFF" $fullBinaries
}
else
{
$coreClrBinaries = @(
'pwrshplugin.dll',
'pwrshplugin.pdb'
)
Build-NativeWindowsBinaries "ON" $coreClrBinaries
# Copy the executable binary from the local build directory to the expected destination to enable Start-DevPowerShell to work
#
# TODO: This should be updated to handle per-architecture builds gracefully.
$dstPath = ($script:Options).Top
@(
'powershell.exe',
'powershell.pdb',
'pwrshplugin.dll',
'pwrshplugin.pdb'
) | % {
$srcPath = Join-Path (Join-Path (Join-Path (Get-Location) "bin") $msbuildConfiguration) "FullCLR/$_"
log " Copying $srcPath to $dstPath"
Copy-Item $srcPath $dstPath
# Place the remoting configuration script in the same directory
# as the binary so it will get published.
Copy-Item .\Install-PowerShellRemoting.ps1 ($script:Options).Top
}
} finally {
Pop-Location

View file

@ -0,0 +1,165 @@
#####################################################################################################
#
# Registers the WinRM endpoint for this instance of PowerShell.
#
# Assumptions:
# 1. This script is run from within the PowerShell that it will register as a WinRM endpoint.
# 2. The CoreCLR and the the PowerShell assemblies are side-by-side in $PSHOME
# 3. Plugins are registered by version number. Only one plugin can be automatically registered
# per PowerShell version. However, multiple endpoints may be manually registered for a given
# plugin.
#
#####################################################################################################
param
(
[Switch]$Verbose
)
function Register-WinRmPlugin
{
param
(
#
# Expected Example:
# %windir%\\system32\\PowerShell\\6.0.0\\pwrshplugin.dll
#
[string]
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
$pluginAbsolutePath,
#
# Expected Example: microsoft.ops.5.1
#
[string]
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
$pluginEndpointName
)
$header = "Windows Registry Editor Version 5.00`n`n"
$regKeyFormatString = "[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WSMAN\Plugin\{0}]`n"
$regKeyName = '"ConfigXML"="{0}"'
#
# Example Values:
#
# Filename = %windir%\\system32\\PowerShell\\6.0.0\\pwrshplugin.dll
# Name = PowerShell.6.0.0
#
$regKeyValueFormatString = '<PlugInConfiguration xmlns=\"http://schemas.microsoft.com/wbem/wsman/1/config/PluginConfiguration\" Name=\"{0}\" Filename=\"{1}\" SDKVersion=\"2\" XmlRenderingType=\"text\" Enabled=\"True\" OutputBufferingMode=\"Block\" ProcessIdleTimeoutSec=\"0\" Architecture=\"64\" UseSharedProcess=\"false\" RunAsUser=\"\" RunAsPassword=\"\" AutoRestart=\"false\"><InitializationParameters><Param Name=\"PSVersion\" Value=\"5.0\"/></InitializationParameters><Resources><Resource ResourceUri=\"http://schemas.microsoft.com/powershell/{0}\" SupportsOptions=\"true\" ExactMatch=\"true\"><Security Uri=\"http://schemas.microsoft.com/powershell/{0}\" ExactMatch=\"true\" Sddl=\"O:NSG:BAD:P(A;;GA;;;BA)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)\"/><Capability Type=\"Shell\"/></Resource></Resources><Quotas IdleTimeoutms=\"7200000\" MaxConcurrentUsers=\"5\" MaxProcessesPerShell=\"15\" MaxMemoryPerShellMB=\"1024\" MaxShellsPerUser=\"25\" MaxConcurrentCommandsPerShell=\"1000\" MaxShells=\"25\" MaxIdleTimeoutms=\"43200000\"/></PlugInConfiguration>'
$valueString = $regKeyValueFormatString -f $pluginEndpointName, $pluginAbsolutePath
$keyValuePair = $regKeyName -f $valueString
$regKey = $regKeyFormatString -f $pluginEndpointName
$fileName = "$pluginEndpointName.reg"
Set-Content -path .\$fileName "$header$regKey$keyValuePair`n"
Write-Verbose "Performing WinRM registration with: $fileName"
reg.exe import .\$fileName
# Clean up
# Remove-Item .\$fileName
}
function Generate-PluginConfigFile
{
param
(
[string]
[parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
$pluginFile
)
# This always overwrites the file with a new version of it if the
# script is invoked multiple times.
Set-Content -Path $pluginFile -Value "PSHOMEDIR=$PSHOME"
Add-Content -Path $pluginFile -Value "CORECLRDIR=$PSHOME"
Write-Verbose "Created Plugin Config File: $pluginFile"
}
######################
# #
# Install the plugin #
# #
######################
if (! ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{
Write-Error "WinRM registration requires Administrator rights. To run this cmdlet, start PowerShell with the `"Run as administrator`" option."
Break
}
$originalVerbosePreference = $VerbosePreference
if ($Verbose)
{
$VerbosePreference = "Continue"
}
$powershellVersion = $PSVersionTable.PSVersion
$pluginBasePath = Join-Path "$env:WINDIR\System32\PowerShell" $powerShellVersion
$resolvedPluginAbsolutePath = ""
if (! (Test-Path $pluginBasePath))
{
Write-Verbose "Creating $pluginBasePath"
$resolvedPluginAbsolutePath = New-Item -Type Directory -Path $pluginBasePath
}
else
{
$resolvedPluginAbsolutePath = Resolve-Path $pluginBasePath
}
# The registration reg file requires "\\" instead of "\" in its path so it is properly escaped in the XML
$pluginRawPath = Join-Path $resolvedPluginAbsolutePath "pwrshplugin.dll"
$fixedPluginPath = $pluginRawPath -replace '\\','\\'
# This is forced to ensure the the file is placed correctly
Copy-Item $PSHOME\pwrshplugin.dll $resolvedPluginAbsolutePath -Force -Verbose
$pluginFile = Join-Path $resolvedPluginAbsolutePath "RemotePowerShellConfig.txt"
Generate-PluginConfigFile $pluginFile
$pluginEndpointName = "powershell.$powershellVersion"
# Register the plugin
Register-WinRmPlugin $fixedPluginPath $pluginEndpointName
# Reset verbosity
if ($Verbose)
{
$VerbosePreference = $originalVerbosePreference
}
####################################################################
# #
# Validations to confirm that everything was registered correctly. #
# #
####################################################################
if (! (Test-Path $pluginFile))
{
throw "WinRM Plugin configuration file not created. Expected = $pluginFile"
}
if (! (Test-Path $resolvedPluginAbsolutePath\pwrshplugin.dll))
{
throw "WinRM Plugin DLL missing. Expected = $resolvedPluginAbsolutePath\pwrshplugin.dll"
}
try
{
Get-PSSessionConfiguration $pluginEndpointName
}
catch [Microsoft.PowerShell.Commands.WriteErrorException]
{
Write-Error "No remoting session configuration matches the name $pluginEndpointName."
}

View file

@ -46,6 +46,9 @@
}
},
"include": [
"pwrshplugin.dll",
"pwrshplugin.pdb",
"Install-PowerShellRemoting.ps1",
"../../powershell.version"
],
},