Ошибка сеанса входа в систему с помощью Remote PowerShell (Invoke-Command) - PullRequest
0 голосов
/ 04 июля 2019

Я пытаюсь настроить SAML / ADFSRelyingPartyTrust удаленно.Я знаю, что сам скрипт работает, потому что я могу сам вызывать часть ScriptBlock, войдя в систему на сервере, передать ему параметр, и он работает.

Хотя я хочу сделать это удаленно, и я получаюошибка

[blah20.blah.blah.com] Connecting to remote server blah20.blah.blah.com failed
with the following error message : A specified logon session does not exist. It
may already have been terminated. For more information, see the
about_Remote_Troubleshooting Help topic.
    + CategoryInfo          : OpenError: (blah20.blah.blah.com:String) [], PSRemotingTransportException
    + FullyQualifiedErrorId : 1312,PSSessionStateBroken

На самом деле я не пробовал ничего другого из-за неуверенности в том, где настроить.Я впервые пытаюсь выполнять удаленные команды, но я думаю, что это правильный путь.

Я видел упоминания о необходимости наличия учетных данных, но в идеале я просто хотел, чтобы он работал как пользователь, которыйвошли в систему на своем компьютере.

CLS
$Title = "SAML Server Choice"
$Info = "Please pick the server you wish to configure SAML on"

$options = [System.Management.Automation.Host.ChoiceDescription[]] @("&LIVE", "&TEST")
[int]$defaultchoice = 1
$opt = $host.UI.PromptForChoice($Title , $Info , $Options,$defaultchoice)
switch ($opt) {
    0 { Write-Host "LIVE" -ForegroundColor Green}
    1 { Write-Host "TEST" -ForegroundColor Green}
}

switch ($opt) {
    0 {"SAML Server is blah20.blah.com"; $SAMLServer = "blah20.blah.blah.com"}
    1 {"SAML Server is blah50.blah.com"; $SAMLServer = "blah50.blah.blah.com"}
}

$EnvironmentName = Read-Host "Please enter the customer name: "

