Add browser auth for headless runs
This commit is contained in:
Binary file not shown.
Binary file not shown.
10
Core.psm1
10
Core.psm1
@@ -63,6 +63,16 @@ function Start-CoreApp
|
|||||||
|
|
||||||
Invoke-ModuleFunction "Invoke-InitializeModule"
|
Invoke-ModuleFunction "Invoke-InitializeModule"
|
||||||
|
|
||||||
|
if($View)
|
||||||
|
{
|
||||||
|
$global:currentViewObject = $global:viewObjects | Where-Object { $_.ViewInfo.Id -eq $View } | Select-Object -First 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if(-not $global:currentViewObject)
|
||||||
|
{
|
||||||
|
$global:currentViewObject = $global:viewObjects | Select-Object -First 1
|
||||||
|
}
|
||||||
|
|
||||||
if(-not $global:SilentBatchFile)
|
if(-not $global:SilentBatchFile)
|
||||||
{
|
{
|
||||||
Write-Log "SilentBatchFile must be specified" 3
|
Write-Log "SilentBatchFile must be specified" 3
|
||||||
|
|||||||
@@ -563,6 +563,14 @@ function Add-MSALPrereq
|
|||||||
}
|
}
|
||||||
$RequiredAssemblies.Add('System.Security.dll')
|
$RequiredAssemblies.Add('System.Security.dll')
|
||||||
$RequiredAssemblies.Add('mscorlib.dll')
|
$RequiredAssemblies.Add('mscorlib.dll')
|
||||||
|
if($PSVersionTable.PSVersion.Major -ge 7)
|
||||||
|
{
|
||||||
|
$netStandardAssembly = [AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GetName().Name -eq "netstandard" } | Select-Object -First 1
|
||||||
|
if($netStandardAssembly -and $netStandardAssembly.Location)
|
||||||
|
{
|
||||||
|
$RequiredAssemblies.Add($netStandardAssembly.Location)
|
||||||
|
}
|
||||||
|
}
|
||||||
if($PSVersionTable.PSVersion.Major -ge 7) {
|
if($PSVersionTable.PSVersion.Major -ge 7) {
|
||||||
$RequiredAssemblies.Add('System.Security.Cryptography.ProtectedData.dll')
|
$RequiredAssemblies.Add('System.Security.Cryptography.ProtectedData.dll')
|
||||||
}
|
}
|
||||||
@@ -574,6 +582,7 @@ function Add-MSALPrereq
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
$global:SkipTokenCacheHelperEx = $true
|
||||||
Write-LogError "Failed to compile TokenCacheHelperEx. The access token will not be cached. Check write access to the CS folder and ASR policies" $_.Exception
|
Write-LogError "Failed to compile TokenCacheHelperEx. The access token will not be cached. Check write access to the CS folder and ASR policies" $_.Exception
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -732,7 +741,10 @@ function Add-MSALPrereq_old
|
|||||||
$global:SkipTokenCacheHelperEx = $true
|
$global:SkipTokenCacheHelperEx = $true
|
||||||
Write-LogError "Failed to compile TokenCacheHelperEx. The access token will not be cached. Check write access to the CS folder and ASR policies" $_.Exception
|
Write-LogError "Failed to compile TokenCacheHelperEx. The access token will not be cached. Check write access to the CS folder and ASR policies" $_.Exception
|
||||||
}
|
}
|
||||||
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
|
if(Test-IsWindowsPlatform)
|
||||||
|
{
|
||||||
|
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Connect-MSALClientApp
|
function Connect-MSALClientApp
|
||||||
@@ -931,7 +943,14 @@ function Get-MSALApp
|
|||||||
|
|
||||||
[void]$appBuilder.WithAuthority($authority)
|
[void]$appBuilder.WithAuthority($authority)
|
||||||
|
|
||||||
if($appInfo.RedirectUri) { [void]$appBuilder.WithRedirectUri($appInfo.RedirectUri) }
|
if($appInfo.RedirectUri)
|
||||||
|
{
|
||||||
|
[void]$appBuilder.WithRedirectUri($appInfo.RedirectUri)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[void]$appBuilder.WithDefaultRedirectUri()
|
||||||
|
}
|
||||||
|
|
||||||
[void] $appBuilder.WithClientName("CloudAPIPowerShellManagement")
|
[void] $appBuilder.WithClientName("CloudAPIPowerShellManagement")
|
||||||
[void] $appBuilder.WithClientVersion($PSVersionTable.PSVersion)
|
[void] $appBuilder.WithClientVersion($PSVersionTable.PSVersion)
|
||||||
@@ -952,7 +971,7 @@ function Get-MSALApp
|
|||||||
|
|
||||||
$msalApp = $appBuilder.Build()
|
$msalApp = $appBuilder.Build()
|
||||||
|
|
||||||
if($global:SkipTokenCacheHelperEx -ne $true -and (Get-SettingValue "CacheMSALToken"))
|
if($global:SkipTokenCacheHelperEx -ne $true -and ("TokenCacheHelperEx" -as [type]) -and (Get-SettingValue "CacheMSALToken"))
|
||||||
{
|
{
|
||||||
[TokenCacheHelperEx]::EnableSerialization($msalApp.UserTokenCache, (Join-Path (Get-CloudApiDataFolder) "msalcahce.bin3"))
|
[TokenCacheHelperEx]::EnableSerialization($msalApp.UserTokenCache, (Join-Path (Get-CloudApiDataFolder) "msalcahce.bin3"))
|
||||||
}
|
}
|
||||||
@@ -961,6 +980,53 @@ function Get-MSALApp
|
|||||||
return $msalApp
|
return $msalApp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Get-HeadlessPublicClientAppInfo
|
||||||
|
{
|
||||||
|
$appObj = $null
|
||||||
|
|
||||||
|
if($global:MSGraphGlobalApps)
|
||||||
|
{
|
||||||
|
$templateApp = $global:MSGraphGlobalApps | Where-Object ClientId -eq $global:AzureAppId | Select-Object -First 1
|
||||||
|
if($templateApp)
|
||||||
|
{
|
||||||
|
$appObj = [PSCustomObject]@{
|
||||||
|
Name = $templateApp.Name
|
||||||
|
ClientId = $templateApp.ClientId
|
||||||
|
RedirectUri = $templateApp.RedirectUri
|
||||||
|
Authority = $templateApp.Authority
|
||||||
|
TenantId = $global:TenantId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(-not $appObj)
|
||||||
|
{
|
||||||
|
$appObj = [PSCustomObject]@{
|
||||||
|
Name = "Headless Browser Login"
|
||||||
|
ClientId = $global:AzureAppId
|
||||||
|
RedirectUri = $null
|
||||||
|
Authority = $null
|
||||||
|
TenantId = $global:TenantId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif($appObj.RedirectUri -and $appObj.RedirectUri -notmatch '^http://localhost(:\d+)?/?$')
|
||||||
|
{
|
||||||
|
$appObj.RedirectUri = $null
|
||||||
|
}
|
||||||
|
|
||||||
|
if($global:MSALRedirectUri)
|
||||||
|
{
|
||||||
|
$appObj.RedirectUri = $global:MSALRedirectUri
|
||||||
|
}
|
||||||
|
|
||||||
|
if($global:TenantId)
|
||||||
|
{
|
||||||
|
$appObj.TenantId = $global:TenantId
|
||||||
|
}
|
||||||
|
|
||||||
|
$appObj
|
||||||
|
}
|
||||||
|
|
||||||
function Get-MSALAppAuthority
|
function Get-MSALAppAuthority
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -1001,20 +1067,33 @@ function Connect-MSALUser
|
|||||||
|
|
||||||
if($global:hideUI -eq $true)
|
if($global:hideUI -eq $true)
|
||||||
{
|
{
|
||||||
if($global:AzureAppId -and $global:ClientSecret -and $global:TenantId)
|
$headlessAuthMode = ?? $global:HeadlessAuthMode "AppOnly"
|
||||||
|
|
||||||
|
if($headlessAuthMode -eq "Browser")
|
||||||
|
{
|
||||||
|
if(-not $global:AzureAppId -or -not $global:TenantId)
|
||||||
|
{
|
||||||
|
Write-Log "Azure AppId and Tenant Id must be specified for browser auth" 3
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$global:appObj = Get-HeadlessPublicClientAppInfo
|
||||||
|
}
|
||||||
|
elseif($global:AzureAppId -and $global:ClientSecret -and $global:TenantId)
|
||||||
{
|
{
|
||||||
Connect-MSALClientApp $global:AzureAppId $global:TenantId -secret $global:ClientSecret
|
Connect-MSALClientApp $global:AzureAppId $global:TenantId -secret $global:ClientSecret
|
||||||
|
return
|
||||||
}
|
}
|
||||||
elseif($global:AzureAppId -and $global:ClientCert -and $global:TenantId)
|
elseif($global:AzureAppId -and $global:ClientCert -and $global:TenantId)
|
||||||
{
|
{
|
||||||
Connect-MSALClientApp $global:AzureAppId $global:TenantId -certificate $global:ClientCert
|
Connect-MSALClientApp $global:AzureAppId $global:TenantId -certificate $global:ClientCert
|
||||||
|
return
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Write-Log "Azure AppId, Tenant Id and Sercret/Cert must be specified for batch jobs" 3
|
Write-Log "Azure AppId, Tenant Id and Secret/Cert must be specified for AppOnly auth, or use browser auth" 3
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# No login during first time the app is started
|
# No login during first time the app is started
|
||||||
@@ -1348,7 +1427,7 @@ function Connect-MSALUser
|
|||||||
|
|
||||||
$app = $appBuilder.Build()
|
$app = $appBuilder.Build()
|
||||||
|
|
||||||
if((Get-SettingValue "CacheMSALToken"))
|
if($global:SkipTokenCacheHelperEx -ne $true -and ("TokenCacheHelperEx" -as [type]) -and (Get-SettingValue "CacheMSALToken"))
|
||||||
{
|
{
|
||||||
[TokenCacheHelperEx]::EnableSerialization($app.UserTokenCache, (Join-Path (Get-CloudApiDataFolder) "msalcahce.bin3"))
|
[TokenCacheHelperEx]::EnableSerialization($app.UserTokenCache, (Join-Path (Get-CloudApiDataFolder) "msalcahce.bin3"))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1313,6 +1313,7 @@ function Show-GraphExportForm
|
|||||||
function Invoke-InitSilentBatchJob
|
function Invoke-InitSilentBatchJob
|
||||||
{
|
{
|
||||||
$global:MSALToken = $null
|
$global:MSALToken = $null
|
||||||
|
$headlessAuthMode = ?? $global:HeadlessAuthMode "AppOnly"
|
||||||
|
|
||||||
if(-not $global:TenantId)
|
if(-not $global:TenantId)
|
||||||
{
|
{
|
||||||
@@ -1320,12 +1321,15 @@ function Invoke-InitSilentBatchJob
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if(-not $global:AzureAppId -or (-not $global:ClientSecret -and -not $global:ClientCert))
|
if(-not $global:AzureAppId -or ($headlessAuthMode -eq "AppOnly" -and (-not $global:ClientSecret -and -not $global:ClientCert)))
|
||||||
{
|
{
|
||||||
# Get login info for silent job from settings
|
# Get login info for silent job from settings
|
||||||
$global:AzureAppId = Get-SettingValue "GraphAzureAppId" -TenantID $global:TenantId
|
$global:AzureAppId = Get-SettingValue "GraphAzureAppId" -TenantID $global:TenantId
|
||||||
$global:ClientSecret = Get-SettingValue "GraphAzureAppSecret" -TenantID $global:TenantId
|
if($headlessAuthMode -eq "AppOnly")
|
||||||
$global:ClientCert = Get-SettingValue "GraphAzureAppCert" -TenantID $global:TenantId
|
{
|
||||||
|
$global:ClientSecret = Get-SettingValue "GraphAzureAppSecret" -TenantID $global:TenantId
|
||||||
|
$global:ClientCert = Get-SettingValue "GraphAzureAppCert" -TenantID $global:TenantId
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(-not $global:AzureAppId)
|
if(-not $global:AzureAppId)
|
||||||
@@ -1334,7 +1338,7 @@ function Invoke-InitSilentBatchJob
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if(-not $global:ClientSecret -and -not $global:ClientCert)
|
if($headlessAuthMode -eq "AppOnly" -and -not $global:ClientSecret -and -not $global:ClientCert)
|
||||||
{
|
{
|
||||||
Write-Log "Secret or Certificate must be specified. Either specify Secret/Certificate in Settings or Command Line" 3
|
Write-Log "Secret or Certificate must be specified. Either specify Secret/Certificate in Settings or Command Line" 3
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -37,13 +37,19 @@ function New-TemporaryBatchFile
|
|||||||
function Test-AuthParameters
|
function Test-AuthParameters
|
||||||
{
|
{
|
||||||
param(
|
param(
|
||||||
|
[string]$AuthMode,
|
||||||
[string]$Secret,
|
[string]$Secret,
|
||||||
[string]$Certificate
|
[string]$Certificate
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if($AuthMode -eq "Browser")
|
||||||
|
{
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if((-not $Secret) -and (-not $Certificate))
|
if((-not $Secret) -and (-not $Certificate))
|
||||||
{
|
{
|
||||||
throw "Specify -Secret or -Certificate."
|
throw "Specify -Secret or -Certificate for AppOnly auth, or use -AuthMode Browser."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +66,11 @@ function Invoke-IntuneHeadlessBatch
|
|||||||
|
|
||||||
[string]$Certificate,
|
[string]$Certificate,
|
||||||
|
|
||||||
|
[ValidateSet("AppOnly","Browser")]
|
||||||
|
[string]$AuthMode = "AppOnly",
|
||||||
|
|
||||||
|
[string]$RedirectUri,
|
||||||
|
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[psobject]$BatchConfig,
|
[psobject]$BatchConfig,
|
||||||
|
|
||||||
@@ -68,7 +79,7 @@ function Invoke-IntuneHeadlessBatch
|
|||||||
[string]$BatchFile
|
[string]$BatchFile
|
||||||
)
|
)
|
||||||
|
|
||||||
Test-AuthParameters -Secret $Secret -Certificate $Certificate
|
Test-AuthParameters -AuthMode $AuthMode -Secret $Secret -Certificate $Certificate
|
||||||
|
|
||||||
$projectRoot = Get-IntuneManagementProjectRoot
|
$projectRoot = Get-IntuneManagementProjectRoot
|
||||||
$runtimeModule = Join-Path $projectRoot "Runtime/IntuneManagement.Runtime.psd1"
|
$runtimeModule = Join-Path $projectRoot "Runtime/IntuneManagement.Runtime.psd1"
|
||||||
@@ -98,13 +109,19 @@ function Invoke-IntuneHeadlessBatch
|
|||||||
TenantId = $TenantId
|
TenantId = $TenantId
|
||||||
AppId = $AppId
|
AppId = $AppId
|
||||||
SilentBatchFile = $BatchFile
|
SilentBatchFile = $BatchFile
|
||||||
|
AuthMode = $AuthMode
|
||||||
}
|
}
|
||||||
|
|
||||||
if($Secret)
|
if($RedirectUri)
|
||||||
|
{
|
||||||
|
$invokeParams.RedirectUri = $RedirectUri
|
||||||
|
}
|
||||||
|
|
||||||
|
if($AuthMode -eq "AppOnly" -and $Secret)
|
||||||
{
|
{
|
||||||
$invokeParams.Secret = $Secret
|
$invokeParams.Secret = $Secret
|
||||||
}
|
}
|
||||||
else
|
elseif($AuthMode -eq "AppOnly")
|
||||||
{
|
{
|
||||||
$invokeParams.Certificate = $Certificate
|
$invokeParams.Certificate = $Certificate
|
||||||
}
|
}
|
||||||
@@ -135,6 +152,11 @@ function Export-IntunePolicies
|
|||||||
|
|
||||||
[string]$Certificate,
|
[string]$Certificate,
|
||||||
|
|
||||||
|
[ValidateSet("AppOnly","Browser")]
|
||||||
|
[string]$AuthMode = "AppOnly",
|
||||||
|
|
||||||
|
[string]$RedirectUri,
|
||||||
|
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string]$ExportPath,
|
[string]$ExportPath,
|
||||||
|
|
||||||
@@ -167,6 +189,8 @@ function Export-IntunePolicies
|
|||||||
-AppId $AppId `
|
-AppId $AppId `
|
||||||
-Secret $Secret `
|
-Secret $Secret `
|
||||||
-Certificate $Certificate `
|
-Certificate $Certificate `
|
||||||
|
-AuthMode $AuthMode `
|
||||||
|
-RedirectUri $RedirectUri `
|
||||||
-BatchConfig $batchConfig `
|
-BatchConfig $batchConfig `
|
||||||
-SettingsFile $SettingsFile `
|
-SettingsFile $SettingsFile `
|
||||||
-BatchFile $BatchFile
|
-BatchFile $BatchFile
|
||||||
@@ -186,6 +210,11 @@ function Import-IntunePolicies
|
|||||||
|
|
||||||
[string]$Certificate,
|
[string]$Certificate,
|
||||||
|
|
||||||
|
[ValidateSet("AppOnly","Browser")]
|
||||||
|
[string]$AuthMode = "AppOnly",
|
||||||
|
|
||||||
|
[string]$RedirectUri,
|
||||||
|
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string]$ImportPath,
|
[string]$ImportPath,
|
||||||
|
|
||||||
@@ -225,6 +254,8 @@ function Import-IntunePolicies
|
|||||||
-AppId $AppId `
|
-AppId $AppId `
|
||||||
-Secret $Secret `
|
-Secret $Secret `
|
||||||
-Certificate $Certificate `
|
-Certificate $Certificate `
|
||||||
|
-AuthMode $AuthMode `
|
||||||
|
-RedirectUri $RedirectUri `
|
||||||
-BatchConfig $batchConfig `
|
-BatchConfig $batchConfig `
|
||||||
-SettingsFile $SettingsFile `
|
-SettingsFile $SettingsFile `
|
||||||
-BatchFile $BatchFile
|
-BatchFile $BatchFile
|
||||||
@@ -248,6 +279,11 @@ function Invoke-IntunePolicyAction
|
|||||||
|
|
||||||
[string]$Certificate,
|
[string]$Certificate,
|
||||||
|
|
||||||
|
[ValidateSet("AppOnly","Browser")]
|
||||||
|
[string]$AuthMode = "AppOnly",
|
||||||
|
|
||||||
|
[string]$RedirectUri,
|
||||||
|
|
||||||
[string]$SettingsFile,
|
[string]$SettingsFile,
|
||||||
|
|
||||||
[string]$BatchFile,
|
[string]$BatchFile,
|
||||||
@@ -282,6 +318,8 @@ function Invoke-IntunePolicyAction
|
|||||||
-AppId $AppId `
|
-AppId $AppId `
|
||||||
-Secret $Secret `
|
-Secret $Secret `
|
||||||
-Certificate $Certificate `
|
-Certificate $Certificate `
|
||||||
|
-AuthMode $AuthMode `
|
||||||
|
-RedirectUri $RedirectUri `
|
||||||
-ExportPath $ExportPath `
|
-ExportPath $ExportPath `
|
||||||
-SettingsFile $SettingsFile `
|
-SettingsFile $SettingsFile `
|
||||||
-BatchFile $BatchFile `
|
-BatchFile $BatchFile `
|
||||||
@@ -298,6 +336,8 @@ function Invoke-IntunePolicyAction
|
|||||||
-AppId $AppId `
|
-AppId $AppId `
|
||||||
-Secret $Secret `
|
-Secret $Secret `
|
||||||
-Certificate $Certificate `
|
-Certificate $Certificate `
|
||||||
|
-AuthMode $AuthMode `
|
||||||
|
-RedirectUri $RedirectUri `
|
||||||
-ImportPath $ImportPath `
|
-ImportPath $ImportPath `
|
||||||
-SettingsFile $SettingsFile `
|
-SettingsFile $SettingsFile `
|
||||||
-BatchFile $BatchFile `
|
-BatchFile $BatchFile `
|
||||||
|
|||||||
@@ -25,3 +25,12 @@ Export-IntunePolicies `
|
|||||||
-Secret "<client-secret>" `
|
-Secret "<client-secret>" `
|
||||||
-ExportPath "/tmp/intune-export"
|
-ExportPath "/tmp/intune-export"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
Export-IntunePolicies `
|
||||||
|
-TenantId "<source-tenant-id>" `
|
||||||
|
-AppId "<public-client-app-id>" `
|
||||||
|
-AuthMode Browser `
|
||||||
|
-RedirectUri "http://localhost" `
|
||||||
|
-ExportPath "/tmp/intune-export"
|
||||||
|
```
|
||||||
|
|||||||
37
README.md
37
README.md
@@ -6,7 +6,7 @@ This repository is now CLI-first. The old WPF application surface has been remov
|
|||||||
|
|
||||||
1. export policies from a source tenant
|
1. export policies from a source tenant
|
||||||
2. store the exported JSON and migration table
|
2. store the exported JSON and migration table
|
||||||
3. import into a target tenant with app-only authentication
|
3. import into a target tenant with app-only or browser authentication
|
||||||
|
|
||||||
## Entry points
|
## Entry points
|
||||||
|
|
||||||
@@ -18,8 +18,8 @@ This repository is now CLI-first. The old WPF application surface has been remov
|
|||||||
## Runtime
|
## Runtime
|
||||||
|
|
||||||
* `pwsh` 7+
|
* `pwsh` 7+
|
||||||
* Microsoft Graph app registration with app-only access
|
* Microsoft Graph app registration
|
||||||
* Client secret or certificate
|
* App-only auth with client secret or certificate, or browser auth with a public client redirect URI
|
||||||
|
|
||||||
## Default object types
|
## Default object types
|
||||||
|
|
||||||
@@ -45,6 +45,16 @@ pwsh ./Scripts/Export-Policies.ps1 `
|
|||||||
-IncludeAssignments
|
-IncludeAssignments
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Export with browser auth
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
pwsh ./Scripts/Export-Policies.ps1 `
|
||||||
|
-TenantId "<source-tenant-id>" `
|
||||||
|
-AppId "<public-client-app-id>" `
|
||||||
|
-AuthMode Browser `
|
||||||
|
-ExportPath "/tmp/intune-export"
|
||||||
|
```
|
||||||
|
|
||||||
## Import
|
## Import
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
@@ -59,6 +69,16 @@ pwsh ./Scripts/Import-Policies.ps1 `
|
|||||||
-ReplaceDependencyIds
|
-ReplaceDependencyIds
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Import with browser auth
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
pwsh ./Scripts/Import-Policies.ps1 `
|
||||||
|
-TenantId "<target-tenant-id>" `
|
||||||
|
-AppId "<public-client-app-id>" `
|
||||||
|
-AuthMode Browser `
|
||||||
|
-ImportPath "/tmp/intune-export/SourceTenantName"
|
||||||
|
```
|
||||||
|
|
||||||
## Single entrypoint
|
## Single entrypoint
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
@@ -80,8 +100,19 @@ pwsh ./Start-HeadlessIntune.ps1 `
|
|||||||
-ImportType alwaysImport
|
-ImportType alwaysImport
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
pwsh ./Start-HeadlessIntune.ps1 `
|
||||||
|
-Action Export `
|
||||||
|
-TenantId "<source-tenant-id>" `
|
||||||
|
-AppId "<public-client-app-id>" `
|
||||||
|
-AuthMode Browser `
|
||||||
|
-RedirectUri "http://localhost" `
|
||||||
|
-ExportPath "/tmp/intune-export"
|
||||||
|
```
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
* Export writes a migration table used during cross-tenant import.
|
* Export writes a migration table used during cross-tenant import.
|
||||||
* Import can translate dependency IDs and recreate missing assignment groups.
|
* Import can translate dependency IDs and recreate missing assignment groups.
|
||||||
* This repo intentionally does not preserve the old Windows UI launch flow.
|
* This repo intentionally does not preserve the old Windows UI launch flow.
|
||||||
|
* Browser auth uses the system browser and a loopback redirect. If your app registration does not allow loopback redirects, pass `-RedirectUri "http://localhost"` and configure the same redirect URI in Entra ID.
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ function Initialize-IntuneManagementRuntime
|
|||||||
[string]$AppId,
|
[string]$AppId,
|
||||||
[string]$Secret,
|
[string]$Secret,
|
||||||
[string]$Certificate,
|
[string]$Certificate,
|
||||||
|
[ValidateSet("AppOnly","Browser")]
|
||||||
|
[string]$AuthMode = "AppOnly",
|
||||||
|
[string]$RedirectUri,
|
||||||
[string]$GraphEnvironment,
|
[string]$GraphEnvironment,
|
||||||
[string]$GCCType
|
[string]$GCCType
|
||||||
)
|
)
|
||||||
@@ -30,6 +33,8 @@ function Initialize-IntuneManagementRuntime
|
|||||||
$global:AzureAppId = $AppId
|
$global:AzureAppId = $AppId
|
||||||
$global:ClientSecret = $Secret
|
$global:ClientSecret = $Secret
|
||||||
$global:ClientCert = $Certificate
|
$global:ClientCert = $Certificate
|
||||||
|
$global:HeadlessAuthMode = $AuthMode
|
||||||
|
$global:MSALRedirectUri = $RedirectUri
|
||||||
$global:UseGraphEnvironment = $GraphEnvironment
|
$global:UseGraphEnvironment = $GraphEnvironment
|
||||||
$global:UseGCCType = $GCCType
|
$global:UseGCCType = $GCCType
|
||||||
$global:UseJSonSettings = ($JSonSettings -eq $true)
|
$global:UseJSonSettings = ($JSonSettings -eq $true)
|
||||||
@@ -68,6 +73,10 @@ function Initialize-IntuneManagementRuntime
|
|||||||
{
|
{
|
||||||
Write-Host "Using Azure App Certificate"
|
Write-Host "Using Azure App Certificate"
|
||||||
}
|
}
|
||||||
|
elseif($global:HeadlessAuthMode -eq "Browser")
|
||||||
|
{
|
||||||
|
Write-Host "Using browser authentication"
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Write-Warning "Azure App Secret or Certificate is missing. Use -Secret <Secret> or -Certificate <Certificate>."
|
Write-Warning "Azure App Secret or Certificate is missing. Use -Secret <Secret> or -Certificate <Certificate>."
|
||||||
|
|||||||
@@ -14,6 +14,11 @@ param(
|
|||||||
|
|
||||||
[string]$Certificate,
|
[string]$Certificate,
|
||||||
|
|
||||||
|
[ValidateSet("AppOnly","Browser")]
|
||||||
|
[string]$AuthMode = "AppOnly",
|
||||||
|
|
||||||
|
[string]$RedirectUri,
|
||||||
|
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string]$ExportPath,
|
[string]$ExportPath,
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,11 @@ param(
|
|||||||
|
|
||||||
[string]$Certificate,
|
[string]$Certificate,
|
||||||
|
|
||||||
|
[ValidateSet("AppOnly","Browser")]
|
||||||
|
[string]$AuthMode = "AppOnly",
|
||||||
|
|
||||||
|
[string]$RedirectUri,
|
||||||
|
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string]$ImportPath,
|
[string]$ImportPath,
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,11 @@ param(
|
|||||||
|
|
||||||
[string]$Certificate,
|
[string]$Certificate,
|
||||||
|
|
||||||
|
[ValidateSet("AppOnly","Browser")]
|
||||||
|
[string]$AuthMode = "AppOnly",
|
||||||
|
|
||||||
|
[string]$RedirectUri,
|
||||||
|
|
||||||
[string]$SettingsFile,
|
[string]$SettingsFile,
|
||||||
|
|
||||||
[string]$BatchFile,
|
[string]$BatchFile,
|
||||||
@@ -45,6 +50,7 @@ $invokeParams = @{
|
|||||||
Action = $Action
|
Action = $Action
|
||||||
TenantId = $TenantId
|
TenantId = $TenantId
|
||||||
AppId = $AppId
|
AppId = $AppId
|
||||||
|
AuthMode = $AuthMode
|
||||||
SettingsFile = $SettingsFile
|
SettingsFile = $SettingsFile
|
||||||
BatchFile = $BatchFile
|
BatchFile = $BatchFile
|
||||||
NameFilter = $NameFilter
|
NameFilter = $NameFilter
|
||||||
@@ -71,4 +77,9 @@ elseif($Certificate)
|
|||||||
$invokeParams.Certificate = $Certificate
|
$invokeParams.Certificate = $Certificate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if($RedirectUri)
|
||||||
|
{
|
||||||
|
$invokeParams.RedirectUri = $RedirectUri
|
||||||
|
}
|
||||||
|
|
||||||
Invoke-IntunePolicyAction @invokeParams
|
Invoke-IntunePolicyAction @invokeParams
|
||||||
|
|||||||
Reference in New Issue
Block a user