3.3.0
Beta release
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user