$ScriptBlockContent = {
    $EnvironmentURL = 'https://'+$EnvironmentName+'.blah.com';
    $EndPoint = 'https://'+$EnvironmentName+'.blah.com/app_pages/admin/saml.aspx';
    $folderPath = "C:\SAMLAutoSetup\";
    $claimsFilePath = $folderPath + "claims.txt";
    $rulesFilePath = $folderPath + "rules.txt";
    $claims = '@RuleTemplate = "LdapClaims"
               @RuleName = "LDAP"
               c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
                => issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn",
               "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", "http://schemas.xmlsoap.org/claims/Group",
               "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"), query =
               ";userPrincipalName,displayName,tokenGroups,mail;{0}", param = c.Value); ';

    $claims | Out-File $claimsFilePath -Force;

    $rules = '@RuleTemplate = "AllowAllAuthzRule"
                                         => issue(Type = "http://schemas.microsoft.com/authorization/claims/permit", Value = "true");';

    $rules | Out-File $rulesFilePath -Force; 

    Add-PSSnapin Microsoft.Adfs.PowerShell; 

    if (Get-ADFSRelyingPartyTrust -Name $EnvironmentName) {
        Write-Host `n"$EnvironmentName Relying Party Trust already exists";
    } else {
        Write-Host `n"$EnvironmentName Relying Party Trust doesn't exist! Need to Create";
        $samlEndPoint = New-ADFSSamlEndpoint -Protocol SAMLAssertionConsumer -Uri $EndPoint -Binding POST -IsDefault $false -Index 0;
        Add-ADFSRelyingPartyTrust -Name $EnvironmentName -Identifier $EnvironmentURL -SamlEndpoint $samlEndPoint -IssuanceTransformRulesFile $claimsFilePath -IssuanceAuthorizationRulesFile $rulesFilePath;
        Write-Host `n"$EnvironmentName Created successfully!";
    }
}

Invoke-Command -ComputerName $SAMLServer -ScriptBlock $ScriptBlockContent -ArgumentList $EnvironmentName

Возможно, я неправильно структурировал скрипт, довольно плохо знакомый со всем этим, поэтому открыт для предложений по реструктуризации, чтобы заставить его работать!

1 Ответ

0 голосов
/ 05 июля 2019

Это не проблема кода PowerShell.Это среда / Аутентификация / права доступа для самой Windows.

PSRemoting должен быть правильно настроен на удаленном хосте, и вы должны быть локальным администратором на удаленном хосте, чтобы полностью использовать удаленное взаимодействие PowerShell.

Вы должны правильно использовать свой код в явном или неявном сеансе PSRemoting.Это сообщение об ошибке является очень конкретным, пожалуйста, прочтите PSRemoting, поскольку в сообщении говорится.

Что касается этого…

Указанный сеанс входа в систему не существует.

... он не уникален для PowerShell, эта же ошибка можетдля других случаев использования в Windows.

Что касается этого ...

в идеале я просто хотел, чтобы он работал как пользователь, вошедший в систему на своем компьютере.

... вы не можете запускать удаленные команды в контексте текущего вошедшего в систему пользователя, используя собственный PowerShell.PowerShell всегда будет использовать пользовательский контекст, который запускал скрипт.Это правильная граница безопасности Windows.Поэтому, если вы запустите этот сценарий, он всегда будет в вашем пользовательском контексте.

Либо вошедший в систему пользователь должен запустить этот сценарий напрямую и иметь для этого надлежащие учетные данные, либо вы установили запланированное задание на выполнение.это опять же с использованием пользовательских кредитов (которые вы не будете знать, поэтому им придется это настроить).

Если вы пытаетесь запустить код в контексте другого пользователя.Вам нужно использовать что-то вроде MS SysInternals PSExec в вашем скрипте.

Для того, что вы делаете, пользователь, подключенный к системе, по-прежнему нуждается в командлетах ADDS и ADFS, установленных / проксируемых на их хосте, для выполнения этого, или они должны быть на сервере DC / ADFS (физически илиудаленно (RDP / PSRemoting неявно / явно), чтобы сделать это.

Наконец, использование переменных должно находиться в области видимости, и вы не можете использовать локальные переменные в удаленном сеансе, если они не видны в области действия вызывающего кода.,См. Файлы справки по теме.

У вас также есть несколько вещей, которые синтаксически (как вы используете символ перевода строки - одна из них) неверны, и все лишние точки с запятой не нужны дляPowerShell в целом.Есть несколько случаев, когда они есть, но то, что вы делаете, на самом деле не является одним из них.

Таким образом, игнорирование ...

Указанный сеанс входа в систему не существует.

... ошибка на мгновение.Настраивая ваш размещенный код, я бы предложил это.У других, конечно, будет своя тема.Кстати ... не проверено, и я не в среде, которую я могу проверить в это время.

### configure SAML/ADFSRelyingPartyTrust

Clear-Host

<#
Import needed PowerShell modules and must be on the ADFS server and have the 
ADDS cmdlets via the RSAT Tools installed and enabled locally or proxied via 
PowerSehll Remoting
#>

Import-Module -Name ServerManager, ActiveDirectory, ADFS -Force
Add-PSSnapin Microsoft.Adfs.PowerShell

<#
Force environment specifications

about_Requires | Microsoft Docs
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_requires
#>

#Requires -Version 4
#Requires -PSSnapin Microsoft.Adfs.PowerShell
#Requires -Modules ServerManager, ActiveDirectory, ADFS 
#Requires -RunAsAdministrator


<#
Ensure that any local variables are properly scoped for PSRemote sessions

about_scopes | Microsoft Docs
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes

The Using scope modifier

Using is a special scope modifier that identifies a local variable in a remote 
command. Without a modifier, PowerShell expects variables in remote commands to 
be defined in the remote 
session.

The Using scope modifier is introduced in PowerShell 3.0.

For more information, see about_Remote_Variables.
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_remote_variables?view=powershell-6

Using local variables

You can also use local variables in remote commands, but you must indicate that 
the variable is defined in the local session.

Beginning in Windows PowerShell 3.0, you can use the Using scope modifier to 
identify a local variable in a remote command.

The syntax of Using is as follows:

$Using:<VariableName>


# Simple strings only need single quotes, variable / string expansion requires double quotes

about_Quoting_Rules | Microsoft Docs
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules

The Difference Between Single and Double Quotes in PowerShell
https://blog.techsnips.io/the-difference-between-single-and-double-quotes-in-powershell
https://www.sconstantinou.com/powershell-quotes/

#>

$Title = 'SAML Server Choice'
$Info = 'Please pick the server you wish to configure SAML on'

$options = [System.Management.Automation.Host.ChoiceDescription[]] @('&LIVE', '&TEST')

[int]$defaultchoice = 1

$opt = $host.UI.PromptForChoice($Title , $Info , $Options,$defaultchoice)

<# 
Using write-Host for colorizing screen text - otherwise Write-Host is not needed.

Output to the screen is the PowerShell default, unless you:
- assign to a variable (and not using varialbe squeezing)
- not use Out-Host
- or use Out-NUll
#>

switch ($opt) {
    0 { Write-Host 'LIVE' -ForegroundColor Green}
    1 { Write-Host 'TEST' -ForegroundColor Green}
}

<#
Using variable squeezing to assign value to the variable and output to screen

Server names are hardcoded here, but the user domain is dynamically discovered
via PowerShell $ENv variable.

One could just as easily discover the DC/ADFS/SAML server FQDN from ADDS to
avoid this hard coding effort.
#>

switch ($opt) {
    0 {"SAML Server is $(($SAMLServer = "blah20.$env:USERDNSDOMAIN"))"}
    1 {"SAML Server is $(($SAMLServer = "blah50.$env:USERDNSDOMAIN"))"}
}

$EnvironmentName = Read-Host 'Please enter the customer name: '

$ScriptBlockContent = {
    $EnvironmentURL = "https://$EnvironmentName.$env:USERDNSDOMAIN"
    $EndPoint = "$EnvironmentURL/app_pages/admin/saml.aspx"

    $folderPath = 'C:\SAMLAutoSetup\'

    $claimsFilePath = "$folderPath claims.txt"
    $claims = '@RuleTemplate = "LdapClaims"
               @RuleName = "LDAP"
               c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"]
                => issue(store = "Active Directory", types = ("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn",
               "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", "http://schemas.xmlsoap.org/claims/Group",
               "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"), query =
               ";userPrincipalName,displayName,tokenGroups,mail;{0}", param = c.Value); ';

    $claims | 
    Out-File $claimsFilePath -Force

    $rules = '@RuleTemplate = "AllowAllAuthzRule"
                                         => issue(Type = "http://schemas.microsoft.com/authorization/claims/permit", Value = "true");';

    $rulesFilePath = "$folderPath rules.txt"
    $rules | 
    Out-File $rulesFilePath -Force

    <# 
    Special formatting characters, like the new line `n, needs to be properly
    quoted to be used. Avoid unnecessary string concatenation where possible.

    https://leanpub.com/thebigbookofpowershellgotchas/read
    https://leanpub.com/thebigbookofpowershellgotchas/read#leanpub-auto-dontconcatenatestrings
    https://devops-collective-inc.gitbook.io/the-big-book-of-powershell-gotchas/dont-concatenate-strings
    https://github.com/devops-collective-inc/big-book-of-powershell-gotchas

    See also
    PowerShell: Using the -F format Operator
    https://social.technet.microsoft.com/wiki/contents/articles/7855.powershell-using-the-f-format-operator.aspx

    The Unofficial PowerShell Best Practices and Style Guide
    https://github.com/PoshCode/PowerShellPracticeAndStyle
    #>

    if (Get-ADFSRelyingPartyTrust -Name $EnvironmentName) 
    { "`n$EnvironmentName Relying Party Trust already exists"    } 
    else 
    {
        "`n$EnvironmentName Relying Party Trust doesn't exist! Need to Create"

        <#
        Leveraging PowerShell Splatting for readability

        about_Splatting | Microsoft Docs
        https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_splatting
        #>

        $newADFSSamlEndpointSplat = @{
            Protocol = 'SAMLAssertionConsumer'
            IsDefault = $false
            Index = 0
            Uri = $EndPoint
            Binding = 'POST'
        }
        $samlEndPoint = New-ADFSSamlEndpoint @newADFSSamlEndpointSplat

        $addADFSRelyingPartyTrustSplat = @{
            IssuanceAuthorizationRulesFile = $rulesFilePath
            SamlEndpoint = $samlEndPoint
            Name = $EnvironmentName
            Identifier = $EnvironmentURL
            IssuanceTransformRulesFile = $claimsFilePath
        }
        Add-ADFSRelyingPartyTrust @addADFSRelyingPartyTrustSplat


        "`n$EnvironmentName Created successfully!"
    }
}

$invokeCommandSplat = @{
    Credential = (Get-Credential -Credential "$env:USERDOMAIN\$env:USERNAME")
    ComputerName = $SAMLServer
    ArgumentList = $EnvironmentName
    ScriptBlock = $ScriptBlockContent
}
Invoke-Command @invokeCommandSplat

<#
If using Implicit PSRemoting to the DC or a server running the RSAT and ADFS tools, 
from a remote workstation, then you'd not need to use Invoke-Command at all. 
You'd just run the script as if you were on the DC/ADFS server directly.


An Introduction to PowerShell Remoting Part Four: Sessions and Implicit Remoting
https://devblogs.microsoft.com/scripting/an-introduction-to-powershell-remoting-part-four-sessions-and-implicit-remoting
https://devblogs.microsoft.com/scripting/remoting-the-implicit-way

PowerShell Implicit Remoting: Never Install a Module Again
https://www.itprotoday.com/powershell/powershell-implicit-remoting-never-install-module-again
#>

Если вы не в установленном неявном / явном сеансе PSRemote, весь этот код элемента действия должен быть вскрипт-блок, который должен быть запущен на удаленном хосте ..

...