تفويض إدارة جلسة RDP


في المنظمة التي أعمل فيها ، يحظر udalenka من حيث المبدأ. كانت. حتى الأسبوع الماضي. الآن اضطررت إلى تنفيذ الحل على وجه السرعة. من الأعمال - تكييف العمليات إلى تنسيق جديد للعمل ، منا - PKI مع رموز PIN والرموز المميزة ، و VPN ، وتسجيل مفصل وأكثر من ذلك بكثير.
من بين أمور أخرى ، شاركت في تكوين الملقب البنية التحتية سطح المكتب البعيد خدمات المحطة الطرفية. لدينا العديد من عمليات نشر RDS في مراكز البيانات المختلفة. كانت إحدى المهام هي تمكين الزملاء من أقسام تكنولوجيا المعلومات ذات الصلة من الاتصال بجلسات المستخدم بشكل تفاعلي. كما تعلم ، هناك آلية RDS Shadow منتظمة لهذا ، وأسهل طريقة لتفويضها هي منح حقوق المسؤول المحلي على خوادم RDS.
أنا أحترم زملائي وأقدِّرهم ، لكنني جشع جدًا لتوزيع حقوق المسؤول. :) أولئك الذين يتفقون معي ، من فضلك ، تحت القط.

حسنًا ، إن المهمة واضحة الآن.

الخطوة 1


قم بإنشاء مجموعة أمان RDP_Operators في Active Directory وقم بتضمين حسابات هؤلاء المستخدمين الذين نريد تفويض الحقوق إليهم:

$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 "root\CIMV2\terminalservices" `
        -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 وإجبارهم على تسجيل الخروج (يكون ذلك مفيدًا عندما لا يتمكن المستخدم من إنهاء جلسة "التعليق" بشكل مستقل).

يبدو شيء من هذا القبيل:

عن "المدير"


للمستخدم


بعض التعليقات في النهاية


فارق بسيط 1 . إذا كانت جلسة المستخدم التي نحاول التحكم فيها قد بدأت قبل عمل البرنامج النصي Set-RDSPermissions.ps1 على الخادم ، فسوف يتلقى "المدير" خطأ في الوصول. الحل هنا واضح: انتظر حتى يقوم المستخدم المُدار بتسجيل الدخول.

فارق بسيط 2 . بعد عدة أيام من العمل مع RDP ، لاحظ الظل وجود خطأ أو ميزة مثيرة للاهتمام: بعد الانتهاء من جلسة الظل ، يختفي المستخدم الذي كان متصلاً بشريط اللغة في الدرج ولإعادته ، يحتاج المستخدم إلى تسجيل الدخول. كما اتضح ، لسنا وحدنا: واحد ، اثنان ، ثلاثة .

هذا كل شئ. أتمنى لك وخوادمك صحة جيدة. كما هو الحال دائمًا ، أتطلع إلى التعليقات الواردة في التعليقات وأطلب منك إجراء استطلاع صغير أدناه.

المصادر



All Articles