RDP セッションの管理の委任

RDP セッションの管理の委任
私が働いている組織ではリモートワークが原則禁止となっています。 だった。 先週までは。 今、私たちは早急に解決策を導入する必要がありました。 ビジネスからはプロセスを新しい作業形式に適応させ、私たちからは PIN コードとトークンを使用した PKI、VPN、詳細なログなどを提供します。
とりわけ、私はリモート デスクトップ インフラストラクチャ、別名ターミナル サービスをセットアップしていました。 当社では、さまざまなデータセンターに複数の RDS を導入しています。 目標の XNUMX つは、関連する IT 部門の同僚がユーザー セッションに対話的に接続できるようにすることでした。 ご存知のとおり、これには標準の RDS シャドウ メカニズムがあり、これを委任する最も簡単な方法は、RDS サーバーのローカル管理者権限を与えることです。
私は同僚を尊敬し、大切にしていますが、管理者権限を与えることに関しては非常に貪欲です。 🙂 共感していただける方はフォローお願いします。

さて、課題は明確です。さあ、本題に取り掛かりましょう。

ステップ1

Active Directory にセキュリティ グループを作成しましょう RDP_オペレーター その中に、権限を委任したいユーザーのアカウントを含めます。

$Users = @(
    "UserLogin1",
    "UserLogin2",
    "UserLogin3"
)
$Group = "RDP_Operators"
New-ADGroup -Name $Group -GroupCategory Security -GroupScope DomainLocal
Add-ADGroupMember -Identity $Group -Members $Users

複数の AD サイトがある場合は、すべてのドメイン コントローラーにレプリケートされるまで待ってから、次の手順に進む必要があります。 通常、これには 15 分もかかりません。

ステップ2

各 RDSH サーバー上のターミナル セッションを管理するための権限をグループに与えましょう。

Set-RDSPermissions.ps1

$Group = "RDP_Operators"
$Servers = @(
    "RDSHost01",
    "RDSHost02",
    "RDSHost03"
)
ForEach ($Server in $Servers) {
    #Делегируем право на теневые сессии
    $WMIHandles = Get-WmiObject `
        -Class "Win32_TSPermissionsSetting" `
        -Namespace "rootCIMV2terminalservices" `
        -ComputerName $Server `
        -Authentication PacketPrivacy `
        -Impersonation Impersonate
    ForEach($WMIHandle in $WMIHandles)
    {
        If ($WMIHandle.TerminalName -eq "RDP-Tcp")
        {
        $retVal = $WMIHandle.AddAccount($Group, 2)
        $opstatus = "успешно"
        If ($retVal.ReturnValue -ne 0) {
            $opstatus = "ошибка"
        }
        Write-Host ("Делегирование прав на теневое подключение группе " +
            $Group + " на сервере " + $Server + ": " + $opstatus + "`r`n")
        }
    }
}

ステップ3

グループをローカル グループに追加する リモート デスクトップ ユーザー 各 RDSH サーバー上で。 サーバーがセッション コレクションに結合されている場合、これをコレクション レベルで行います。

$Group = "RDP_Operators"
$CollectionName = "MyRDSCollection"
[String[]]$CurrentCollectionGroups = @(Get-RDSessionCollectionConfiguration -CollectionName $CollectionName -UserGroup).UserGroup
Set-RDSessionCollectionConfiguration -CollectionName $CollectionName -UserGroup ($CurrentCollectionGroups + $Group)

私たちが使用する単一サーバーの場合 グループ ポリシー、サーバーに適用されるのを待っています。 待つのが面倒な人は、古き良き gpupdate を使用してプロセスを高速化できます。 一元的に.

ステップ4

「マネージャー」用に次の PS スクリプトを準備しましょう。

RDSManagement.ps1

$Servers = @(
    "RDSHost01",
    "RDSHost02",
    "RDSHost03"
)

function Invoke-RDPSessionLogoff {
    Param(
        [parameter(Mandatory=$True, Position=0)][String]$ComputerName,
        [parameter(Mandatory=$true, Position=1)][String]$SessionID
    )
    $ErrorActionPreference = "Stop"
    logoff $SessionID /server:$ComputerName /v 2>&1
}

function Invoke-RDPShadowSession {
    Param(
        [parameter(Mandatory=$True, Position=0)][String]$ComputerName,
        [parameter(Mandatory=$true, Position=1)][String]$SessionID
    )
    $ErrorActionPreference = "Stop"
    mstsc /shadow:$SessionID /v:$ComputerName /control 2>&1
}

Function Get-LoggedOnUser {
    Param(
        [parameter(Mandatory=$True, Position=0)][String]$ComputerName="localhost"
    )
    $ErrorActionPreference = "Stop"
    Test-Connection $ComputerName -Count 1 | Out-Null
    quser /server:$ComputerName 2>&1 | Select-Object -Skip 1 | ForEach-Object {
        $CurrentLine = $_.Trim() -Replace "s+"," " -Split "s"
        $HashProps = @{
            UserName = $CurrentLine[0]
            ComputerName = $ComputerName
        }
        If ($CurrentLine[2] -eq "Disc") {
            $HashProps.SessionName = $null
            $HashProps.Id = $CurrentLine[1]
            $HashProps.State = $CurrentLine[2]
            $HashProps.IdleTime = $CurrentLine[3]
            $HashProps.LogonTime = $CurrentLine[4..6] -join " "
            $HashProps.LogonTime = $CurrentLine[4..($CurrentLine.GetUpperBound(0))] -join " "
        }
        else {
            $HashProps.SessionName = $CurrentLine[1]
            $HashProps.Id = $CurrentLine[2]
            $HashProps.State = $CurrentLine[3]
            $HashProps.IdleTime = $CurrentLine[4]
            $HashProps.LogonTime = $CurrentLine[5..($CurrentLine.GetUpperBound(0))] -join " "
        }
        New-Object -TypeName PSCustomObject -Property $HashProps |
        Select-Object -Property UserName, ComputerName, SessionName, Id, State, IdleTime, LogonTime
    }
}

$UserLogin = Read-Host -Prompt "Введите логин пользователя"
Write-Host "Поиск RDP-сессий пользователя на серверах..."
$SessionList = @()
ForEach ($Server in $Servers) {
    $TargetSession = $null
    Write-Host "  Опрос сервера $Server"
    Try {
        $TargetSession = Get-LoggedOnUser -ComputerName $Server | Where-Object {$_.UserName -eq $UserLogin}
    }
    Catch {
        Write-Host "Ошибка: " $Error[0].Exception.Message -ForegroundColor Red
        Continue
    }
    If ($TargetSession) {
        Write-Host "    Найдена сессия с ID $($TargetSession.ID) на сервере $Server" -ForegroundColor Yellow
        Write-Host "    Что будем делать?"
        Write-Host "      1 - подключиться к сессии"
        Write-Host "      2 - завершить сессию"
        Write-Host "      0 - ничего"
        $Action = Read-Host -Prompt "Введите действие"
        If ($Action -eq "1") {
            Invoke-RDPShadowSession -ComputerName $Server -SessionID $TargetSession.ID
        }
        ElseIf ($Action -eq "2") {
            Invoke-RDPSessionLogoff -ComputerName $Server -SessionID $TargetSession.ID
        }
        Break
    }
    Else {
        Write-Host "    сессий не найдено"
    }
}

PS スクリプトを実行しやすくするために、PS スクリプトと同じ名前の cmd ファイルの形式でそのシェルを作成します。

RDSManagement.cmd

@ECHO OFF
powershell -NoLogo -ExecutionPolicy Bypass -File "%~d0%~p0%~n0.ps1" %*

両方のファイルを「マネージャー」がアクセスできるフォルダーに置き、再ログインを求めます。 これで、cmd ファイルを実行することで、RDS シャドウ モードで他のユーザーのセッションに接続し、強制的にログアウトできるようになります (これは、ユーザーが「ハング」セッションを独自に終了できない場合に便利です)。

それはこのように見えます:

「マネージャー」にとってはRDP セッションの管理の委任

ユーザーにとってRDP セッションの管理の委任

最後にいくつかのコメント

ニュアンス1。 Set-RDSPermissions.ps1 スクリプトがサーバー上で実行される前に、制御を取得しようとしているユーザー セッションが起動された場合、「マネージャー」はアクセス エラーを受け取ります。 ここでの解決策は明らかです。管理対象ユーザーがログインするまで待ちます。

ニュアンス2。 RDP Shadow を数日間使用した後、興味深いバグまたは機能に気づきました。シャドウ セッションの終了後、接続しているユーザーのトレイの言語バーが消えます。言語バーを元に戻すには、ユーザーは言語バーを再表示する必要があります。 -ログイン。 結局のところ、私たちは一人ではありません。 時間, два, 3.

それだけです。 あなたとあなたのサーバーの健康を祈っています。 いつものように、コメント欄でのフィードバックを楽しみにしています。また、以下の簡単なアンケートにご協力ください。

ソース

登録ユーザーのみがアンケートに参加できます。 ログインお願いします。

あなたは何を使うのですか?

  • 視聴者の38%がアミー管理者5

  • 視聴者の38%がエニーデスク11

  • 視聴者の38%がダメウェア6

  • 視聴者の38%がラドミン15

  • 視聴者の38%がRDSシャドウ9

  • 視聴者の38%がクイックアシスト / Windows リモート アシスタンス1

  • 視聴者の38%がTeamViewer24

  • 視聴者の38%がVNC20

  • 視聴者の38%がその他20

  • 視聴者の38%がLiteManager2

62 人のユーザーが投票しました。 22名のユーザーが棄権した。

出所: habr.com

コメントを追加します