PSGISP.ActiveDirectory.psm1
#--------------------------------------------- #------------------ Classes ------------------ #--------------------------------------------- #--------------------------------------------- #------------- Private Functions ------------- #--------------------------------------------- #--------------------------------------------- #-------------- Public Functions ------------- #--------------------------------------------- Function Import-BulkGPO { <# .SYNOPSIS Import multiple GPO .DESCRIPTION If you export multiple GPOs they want have have the correct and again import, they wan't have the correct GPO Name. This function is able to get the correct Name out of the Manifest XML File, which is an automatically created and hidden File. .PARAMETER Path Path to GPOs .INPUTS System.String[] .OUTPUTS None .EXAMPLE Import-BulkGPO -Path .\Desktop\GPO .LINK https://github.com/gisp497/psgisp #> [CmdletBinding(SupportsShouldProcess)] param ( [Parameter( Mandatory = $true, HelpMessage = "Path of the GPO folder" )] [string]$Path ) Begin{ Write-Verbose "Install GroupPolicy module" if(Get-Module -ListAvailable GroupPolicy){ Import-Module GroupPolicy }else{ Try{ Install-WindowsFeature -Name "GPMC" Import-Module GroupPolicy }catch{ Throw "Cant import module GroupPolicy. Error: $_" } } Write-Verbose "Test if the GPO path exist." try { $null = Test-Path $Path -ErrorAction Stop } catch { Throw "The GPO path does not exist. Error: $_" } Write-Verbose "Test if the manifest.xml file exist." try { $pathmanifest = $Path.Trim('\') + '\manifest.xml' $null = Test-Path $pathmanifest -ErrorAction Stop } catch { Throw "The GPO manisfest does not exist. Error: $_" } #Create Write-Progress Variable $gpocount = (Get-ChildItem -Path $Path | Where-Object Name -ne manifest.xml).count $loopcount = 0 } Process{ #Import GPO loop Get-ChildItem -Path $Path -Directory | ForEach-Object{ Write-Verbose "Create new PSObject" $folderid = New-Object PSObject -Property @{id=$_.BaseName} Write-Verbose "Get content from manifest." [xml]$xml = Get-Content $pathmanifest $manifest = Foreach ($x in $xml.Backups.BackupInst) { New-Object PSObject -property @{id=$($x.ID | Select-Object -expand "#cdata-section");name=$($x.GPODisplayName | Select-Object -expand "#cdata-section");} } $gponame = $manifest | Where-Object {$folderid.id -eq $_.id} | Select-Object name #Create counter $loopcount++ Write-Progress -Activity 'GPO Import' -PercentComplete (($loopcount / $gpocount) * 100) Write-Verbose "Import GPO" try { $null = Import-GPO -BackupId $_.BaseName -Path $Path -TargetName $gponame.name -CreateIfNeeded -ErrorAction Stop } catch { Throw "The GPOs can't be imported. Error: $_" } } } End{ } } Function Import-PrintGPO { <# .SYNOPSIS Import printer to print gpo .DESCRIPTION This function can import printer to the print gpo. It is important, to add one printer manually to the print gpo! Otherwise the function will not work. .PARAMETER GPO The GPO which will be updated. .PARAMETER Printer The Shared path of the printer. .PARAMETER Action Execution of the GPO (create,replace,update) .PARAMETER DefaultPrinter Sets printer as default printer .PARAMETER GroupFilter Is used to deploy the printer only to specific groups. .INPUTS system.string[] .OUTPUTS none .EXAMPLE Import-PrintGPO -GPO usr-print-gpo -Printer "\\printserver\printer1","\\printserver\printer2" -Action create -DefaultPrinter -GroupFilter "group1" .LINK https://github.com/gisp497/psgisp #> [CmdletBinding(SupportsShouldProcess)] param ( [Parameter(Mandatory = $true, HelpMessage = "The GPO which will be updated.")] [string]$GPO, [Parameter(Mandatory = $true, HelpMessage = "The Shared path of the printer.")] $Printer, [Parameter(Mandatory = $false, HelpMessage = "GPO action (create, replace or update)")] [ValidateSet('create', 'replace','update')] [string]$Action = 'update', [Parameter(Mandatory = $false, HelpMessage = "Sets printer as default printer")] [switch]$DefaultPrinter, [Parameter(Mandatory = $false, HelpMessage = "Is used to deploy the printer only to specific groups.")] $GroupFilter = $null ) Begin{ Write-Verbose "Install ActiveDirectory module" if(Get-Module -ListAvailable ActiveDirectory){ Import-Module ActiveDirectory }else{ Try{ Install-WindowsFeature -Name "RSAT-AD-PowerShell" }catch{ Throw "Cant import module ActiveDirectory. Error: $_" } } Write-Verbose "Install GroupPolicy module" if(Get-Module -ListAvailable GroupPolicy){ Import-Module GroupPolicy }else{ Try{ Install-WindowsFeature -Name "GPMC" }catch{ Throw "Cant import module GroupPolicy. Error: $_" } } Write-Verbose "Get date" $date = Get-Date -Format 'yyyy-MM-dd HH:mm:ss' Write-Verbose "Get gpo action type" switch ($Action) { create { $printgpoimage = 0 $printgpoaction = 'C' } replace { $printgpoimage = 1 $printgpoaction = 'R' } update { $printgpoimage = 2 $printgpoaction = 'U' } } Write-Verbose "Get default printer option" if($DefaultPrinter){ $printgpo_defaultprinter = 1 }else{ $printgpo_defaultprinter = 0 } Write-Verbose "Get groupfilter option" if($null -ne $GroupFilter){ try { $printgpogroupfilter = '<Filters><FilterGroup bool="AND" not="0" name="' + (Get-ADGroup -Filter 'Name -eq $GroupFilter').Name + '" sid="' + (Get-ADGroup -Filter 'Name -eq $GroupFilter').SID + '" userContext="1" primaryGroup="0" localGroup="0"/></Filters>' } catch { Write-Error "The ad group can't be found." } } Write-Verbose "Get GPO" try { $printgpo_id = (Get-GPO -DisplayName $GPO -ErrorAction Stop).id } catch { Throw "GPO does not exist. Create GPO and add at least 1 printer to it." } } Process{ Write-Verbose "Create backup from GPO" $gpobackupfolder = $env:APPDATA + '\printgpo' try { if (Test-Path -Path $gpobackupfolder) { Remove-Item -Path $gpobackupfolder -Force -Recurse } $null = New-Item -Path $gpobackupfolder -ItemType Directory -Force -ErrorAction Stop $null = Backup-GPO -Id $printgpo_id -Path $gpobackupfolder -ErrorAction Stop } catch { Throw "The GPO could not be backed up." } Write-Verbose "Check if printer.xml file exists" $printerxml = (Get-ChildItem -Path $gpobackupfolder).FullName + '\DomainSysvol\GPO\User\Preferences\Printers\Printers.xml' if(Test-Path -Path $printerxml) { $printerxmlcontent = Get-Content $printerxml }else { Throw "One printer must be already added to the gpo!" } Write-Verbose "Remove end of printers.xml file" $printerxmlcontent = $printerxmlcontent -replace '</Printers>','' $printerxmlcontent = $printerxmlcontent | Where-Object {$_.trim() -ne "" } $null = Set-Content -Path $printerxml -Value $printerxmlcontent Write-Verbose "Add Printers to printers.xml file" $Printer | ForEach-Object { $uid = New-Guid $printername = $_.substring($_.lastindexof("\")+1) $printgpo_xmldata = '<SharedPrinter clsid="{9A5E9697-9095-436d-A0EE-4D128FDFBCE5}" name="' + $printername + '" status="' + $printername + '" image="' + $printgpoimage + '" changed="' + $date + '" uid="' + $uid + '" userContext="1" bypassErrors="1"><Properties action="' + $printgpoaction + '" comment="" path="' + $_ + '" location="" default="' + $printgpo_defaultprinter + '" skipLocal="0" deleteAll="0" persistent="0" deleteMaps="0" port=""/>' + $printgpogroupfilter + '</SharedPrinter>' $null = Add-Content -Path $printerxml -Value $printgpo_xmldata } Write-Verbose "Add End of printers.xml file again" $null = Add-Content -Path $printerxml -Value '</Printers>' Write-Verbose "Restore GPO with new printers" try { $null = Restore-GPO -Guid $printgpo_id -Path $gpobackupfolder } catch { Throw "The GPO could not be restored. Error: $_" } } End{ Write-Verbose "Remove old files" $null = Remove-Item -Path $gpobackupfolder -Force -Recurse } } Function New-NetworkDrive { <# .SYNOPSIS Create folder an ad group for network drive .DESCRIPTION This function creates folders and groups for network drives. The groups can be used to give access via gpo. .PARAMETER Name Array object of names which will be the new network drives. .PARAMETER Path Path in which the folders will be created. .PARAMETER GroupDriveOrganizationalUnit AD Organizationl Unit to safe new AD group. Those groups can be used to give users the folder as network drive (GPO). .PARAMETER GroupAccessOrganizationalUnit AD Organizationl Unit to safe new AD group. Those groups can be used to give users access to the folder. .INPUTS Array String .OUTPUTS None .EXAMPLE New-NetworkDrive -Name @("drive1", "drive2") -Path "D:\data" -GroupDriveOrganizationalUnit (Get-ADOrganizationalUnit -Identity "OU=Drives,OU=Groups,OU=test,DC=test,DC=local") -GroupAccessOrganizationalUnit (Get-ADOrganizationalUnit -Identity "OU=Access,OU=Groups,OU=test,DC=test,DC=local") .LINK https://github.com/gisp497/psgisp #> [CmdletBinding(SupportsShouldProcess)] param ( [Parameter( Mandatory = $true, HelpMessage = "Name of the Folders/Networkdrives" )] [Array]$Name, [Parameter( Mandatory = $true, HelpMessage = "Path in which the folders should be created." )] [String]$Path, [Parameter( Mandatory = $true, HelpMessage = "AD Organizationl Unit to safe new AD group. Those groups can be used to give users the folder as network drive (GPO)." )] $GroupDriveOrganizationalUnit, [Parameter( Mandatory = $true, HelpMessage = "AD Organizationl Unit to safe new AD group. Those groups can be used to give users access to the folder." )] $GroupAccessOrganizationalUnit ) Begin { } Process { $Name | ForEach-Object { #create folder $folder = New-Item -Path $Path -Name $_ -ItemType Directory #create groups $drivegroup = New-ADGroup -Name ('d_' + $_) -GroupScope Global -GroupCategory Security -Path $GroupDriveOrganizationalUnit -PassThru $accessreadgroup = New-ADGroup -Name ('a_' + $_ + '_r') -GroupScope Global -GroupCategory Security -Path $GroupAccessOrganizationalUnit -PassThru $accesswritegroup = New-ADGroup -Name ('a_' + $_ + '_rw') -GroupScope Global -GroupCategory Security -Path $GroupAccessOrganizationalUnit -PassThru #add access groups to drive group Add-ADGroupMember -Identity $drivegroup -Members $accessreadgroup,$accesswritegroup #format group to correct syntax $netbios = (Get-ADDomain).NetBIOSName $accessreadgroup = $netbios + '\' + $accessreadgroup.Name $accesswritegroup = $netbios + '\' + $accesswritegroup.Name #get current access rights $permission = Get-Acl $folder.FullName #disable inheritance but let permissions the same $permission.SetAccessRuleProtection($true,$true) Set-Acl -AclObject $permission -Path $folder.FullName $permission = Get-Acl $folder.FullName #create new permissions for both groups $accessread = New-Object System.Security.AccessControl.FileSystemAccessRule($accessreadgroup,"ReadAndExecute, Synchronize","ContainerInherit,ObjectInherit", "None","Allow") $accesswrite = New-Object System.Security.AccessControl.FileSystemAccessRule($accesswritegroup,"DeleteSubdirectoriesAndFiles, Modify, Synchronize","ContainerInherit,ObjectInherit", "None","Allow") $permission.SetAccessRule($accessread) $permission.SetAccessRule($accesswrite) #remove permission for builtin users $builtinusers = New-Object System.Security.Principal.Ntaccount ("BUILTIN\Users") $permission.PurgeAccessRules($builtinusers) #set permissions to folder Set-Acl -AclObject $permission -Path $folder.FullName } } End { } } Function Set-ADUserPassword { <# .SYNOPSIS Set password for AD user .DESCRIPTION This script creates random password and sets them to specific ad users. .PARAMETER User Ad user to get a new password. .PARAMETER PasswordLength The length of the new password. .INPUTS System.String[] System.Object[] System.Int[] .OUTPUTS System.Object[] .EXAMPLE Set-ADUserPassword -User gisp -PasswordLength 12 .LINK https://github.com/gisp497/psgisp #> [CmdletBinding(SupportsShouldProcess)] param ( [Parameter( Mandatory=$true, HelpMessage="Ad user to get a new password" )] $User, [Parameter( Mandatory=$false, HelpMessage="Length of the password" )] [int]$PasswordLength = 24, [Parameter( Mandatory = $false, HelpMessage = "number of special characters in password")] [int]$SpecialCharacter = 8 ) Begin{ Write-Verbose "Install ActiveDirectory module" if(Get-Module -ListAvailable ActiveDirectory){ Import-Module ActiveDirectory }else{ Try{ Install-WindowsFeature -Name "RSAT-AD-PowerShell" }catch{ Throw "Cant import module ActiveDirectory. Error: $_" } } #create Output Array $OutputObject = @() } Process{ #Get ADuser $user | Get-ADUser | Foreach-Object{ Write-Verbose "Set the new user password" $password = Get-RandomString -Length $PasswordLength -SpecialCharacter $SpecialCharacter -SecureString Set-ADAccountPassword -Identity $_ -NewPassword $password -Reset #Create psobject $credential = New-Object -TypeName System.Management.Automation.PSCredential ($_.SamAccountName, $password) #Add Object to Array $OutputObject += $credential } } End{ #Return output return $OutputObject } } #--------------------------------------------- #--------- Export Public Functions ----------- #--------------------------------------------- $PublicFunctions = @( 'Import-BulkGPO', 'Import-PrintGPO', 'New-NetworkDrive', 'Set-ADUserPassword' ) Export-ModuleMember -Function $PublicFunctions |