Delegarea managementului sesiunilor RDP

Delegarea managementului sesiunilor RDP
În organizația în care lucrez, munca la distanță este interzisă în principiu. A fost. Până săptămâna trecută. Acum trebuia să implementăm urgent o soluție. De la business - adaptarea proceselor la un nou format de lucru, de la noi - PKI cu coduri PIN și jetoane, VPN, înregistrare detaliată și multe altele.
Printre altele, configuram Remote Desktop Infrastructure alias Terminal Services. Avem mai multe implementări RDS în diferite centre de date. Unul dintre obiective a fost acela de a permite colegilor din departamentele IT conexe să se conecteze la sesiunile utilizatorilor în mod interactiv. După cum știți, există un mecanism standard RDS Shadow pentru acest lucru, iar cel mai simplu mod de a-l delega este să acordați drepturi de administrator local pe serverele RDS.
Îmi respect și prețuiesc colegii, dar sunt foarte lacom când vine vorba de a da drepturi de administrator. 🙂 Pentru cei care sunt de acord cu mine, vă rog să urmați tăietura.

Ei bine, sarcina este clară, acum să trecem la treabă.

Pasul 1

Să creăm un grup de securitate în Active Directory RDP_Operatori și includeți în el conturile acelor utilizatori cărora dorim să le delegăm drepturi:

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

Dacă aveți mai multe site-uri AD, va trebui să așteptați până când este replicat la toate controlerele de domeniu înainte de a trece la pasul următor. De obicei, acest lucru nu durează mai mult de 15 minute.

Pasul 2

Să acordăm grupului drepturi pentru a gestiona sesiunile terminale pe fiecare dintre serverele 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")
        }
    }
}

Pasul 3

Adăugați grupul la grupul local Utilizatori de desktop la distanță pe fiecare dintre serverele RDSH. Dacă serverele dvs. sunt combinate în colecții de sesiune, atunci facem acest lucru la nivel de colecție:

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

Pentru serverele individuale pe care le folosim Politica de grup, așteptând să fie aplicat pe servere. Cei cărora le este prea lene să aștepte pot accelera procesul folosind gpupdate vechi, de preferință central.

Pasul 4

Să pregătim următorul script PS pentru „manageri”:

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 "    сессий не найдено"
    }
}

Pentru ca scriptul PS să fie ușor de rulat, vom crea un shell pentru acesta sub forma unui fișier cmd cu același nume ca și scriptul PS:

RDSManagement.cmd

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

Punem ambele fișiere într-un folder care va fi accesibil „administratorilor” și le cerem să se reconnecteze. Acum, prin rularea fișierului cmd, aceștia se vor putea conecta la sesiunile altor utilizatori în modul RDS Shadow și îi vor forța să se deconecteze (acest lucru poate fi util atunci când utilizatorul nu poate încheia în mod independent o sesiune „agățată”).

Arată ceva astfel:

Pentru "manager"Delegarea managementului sesiunilor RDP

Pentru utilizatorDelegarea managementului sesiunilor RDP

Câteva comentarii finale

Nuanța 1. Dacă sesiunea de utilizator asupra căreia încercăm să obținem controlul a fost lansată înainte ca scriptul Set-RDSPermissions.ps1 să fie executat pe server, atunci „managerul” va primi o eroare de acces. Soluția aici este evidentă: așteptați până când utilizatorul gestionat se conectează.

Nuanța 2. După câteva zile de lucru cu RDP Shadow, am observat o eroare sau o caracteristică interesantă: după sfârșitul sesiunii de umbră, bara de limbă din tavă dispare pentru utilizatorul la care este conectat și pentru a o recupera, utilizatorul trebuie să reia. -log in. După cum se dovedește, nu suntem singuri: timp, два, trei.

Asta e tot. Îți doresc multă sănătate ție și serverelor tale. Ca întotdeauna, aștept cu nerăbdare feedbackul dumneavoastră în comentarii și vă rog să răspundeți la scurtul sondaj de mai jos.

surse

Numai utilizatorii înregistrați pot participa la sondaj. Loghează-te, Vă rog.

Ce folosesti?

  • 8,1%AMMYY Admin5

  • 17,7%AnyDesk11

  • 9,7%DameWare6

  • 24,2%Radmin15

  • 14,5%RDS Shadow9

  • 1,6%Asistență rapidă / Asistență la distanță Windows1

  • 38,7%TeamViewer24

  • 32,3%VNC20

  • 32,3%altele20

  • 3,2%LiteManager2

Au votat 62 de utilizatori. 22 de utilizatori s-au abținut.

Sursa: www.habr.com

Adauga un comentariu