Private/datalake-acls.ps1
using namespace Azure.Storage.Files.DataLake.Models $script:Global_ctxStorageAccountName = "" $script:Global_ctxContainerName = "" $script:Global_ctx = "" function Get-RKStorageContext { [CmdletBinding()] param([string]$StorageAccountName, [string]$ContainerName) #Wrap call in $Null to prevent any additional piped output from being sent back as context. $Null = @( # If the storage account in use has changed update the Context if (($script:Global_ctxStorageAccountName -ne $StorageAccountName) ` -or ($script:Global_ctxContainerName -ne $ContainerName)) { # Flush the cache if changing Update-RKLakeFromCache $script:Global_ctx = New-AzStorageContext -StorageAccountName $StorageAccountName -UseConnectedAccount $script:Global_ctxStorageAccountName = $StorageAccountName $script:Global_ctxContainerName = $ContainerName Reset-RKCache } ) return $script:Global_ctx } function Get-RKLakePathAcl { [CmdletBinding()] param ( [string]$Path, [string]$ContainerName, $ctx ) if ("" -eq $Path) { $Path = '/' } if ($script:aclCache.ContainsKey($Path)) { return $script:aclCache[$Path] } elseif ($Path -eq '/') { $acl = (Get-AzDataLakeGen2Item -Context $ctx -FileSystem $ContainerName).ACL } else { $acl = (Get-AzDataLakeGen2Item -Context $ctx -FileSystem $ContainerName -Path $Path).ACL } $script:aclCache[$Path] = $acl return $acl } function Test-RKLakePermission { [CmdletBinding()] param( [string]$Path, [string]$AccessControlType, [string]$EntityId, [RolePermissions]$Permissions, [bool]$DefaultScope = $False, [string]$ContainerName, $ctx ) $Current = Get-RKLakePathAcl -Path $Path -ContainerName $ContainerName -ctx $ctx $MatchedAcls = $Current | Where-Object { (($_.AccessControlType -eq $AccessControlType) ` -and ($_.EntityId -eq $EntityId ) ` -and ($_.DefaultScope -eq $DefaultScope ) ) } if (-not $MatchedAcls) { return $false } else { return (($MatchedAcls.Permissions) -eq $Permissions) } } function ConvertTo-RKRolePermissions { [CmdletBinding()] param($TargetPermissions) if ($TargetPermissions.Length -gt 0) { $TargetPermissions = $TargetPermissions.replace("r", 'Read,').replace("w", 'Write,').replace("x", 'Execute,') $TargetPermissions = $TargetPermissions.Substring(0, $TargetPermissions.Length - 1) $TargetPermissions = [RolePermissions]$TargetPermissions } else { $TargetPermissions = [RolePermissions]::None } return $TargetPermissions } function ConvertTo-RKPermissionString { [CmdletBinding()] param( [RolePermissions]$Permissions ) if (($Permissions -band 'Read') -eq 'Read') { $Res = "r" } else { $Res = "-" } if (($Permissions -band 'Write') -eq 'Write') { $Res = $Res + "w" } else { $Res = $Res + "-" } if (($Permissions -band 'Execute') -eq 'Execute') { $Res = $Res + "x" } else { $Res = $Res + "-" } return $Res } function Get-RKUpperPath { [CmdletBinding()] param([string]$Path) if (-not $Path.Contains('/')) { return $null } $Paths = $path.split('/') return $Paths[0..($Paths.Count - 2)] -join '/' } function Add-RKLakePathAcl { [CmdletBinding()] param( [string]$Path, [string]$EntityId, [string]$AccessControlType, [string]$Permissions, [bool]$SkipUpperFolders = $False, [bool]$DefaultPermission = $False, [bool]$ApplyToSubFolders = $True, [string]$ContainerName, $ctx ) $Path = $Path.Trim("/") $PermissionsObj = ConvertTo-RKRolePermissions $Permissions $PermissionsStr = ConvertTo-RKPermissionString $PermissionsObj $Exists = Test-RKLakePermission -ContainerName $ContainerName -ctx $ctx -Path $path -AccessControlType $AccessControlType -EntityId $EntityId -Permissions $PermissionsObj -DefaultScope $DefaultPermission if (-not $Exists) { if ($ApplyToSubFolders) { if ($Path -eq "") { $Path = '/' } if ($script:recursiveAclsToApply.ContainsKey($Path)) { $acl = $script:recursiveAclsToApply[$Path] $acl = Set-AzDataLakeGen2ItemAclObject -AccessControlType $AccessControlType -Permission $PermissionsStr -EntityId $EntityId -DefaultScope:$DefaultPermission -InputObject $acl } else { $acl = Set-AzDataLakeGen2ItemAclObject -AccessControlType $AccessControlType -Permission $PermissionsStr -EntityId $EntityId -DefaultScope:$DefaultPermission } $script:recursiveAclsToApply[$path] = $acl } else { if ($Path -eq "") { $Path = '/' } $script:aclCache[$Path] = Set-AzDataLakeGen2ItemAclObject -AccessControlType $AccessControlType -EntityID $EntityId -Permission $PermissionsStr -InputObject $script:aclCache[$path] -DefaultScope:$DefaultPermission $script:changedPaths += $Path } } if ((-not $SkipUpperFolders) -and ($Path -ne "")) { $Path = Get-RKUpperPath -Path $Path Add-RKLakePathAcl -ContainerName $ContainerName -ctx $ctx -Path $Path -EntityId $EntityId -AccessControlType $AccessControlType -Permissions "rx" -ApplyToSubFolders $False -DefaultPermission $False -SkipUpperFolders $False } } function Test-RKFolderExists { [CmdletBinding()] param( $Path, [string]$ContainerName, $ctx ) if (($Path -ne '/') -and (Get-AzDataLakeGen2Item -Context $ctx -FileSystem $ContainerName -Path $Path -ErrorAction:SilentlyContinue)) { return $true } elseif (($Path -eq '/') -and (Get-AzDataLakeGen2Item -Context $ctx -FileSystem $ContainerName -ErrorAction:SilentlyContinue)) { return $true } else { return $false } } function New-RKFolder { [CmdletBinding()] param( $Path, [string]$ContainerName, $ctx ) $dir = New-AzDataLakeGen2Item -Context $ctx -FileSystem $ContainerName -Path $path -Directory } function Set-RKLakePathAcl { [CmdletBinding()] param( [string]$ObjectType, [string]$DisplayName, [string]$Path, [string]$Permissions, [string]$ContainerName, [boolean]$IgnoreUpperFolder = $false, $ctx ) $EntityId = Get-RKAADObjectId -ObjectType $ObjectType -DisplayName $DisplayName if (-not (Test-RKFolderExists -Path $Path -ctx $ctx -ContainerName $ContainerName)) { New-RKFolder -Path $Path -ctx $ctx -ContainerName $ContainerName } if ($ObjectType -eq "Group") { $AccessControlType = "group" } else { $AccessControlType = "user" } if ($IgnoreUpperFolder){ # Apply permissions on existing directory only Add-RKLakePathAcl -Path $Path -EntityId $EntityId -AccessControlType $AccessControlType ` -Permissions $Permissions -SkipUpperFolders $true -DefaultPermission $False -ApplyToSubFolders $true ` -ContainerName $ContainerName -ctx $ctx } else { # Apply permissions on existing items (apply default above, and recurse down) Add-RKLakePathAcl -Path $Path -EntityId $EntityId -AccessControlType $AccessControlType ` -Permissions $Permissions -SkipUpperFolders $False -DefaultPermission $False -ApplyToSubFolders $true ` -ContainerName $ContainerName -ctx $ctx } # Apply default permissions for new items (no need to apply above, but must recurse) Add-RKLakePathAcl -Path $Path -EntityId $EntityId -AccessControlType $AccessControlType ` -Permissions $Permissions -SkipUpperFolders $true -DefaultPermission $true -ApplyToSubFolders $true ` -ContainerName $ContainerName -ctx $ctx } function Reset-RKCache { [CmdletBinding()] $script:aclCache = @{} $script:recursiveAclsToApply = @{} $script:changedPaths = @() } function Update-RKLakeFromCache { # Parameter help description $ContainerName = $script:Global_ctxContainerName $ctx = $script:Global_ctx foreach ($Path in $script:changedPaths) { $acl = $script:aclCache[$Path] Write-Host "Updating $Path Single ACL" if ($Path -eq "/") { Update-AzDataLakeGen2Item -Context $ctx -FileSystem $ContainerName -Acl $acl } else { Update-AzDataLakeGen2Item -Context $ctx -FileSystem $ContainerName -Path $Path -Acl $acl } } foreach ($Path in $script:recursiveAclsToApply.Keys) { $acl = $script:recursiveAclsToApply[$Path] Write-Host "Updating $Path Recursively" if ($Path -eq "/") { Update-AzDataLakeGen2AclRecursive -Context $ctx -FileSystem $ContainerName -Acl $acl } else { Update-AzDataLakeGen2AclRecursive -Context $ctx -FileSystem $ContainerName -Path $Path -Acl $acl } } Reset-RKCache } |