private/export/Export-Database.ps1
function Export-Database { <# .SYNOPSIS Creates a database with the data files found in the specified folder. .DESCRIPTION Creates a database with the data files found in the specified folder. Database will be created in the subfolder "db". If the folder already exists, it will be deleted before commencing. .PARAMETER ExportPath The folder in which to look for data and under which to create the database. This expects that previously all relevant data has already been exported from the tenant. .PARAMETER Pillar Which Zero Trust Pillar to process. Defaults to "All". .EXAMPLE PS C:\> Export-Database -ExportPath . Creates the database from the exported data found in the current folder. #> [CmdletBinding()] param ( # The path to the folder where all the files were exported. [Parameter(Mandatory = $true)] [PSFDirectorySingle]$ExportPath, # The Zero Trust pillar to assess. Defaults to All. [ValidateSet('All', 'Identity', 'Devices')] [string] $Pillar = 'All' ) #region Utility Function function Get-RoleSelectSql { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string] $TableName, [Parameter(Mandatory = $true)] [string] $PrivilegeType, [switch] $AddUnion ) $sql = @" select rd.isPrivileged, cast(r."roleDefinitionId" as varchar) as roleDefinitionId, cast(r.principal.displayName as varchar) as principalDisplayName, rd.displayName as roleDisplayName, cast(r.principal.userPrincipalName as varchar) as userPrincipalName, cast(r.principal."@odata.type" as varchar) as "@odata.type", cast(r.principalId as varchar) as principalId, '$PrivilegeType' as privilegeType from main."$TableName" r left join main."RoleDefinition" rd on r."roleDefinitionId" = rd.id "@ if ($AddUnion) { $sql += 'union all' } return $sql } function New-ViewRole { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [DuckDB.NET.Data.DuckDBConnection] $Database ) $sql = @" create view vwRole as "@ $RoleAssignmentScheduleCountSql = 'select count(*) as RoleAssignmentScheduleCount from RoleAssignmentSchedule where id is not null' $result = Invoke-DatabaseQuery -Database $Database -Sql $RoleAssignmentScheduleCountSql if ($result.RoleAssignmentScheduleCount -gt 0) { # Is P2 tenant, don't read RoleAssignment because it contains PIM Eligible temporary users and has no way to filter it out. $sql += Get-RoleSelectSql -TableName 'RoleAssignmentSchedule' -PrivilegeType 'Permanent' -AddUnion } else { # Is Free or P1 tenant so we only have the RoleAssignment table to go on. $sql += Get-RoleSelectSql -TableName "RoleAssignment" -PrivilegeType 'Permanent' -AddUnion } # Now read RoleEligibilityScheduleRequest to get PIM Eligible users $sql += Get-RoleSelectSql -TableName "RoleEligibilityScheduleRequest" -PrivilegeType 'Eligible' Invoke-DatabaseQuery -Database $Database -Sql $sql -NonQuery } #endregion Utility Function # Nothing to do if the Pillar is Devices (for now) if ($Pillar -eq 'Devices') { Write-PSFMessage 'Skipping data export for Device pillar.' -Tag Import return } $activity = "Creating database" Write-ZtProgress -Activity $activity -Status "Starting" Write-PSFMessage "Importing data from $ExportPath" -Tag Import $dbFolderName = 'db' $dbFolder = Join-Path $ExportPath $dbFolderName $dbPath = Join-Path $ExportPath $dbFolderName "zt.db" if (Test-Path $dbFolder) { Write-PSFMessage "Clearing previous db $dbFolder" -Tag Import $database = Connect-Database -Path $dbPath -PassThru Invoke-DatabaseQuery -Database $database -Sql "FORCE CHECKPOINT;" -NonQuery Disconnect-Database -Database $database Remove-Item $dbFolder -Recurse -Force # Remove the existing database } $null = New-Item -ItemType Directory -Path $dbFolder -Force -ErrorAction Stop $database = Connect-Database -Path $dbPath -PassThru Import-EntraTable -Database $database -ExportPath $ExportPath -TableName 'User' Import-EntraTable -Database $database -ExportPath $ExportPath -TableName 'Application' Import-EntraTable -Database $database -ExportPath $ExportPath -TableName 'ServicePrincipal' Import-EntraTable -Database $database -ExportPath $ExportPath -TableName 'ServicePrincipalSignIn' Import-EntraTable -Database $database -ExportPath $ExportPath -TableName 'SignIn' Import-EntraTable -Database $database -ExportPath $ExportPath -TableName 'RoleDefinition' Import-EntraTable -Database $database -ExportPath $ExportPath -TableName 'RoleAssignment' Import-EntraTable -Database $database -ExportPath $ExportPath -TableName 'RoleAssignmentGroup' Import-EntraTable -Database $database -ExportPath $ExportPath -TableName 'RoleAssignmentSchedule' Import-EntraTable -Database $database -ExportPath $ExportPath -TableName 'RoleEligibilityScheduleRequest' Import-EntraTable -Database $database -ExportPath $ExportPath -TableName 'RoleEligibilityScheduleRequestGroup' Import-EntraTable -Database $database -ExportPath $ExportPath -TableName 'RoleManagementPolicyAssignment' Import-EntraTable -Database $database -ExportPath $ExportPath -TableName 'UserRegistrationDetails' New-ViewRole -Database $database $database } |