Last active
July 17, 2018 22:46
-
-
Save rjmholt/4d00bc7bb07a8c2be49184ac84fb993b to your computer and use it in GitHub Desktop.
Script for ACL-ing things to the current user in PowerShell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
param( | |
[ValidateNotNullOrEmpty()] | |
[string]$KeyFileName, | |
[ValidateNotNullOrEmpty()] | |
[string]$KeyFileDir = $null | |
) | |
# Test if the given Windows Identity is the Built-in Administrator | |
function Test-IsAdministrator | |
{ | |
param([System.Security.Principal.WindowsIdentity]$Identity) | |
$principal = [System.Security.Principal.WindowsPrincipal]::new($Identity) | |
return $principal.IsInRole([System.Security.Principal.WindowsBuiltInRole]::Administrator) | |
} | |
# Remove all ACL access rules on a given file system security object | |
function Remove-AllAccessRules | |
{ | |
param([System.Security.AccessControl.FileSystemSecurity]$FSSecurityObj) | |
$FSSecurityObj.SetAccessRuleProtection($true, $false) | |
foreach ($rule in $FSSecurityObj.Access) | |
{ | |
$FSSecurityObj.RemoveAccessRuleAll($rule) | |
} | |
} | |
# Check if a file/directory can be accessed by anyone other than the user with the given SID | |
function Test-ItemCanBeAccessedByOthers | |
{ | |
param( | |
[System.Security.AccessControl.FileSystemSecurity]$FSSecurityObj, | |
[System.Security.Principal.IdentityReference]$UserSid | |
) | |
foreach ($accessRule in $itemSecurityObj.Access) | |
{ | |
if ($accessRule.IdentityReference -ne $UserSid) | |
{ | |
if ($accessRule.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow) | |
{ | |
return $true | |
} | |
} | |
} | |
} | |
# Set Read/Write (inlcuding delete) only permissions only to the current user | |
function Set-ThisUserOnlyRWPermissions | |
{ | |
param( | |
[string]$Path | |
) | |
# *nix is just a case of chmodding the file | |
if ($IsLinux -or $IsMacOS) | |
{ | |
chown -R $(whoami) $Path | |
chmod -R 700 $Path | |
return | |
} | |
# Get the current user | |
$currUser = [System.Security.Principal.WindowsIdentity]::GetCurrent() | |
# If the current user is in the Administrator role, we need to ACL to Administrator | |
$idToAclTo = if (Test-IsAdministrator $currUser) { | |
[System.Security.Principal.SecurityIdentifier]::new([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid, $null) | |
} else { | |
$currUser.User | |
} | |
# Get the current ACL on the file | |
$fileSecurityObj = Get-Acl -Path $Path | |
# If the file is already ACL'd properly, there's nothing to do | |
if (-not (Test-ItemCanBeAccessedByOthers -FSSecurityObj $fileSecurityObj -User $idToAclTo)) | |
{ | |
# TODO: Possibly test to see if the current user has the neccessary rw permissions | |
return | |
} | |
# Set the access rights here | |
$rw = [System.Security.AccessControl.FileSystemRights]::Read -bor | |
[System.Security.AccessControl.FileSystemRights]::Write -bor | |
[System.Security.AccessControl.FileSystemRights]::Modify -bor | |
[System.Security.AccessControl.FileSystemRights]::Delete -bor | |
[System.Security.AccessControl.FileSystemRights]::DeleteSubdirectoriesAndFiles | |
# Set recursive rights inheritance | |
$recursive = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor | |
[System.Security.AccessControl.InheritanceFlags]::ObjectInherit | |
# Set no propagation flags | |
$noPropagation = [System.Security.AccessControl.PropagationFlags]::None | |
# Make this an allow ACL | |
$allow = [System.Security.AccessControl.AccessControlType]::Allow | |
# Construct the access rule | |
$thisUserRWOnlyAccess = [System.Security.AccessControl.FileSystemAccessRule]::new( | |
$idToAclTo, | |
$rw, | |
$recursive, | |
$noPropagation, | |
$allow | |
) | |
# Remove all existing ACLs | |
Remove-AllAccessRules -FSSecurityObj $fileSecurityObj | |
# Set the one we want | |
$fileSecurityObj.AddAccessRule($thisUserRWOnlyAccess) | |
# Set the ACL | |
Set-Acl -Path $Path -AclObject $fileSecurityObj | |
} | |
# Create a new strong-cryptographically-random byte array of the given size | |
function New-CryptoKey | |
{ | |
[OutputType([byte[]])] | |
param( | |
# Default is 64 bytes = 512 bits | |
[int]$KeyByteSize = 64 | |
) | |
$keyBytes = [byte[]]::new($KeyByteSize) | |
$rng = [System.Security.Cryptography.RandomNumberGenerator]::Create() | |
$rng.GetBytes($keyBytes) | |
$rng.Dispose() | |
return $keyBytes | |
} | |
# Default name of KeyFileDir is "keys" | |
if (-not $KeyFileDir) | |
{ | |
$KeyFileDir = Join-Path -Path $PSScriptRoot -ChildPath 'keys' | |
} | |
# Get the full path of the key file | |
$KeyFilePath = Join-Path -Path $KeyFileDir -ChildPath $KeyFileName | |
# Ensure the path is absolute, relative meaning relative to this script | |
if (-not [System.IO.Path]::IsPathRooted($KeyFilePath)) | |
{ | |
$KeyFilePath = Join-Path -Path $PSScriptRoot -ChildPath $KeyFilePath | |
} | |
# Make sure the key file doesn't already exist | |
if (Test-Path $KeyFilePath) | |
{ | |
throw "Key file already exists at '$KeyFilePath'" | |
} | |
# Create the key directory if it doesn't already exist as a directory | |
if (-not (Test-Path $KeyFileDir -PathType Container)) | |
{ | |
if (Test-Path $KeyFileDir) | |
{ | |
throw "Cannot create key file directory at '$KeyFileDir': it already exists as a file" | |
} | |
New-Item -Path $KeyFileDir -ItemType Directory | |
} | |
# Create the empty key file | |
New-Item -Path $KeyFilePath -ItemType File | |
# Set the relevant permissions on the directory | |
Set-ThisUserOnlyRWPermissions -Path $KeyFileDir | |
# Now add the secret to the file | |
[IO.File]::WriteAllBytes($KeyFilePath, (New-CryptoKey)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment