Beta release
This commit is contained in:
Mikael Karlsson
2021-10-17 14:02:08 +11:00
parent 5976b0bffd
commit 4add87884a
18 changed files with 959 additions and 107 deletions

View File

@@ -11,7 +11,7 @@ Objects can be compared based on Properties or Documentatation info.
function Get-ModuleVersion
{
'1.0.7'
'1.0.8'
}
function Invoke-InitializeModule
@@ -50,16 +50,16 @@ function Add-CompareProvider
if($global:compareProviders.Count -eq 0)
{
$global:compareProviders += [PSCustomObject]@{
Name = "Exported File"
Name = "Intune Objects with Exported Files"
Value = "export"
ObjectCompare = { Compare-ObjectsBasedonProperty @args }
BulkCompare = { Start-BulkCompareExportObjects @args }
ProviderOptions = "CompareExportOptions"
Activate = { Invoke-ActivateCompareExportObjects @args }
Activate = { Invoke-ActivateCompareWithExportObjects @args }
}
$global:compareProviders += [PSCustomObject]@{
Name = "Named Objects"
Name = "Named Objects in Intune"
Value = "name"
BulkCompare = { Start-BulkCompareNamedObjects @args }
ProviderOptions = "CompareNamedOptions"
@@ -67,6 +67,15 @@ function Add-CompareProvider
RemoveProperties = @("Id")
}
$global:compareProviders += [PSCustomObject]@{
Name = "Files in Exported Folders"
Value = "exportedFolders"
ObjectCompare = { Compare-ObjectsBasedonProperty @args }
BulkCompare = { Start-BulkCompareExportFolders @args }
ProviderOptions = "CompareExportedFilesOptions"
Activate = { Invoke-ActivateCompareExportedObjects @args }
}
$global:compareProviders += [PSCustomObject]@{
Name = "Existing objects"
Value = "existing"
@@ -269,7 +278,9 @@ function Set-CompareProviderOptions
}
}
function Invoke-ActivateCompareExportObjects
# Compare Intune object with exported folder
function Invoke-ActivateCompareWithExportObjects
{
param($providerOptions, $firstTime)
@@ -292,6 +303,39 @@ function Invoke-ActivateCompareExportObjects
}
}
# Compare two exported folders
function Invoke-ActivateCompareExportedObjects
{
param($providerOptions, $firstTime)
if($firstTime)
{
$path = Get-Setting "" "LastUsedFullPath"
if($path)
{
$path = [IO.Directory]::GetParent($path).FullName
}
Set-XamlProperty $providerOptions "txtExportPathSource" "Text" (?? $path (Get-SettingValue "RootFolder"))
Set-XamlProperty $providerOptions "txtExportPathCompare" "Text" (Get-SettingValue "ExportPathCompare")
Add-XamlEvent $providerOptions "browseExportPathSource" "add_click" ({
$folder = Get-Folder (Get-XamlProperty $this.Parent "txtExportPathSource" "Text") "Select root folder for source"
if($folder)
{
Set-XamlProperty $this.Parent "txtExportPathSource" "Text" $folder
}
})
Add-XamlEvent $providerOptions "browseExportPathCompare" "add_click" ({
$folder = Get-Folder (Get-XamlProperty $this.Parent "txtExportPathCompare" "Text") "Select folder to compare the source with"
if($folder)
{
Set-XamlProperty $this.Parent "txtExportPathCompare" "Text" $folder
}
})
}
}
function Invoke-ActivateCompareNamesObjects
{
param($providerOptions, $firstTime)
@@ -468,6 +512,8 @@ function Start-BulkCompareExportObjects
Write-Log "Start bulk Exported Objects compare"
Write-Log "****************************************************************"
$compareObjectsResult = @()
$txtNameFilter = (Get-XamlProperty $global:ccContentProviderOptions.Content "txtCompareNameFilter" "Text").Trim()
$rootFolder = (Get-XamlProperty $global:ccContentProviderOptions.Content "txtExportPath" "Text")
$compareProps = $script:defaultCompareProps
@@ -521,12 +567,20 @@ function Start-BulkCompareExportObjects
Write-Log "Object from file '$($fileObj.FullName)' has no Id property. Compare not supported" 2
continue
}
$objName = Get-GraphObjectName $fileObj.Object $fileObj.ObjectType
if($txtNameFilter -and $objName -notmatch [RegEx]::Escape($txtNameFilter))
{
continue
}
$curObject = $graphObjects | Where { $_.Object.Id -eq $fileObj.Object.Id }
if(-not $curObject)
{
# Add objects that are exported but deleted
Write-Log "Object '$((Get-GraphObjectName $fileObj.Object $fileObj.ObjectType))' with id $($fileObj.Object.Id) not found in Intune. Deleted?" 2
Write-Log "Object '$($objName)' with id $($fileObj.Object.Id) not found in Intune. Deleted?" 2
$compareProperties = @([PSCustomObject]@{
Object1Value = $null
Object2Value = (Get-GraphObjectName $fileObj.Object $item.ObjectType)
@@ -554,13 +608,19 @@ function Start-BulkCompareExportObjects
# Add objects that are not exported
if(($compareObjectsResult | Where { $_.Id -eq $graphObj.Id})) { continue }
$objName = Get-GraphObjectName $graphObj.Object $item.ObjectType
if($txtNameFilter -and $objName -notmatch [RegEx]::Escape($txtNameFilter))
{
continue
}
$compareObjectsResult += [PSCustomObject]@{
Object1 = $curObject.Object
Object2 = $null
ObjectType = $item.ObjectType
Id = $graphObj.Id
Result = @([PSCustomObject]@{
Object1Value = (Get-GraphObjectName $graphObj.Object $item.ObjectType)
Object1Value = $objName
Object2Value = $null
Match = $false
})
@@ -594,18 +654,18 @@ function Start-BulkCompareExportObjects
if($outputType -eq "objectType")
{
Save-BulkCompareResults $compResultValues (Join-Path $rootFolder "Compare_$(((Get-Date).ToString("yyyyMMdd-HHmm"))).csv") $compareProps
Save-BulkCompareResults $compResultValues (Join-Path $folder "Compare_$(((Get-Date).ToString("yyyyMMdd-HHmm"))).csv") $compareProps
}
}
else
{
Write-Log "Folder $folder not found. Skipping import" 2
Write-Log "Folder $folder not found. Skipping compare" 2
}
}
if($outputType -eq "all" -and $compResultValues.Count -gt 0)
{
Save-BulkCompareResults $compResultValues (Join-Path $folder "Compare_$(((Get-Date).ToString("yyyyMMDD-HHmm"))).csv") $compareProps
Save-BulkCompareResults $compResultValues (Join-Path $rootFolder "Compare_$(((Get-Date).ToString("yyyyMMDD-HHmm"))).csv") $compareProps
}
Write-Log "****************************************************************"
@@ -618,6 +678,185 @@ function Start-BulkCompareExportObjects
}
}
function Start-BulkCompareExportFolders
{
Write-Log "****************************************************************"
Write-Log "Start bulk Exported Folders compare"
Write-Log "****************************************************************"
$compareObjectsResult = @()
$txtNameFilter = (Get-XamlProperty $global:ccContentProviderOptions.Content "txtCompareNameFilter" "Text").Trim()
$rootFolderSource = (Get-XamlProperty $global:ccContentProviderOptions.Content "txtExportPathSource" "Text")
$rootFolderCompare = (Get-XamlProperty $global:ccContentProviderOptions.Content "txtExportPathCompare" "Text")
$compareProps = $script:defaultCompareProps
foreach($removeProp in $global:cbCompareProvider.SelectedItem.RemoveProperties)
{
$compareProps.Remove($removeProp) | Out-Null
}
foreach($removeProp in $global:cbCompareType.SelectedItem.RemoveProperties)
{
$compareProps.Remove($removeProp) | Out-Null
}
if(-not $rootFolderSource -or -not $rootFolderCompare)
{
[System.Windows.MessageBox]::Show("Both folders must be specified", "Error", "OK", "Error")
return
}
if([IO.Directory]::Exists($rootFolderSource) -eq $false)
{
[System.Windows.MessageBox]::Show("Root folder $rootFolderSource does not exist", "Error", "OK", "Error")
return
}
if([IO.Directory]::Exists($rootFolderCompare) -eq $false)
{
[System.Windows.MessageBox]::Show("Root folder $rootFolderCompare does not exist", "Error", "OK", "Error")
return
}
$outputType = $global:cbCompareSave.SelectedValue
Save-Setting "Compare" "SaveType" $outputType
$compResultValues = @()
foreach($item in ($global:dgObjectsToCompare.ItemsSource | where Selected -eq $true))
{
Write-Status "Compare $($item.ObjectType.Title) objects" -Force -SkipLog
Write-Log "----------------------------------------------------------------"
Write-Log "Compare $($item.ObjectType.Title) objects"
Write-Log "----------------------------------------------------------------"
$folderSource = Join-Path $rootFolderSource $item.ObjectType.Id
$folderCompare = Join-Path $rootFolderCompare $item.ObjectType.Id
if([IO.Directory]::Exists($folderSource))
{
Save-Setting "" "LastUsedFullPath" $folderSource
$fileCompareObjs = @(Get-GraphFileObjects $folderCompare -ObjectType $item.ObjectType)
foreach ($fileSourceObj in @(Get-GraphFileObjects $folderSource -ObjectType $item.ObjectType))
{
$objName = Get-GraphObjectName $fileSourceObj.Object $item.ObjectType
if($txtNameFilter -and $objName -notmatch [RegEx]::Escape($txtNameFilter))
{
continue
}
if(-not $fileSourceObj.Object.Id)
{
Write-Log "Object from file '$($fileSourceObj.FullName)' has no Id property. Compare not supported" 2
continue
}
$compareObject = $fileCompareObjs | Where { $_.Object.Id -eq $fileSourceObj.Object.Id }
if(-not $compareObject)
{
# Add objects that are exported but deleted
Write-Log "Object '$($objName)' with id $($fileSourceObj.Object.Id) not found in Intune. Deleted?" 2
$compareProperties = @([PSCustomObject]@{
Object1Value = $null
Object2Value = (Get-GraphObjectName $fileSourceObj.Object $fileSourceObj.ObjectType)
Match = $false
})
}
else
{
$fileSourceObj.Object | Add-Member Noteproperty -Name "@ObjectFromFile" -Value $true -Force
$compareObject.Object | Add-Member Noteproperty -Name "@ObjectFromFile" -Value $true -Force
$compareProperties = Compare-Objects $compareObject.Object $fileSourceObj.Object $item.ObjectType
}
$compareObjectsResult += [PSCustomObject]@{
Object1 = $compareObject.Object
Object2 = $fileSourceObj.Object
ObjectType = $item.ObjectType
Id = $fileSourceObj.Object.Id
Result = $compareProperties
}
}
foreach($fileCompareObj in $fileCompareObjs)
{
# Add objects that were not exported in source folder
if(($compareObjectsResult | Where { $_.Id -eq $fileCompareObj.Object.Id})) { continue }
$objName = Get-GraphObjectName $fileCompareObj.Object $item.ObjectType
if($txtNameFilter -and $objName -notmatch [RegEx]::Escape($txtNameFilter))
{
continue
}
$compareObjectsResult += [PSCustomObject]@{
Object1 = $fileCompareObj.Object
Object2 = $null
ObjectType = $item.ObjectType
Id = $fileCompareObj.Object.Id
Result = @([PSCustomObject]@{
Object1Value = (Get-GraphObjectName $fileCompareObj.Object $item.ObjectType)
Object2Value = $null
Match = $false
})
}
}
if($outputType -eq "objectType")
{
$compResultValues = @()
}
foreach($compObj in @($compareObjectsResult | Where { $_.ObjectType.Id -eq $item.ObjectType.Id }))
{
$objName = Get-GraphObjectName (?? $compObj.Object1 $compObj.Object2) $item.ObjectType
foreach($compValue in $compObj.Result)
{
$compResultValues += [PSCustomObject]@{
ObjectName = $objName
Id = $compObj.Id
Type = $compObj.ObjectType.Title
ODataType = $compObj.Object1.'@OData.Type'
Property = $compValue.PropertyName
Value1 = $compValue.Object1Value
Value2 = $compValue.Object2Value
Category = $compValue.Category
SubCategory = $compValue.SubCategory
Match = $compValue.Match
}
}
}
if($outputType -eq "objectType")
{
Save-BulkCompareResults $compResultValues (Join-Path $folderSource "Compare_$(((Get-Date).ToString("yyyyMMdd-HHmm"))).csv") $compareProps
}
}
else
{
Write-Log "Folder $folderSource not found. Skipping compare" 2
}
}
if($outputType -eq "all" -and $compResultValues.Count -gt 0)
{
Save-BulkCompareResults $compResultValues (Join-Path $rootFolderSource "Compare_$(((Get-Date).ToString("yyyyMMDD-HHmm"))).csv") $compareProps
}
Write-Log "****************************************************************"
Write-Log "Bulk compare Exported Folders finished"
Write-Log "****************************************************************"
Write-Status ""
if($compareObjectsResult.Count -eq 0)
{
[System.Windows.MessageBox]::Show("No objects were comparced. Verify folder and exported files", "Error", "OK", "Error")
}
}
function Save-BulkCompareResults
{
param($compResultValues, $file, $props)
@@ -1064,6 +1303,11 @@ function Compare-ObjectsBasedonDocumentation
$val1 = $prop.$settingsValue
$prop2 = $docObj2.Settings | Where { $_.EntityKey -eq $prop.EntityKey -and $_.Category -eq $prop.Category -and $_.SubCategory -eq $prop.SubCategory -and $_.Enabled -eq $prop.Enabled }
$val2 = $prop2.$settingsValue
if($val1 -isnot [array] -and $val2 -is [array] -and $val2.Count -gt 1)
{
Write-Log "Multiple compare results returend for $($prop.Name). Using first result" 2
$val2 = $val2[0]
}
Add-CompareProperty $prop.Name $val1 $val2 $prop.Category $prop.SubCategory
}
@@ -1075,7 +1319,13 @@ function Compare-ObjectsBasedonDocumentation
$addedProperties += ($prop.EntityKey + $prop.Category + $prop.SubCategory)
$val2 = $prop.$settingsValue
$prop2 = $docObj1.Settings | Where { $_.EntityKey -eq $prop.EntityKey -and $_.Category -eq $prop.Category -and $_.SubCategory -eq $prop.SubCategory -and $_.Enabled -eq $prop.Enabled }
$val1 = $prop2.$settingsValue
$val1 = $prop2.$settingsValue
if($val2 -isnot [array] -and $val1 -is [array] -and $val1.Count -gt 1)
{
Write-Log "Multiple compare results returend for $($prop.Name). Using first result" 2
$val1 = $val1[0]
}
Add-CompareProperty $prop.Name $val1 $val2 $prop.Category $prop.SubCategory
}
}

