Parancskészlet szűkítése

Az én példám egy helpdesk csapat számára kialakított speciális távoli hozzáférési felület a tartományvezérlőhöz, amin keresztül a helpdesk szakemberek az Active Directory csak lekérdező parancsaihoz férnek hozzá, ezen kívül csak a munkájukhoz szükséges Set-ADAccountPassword és Set-ADUser parancsokhoz. Nem ez jelenti a tényleges biztonsági beállítást, hiszen az AD-ben jogok delegálásával kell azt beállítani, de a PowerShell lehetőségek szűkítése hatékonyabbá teszi a munkavégzést, hiszen még véletlenül sem tévedhetnek a munkatársak olyan cmdletek közelébe, amelyek futtatása során úgyis jogosultsági hibajelzéseket kapnának.

Elsőként létrehozom a tartományvezérlőn azt a szkriptet, amelyik majd kialakítja a lekorlátozott környezetet. Ehhez Windows Server 2008 R2 tartományvezérlő vagy Management Gateway kell, hiszen ott áll rendelkezésre az ActiveDirectory modul:

Import-Module activedirectory

 

$commands = (Get-Command -Module activedirectory |

     where-object {$_.verb -eq "get"} | %{$_.name} )

$commands += "Set-ADUser"

$commands += "Set-ADAccountPassword"

"Get-Command", "Get-FormatData", "Select-Object",

     "Get-Help", "Measure-Object" | ForEach-Object {$commands += $_ }

 

$ExecutionContext.SessionState.Applications.Clear()

$ExecutionContext.SessionState.Scripts.Clear()

 

Get-Command | ?{$Commands -notcontains $_.name} |

     ForEach-Object {$_.Visibility="Private"}

 

$ExecutionContext.SessionState.LanguageMode="RestrictedLanguage"

Első lépésként importálom tehát az ActiveDirectory modult, hiszen a helpdeskeseknek biztosítani akarom a címtárral kapcsolatos cmdletek egy részét. Ezután pont a számukra szükséges parancskészletet alakítom ki azzal, hogy kiválogatom a számukra elérhető cmdleteket a $commands változóba. Ezek a cmdletek az AD modul összes Get igéjű cmdletje, plusz az ő tevékenységükhöz szükséges két Set cmdlet, a Set-ADUser és a Set-ADAccountPassword. Valamint van néhány kötelezően engedélyezendő cmdlet, ezeket látjuk a következő sorban. Ezekkel túl sok kárt nem lehet okozni, így ennek semmilyen biztonsági kockázata sincsen, viszont enélkül nem működik a távoli futtatási környezet.

Ezután az $ExecutionContext automatikus változó SessionState tulajdonságának jellemzőit állítom be. Egyrészt letiltom az elérhető alkalmazásokat. Ilyen alkalmazás pl. a WinRM szolgáltatás használata, azaz letiltom, hogy az ide, a tartományvezérlőhöz kapcsolódó személy még távolabbi gépre kezdeményezhessen távoli kapcsolatot. Hasonló módon a szkripteket is letiltom, azaz például a helyi profilok szkriptjeit.

Ezután az összes elérhető cmdletet, amelyek nincsenek rajta az engedélyezett cmdletek listáján, láthatatlanná teszem azáltal, hogy a Visibility tulajdonságukat Private-ra állítom.

A legvégén az egész környezetet ebben a formában lezárom, hogy nehogy ezeket a beállításokat vissza tudja csinálni a leleményes helpdeskes. Ezt a LanguageMode tulajdonság beállításával tettem meg.

Ezután szintén a tartományvezérlőn létrehozok egy új távoli kapcsolódási környezetet, egy un. PSSessionConfiguration objektumot. Előtte, ha szükséges, engedélyezzük a távoli futtatás lehetőségét:

Enable-PSRemoting # ha még nem volt engedélyezve

 

register-pssessionConfiguration -name HelpDesk -startupScript ` C:\lurdy\startup.ps1 –ShowSecurityDescriptorUI

Ez létrehoz egy HelpDesk nevű „játszóteret” távoli futtatás céljára, ahol tehát eleve be lesz importálva az ActiveDirectory modul, viszont egy csomó cmdlet nem lesz elérhető. Mindezt a korábban látott startup.ps1 szkript alakítja ki. Ezt a játszóteret még a jogosultság megfelelő beállításával is védjük, hogy ne csatlakozhasson ide bárki, mindjárt látjuk, hogy hogyan.

Ezt futtatva ilyen kimenetet kapunk:

[62] PS C:\> register-pssessionConfiguration -name HelpDesk -startupScript ` C:\lurdy\startup.ps1 –ShowSecurityDescriptorUI

 

Confirm

Are you sure you want to perform this action?

Performing operation "Register-PSSessionConfiguration" on Target "Name:

HelpDesk. This will allow administrators to remotely run Windows PowerShell

commands on this computer".

[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help

(default is "Y"):y

 

 

   WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Plugin

 

Name                      Type                 Keys

----                      ----                 ----

HelpDesk                  Container            {Name=HelpDesk}

 

Confirm

Are you sure you want to perform this action?

Performing operation ""Restart-Service"" on Target "Name: WinRM".

[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help

(default is "Y"):y

 

Confirm

Are you sure you want to perform this action?

Performing operation "Restart-Service" on Target "Windows Remote Management

(WS-Management) (winrm)".

[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help

(default is "Y"):y

Néhány megerősítést kért tőlünk, és megjelent (lásd alább) a –ShowSecurityDescriptorUI kapcsoló hatására a következő grafikus dialógusablak:

137 . ábra Grafikus - karakteres együttműködés

Ezen a felületen megadtam a Helpdesk Hugó részére (a demó rendszeremen ő szimbolizálja a helpdesk csoportot) a szükséges Execute (Invoke) jogot. Itt ezt sokkal egyszerűbb beállítani, mint a karakteres konzolon, de ott is meg lehetett volna tenni.

Nézzük, hogy a távoli gépen hogyan lehet ehhez a környezethez csatlakozni:

PS C:\> $s = New-PSSession -ComputerName dc -ConfigurationName helpdesk

Ez nem túl bonyolult, de vajon hogyan tudja lekérdezni Hugó a felhasználókat az AD-ből?

PS C:\> Invoke-Command -Session $s -ScriptBlock {get-aduser -filter 'name -like

 "főn*"'}

 

 

PSComputerName     : dc

RunspaceId         : 81cb2f79-afa9-4e9a-8552-f8d296380932

PSShowComputerName : True

DistinguishedName  : CN=Főnök Ferenc,OU=Managed Users,DC=r2,DC=dom

Enabled            : True

GivenName          : Ferenc

Name               : Főnök Ferenc

ObjectClass        : user

ObjectGUID         : a067ce05-b902-4f26-812e-4bbb62280ea8

SamAccountName     : ff

SID                : S-1-5-21-3398938913-3940250523-927435294-1123

Surname            : Főnök

UserPrincipalName  : ff@r2.dom

Itt már némi szomorúságot vélek felfedezni lelki szemeim előtt Hugó arcán. Elég macerás ez neki, főleg, hogy a „restricted” üzemmódú környezetben nem használhat scriptblock adattípust, így a –Filter-hez idézőjellel kell megadnia a feltételt. Szerencsére a PowerShell nagyon humánus, nem kárhoztatja a szegény helpdeskeseket állandó Invoke-Command parancsok használatára, mert be lehet importálni a távoli környezet lehetőségeit a lokális környezetbe az Import-PSSession cmdlet segítségével:

PS C:\> Import-PSSession -Session $s

 

ModuleType Name                      ExportedCommands

---------- ----                      ----------------

Script     tmp_e8a8b3de-e7fe-472a... {Get-ADUser, Get-ADServiceAccount, Get...

Ez a parancs „áthozza” a távoli környezet cmdleteit, valójában ugyanolyan nevű függvényeket hoz létre, mint a távoli cmdletek, és ebbe a függvénybe ágyazza be azt az Invoke-Command kifejezést, ami valójában a távoli parancsot végrehajtja. Nézzünk ezeket a függvényeket:

PS C:\> Get-Command -CommandType function | ?{$_.name -match "-AD"}

 

CommandType     Name                            Definition

-----------     ----                            ----------

Function        Get-ADAccountAuthorizationGroup ...

Function        Get-ADAccountResultantPasswo... ...

Function        Get-ADComputer                  ...

Function        Get-ADComputerServiceAccount    ...

Function        Get-ADDefaultDomainPasswordP... ...

Function        Get-ADDomain                    ...

Function        Get-ADDomainController          ...

Function        Get-ADDomainControllerPasswo... ...

Function        Get-ADDomainControllerPasswo... ...

Function        Get-ADFineGrainedPasswordPolicy ...

Function        Get-ADFineGrainedPasswordPol... ...

Function        Get-ADForest                    ...

Function        Get-ADGroup                     ...

Function        Get-ADGroupMember               ...

Function        Get-ADObject                    ...

Function        Get-ADOptionalFeature           ...

Function        Get-ADOrganizationalUnit        ...

Function        Get-ADPrincipalGroupMembership  ...

Function        Get-ADRootDSE                   ...

Function        Get-ADServiceAccount            ...

Function        Get-ADUser                      ...

Function        Get-ADUserResultantPasswordP... ...

Function        Set-ADAccountPassword           ...

Function        Set-ADUser                      ...

Láthatjuk, hogy az elérhető AD cmdletek tényleg csak a Get igéjűeket tartalmazzák, plusz a Set-ADAccountPassword és a Set-ADUser. Pillantsunk bele egy függvénydefinícióba is (kicsit megvágtam a paraméterdefiníciós rész):

PS C:\> ${function:get-aduser}

 

    param(

 

    [Alias('db')]

    [Switch]

    ${Debug},

 

    [Alias('wv')]

    ${WarningVariable},

 

    [Alias('Property')]

    ${Properties},

 

    ${SearchBase},

 

    ${ResultPageSize},

 

    ${Credential},

begin {

 

        try {

            $positionalArguments = & $script:NewObject collections.arraylist

            foreach ($parameterName in $PSBoundParameters.BoundPositionally)

            {

                $null = $positionalArguments.Add( $PSBoundParameters[$paramete

rName] )

                $null = $PSBoundParameters.Remove($parameterName)

            }

            $positionalArguments.AddRange($args)

 

            $clientSideParameters = Get-PSImplicitRemotingClientSideParameters

 $PSBoundParameters $True

 

            $scriptCmd = { & $script:InvokeCommand `

                            @clientSideParameters `

                            -HideComputerName `

                            -Session (Get-PSImplicitRemotingSession -CommandNa

me 'Get-ADUser') `

                            -Arg ('Get-ADUser', $PSBoundParameters, $positiona

lArguments) `

                            -Script { param($name, $boundParams, $unboundParam

s) & $name @boundParams @unboundParams } `

                         }

 

            $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation

.CommandOrigin)

            $steppablePipeline.Begin($myInvocation.ExpectingInput, $ExecutionC

ontext)

}

Ez tulajdonképpen szerkezetileg egy olyan függvény, mint amit a 2.5.7 Meglevő cmdletek kiegészítése, átalakítása fejezetben láttunk. Az elején ugyanolyan paramétereket definiál a függvény, mint ami az eredeti cmdletnek van, majd a paraméterátadáshoz szétválogatja a pozícionális paramétereket és a nevesítetteket. Nem mondom, hogy minden világos pontosan számomra, hogy mi is történik, a lényeg, hogy meg lesz hívva távoli módon az eredeti cmdlet.

Ráadásul így a TAB kiegészítés is működik, ezzel még kényelmesebb lesz a helpdeskes munkája. Nézzük, hogyan tudja a korábbi parancsot futtatni:

PS C:\> Get-ADUser -Filter {name -like "főn*"}

 

 

RunspaceId        : 81cb2f79-afa9-4e9a-8552-f8d296380932

DistinguishedName : CN=Főnök Ferenc,OU=Managed Users,DC=r2,DC=dom

Enabled           : True

GivenName         : Ferenc

Name              : Főnök Ferenc

ObjectClass       : user

ObjectGUID        : a067ce05-b902-4f26-812e-4bbb62280ea8

SamAccountName    : ff

SID               : S-1-5-21-3398938913-3940250523-927435294-1123

Surname           : Főnök

UserPrincipalName : ff@r2.dom

Láthatjuk, hogy minden ugyanúgy működik, mintha ott ülne az illető a tartományvezérlőre bejelentkezve! Mindezt úgy, hogy nem kellett telepíteni semmit sem a helpdeskes munkaállomására.



Word To HTML Converter