src/Private/datalake-acls.ps1
using namespace Azure.Storage.Files.DataLake.Models $script:Global_ctxStorageAccountName = "" $script:Global_ctxContainerName = "" $script:Global_ctx = "" function getStorageContext{ [CmdletBinding()] param([string]$StorageAccountName, [string]$ContainerName) # If the storage account in use has changed update the Context if (($script:Global_ctxStorageAccountName -ne $StorageAccountName) ` -or ($cript:Global_ctxContainerName -ne $ContainerName)) { # Flush the cache if changing UpdateLakeFromCache $script:Global_ctx = New-AzStorageContext -StorageAccountName $StorageAccountName -UseConnectedAccount $script:Global_ctxStorageAccountName = $StorageAccountName $script:Global_ctxContainerName = $ContainerName ResetCache } return $script:Global_ctx } function Get-LakePathAcl { [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 Check-LakePermission{ [CmdletBinding()] param( [string]$Path, [string]$AccessControlType, [string]$EntityId, [RolePermissions]$Permissions, [bool]$DefaultScope=$False, [string]$ContainerName, $ctx ) $Current = Get-LakePathAcl -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-RolePermissions{ [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-PermissionString{ [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-UpperPath{ [CmdletBinding()] param([string]$Path) if (-not $Path.Contains('/')){ return $null } $Paths = $path.split('/') return $Paths[0..($Paths.Count-2)] -join '/' } function Add-LakePathAcl{ [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-RolePermissions $Permissions $PermissionsStr = ConvertTo-PermissionString $PermissionsObj $Exists = Check-LakePermission -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-UpperPath -Path $Path Add-LakePathAcl -ContainerName $ContainerName -ctx $ctx -Path $Path -EntityId $EntityId -AccessControlType $AccessControlType -Permissions "rx" -ApplyToSubFolders $False -DefaultPermission $False -SkipUpperFolders $False } } function Check-FolderExists{ [CmdletBinding()] param( $Path, [string]$ContainerName, $ctx ) if (Get-AzDataLakeGen2Item -Context $ctx -FileSystem $ContainerName -Path $Path -ErrorAction:SilentlyContinue){ return $true } else{ return $false } } function New-Folder{ [CmdletBinding()] param( $Path, [string]$ContainerName, $ctx ) $dir = New-AzDataLakeGen2Item -Context $ctx -FileSystem $ContainerName -Path $path -Directory -ErrorAction:SilentlyContinue } function Apply-LakePathAcl{ [CmdletBinding()] param( [string]$ObjectType, [string]$DisplayName, [string]$Path, [string]$Permissions, [string]$ContainerName, $ctx ) $EntityId = Get-RedkiteAadObjectId -ObjectType $ObjectType -DisplayName $DisplayName if (-not (Check-FolderExists -Path $Path -ctx $ctx -ContainerName $ContainerName)){ New-Folder -Path $Path -ctx $ctx -ContainerName $ContainerName } if ($ObjectType -eq "Group"){ $AccessControlType = "group" } else{ $AccessControlType = "user" } # Apply permissions on existing items (apply default above, and recurse down) Add-LakePathAcl -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-LakePathAcl -Path $Path -EntityId $EntityId -AccessControlType $AccessControlType ` -Permissions $Permissions -SkipUpperFolders $true -DefaultPermission $true -ApplyToSubFolders $true ` -ContainerName $ContainerName -ctx $ctx } function ResetCache{ [CmdletBinding()] $script:aclCache = @{} $script:recursiveAclsToApply = @{} $script:changedPaths = @() } function UpdateLakeFromCache{ # 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 } } ResetCache } |