View File

@@ -3,7 +3,7 @@
#https://docs.microsoft.com/en-us/office/vba/api/overview/word
function Get-ModuleVersion
{
'1.0.4'
'1.0.5'
}
function Invoke-InitializeModule
@@ -117,6 +117,7 @@ function Invoke-WordPreProcessItems
Save-Setting "Documentation" "WordExportProperties" $global:cbWordDocumentationProperties.SelectedValue
Save-Setting "Documentation" "WordCustomDisplayProperties" $global:txtWordCustomProperties.Text
Save-Setting "Documentation" "WordDocumentTemplate" $global:txtWordDocumentTemplate.Text
Save-Setting "Documentation" "WordDocumentName" $global:txtWordDocumentName.Text
Save-Setting "Documentation" "WordAddCategories" $global:chkWordAddCategories.IsChecked
Save-Setting "Documentation" "WordAddSubCategories" $global:chkWordAddSubCategories.IsChecked

View File

@@ -9,7 +9,7 @@ Module for listing Intune assignments
#>
function Get-ModuleVersion
{
'1.0.1'
'1.0.2'
}
function Invoke-InitializeModule
@@ -170,6 +170,7 @@ function Get-EMIntuneAssignments
}
else
{
$assignmentObj = $assignment.target.groupId
Write-Warning "Could not find a group with ID $($assignment.target.groupId)"
}
$included = $assignment.target.'@odata.type' -eq "#microsoft.graph.groupAssignmentTarget"

