Windows Powershell – The Basics 7
Welkom in een vers jaar! 2018 is nog jong en barst nog van de potentie! Toch gaan we in dit prille jaar alweer de eerste zaken afsluiten. Dit is de laatste post in de “Windows Powershell – The Basics” serie. In dit zevende deel wil ik graag nog een aantal items belichten om de uniforme kracht en flexibiliteit van Powershell te belichten en dat zijn de Powershell Modules en SnapIns. Ga je nog 1 keer mee op onderzoek in de wondere wereld van de PowerShell?
Echte Administrators gebruiken Powershell Modules om de beheertaken nog makkelijker te maken. Vroeger (Powershell V1) werkte met Snap-Ins. Powershell V2 ondersteund echter modules waarmee het makkelijker wordt voor coders om hun eigen modules te maken en distribueren.
Laten we eerst eens kijken wat een Powershell module nu exact is?
Een Powershell Module zorgt ervoor dat de default Powershell omgeving voorzien wordt van extra functionaliteiten. Een module is vaak een bundel scriptbestanden waarmee nieuwe Powershell functies mogelijk gemaakt worden.
Een module bestaat uit een folder waarin een aantal bestanden zitten zoals 1 of meerdere Powershell scriptbestanden of managed cmdlet assembly bestanden, eventuele ondersteunende bestanden voor de scriptbestanden zoals help bestanden of hulp scripts en een manifest file welke alle bestanden in de directory beschrijft en diverse metadata bevat.
Er bestaan verschillende soorten modules zoals:
- Binary Module
Dit is een .NET Framework Assembly (.dll) welke compiled code bevat zoals C#. - Script Module
Dit is een module met scriptfiles ofwel “*.psm1” bestanden. Deze scriptbestanden bestaan uit valide Powershell code. - Manifest Module
Deze modules (*.psd1 bestanden) gebruiken een manifest file om alle componenten te beschrijven. - Dynamic Module
Dit zijn geen statische modules maar modules die on-the-fly gemaakt worden door een script met de “New-Module” Cmdlet.
Modules moeten geïnstalleerd worden in de modulepaden die Powershell voor modules gebruikt. Deze kun je vinden met het volgende commando:
$Env:PSModulePath |
Er zijn 2 modulepaden. 1 voor jezelf (1 gebruiker) en 1 voor alle gebruikers:
Pad voor jezelf:
$home\Documents\WindowsPowerShell\Modules\<Module Folder>\<Module Files> |
Pad voor iedereen:
$EnvProgramFiles\WindowsPowerShell\Modules\<Module Folder>\<Module Files> |
Het is ook mogelijk om modules te installeren in alternatieve paden echter moeten deze paden dan nog toegewezen worden aan het “PSModulePath“. Dit doe je met onderstaande commando:
$env:psmodulepath = $env:psmodulepath + "C:\Nieuwe_PSModule_Locatie" |
Na installatie moeten de modules nog geladen worden. Modules nestelen zich niet in het register zoals de ouderwetse PS SnapIns en kunnen ook een stuk makkelijker geïnstalleerd worden.
Om alle modules te bekijken welke beschikbaar zijn (Powershell V3) gebruik je het commando:
Get-Module -ListAvailable |
Om alle modules te bekijken welke momenteel in de sessie geladen zijn gebruik je de “-All” flag:
Get-Module -All |
Een nieuwe module importeren doe je met de “Import-Module” Cmdlet:
Import-Module -Name Nieuwe-Module |
Aan te raden is om bij het importeren van een module de “-Verbose” optie te gebruiken zodat je meteen inzichtelijk hebt welke Cmdlets, functies en aliassen beschikbaar worden nadat de module geïmporteerd is:
Import-Module -Name Nieuwe-Module -Verbose |
Om de module weer te verwijderen gebruiken we “Remove-Module“:
Remove-Module -Name Nieuwe-Module -Verbose |
SnapIns
Microsoft predikt developers om af te stappen van de ouderwetste (Powershell V1) SnapIns. SnapIns worden echter nog steeds gebruikt. Zelfs grote distributeurs zoals VMWare PowerCLI gebruiken nog SnapIns en dus zullen we waarschijnlijk nog een tijdje met SnapIns werken.
Het schrijven van SnapIns is lastiger. SnapIns zijn geschreven in .NET in tegenstelling tot modules welke in C# of gewoon in Powershell scripting geschreven kunnen zijn. Daarnaast zijn SnapIns lastiger te distribueren en lastiger om mee te werken. SnapIns zijn DLL’s welke op het systeem geregistreerd moeten worden alvorens ze gebruikt kunnen worden. Om alle geregistreerde SnapIns te bekijken gebruiken we de PSSnapIn Cmdlet. In dit geval “Get-PSSnapIn”:
Get-PSSnapIn -Registered |
Om een SnapIn te laden gebruiken we “Add-PSSnapIn”:
Add-PSSnapIn -Name Nieuwe_SnapIn |
Om de SnapIn weer uit de sessie te verwijderen:
Remove-PSSnapIn -Name Nieuwe_SnapIn |
Om alle geladen Cmdlets en functies te bekijken van de zojuist ingeladen SnapIn gebruiken we de “Get-Command” Cmdlet. Het toevoegen van de “-Verbose” flag tijdens het inladen, zoals we dat bij een module deden kan wel maar geeft geen nuttige output. We gebruiken dus:
Get-Command -Module Nieuwe_SnapIn |
Omdat SnapIns beperkter zijn is het managen van SnapIns iets simpeler dan het managen van modules. Maar dit voordeel weegt niet af tegen alle overige voordelen van modules. Het idee is echter duidelijk een SnapIn en een Module zijn niet exact hetzelfde qua opzet maar wel qua functionaliteit, namelijk “het vergroten van de default Powershell mogelijkheden”!
Vele die voor het eerst met Powershell in aanraking komen zijn systeem administrators die na installatie van Active Directory, Exchange of Sharepoint een zogenaamde “Management Shell” vinden. In werkelijkheid is dit geen echte dedicated shell maar is het gewoon Powershell met een geladen module of SnapIn.
In dit voorbeeld gaan we kort kijken naar de Active Directory Powershell Module. De module heet “ActiveDirectory” en is verkrijgbaar v.a. Windows2008R2 en hoger. De ActiveDirectory module wordt geïnstalleerd tijdens installatie van de AD DS en de AD LDS server roles. De module wordt ook geïnstalleerd wanneer je de server opwaardeert tot Domain Controller (DCPromo) of is onderdeel van de Remote Server Administration Tools (RSAT).
Als de module geïnstalleerd is vindt u een nieuwe shell onder de Administrative Tools genaamd “Active Directory Module for Windows PowerShell”. Als je hierop klikt wordt Powershell gestart en de module wordt geladen.
Nu de ActiveDirectory module geladen is hebben we een ton aan AD gerelateerde Cmdlets erbij gekregen waarmee we dus onze volledige AD omgeving kunnen aanmaken en beheren. Denk aan gebruikerbeheer, computerbeheer, OU’s, groepen, password policies, etc. Hierbij een klein voorproefje ter leering ende vermaak.
Allereerst gaan we even onze AD gegevens bekijken, gewoon wat basis informatie via:
Get-AdDomain |
Nu wil ik graag weten welke Cmdlets en functies we kunnen gebruiken met deze module. Omdat deze “module” stiekem een SnapIn is gebruiken we:
Get-Command -Module ActiveDirectory |
Om alleen alle “Get” Cmdlets te zien kan ik het volgende gebruiken door toevoeging van de “-Verb” flag:
Get-Command -Module ActiveDirectory -Verb Get |
Een van de commando’s is het “Get-ADUser” commando. Met dit commando kun je gegevens van een gebruiker opvragen:
Get-ADUser Jarno |
Dit commando vereist een filter. We Kunnen verschillende filters gebruiken waaronder:
- samAccountName
- Name
- SSID
- GivenName
- ObjectClass
Bijvoorbeeld:
Get-ADUser -Filter 'SamAccountName -eq "Jarno"' |
Als we alle gebruikers binnen AD willen zien:
Get-ADUser -Filter 'ObjectClass -eq "User"' |
Uiteraard kunnen we ook alle gebruikers naar een log schrijven zoals we gewend zijn:
Get-ADUser -Filter 'ObjectClass -eq "User"' | Out-File c:\temp\userlog.txt |
Uiteraard kunnen we ook OU’s, security groups en users aanmaken. Een user heeft natuurlijk heel veel eigenschappen waardoor een Powershell script een betere optie is om een gebruiker aan te maken. We kunnen echter ook de “New-ADUser” Cmdlet gebruiken welke er als volgt uit zou kunnen zien:
New-ADUser -Name "Test1gebruiker1" -GivenName Test1 -Surname Gebruiker1 -Path "OU=Users,DC=Testbedrijf,DC=NL" -SamAccountName tgebruiker1 -UserPrincipalName tgebruiker1@samenwerkendetandartsen.nl -AccountPassword (Read-Host -AsSecureString "Test@@1a9t") -PassThru | Enable-ADAccount |
Gebruikersnaam:
-Name “Test1gebruiker1”
Voornaam:
-GivenName Test1
Achternaam:
-Surname Gebruiker1
Specificeer OU:
-Path “OU=Users,DC=Testbedrijf,DC=NL”
SAM naam:
-SamAccountName tgebruiker1
User Principal Name (username in e-mail format):
-UserPrincipalName tgebruiker1@samenwerkendetandartsen.nl
Wachtwoord:
-AccountPassword (Read-Host -AsSecureString “Test@@1a9t”)
Account Activeren:
-PassThru | Enable-ADAccount
In de vorige les konden we kort snuffelen aan scripts en dit is waar scripts pas echt handig gaan worden. Zo kunnen we gemakkelijk een script maken die bovenstaande vragen “als vraag” aan ons stelt en vervolgens de gebruiker aanmaakt. Of beter nog, een script welke de waardes uit een Excel of CSV bestand leest en zo in bulk de gebruikers aan kan maken.
Scripts zullen we een klein beetje toepassen bij het volgende voorbeeld en dat is namelijk het managen van Office365 of met name ExchangeOnline.
Beheer Office365 en ExchangeOnline met Powershell
De GUI omgeving van Office365 is qua functionaliteiten erg beperkt. De reguliere werkzaamheden kunnen gedaan worden maar zodra het speciale werkzaamheden zijn (die we als beheerder geregeld tegenkomen) biedt de GUI geen oplossing. Er zijn tools van o.a. CodeTwo en ManageEngine die in sommige scenario’s uitkomst bieden. Echter geeft Powershell ons dezelfde tools en meer. We kunnen dus gemakkelijk onze Office365 omgeving beheren met een beetje coding.
Verbinden met Office365 is erg simpel. We hebben hier geen separate “shell / module” voor nodig. We kunnen namelijk gewoon vanuit onze on-premise Powershell verbinden met onze Office365 Online Powershell.
Dit proces bestaat uit slechts 2 stappen:
Powershell moet voor het opzetten van de verbinding remote (signed) scripts kunnen draaien. Als je dit nog niet hebt ingesteld open dan Powershell als Administrator en voer het volgende commando uit:
Set-ExecutionPolicy RemoteSigned |
1. We gaan verbinden met de Office365 Online Powershell. Dit doen we met onderstaande commando. We gaan onze Ofice365 credentials opslaan in de “UserCredential” variabele:
$UserCredential = Get-Credential |
Er volgt nu een pop-up waar je je inloggegevens invoert om de verbinding te maken.
2. Vervolgens verbinden we met de opgegeven credentials met Office365 Online Powershell:
Import-Module MsOnline Connect-MsolService -Credential $UserCredential |
Om met andere diensten te verbinden moet stap 2 vervangen worden voor andere code’s. Om b.v. met ExchangeOnline te verbinden vervang je stap 2 voor onderstaande stap 3 en 4:
3. Nu gaan we de sessie eigenschappen zoals connectie URL, Authenticatie e.d. specificeren en opslaan in de $Session variabele. We geven ook weer onze inlog credentials mee maar gebruiken hiervoor de eerder gedefinieerde variabele $UserCredential:
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection |
Nu we de sessie eigenschappen gedefinieerd hebben kunnen we de sessie opzetten met het commando:
Import-PSSession $Session |
Voor het verbinden met SharePoint Online vervang je stap 2 voor onderstaande commando’s:
Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking Connect-SPOService -Url https://mijndomeinnaam-admin.sharepoint.com -credential $UserCredential |
Voor het verbinden met Skype Online vervang je stap 2 voor onderstaande commando’s:
Import-Module SkypeOnlineConnector $sfboSession = New-CsOnlineSession -Credential $UserCredential $sfboSession = New-CsOnlineSession -Credential $credential |
Voor het verbinden met Security & Compliance Center vervang je stap 2 voor onderstaande commando’s:
$ccSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection Import-PSSession $ccSession -Prefix cc |
LET OP dat je de sessie sluit als je klaar bent met je werkzaamheden. Gebruik dus niet het kruisje van Powershell want dan wordt je sessie niet gesloten. Je hebt als gebruikers maar een beperkt aantal sessies ter beschikking. Als je dus teveel sessies open hebt staan kun je niet meer inloggen en moet je wachten tot de sessies verlopen zijn.
De sessie sluiten doe je met het “Remove-PSSession” commando:
Remove-PSSession $Session |
Mocht je bovenstaande connecties in 1 sessie willen open dan gebruik je het volgende codeblok:
$domainHost="mijndomeinnaam" $credential = Get-Credential Import-Module MsOnline Connect-MsolService -Credential $UserCredential Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking Connect-SPOService -Url https://$domainHost-admin.sharepoint.com -credential $UserCredential Import-Module SkypeOnlineConnector $sfboSession = New-CsOnlineSession -Credential $UserCredential Import-PSSession $sfboSession $exchangeSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://outlook.office365.com/powershell-liveid/" -Credential $UserCredential -Authentication "Basic" -AllowRedirection Import-PSSession $exchangeSession -DisableNameChecking $ccSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection Import-PSSession $ccSession -Prefix cc |
Bovenstaande sessies sluit je vervolgens met onderstaande commando:
Remove-PSSession $sfboSession ; Remove-PSSession $exchangeSession ; Remove-PSSession $ccSession ; Disconnect-SPOService |
Nu we een actieve sessie hebben met de Office365 Online Powershell kunnen we vele soorten taken uitvoeren. Hier een paar voorbeelden:
Overzicht van alle beschikbare Cmdlets:
Get-Command -Module msonline |
Overzicht van subscriptions en beschikbare licenties:
Get-MsolAccountSku |
Voor het bekijken van alle beschikbare diensten binnen onze subscriptions:
Get-MsolAccountSku | Select -ExpandProperty ServiceStatus |
Alle Office365 users opvragen (verhoog de “-MaxResults” waarde naar eigen inzicht) met “Get-Msoluser“:
Get-Msoluser -MaxResults 800 |
Om informatie van een specifieke gebruiker opvragen d.m.v. “UserPrincipalName” doe je als volgt:
Get-MsolUser -UserPrincipalName "jarno@jarnobaselier.nl" |
Gebruikers opvragen met de “City” value waarbij we “Where-Object” gebruiken:
Get-MsolUser | Where-Object {$_.City -eq "Rotterdam"} |
Specifieke gebruikersgegevens opvragen:
Get-MsolUser -UserPrincipalName "jarno@jarnobaselier.nl" | Select-Object DisplayName, Department, UsageLocation |
Of gewoon alle eigenschappen van een gebruiker opvragen:
Get-MsolUser -UserPrincipalName "jarno@jarnobaselier.nl" | Select-Object * |
Alle disabled users opvragen:
Get-MSolUser -All -EnabledFilter DisabledOnly |
Verwijderde gebruikers opvragen:
Get-MsolUser -ReturnDeletedUsers |
Zoeken naar een gebruiker:
Get-MsolUser -All -SearchString jarno |
Ongelicenseerde gebruikers bekijken:
Get-MsolUser -All -UnlicensedUsersOnly |
Om specifieke gebruikersinformatie naar een CSV te exporteren kunnen we het volgende gebruiken:
Get-ADUser -Filter {Department -eq 'Hoofdkantoor'} -Properties Department, SamAccountName, legacyExchangeDN | Export-Csv -Path $env:USERPROFILE\Desktop\users.csv |
Maar we kunnen niet alleen informatie bekijken of exporteren, natuurlijk kunnen we deze ook aanpassen.
Om een licentie aan een gebruiker toe te kennen gebruik je de “Set-MsolUserLicense” Cmdlet:
Set-MsolUserLicense -UserPrincipalName "jarno@jarnobaselier.nl" -AddLicenses "<AccountSkuId>" |
Set-MsolUserLicense -UserPrincipalName "jarno@jarnobaselier.nl" -AddLicenses "ENTERPRISEPACK" |
Om meerdere gebruikers vanuit een CSV een licentie toe te kennen en daarbij specifieke producten in en/of uit te schakelen kun je een script maken. Bijvoorbeeld:
$list = Import-Csv -Path $env:USERPROFILE\Desktop\users.csv $UserCredential = Get-Credential Connect-MsolService -Credential $UserCredential $MyLicenseAssignmentOption = New-MsolLicenseOptions -AccountSkuId "jarnobaselier:ENTERPRISEPACK" -DisabledPlans INTUNE_O365 ForEach ($entry in $list) { $UPN = $entry.UserPrincipalName $SAN = $entry.SamAccountName IF (Get-MsolUser -UserPrincipalName $UPN) { Set-MsolUser -UserPrincipalName $UPN -UsageLocation "NL" Set-MsolUserLicense -UserPrincipalName $UPN -LicenseOptions $MyLicenseAssignmentOption "$SAN licentie opties toegevoegd"} Else { "$SAN heeft nog geen mailbox"} } |
Om bepaalde properties van een gebruiker aan te passen gebruiken we de “Set-MSolUser” Cmdlet:
Set-MSolUser -UserPrincipalName "jarno@jarnobaselier.nl" -UsageLocation "NL" -City "Breda" -LastName "Baselier" |
We kunnen ook in bulk bepaalde properties van meerdere gebruikers aanpassen. Om bijvoorbeeld de “City” property aan te passen bij alle gebruikers op de afdeling “Finance” kun je een combinatie gebruiken van “Get-MSolUser”, “Where-Object” en “Set-MSolUser”:
Get-MSolUser | Where-Object {$_.Department -eq "Finance"} | Set-MSolUser -City "Breda" |
Een volledig nieuwe gebruiker aanmaken kun je de “New-MSolUser” Cmdlet gebruiken. Bijvoorbeeld:
New-MsolUser -DisplayName "Jarno Baselier" -FirstName Jarno -LastName Baselier -UserPrincipalName jarno@jarnobaselier.nl -UsageLocation NL -LicenseAssignment jarnobaselier:ENTERPRISEPACK |
Wanneer je een sessie met ExchangeOnline opzet kun je op dezelfde manier Exchange specifieke taken uitvoeren.
Om bijvoorbeeld een dynamische distributielijst aan te maken waarin alle gebruikers komen met de naam “accountant” in de functietitel voer je het volgende commando uit:
New-DynamicDistributionGroup "Accountants" -RecipientFilter {((RecipientType -eq 'UserMailbox') -and (Title -eq 'accountant'))} |
Een remote routing adres toevoegen aan een gebruiker (meestal in een Exchange Hybride configuratie):
$gebruikersaccount = "JBaselier" Enable-RemoteMailbox $gebruikersaccount -alias $gebruikersaccount -RemoteRoutingAddress $jbaselier@jarnobaselier.mail.onmicrosoft.com |
En een mailbox verwijderen met “Disable-RemoteMailbox“:
Disable-RemoteMailbox "JBaselier" |
En om nog een stapje verder te gaan zou je zelfs de layout aan kunnen passen van de “encrypted e-mail portal”:
Set-OMEConfiguration -Identity "OME Configuration" -EmailText "Versleuteld bericht van Jarno Baselier" Set-OMEConfiguration -Identity "OME Configuration" -DisclaimerText "Dit bericht is strikt vertrouwelijk en mag alleen gelezen worden door de rechtmatige ontvanger." Set-OMEConfiguration -Identity "OME Configuration" -PortalText "Veilige e-mail portal van Jarno Baselier" Set-OMEConfiguration -Identity "OME configuration" -Image (Get-Content "C:\Temp\jarnobaselierlogo.png" -Encoding byte) |
Etc. etc. etc. We kunnen nog heel erg lang doorgaan met het geven van voorbeelden. Feit is dat Powershell een krachtige tool is en door toevoeging van modules nog krachtiger wordt en de administrator ondersteund tijdens zijn beheerstaken. Maar onthoud… “With great power, comes great responsibility”. Met andere woorden: 1 simpel commando kan je hele omgeving in de war schoppen. Kijk uit en test je Powershell commando’s altijd binnen een testomgeving.
Ik hoop dat na deze serie van 7 Powerhell posts je iets geleerd hebt over Powershell en je vol vertrouwen zelf aan de slag kunt met deze mooie command-line omgeving. Wat sowieso duidelijk moet zijn na deze posts is de opbouw van de commando’s, benamingen van diverse Cmdlets, toepassen van diverse filters en het gebruiken van meerdere commando’s welke middels piping symbolen aan elkaar gekoppeld zijn.
En mocht je blij zijn met de uitleg like dan s.v.p. deze en/of de andere posts in deze serie. Ik schrijf ze heel erg graag maar een like zie ik toch als een waardering voor de moeite en de tijd die ik geïnvesteerd heb in het schrijven van deze posts. Je bent een nog grotere topper als je mijn post wilt delen op je eigen website of je eigen sociale media. Hartelijk dank alvast en tot de volgende!!
Keep on scripting (en deel mooie scripts gerust met me)… love it!