Delegar o gerenciamento de sessões RDP

Delegar o gerenciamento de sessões RDP
Na organização onde trabalho, o trabalho remoto é proibido por princípio. Era. Até a semana passada. Agora, tivemos que implementar uma solução com urgência. Do lado do negócio — adaptar processos ao novo formato de trabalho, do nosso lado — PKI com PINs e tokens, VPN, log detalhado e muito mais.
Além de tudo, estive configurando a infraestrutura de áreas de trabalho remotas, também conhecidas como serviços de terminais. Temos várias implementações de RDS em diferentes data centers. Uma das tarefas era permitir que colegas de departamentos de TI conectassem-se a sessões de usuários em modo interativo. Como é sabido, existe um mecanismo padrão RDS Shadow e a maneira mais simples de delegá-lo é conceder direitos de administrador local nos servidores RDS.
Eu respeito e valorizo meus colegas, mas sou muito avesso a conceder direitos de administrador. 🙂 Aqueles que concordam comigo, por favor, cliquem abaixo.

Bem, a tarefa está clara, agora — mãos à obra.

Passo 1

Vamos criar um grupo de segurança no Active Directory RDP_Operators e incluir nele as contas dos usuários a quem desejamos delegar direitos:

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

Se você tiver vários sites AD, então antes de passar para o próximo passo, deve esperar até que isso seja replicado em todos os controladores de domínio. Normalmente, isso leva no máximo 15 minutos.

Passo 2

Vamos conceder ao grupo direitos para gerenciar sessões de terminais em cada um dos servidores RDSH:

Set-RDSPermissions.ps1

$Group = "RDP_Operators"
$Servers = @(
    "RDSHost01",
    "RDSHost02",
    "RDSHost03"
)
ForEach ($Server in $Servers) {
    #Delegamos o direito a sessões sombreadas
    $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 = "sucesso"
        If ($retVal.ReturnValue -ne 0) {
            $opstatus = "erro"
        }
        Write-Host ("Delegação de direitos para conexão sombreadas ao grupo " +
            $Group + " no servidor " + $Server + ": " + $opstatus + "`r`n")
        }
    }
}

Passo 3

Vamos adicionar o grupo ao grupo local Usuários de área de trabalho remota em cada um dos servidores RDSH. Se você tiver servidores agrupados em coleções de sessões, faça isso a nível de coleção:

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

Para servidores individuais, utilizamos política de grupo, aguardando sua aplicação nos servidores. Aqueles que não querem esperar podem forçar o processo com o bom e velho gpupdate, se possível de forma centralizada.

Passo 4

Vamos preparar um script PS para os "gestores":

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 "Digite o login do usuário"
Write-Host "Pesquisando sessões RDP do usuário nos servidores..."
$SessionList = @()
ForEach ($Server in $Servers) {
    $TargetSession = $null
    Write-Host "  Consultando o servidor $Server"
    Try {
        $TargetSession = Get-LoggedOnUser -ComputerName $Server | Where-Object {$_.UserName -eq $UserLogin}
    }
    Catch {
        Write-Host "Erro: " $Error[0].Exception.Message -ForegroundColor Red
        Continue
    }
    If ($TargetSession) {
        Write-Host "    Sessão encontrada com ID $($TargetSession.ID) no servidor $Server" -ForegroundColor Yellow
        Write-Host "    O que deseja fazer?"
        Write-Host "      1 - conectar à sessão"
        Write-Host "      2 - encerrar sessão"
        Write-Host "      0 - nada"
        $Action = Read-Host -Prompt "Digite a ação"
        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 "    nenhuma sessão encontrada"
    }
}

Para facilitar a execução do script PS, vamos criar um shell em formato de arquivo .cmd com o mesmo nome que o script PS:

RDSManagement.cmd

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

Colocamos ambos arquivos na pasta que estará disponível para os "gestores" e pedimos que eles façam login novamente. Agora, ao executar o arquivo cmd, poderão se conectar às sessões de outros usuários no modo RDS Shadow e forçá-los a sair (útil quando o usuário não consegue encerrar uma sessão "congelada" sozinho).

Isso se apresenta da seguinte forma:

Para o "gestor"Delegar o gerenciamento de sessões RDP

Para o usuárioDelegar o gerenciamento de sessões RDP

Algumas observações finais

Detalhe 1. Se a sessão do usuário à qual tentamos obter controle foi iniciada antes que o script Set-RDSPermissions.ps1 fosse executado no servidor, o "gestor" receberá um erro de acesso. A solução aqui é óbvia: esperar até que o usuário gerenciado faça login novamente.

Detalhe 2. Após alguns dias de trabalho com o RDP Shadow, notamos uma característica interessante, que pode ser um bug ou uma função: após o término da sessão sombra do usuário ao qual nos conectamos, a barra de idiomas desaparece na bandeja e, para reconfigurá-la, o usuário precisa fazer login novamente. Aparentemente, não estamos sozinhos: um, dois, três.

Isso é tudo. Desejo saúde a você e aos seus servidores. Como sempre, aguardo seu feedback nos comentários e peço que participe de uma rápida pesquisa abaixo.

Fontes

Apenas usuários registrados podem participar da pesquisa. Entre, por favor.

De que você utiliza?

  • 8,1%AMMYY Admin5

  • 17,7%AnyDesk11

  • 9,7%DameWare6

  • 24,2%Radmin15

  • 14,5%RDS Shadow9

  • 1,6%Assistência Rápida / Assistência Remota do Windows1

  • 38,7%TeamViewer24

  • 32,3%VNC20

  • 32,3%outro20

  • 3,2%LiteManager2

62 usuários votaram. 22 usuários se abstiveram.

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster