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

Делегиране на управление на RDP сесии
В организацията, в която работя, дистанционната работа е принципно забранена. Беше. До миналата седмица. Сега трябваше спешно да приложим решение. От бизнеса - адаптиране на процесите към нов формат на работа, от нас - PKI с ПИН кодове и токени, VPN, детайлно логване и много други.
Освен всичко друго, настройвах Remote Desktop Infrastructure, известна още като Terminal Services. Имаме няколко внедрявания на RDS в различни центрове за данни. Една от целите беше да се даде възможност на колеги от свързани ИТ отдели да се свързват интерактивно с потребителски сесии. Както знаете, има стандартен RDS Shadow механизъм за това и най-лесният начин да го делегирате е да дадете права на локален администратор на 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 скрипта удобен за изпълнение, ще създадем обвивка за него под формата на 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 забелязахме интересен бъг или функция: след края на shadow сесията езиковата лента в трея изчезва за потребителя, към който се свързва, и за да я върне, потребителят трябва да -Влизам. Както се оказва, не сме сами: път, два, три.

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

източници

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

какво използваш

  • 8,1%AMMYY Admin5

  • 17,7%AnyDesk11

  • 9,7%DameWare6

  • 24,2%Radmin15

  • 14,5%RDS Shadow9

  • 1,6%Бърза помощ / Отдалечена помощ на Windows1

  • 38,7%TeamViewer24

  • 32,3%VNC20

  • 32,3%други20

  • 3,2%LiteManager2

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

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

Добавяне на нов коментар