Delegere administrasjon av RDP-økter

Delegere administrasjon av RDP-økter
I organisasjonen der jeg jobber, er hjemmearbeid i prinsippet forbudt. Det var det. Fram til forrige uke. Nå måtte vi i all hast implementere en løsning. Fra forretningens side – tilpasning av prosessene til det nye arbeidsformatet, fra vår side – PKI med PIN-koder og tokens, VPN, detaljert logging og mye mer.
Som en del av oppgavene mine har jeg jobbet med å sette opp infrastrukturen for fjerntilgang til arbeidsstasjoner, altså terminaltjenester. Vi har flere RDS-distribusjoner i forskjellige datasentre. En av oppgavene var å gi kolleger fra tilknyttede IT-avdelinger muligheten til å koble seg til brukersesjoner i interaktiv modus. Som kjent finnes det en innebygd mekanisme for RDS Shadow, og den enkleste måten å delegere dette på er å gi lokale administratorrettigheter på RDS-serverne.
Jeg respekterer og setter pris på kollegene mine, men jeg er veldig tilbakeholden med å dele ut admin-rettigheter. 🙂 De som er enige med meg, er velkomne til å klikke videre.

Nå, oppgaven er klar, la oss komme i gang.

Trinn 1

Vi oppretter en sikkerhetsgruppe i Active Directory RDP_Operators og legger inn brukerkontoene til de brukerne vi ønsker å delegere rettigheter til:

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

Hvis du har flere AD-domenesteder, må du vente til det er replikert til alle domenekontrollere før du går videre til neste steg. Dette tar vanligvis ikke mer enn 15 minutter.

Trinn 2

Vi gir gruppen rettigheter til å administrere terminalsesjoner på hver av RDSH-serverne:

Set-RDSPermissions.ps1

$Group = "RDP_Operators"
$Servers = @(
    "RDSHost01",
    "RDSHost02",
    "RDSHost03"
)
ForEach ($Server in $Servers) {
    # Delegere retten til skyggesessjoner
    $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 = "suksess"
        If ($retVal.ReturnValue -ne 0) {
            $opstatus = "feil"
        }
        Write-Host ("Delegere rettigheter til skyggesession for gruppen " +
            $Group + " på serveren " + $Server + ": " + $opstatus + "`r`n")
        }
    }
}

Trinn 3

Legg gruppen til den lokale gruppen Brukere av eksterne skrivebord på hver av RDSH-serverne. Hvis serverne dine er samlet i samlingssesjoner, gjør vi dette på samlingsnivå:

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

For single servers, we will use group policy, waiting for it to apply on the servers. Those who are too lazy to wait can force the process with the old reliable gpupdate, preferably centrally.

Trinn 4

We will prepare the following PS script for the "managers":

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

For ease of running the PS script, let's create a wrapper in the form of a cmd file with the same name as the PS script:

RDSManagement.cmd

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

Vi legger begge filene i en mappe som vil være tilgjengelig for "ledere" og ber dem logge inn på nytt. Nå, når de kjører cmd-filen, kan de koble seg til økter til andre brukere i RDS Shadow-modus og tvinge dem til å logge ut (det kan være nyttig når brukeren ikke kan avslutte en "frosset" økt selv).

Slik ser det omtrent ut:

For "lederen"Delegere administrasjon av RDP-økter

For brukerenDelegere administrasjon av RDP-økter

Noen merknader til slutt

Nyanse 1. Hvis brukerens økt, som vi prøver å få kontroll over, ble startet før skriptet Set-RDSPermissions.ps1 hadde kjørt på serveren, vil "lederen" motta en tilgangsfeil. Løsningen her er å vente til den styrte brukeren logger inn på nytt.

Nyanse 2. Etter noen dager med å jobbe med RDP Shadow bemerkes en interessant bug eller funksjon: Etter avslutningen av den skyggeaktige økten til brukeren, som vi koblet til, forsvinner språkpanelet fra systemstatusfeltet, og for å få det tilbake må brukeren logge inn på nytt. Det viste seg at vi ikke er alene: ein, to, tre.

Det er alt. Jeg ønsker deg og serverne dine god helse. Som alltid, ser jeg frem til tilbakemeldinger i kommentarene, og ber om at du deltar i en liten undersøkelse nedenfor.

Kilder

Kun registrerte brukere kan delta i undersøkelsen. Logg inn, vær så snill.

Hva bruker du?

  • 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%annet20

  • 3,2%LiteManager2

62 brukere stemte. 22 brukere avholdt seg.

Kilde: habr.com

Kjøp pålitelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere 🔥 Kjøp pålitelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere | ProHoster