Делегиране на управлението на RDP сесиите

Делегиране на управлението на RDP сесиите
В организацията, в която работя, работата от разстояние беше забранена принципно. Беше. До миналата седмица. Сега беше необходимо спешно да внедрим решение. От бизнеса – адаптация на процесите към новия формат на работа, от наша страна – PKI с ПИН кодове и токени, VPN, детайлно логване и много други.
Освен всичко друго, занимавах се с настройка на инфраструктурата за отдалечени работни станции, aka терминални услуги. Имаме няколко RDS внедрения в различни ЦОД. Една от задачите беше да предоставим на колегите от сродните ИТ отдели възможност да се свързват с потребителските сесии в интерактивен режим. Както е известно, за това има вграден механизъм RDS Shadow и най-простият начин да го делегираме е да предоставим права на локален администратор на RDS сървърите.
Уважавам и ценя колегите си, но съм много скъперник по отношение на раздаването на администраторски права. 🙂 Тези, които са с мен, моля, под кат.

Както и да е, задачата е ясна, сега – към делото.

Стъпка 1

Нека създадем група за сигурност в Active Directory RDP_Operators и да включим в нея акаунтите на тези потребители, на които искаме да делегираме права:

$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-скрипта, ще направим обвивка за него под формата на cmd файл с име, съвпадащо с името на PS-скрипта:

RDSManagement.cmd

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

Слагаме и двата файла в папка, която ще бъде достъпна за «управляващите» и ги молим да се повторно логнат. Сега, след като стартират cmd файла, те ще могат да се свързват с сесиите на други потребители в режим RDS Shadow и да ги разлогват принудително (полезно е, когато потребителят не може сам да завърши «висналата» сесия).

Изглежда това по следния начин:

За «управляващия»Делегиране на управлението на RDP сесиите

За потребителяДелегиране на управлението на RDP сесиите

Няколко забележки накрая

Нюанс 1. Ако сесията на потребителя, с която се опитваме да получим управление, е стартирана преди скриптът Set-RDSPermissions.ps1 да е работил на сървъра, «управляващият» ще получи грешка за достъп. Решението тук е очевидно: да изчакаме, докато управляваният потребител се повторно логне.

Нюанс 2. След няколко дни работа с RDP Shadow забелязахме интересен или бъг, или функция: след приключване на сянка на сесията на потребителя, към който се свързвахме, езиковата лента изчезва от трея и за да я върне, потребителят трябва да се повторно логне. Оказа се, че не сме единствени: едно, две, три.

На това е всичко. Пожелавам здраве на вас и вашите сървъри. Както винаги, очаквам обратна връзка в коментарите и ви моля да попълните кратко проучване по-долу.

Източници

Само регистрирани потребители могат да участват в анкетата. Влезте, моля.

С какво работите?

  • 8,1%AMMYY Admin5

  • 17,7%AnyDesk11

  • 9,7%DameWare6

  • 24,2%Radmin15

  • 14,5%RDS Shadow9

  • 1,6%Quick Assist / Windows Remote Assistance1

  • 38,7%TeamViewer24

  • 32,3%VNC20

  • 32,3%друго20

  • 3,2%LiteManager2

Гласували 62 потребители. Въздържали се 22 потребители.

Източник: habr.com

Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри 🔥 Купете надежден хостинг за сайтове с защита от DDoS, VPS VDS сървъри | ProHoster