View File

@@ -10,7 +10,7 @@ This module manages Authentication for the application with MSAL. It is also res
#>
function Get-ModuleVersion
{
'3.0.5'
'3.3.0'
}
$global:msalAuthenticator = $null
@@ -18,10 +18,28 @@ function Invoke-InitializeModule
{
$script:MSALAllApps = @()
$global:MSALToken = $null
$global:MSALAuthority = $null
$global:MSALTenantId = $null
$script:AccessableTenants = $null
$global:SkipTokenCacheHelperEx = $null
$script:lstAADEnvironments = @(
[PSCustomObject]@{
Name = "Azure AD Public"
Value = "public"
URL = "login.microsoftonline.com"
},
[PSCustomObject]@{
Name = "Azure AD US Government"
Value = "usGov"
URL = "login.microsoftonline.us"
},
[PSCustomObject]@{
Name = "Azure AD China"
Value = "china"
URL = "login.partner.microsoftonline.cn"
}
)
$global:appSettingSections += (New-Object PSObject -Property @{
Title = "MSAL"
Id = "MSAL"
@@ -68,6 +86,14 @@ function Invoke-InitializeModule
Description = "Request Azure AD Role read permission when getting the token. This can be use to resolve the SIDs to Azure Roles for the wids property on the Access Token. Note: This might trigger a consent prompt"
}) "MSAL"
Add-SettingsObject (New-Object PSObject -Property @{
Title = "Azure Login"
Key = "AzureLogin"
Type = "List"
ItemsSource = $script:lstAADEnvironments
DefaultValue = "public"
}) "MSAL"
Add-MSALPrereq
#$script:MSALDLLMissing = $true #!!!!
@@ -91,9 +117,19 @@ function Get-MSALAuthenticationObject
$global:msalAuthenticator
}
function Invoke-SettingsUpdated
{
Initialize-MSALSettings
}
function Initialize-MSALSettings
{
}
function Clear-MSALCurentUserVaiables
{
$global:MSALAuthority = $null
$global:MSALTenantId = $null
}
function Get-MSALCurrentApp
@@ -485,19 +521,42 @@ function Get-MsalAuthenticationToken
$authResult
}
function Get-MSALLoginEnvironment
{
$loginValue = Get-SettingValue "AzureLogin" "public"
$loginEnv = $script:lstAADEnvironments | Where value -eq $loginValue
return (?? $loginEnv.Environment "login.microsoftonline.com")
}
function Get-MSALApp
{
param($appInfo)
param($appInfo, $loginHint)
$msalApp = $script:MSALAllApps | Where { $_.ClientId -eq $appInfo.ClientID -and (-not $appInfo.RedirectUri -or $_.AppConfig.RedirectUri -eq $appInfo.RedirectUri)}
if(-not $msalApp)
$tenant = ?? $appInfo.TenantId "organizations"
if($loginHint.Environment)
{
Write-Log "Add MSAL App $($appInfo.ClientID) $((?? $appInfo.TenantId $appInfo.Authority))"
$authority = "https://$($loginHint.Environment)/$tenant/"
}
elseif($appInfo.Authority)
{
$authority = $appInfo.Authority
}
else
{
$authority = "https://$((Get-MSALLoginEnvironment))/$tenant/"
}
if(-not $msalApp -or $msalApp.Authority -ne $authority)
{
Write-Log "Add MSAL App $($appInfo.ClientID) $authority"
$appBuilder = [Microsoft.Identity.Client.PublicClientApplicationBuilder]::Create($appInfo.ClientID)
if($appInfo.TenantId) { [void]$appBuilder.WithAuthority("https://login.microsoftonline.com/$($appInfo.TenantId)/") }
elseif ($appInfo.Authority) { [void]$appBuilder.WithAuthority($appInfo.Authority) }
[void]$appBuilder.WithAuthority($authority)
#if($appInfo.TenantId) { [void]$appBuilder.WithAuthority("https://$((?? $loginHint.Environment (Get-MSALLoginEnvironment)))/$($appInfo.TenantId)/") }
#elseif ($appInfo.Authority) { [void]$appBuilder.WithAuthority($appInfo.Authority) }
if($appInfo.RedirectUri) { [void]$appBuilder.WithRedirectUri($appInfo.RedirectUri) }
[void] $appBuilder.WithClientName("CloudAPIPowerShellManagement")
@@ -514,6 +573,18 @@ function Get-MSALApp
return $msalApp
}
function Get-MSALAppAuthority
{
try
{
([uri]$global:MSALApp.Authority).Authority
}
catch
{
Get-MSALLoginEnvironment
}
}
function Connect-MSALUser
{
param(
@@ -529,7 +600,9 @@ function Connect-MSALUser
[switch]
$Interactive,
$Account
$Account,
$Tenant
)
# No login during first time the app is started
@@ -543,11 +616,10 @@ function Connect-MSALUser
return
}
if(-not $global:appObj.TenantId -and -not $global:appObj.Authority)
{
Write-Log "Tenant id/Authority is missing. Cannot authenticate" 3
return
}
#if(-not $global:appObj.TenantId -and -not $global:appObj.Authority)
#{
# Write-Log "Tenant id/Authority is missing. Cannot authenticate" 3
#}
if ($global:SkipTokenCacheHelperEx -ne $true -and -not ("TokenCacheHelperEx" -as [type]))
{
@@ -598,20 +670,21 @@ function Connect-MSALUser
$Scopes = [String[]]$reqScopes
}
$global:MSALApp = Get-MSALApp $global:appObj
$global:MSALApp = Get-MSALApp $global:appObj $Account
$loginHint = ""
$global:MSALAccounts = $global:MSALApp.GetAccountsAsync().GetAwaiter().GetResult()
if($Account)
{
$loginHint = $global:MSALAccounts | Where UserName -eq $Account
if($global:MSALToken -and $global:MSALToken.Account.UserName -ne $Account)
$userName = ?? $Account.UserName $Account
$loginHint = $global:MSALAccounts | Where UserName -eq $userName
if($global:MSALToken -and $global:MSALToken.Account.UserName -ne $userName)
{
# We're logging in with someone else...
Clear-MSALCurentUserVaiables
}
}
# If we force interactive login the skip setting loginHint to force the user select account
if(-not $loginHint -and $Interactive -ne $true)
{
@@ -640,8 +713,8 @@ function Connect-MSALUser
$prompConsent = $false
$authResult = $null
$tenantId = $global:appObj.TenantId
$authority = ?? $global:MSALAuthority $global:appObj.Authority
$tenantId = ?? $global:MSALTenantId $global:appObj.TenantId
#$authority = ?? $global:MSALApp.Authority $global:appObj.Authority
try
{
@@ -652,8 +725,8 @@ function Connect-MSALUser
{
$aquireTokenObj = $global:MSALApp.AcquireTokenSilent($Scopes, $loginHint)
if($ForceRefresh) { [void]$aquireTokenObj.WithForceRefresh($ForceRefresh) }
if ($tenantId) { [void] $aquireTokenObj.WithAuthority("https://login.microsoftonline.com/$($TenantId)/") }
if ($authority) { [void]$aquireTokenObj.WithAuthority($authority) }
if ($tenantId) { [void]$aquireTokenObj.WithAuthority("https://$((Get-MSALAppAuthority))/$($tenantId)/") }
else { [void]$aquireTokenObj.WithAuthority($global:MSALApp.Authority) }
$authResult = Get-MsalAuthenticationToken $aquireTokenObj
@@ -709,7 +782,10 @@ function Connect-MSALUser
}
}
}
catch {}
catch
{
Write-LogError "Failed to perform silent login" $_.Exception
}
# Interactive login is only allowed once the app has started. Skip if silent login failed during startup
if($global:MainAppStarted -and ((-not $authResult -and $Silent -ne $true) -or $prompConsent))
@@ -726,12 +802,12 @@ function Connect-MSALUser
if ($tenantId)
{
Write-Log "Tenant id: $tenantId"
[void] $aquireTokenObj.WithAuthority("https://login.microsoftonline.com/$tenantId)/")
[void]$aquireTokenObj.WithAuthority("https://$((Get-MSALAppAuthority))/$tenantId/")
}
elseif ($authority)
else
{
Write-Log "Authority: $authority"
[void]$aquireTokenObj.WithAuthority($authority)
Write-Log "Authority: $($global:MSALApp.Authority)"
[void]$aquireTokenObj.WithAuthority($global:MSALApp.Authority)
}
if($loginHintName)
@@ -786,8 +862,8 @@ function Connect-MSALUser
# Can we reuse the app used for login?
$appBuilder = [Microsoft.Identity.Client.PublicClientApplicationBuilder]::Create($global:appObj.ClientID)
if($tenantId) { [void]$appBuilder.WithAuthority("https://login.microsoftonline.com/$($tenantId)") }
elseif ($authority) { [void]$appBuilder.WithAuthority($authority) }
if($tenantId) { [void]$appBuilder.WithAuthority("https://$((Get-MSALAppAuthority))/$($tenantId)") }
else { [void]$appBuilder.WithAuthority($global:MSALApp.Authority) }
if($global:appObj.RedirectUri) { [void]$appBuilder.WithRedirectUri($global:appObj.RedirectUri) }
$app = $appBuilder.Build()
@@ -977,7 +1053,7 @@ function Get-MSALProfileEllipse
Write-Status "Logging in with $($this.Tag.UserName)"
Hide-Popup
Clear-MSALCurentUserVaiables
Connect-MSALUser -Account $this.Tag.UserName
Connect-MSALUser -Account $this.Tag #!!!.UserName
if($global:curObjectType)
{
@@ -1200,7 +1276,7 @@ function Get-MSALProfileEllipse
Write-Status "Logging in with $($this.Tag.UserName)"
Hide-Popup
Clear-MSALCurentUserVaiables
Connect-MSALUser -Account $this.Tag.UserName
Connect-MSALUser -Account $this.Tag #!!!.UserName
if($global:curObjectType)
{
@@ -1311,9 +1387,9 @@ function Get-MSALProfileEllipse
$lnkButton.add_Click({
Write-Status "Logging in to $($this.Tag.DisplayName)"
# Set authority to selected tenant
$global:MSALAuthority = "https://login.microsoftonline.com/$($this.Tag.tenantId)/"
Hide-Popup
Connect-MSALUser -Account $global:MSALToken.Account.Username
$global:MSALTenantId = $this.Tag.tenantId
Hide-Popup
Connect-MSALUser -Account ($global:MSALAccounts | Where UserName -eq $global:MSALToken.Account.Username)
if($global:curObjectType)
{

View File

@@ -10,13 +10,14 @@ This module manages Microsoft Grap fuctions like calling APIs, managing graph ob
#>
function Get-ModuleVersion
{
'3.1.7'
'3.1.8'
}
$global:MSGraphGlobalApps = @(
#Authority="https://login.microsoftonline.com/organizations/"
(New-Object PSObject -Property @{Name="";ClientId="";RedirectUri="";Authority=""}),
(New-Object PSObject -Property @{Name="Microsoft Intune PowerShell";ClientId="d1ddf0e4-d672-4dae-b554-9d5bdfd93547";RedirectUri="urn:ietf:wg:oauth:2.0:oob";Authority="https://login.microsoftonline.com/organizations/"}),
(New-Object PSObject -Property @{Name="Microsoft Graph PowerShell";ClientId="14d82eec-204b-4c2f-b7e8-296a70dab67e";RedirectUri="https://login.microsoftonline.com/common/oauth2/nativeclient";Authority="https://login.microsoftonline.com/organizations/"})
(New-Object PSObject -Property @{Name="Microsoft Intune PowerShell";ClientId="d1ddf0e4-d672-4dae-b554-9d5bdfd93547";RedirectUri="urn:ietf:wg:oauth:2.0:oob"; }),
(New-Object PSObject -Property @{Name="Microsoft Graph PowerShell";ClientId="14d82eec-204b-4c2f-b7e8-296a70dab67e";RedirectUri="https://login.microsoftonline.com/common/oauth2/nativeclient";})
)
function Invoke-InitializeModule
@@ -150,6 +151,15 @@ function Invoke-InitializeModule
DefaultValue = $false
Description = "This will enable the option to update/replace an existing object during import"
}) "ImportExport"
Add-SettingsObject (New-Object PSObject -Property @{
Title = "Add ID to export file"
Key = "AddIDToExportFile"
Type = "Boolean"
DefaultValue = $false
Description = "This will add object ID to the export file to support objects with the same name e.g. ObjectName_ObjectId.json"
}) "ImportExport"
}
function Get-GraphAppInfo
@@ -192,6 +202,16 @@ function Invoke-GraphAuthenticationUpdated
$global:migFileObj = $null
}
function Invoke-SettingsUpdated
{
Initialize-GraphSettings
}
function Initialize-GraphSettings
{
}
function Invoke-GraphRequest
{
param (
@@ -296,7 +316,7 @@ function Invoke-GraphRequest
{
# Code to test paging - Force each page to size specified in top parameter below
# Kept for reference
if(($url.IndexOf('?')) -eq -1)
{
$url = "$($url.Trim())?"
@@ -844,7 +864,8 @@ function Show-GraphBulkExportForm
Set-XamlProperty $script:exportForm "txtExportPath" "Text" (?? (Get-Setting "" "LastUsedRoot") (Get-SettingValue "RootFolder"))
Set-XamlProperty $script:exportForm "chkAddCompanyName" "IsChecked" (Get-SettingValue "AddCompanyName")
Set-XamlProperty $script:exportForm "chkExportAssignments" "IsChecked" (Get-SettingValue "ExportAssignments")
Set-XamlProperty $script:exportForm "chkExportAssignments" "IsChecked" (Get-SettingValue "ExportAssignments")
#Set-XamlProperty $script:exportForm "txtExportNameFilter" "Text" (Get-Setting "" "ExportNameFilter")
Add-XamlEvent $script:exportForm "browseExportPath" "add_click" ({
$folder = Get-Folder (Get-XamlProperty $script:exportForm "txtExportPath" "Text") "Select root folder for export"
@@ -903,6 +924,9 @@ function Show-GraphBulkExportForm
Write-Log "****************************************************************"
Write-Log "Start bulk export"
Write-Log "****************************************************************"
$global:AADObjectCache = $null
foreach($item in $script:exportObjects)
{
if($item.Selected -ne $true) { continue }
@@ -911,6 +935,10 @@ function Show-GraphBulkExportForm
Write-Log "Export $($item.ObjectType.Title) objects"
Write-Log "----------------------------------------------------------------"
$txtNameFilter = $global:txtExportNameFilter.Text.Trim()
Save-Setting "" "ExportNameFilter" $txtNameFilter
if($txtNameFilter) { Write-Log "Name filter: $txtNameFilter" }
try
{
$folder = Get-GraphObjectFolder $item.ObjectType (Get-XamlProperty $script:exportForm "txtExportPath" "Text") (Get-XamlProperty $script:exportForm "chkAddObjectType" "IsChecked") (Get-XamlProperty $script:exportForm "chkAddCompanyName" "IsChecked")
@@ -918,7 +946,14 @@ function Show-GraphBulkExportForm
$objects = @(Get-GraphObjects -property $item.ObjectType.ViewProperties -objectType $item.ObjectType)
foreach($obj in $objects)
{
Write-Status "Export $($item.Title): $((Get-GraphObjectName $obj.Object $obj.ObjectType))" -Force
$objName = Get-GraphObjectName $obj.Object $obj.ObjectType
if($txtNameFilter -and $objName -notmatch [RegEx]::Escape($txtNameFilter))
{
continue
}
Write-Status "Export $($item.Title): $objName" -Force
Export-GraphObject $obj.Object $item.ObjectType $folder
}
Save-Setting "" "LastUsedFullPath" $folder
@@ -1064,7 +1099,8 @@ function Show-GraphBulkImportForm
Set-XamlProperty $script:importForm "chkImportScopes" "IsChecked" (Get-SettingValue "ImportScopeTags")
Set-XamlProperty $script:importForm "cbImportType" "ItemsSource" $script:lstImportTypes
Set-XamlProperty $script:importForm "cbImportType" "SelectedValue" (Get-SettingValue "ImportType" "alwaysImport")
#Set-XamlProperty $script:importForm "txtImportNameFilter" "Text" (Get-Setting "" "ImportNameFilter")
if((Get-SettingValue "AllowUpdate") -eq $true)
{
Set-XamlProperty $script:importForm "lblImportType" "Visibility" "Visible"
@@ -1140,6 +1176,10 @@ function Show-GraphBulkImportForm
Get-GraphDependencyDefaultObjects
$importedObjects = 0
$txtNameFilter = $global:txtImportNameFilter.Text.Trim()
Save-Setting "" "ImportNameFilter" $txtNameFilter
if($txtNameFilter) { Write-Log "Name filter: $txtNameFilter" }
$allowUpdate = ((Get-SettingValue "AllowUpdate") -eq $true)
foreach($item in ($script:importObjects | where Selected -eq $true | sort-object -property @{e={$_.ObjectType.ImportOrder}}))
@@ -1172,6 +1212,13 @@ function Show-GraphBulkImportForm
foreach ($fileObj in @($filesToImport))
{
$objName = Get-GraphObjectName $fileObj.Object $item.ObjectType
if($txtNameFilter -and $objName -notmatch [RegEx]::Escape($txtNameFilter))
{
continue
}
if($allowUpdate -and $global:cbImportType.SelectedValue -ne "alwaysImport" -and $graphObjects -and (Reset-GraphObjet $fileObj $graphObjects))
{
$importedObjects++
@@ -1274,6 +1321,8 @@ function Show-GraphBulkDeleteForm
$script:deleteForm = Get-XamlObject ($global:AppRootFolder + "\Xaml\BulkDeleteForm.xaml") -AddVariables
if(-not $script:deleteForm) { return }
Set-XamlProperty $script:deleteForm "txtDeleteNameFilter" "Text" (Get-Setting "" "txtDeleteNameFilter")
$script:deleteObjects = @()
foreach($objType in $global:lstMenuItems.ItemsSource)
{
@@ -1343,13 +1392,24 @@ function Show-GraphBulkDeleteForm
Write-Log "Delete $($item.ObjectType.Title) objects"
Write-Log "----------------------------------------------------------------"
$txtNameFilter = $global:txtDeleteNameFilter.Text.Trim()
Save-Setting "" "DeleteNameFilter" $txtNameFilter
if($txtNameFilter) { Write-Log "Name filter: $txtNameFilter" }
try
{
Write-Status "Get $($item.Title) objects" -Force
$objects = @(Get-GraphObjects -property $item.ObjectType.ViewProperties -objectType $item.ObjectType)
foreach($obj in $objects)
{
Write-Status "Delete $($item.Title): $((Get-GraphObjectName $obj.Object $obj.ObjectType))" -Force
$objName = Get-GraphObjectName $obj.Object $obj.ObjectType
if($txtNameFilter -and $objName -notmatch [RegEx]::Escape($txtNameFilter))
{
continue
}
Write-Status "Delete $($item.Title): $objName" -Force -SkipLog
Remove-GraphObject $obj.Object $obj.ObjectType $folder
}
}
@@ -1875,7 +1935,7 @@ function Add-GraphMigrationObject
$global:migFileObj = $null
}
if(-not $global:migFileObj)
if(-not $global:migFileObj -or ([IO.File]::Exists($migFileName) -eq $false))
{
if(-not ([IO.File]::Exists($migFileName)))
{
@@ -2238,7 +2298,13 @@ function Export-GraphObject
Remove-Property $obj "Assignments"
}
$obj | ConvertTo-Json -Depth 20 | Out-File -LiteralPath ([IO.Path]::Combine($exportFolder, (Remove-InvalidFileNameChars "$((Get-GraphObjectName $obj $objectType)).json"))) -Force
$fileName = Get-GraphObjectName $obj $objectType
if((Get-SettingValue "AddIDToExportFile") -eq $true -and $obj.Id)
{
$fileName = ($fileName + "_" + $obj.Id)
}
$obj | ConvertTo-Json -Depth 20 | Out-File -LiteralPath ([IO.Path]::Combine($exportFolder, (Remove-InvalidFileNameChars "$($fileName).json"))) -Force
if($objectType.PostExportCommand)
{