AdminBox.psm1
<#
.SYNOPSIS Sets the permissions for a user home directory. .DESCRIPTION Sets the permissions for a user home directory by inheriting the rights of the parent folder and in addition granting the user full control explicitly. All subdirectories and files of the user home directory are set to inherit permissions from the parent. .PARAMETER Path The path to a user home directory. .PARAMETER User Specifies the Domain\Name of the object that will be granted full control and become the owner of all subdirectories and files in the home path .EXAMPLE C:\PS> Set-UserDirPermissions -Path 'C:\Users\Norman.Mann' -User 'Norman.Mann' .EXAMPLE Get-ChildItem -Path 'C:\Users' | foreach-object { Set-UserDirPermission -Path $_.FullName -User $_.Name } #> function Set-UserDirPermission { [CmdletBinding()] param ( [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] [ValidateNotNullOrEmpty()] [string[]]$Path, [Parameter(Position=1, Mandatory=$true)] [string]$User, [Parameter(Mandatory=$false)] [switch]$Force=$false ) Begin { Grant-Privilege -Name SeRestorePrivilege $owner = new-object System.Security.Principal.NTAccount($User) } Process { # Take over ownership this directory and all subdirectory and files Reset-OwnerShip -path $Path -Recurse # Get permissions # Get-Acl and Set-Acl do not support -LiteralPath. A workaround was necessary # $acl = Get-Acl -path $Path $item = Get-Item -LiteralPath $Path Write-Verbose $item.FullName $acl = $item.GetAccessControl() # Do not protect against inheritance $acl.SetAccessRuleProtection($false, $true); # Remove all explicit permissions $acl.GetAccessRules($true, $false, [System.Security.Principal.SecurityIdentifier]) | foreach-object { [void]$acl.RemoveAccessRule($_)} # Add explicit permission for user and set owner $accessRule = new-object System.Security.AccessControl.FileSystemAccessRule($User, "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow") $acl.SetAccessRule($accessRule) $acl.SetOwner($owner) # Save permissions # Set-Acl -path $Path -AclObject $acl $item.SetAccessControl($acl) # Get all child items, remove all explicit permissions Get-ChildItem -path $Path -Recurse -Force:$Force | ForEach-Object { Write-Verbose $_.PSPath # Get permissions # $acl = Get-Acl -path $_.PSPath $item = Get-Item -LiteralPath $_.PSPath -Force $acl = $item.GetAccessControl() # Do not protect against inheritance $acl.SetAccessRuleProtection($false, $true); # Remove all explicit permissions $acl.GetAccessRules($true, $false, [System.Security.Principal.SecurityIdentifier]) | foreach-object { [void]$acl.RemoveAccessRule($_)} $acl.SetOwner($owner) # Save permissions # Set-Acl -path $_.PSPath -AclObject $acl $item.SetAccessControl($acl) } } } <# .SYNOPSIS Generates a random password. .DESCRIPTION Generates a random password by randomly taking an entry from the list of provided words and decorating it with a random number. .PARAMETER InputObject Specifies a collection of objects. Get-RandomPassword gets randomly selected objects in random order from the collection. Enter the objects, a variable that contains the objects, or a command or expression that gets the objects. You can also pipe a collection of objects to Get-RandomPassword. .EXAMPLE $words = Get-Content -Path 'C:\Password.txt' Get-RandomPassword -InputObject $words #> function Get-RandomPassword { [CmdletBinding()] param ( [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] [ValidateNotNullOrEmpty()] [PSObject[]]$InputObject ) Process { $password = $InputObject | Get-Random [Int32]$pos = $password.IndexOf(' ') if($pos -eq -1) {$pos = $password.Length / 2} $number = Get-Random -Min 1 -Max 99 $password = $password.Insert($pos, "!" + $number).Replace(' ', '') $password } } function Compress-Path { [CmdletBinding()] param ( [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] [ValidateNotNullOrEmpty()] [string]$Path, [Parameter(Position=1)] [int]$MaxLength = 64 ) $definition = @' [DllImport("shlwapi.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool PathCompactPathEx( System.Text.StringBuilder pszOut, string pszSrc, Int32 cchMax, Int32 dwFlags); '@ Add-Type -MemberDefinition $definition -name StringFunctions -namespace Win32 $sb = New-Object System.Text.StringBuilder(260) $result = [Win32.StringFunctions]::PathCompactPathEx($sb , $Path , $MaxLength+1, 0) $sb.ToString() } <# .SYNOPSIS Grants minimum permissions for browsing a folder hierarchy. .DESCRIPTION Grants minimum permissions required for browsing a folder hierarchy to parent folders of the specified directory. .PARAMETER Path Specifies a path to one or more locations. Wildcards are permitted. The default location is the current directory (.). .PARAMETER Group Specifies the Domain\Name of the object that will be granted permissions. .PARAMETER LevelsUp Determines the number of parent directories that that will processed while climbing up the hierarchy. .PARAMETER ToLevel Specifies the hierarchy level where assigment of permissions stops. .EXAMPLE C:\PS> Grant-BrowsePermissions -Path '\\domain.local\FS\Departments\IT\Help' -Group 'DOMAIN\IT' -LevelsUp 3 .EXAMPLE C:\PS> Grant-BrowsePermissions -Path '\\domain.local\FS\Departments\IT\Help' -Group 'DOMAIN\IT' -ToLevel 2 #> function Grant-BrowsePermissions { [CmdletBinding(SupportsShouldProcess=$true)] param ( [Parameter(ParameterSetName="LevelsUp", Position=0, Mandatory=$true, ValueFromPipeline=$true)] [Parameter(ParameterSetName="ToLevel", Position=0, Mandatory=$true, ValueFromPipeline=$true)] [ValidateNotNullOrEmpty()] [string[]]$Path, [Parameter(ParameterSetName="LevelsUp", Position=1, Mandatory=$true)] [Parameter(ParameterSetName="ToLevel", Position=1, Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$Group, [Parameter(ParameterSetName="LevelsUp", Position=2, Mandatory=$true)] [ValidateRange(1,30)] [int]$LevelsUp = 1, [Parameter(ParameterSetName="ToLevel", Position=2, Mandatory=$true)] [ValidateRange(1,100)] [int]$ToLevel ) Process { Get-Acl -Path $Path | Foreach-Object { $acl = $_ Write-Verbose $acl.Path $accessRules = $acl.GetAccessRules($true, $false, [System.Security.Principal.NTAccount]) #| Where-Object { $_.IdentityReference.Value -eq $Group } if($accessRules.Count -eq 0) { throw "No explicit access rules could be retrieved for the specified path." } $accessRule = $accessRules | Where-Object { $_.IdentityReference.Value -eq $Group } if($accessRule -eq $null) { throw "No access rules could be found for the specified identity." } $identityReference = $accessRule.IdentityReference #$identityReference.Value $item = Get-Item -Path $acl.Path $regExResult = Select-String -InputObject $item.FullName -Pattern "([A-Z]:\\|\\\\[^\\]+\\)([^\\]*\\*)*" if($regExResult -eq $null) { throw "unexpected" } $depth = $regExResult.Matches[0].Groups[2].Captures.Count-1 Write-Debug "$($item.FullName) [Path Depth: $depth]" switch($PSCmdLet.ParameterSetName) { "LevelsUp" { if($depth -lt $LevelsUp) { throw "not possible" } $traversals = $LevelsUp break; } "ToLevel" { if($ToLevel -ge $depth) { throw "nonsense" } $traversals = $depth - $ToLevel break; } } for($i=0; $i -lt $traversals; $i++) { $item = $item.Parent $acl = Get-Acl -Path $item.FullName $accessRules = $acl.GetAccessRules($true, $false, [System.Security.Principal.NTAccount]) | Where-Object { $_.IdentityReference.Value -eq $Group } if($accessRules -eq $null) { $accessRule = new-object System.Security.AccessControl.FileSystemAccessRule($identityReference, "Read", "None", "None", "Allow") $acl.SetAccessRule($accessRule) Set-Acl -Path $item.FullName -AclObject $acl } else { Write-Warning "$($item.FullName) already contains access rules for the specified identity." } } } } } function New-ProtectedItemGroupName { [CmdletBinding(SupportsShouldProcess=$true)] param ( [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] [ValidateNotNullOrEmpty()] [string[]]$Path, [Parameter(Position=1, Mandatory=$true)] [ValidateNotNullOrEmpty()] [string[]]$Permission, [Parameter(Position=2, Mandatory=$false)] [string]$SiteCode, [Parameter(Mandatory=$false)] [switch]$NoServerName=$false, [Parameter(Mandatory=$false)] [string]$Server ) Process { $siteCodeWithSeparator = $SiteCode + $(if(-Not [String]::IsNullOrWhiteSpace($SiteCode)) { " " }) foreach($directory in $Path) { Write-Verbose $directory if($NoServerName) { $corePath = $directory -replace "^\\\\[^\\]+\\" } else { # Replace site code if it is part of the server name or just leading backslashes $corePath = "$($directory -replace "^\\\\$SiteCode|\\\\")" } foreach($fileSystemRight in $Permission) { $fileSystemRightText = $fileSystemRight.Replace("ReadAndExecute", "Read") $groupName = Compress-Path -Path $corePath -MaxLength (64 - $siteCodeWithSeparator.Length - $fileSystemRightText.Length - 3) # additional 3 character for <blank> and () of permission suffix $groupName = "$siteCodeWithSeparator$($groupName -replace "\\", "-") ($fileSystemRightText)" $groupName = $groupName.Trim() -replace "[\\,+]", "-" Write-Debug "$groupName [$($groupName.Length)]" Write-Output $groupName } } } } function Protect-Item { [CmdletBinding(SupportsShouldProcess=$true)] param ( [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] [ValidateNotNullOrEmpty()] [string[]]$Path, [Parameter(Position=1, Mandatory=$true)] [ValidateNotNullOrEmpty()] [string]$GroupContainer, [Parameter(Position=2, Mandatory=$true)] [ValidateNotNullOrEmpty()] [string[]]$Permission, [Parameter(Position=3, Mandatory=$false)] [string]$SiteCode, [Parameter(Mandatory=$false)] [switch]$NoServerName=$false, [Parameter(Mandatory=$false)] [string]$Server ) Process { foreach($p in $Path) { if((Test-Path -Path $p -PathType Container) -eq $false) { Write-Verbose $p throw "Path does not exist." } } $siteCodeWithSeparator = $SiteCode + $(if(-Not [String]::IsNullOrWhiteSpace($SiteCode)) { " " }) foreach($directory in $Path) { Write-Verbose $directory if($NoServerName) { $corePath = $directory -replace "^\\\\[^\\]+\\" } else { # Replace site code if it is part of the server name or just leading backslashes $corePath = "$($directory -replace "^\\\\$SiteCode|\\\\")" } foreach($fileSystemRight in $Permission) { $fileSystemRightText = $fileSystemRight.Replace("ReadAndExecute", "Read") $groupName = Compress-Path -Path $corePath -MaxLength (64 - $siteCodeWithSeparator.Length - $fileSystemRightText.Length - 3) # additional 3 character for <blank> and () of permission suffix $groupName = "$siteCodeWithSeparator$($groupName -replace "\\", "-") ($fileSystemRightText)" $groupName = $groupName.Trim() -replace "[\\,+]", "-" Write-Debug "$groupName [$($groupName.Length)]" $group = $null if([String]::IsNullOrEmpty($Server)) { $group = Get-ADGroup -Filter {(name -eq $groupName)} if($group -eq $null) { $group = New-ADGroup -Name $groupName -Path $GroupContainer -GroupScope DomainLocal -Description $directory -PassThru } } else { $group = Get-ADGroup -Filter {(name -eq $groupName)} -Server $Server if($group -eq $null) { $group = New-ADGroup -Name $groupName -Path $GroupContainer -GroupScope DomainLocal -Description $directory -PassThru -Server $Server } } if($group -ne $null) { $acl = Get-Acl -Path $directory $accessRule = new-object System.Security.AccessControl.FileSystemAccessRule($group.SID, $fileSystemRight, "ObjectInherit, ContainerInherit", "None", "Allow") $acl.SetAccessRule($accessRule) #$acl.AddAccessRule($accessRule) Set-Acl -Path $directory -AclObject $acl } Write-Output $group } } } } <# .SYNOPSIS Determines whether a file is locked. .DESCRIPTION The Test-Lock cmdlet determines whether all a file is locked. It returns TRUE ($true) if the file is locked and otherwise FALSE ($false) .PARAMETER Path Specifies a path to be tested. Wildcards are permitted. If the path includes spaces, enclose it in quotation marks. .EXAMPLE C:\PS> Test-Lock -Path 'C:\Users\Norman.Mann\Flag.txt' #> function Test-Lock { [CmdletBinding()] param ( [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] [ValidateNotNullOrEmpty()] [string[]]$Path ) Process { foreach($p in $Path) { $sendToPipeline = $false if((Test-Path -Path $p -PathType Leaf) -eq $false) { Write-Verbose $p throw "File does not exist." } try{ $stream = [System.IO.File]::Open($p,[System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::None) } catch [System.IO.IOException] { $sendToPipeline = $true } finally { if($stream -ne $null) { $stream.Dispose() } } $sendToPipeline } } } <# .SYNOPSIS Writes a message to a log files .DESCRIPTION Writes a message to a log files .EXAMPLE C:\PS> Write-Log -Path 'C:\Users\Norman.Mann\Flag.txt' #> function Write-Log { [CmdletBinding()] param ( [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)] [ValidateNotNullOrEmpty()] [string]$Message, [Parameter(Position=1)] [IO.FileInfo] $Path = ”$env:temp\PowerShellLog.txt”, [Parameter()] [ValidateSet("Error", "Warning", "Information")] [string] $Level = "Information", [Parameter()] [ValidateRange(1,30)] [Int16] $Indent = 0 ) Begin {} Process { $messageText = '{0}{1} : {2} : {3}' -f (" " * $Indent), (Get-Date -Format “yyyy-MM-dd HH:mm:ss”), $Level.ToUpper(), $Message switch ($Level) { 'Error' { Write-Error $Message } 'Warning' { Write-Warning $Message } 'Information' { Write-Host ('{0}{1}' -f (" " * $Indent), $Message) -ForegroundColor White} } $messageText| Out-File -FilePath $Path -Append } End {} } |