Exchange Online reconnect script v2

A few weeks ago I posted a script that would automatically, periodically, reconnect to Exchange Online. In field testing it would still prompt for credentials after 1-2 days, whatever I did.

So I took a different route and am now rewriting Microsofts’ module on the fly to no longer prompt for credentials. If you use below function to connect to Exchange Online, you should never receive reconnect prompts ๐Ÿ™‚

disclaimer: don’t overwrite $o365Creds with invalid creds elsewhere in your script as those are used globally.

</p>
<p>function buildResilientExchangeOnlineSession {<br />
    Param(<br />
        [Parameter(Mandatory=$true)]$o365Creds,<br />
        $commandPrefix<br />
    )<br />
    Write-Verbose &quot;Connecting to Exchange Online&quot;<br />
    Set-Variable -Scope Global -Name o365Creds -Value $o365Creds -Force<br />
    $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $o365Creds -Authentication Basic -AllowRedirection<br />
    Import-PSSession $Session -AllowClobber -DisableNameChecking<br />
    Write-Verbose &quot;Connected to Exchange Online, exporting module...&quot;<br />
    $temporaryModulePath = (Join-Path $Env:TEMP -ChildPath &quot;temporaryEXOModule&quot;)<br />
    $res = Export-PSSession -Session $Session -CommandName * -OutputModule $temporaryModulePath -AllowClobber -Force<br />
    $temporaryModulePath = Join-Path $temporaryModulePath -ChildPath &quot;temporaryEXOModule.psm1&quot;<br />
    Write-Verbose &quot;Rewriting Exchange Online module, please wait a few minutes...&quot;<br />
    [String]$newContent<br />
    $found = $False<br />
    (Get-Content $temporaryModulePath) | % {<br />
        if(!$found -and $_.IndexOf(&quot;host.UI.PromptForCredential(&quot;) -ge 0){<br />
            $line = &quot;-Credential `$global:o365Creds ``&quot;<br />
            if($line){<br />
                $found = $True<br />
            }<br />
        }<br />
        if($line){<br />
            $newContent += $line<br />
            $line=$Null<br />
        }else{<br />
            $newContent += $_<br />
        }<br />
        $newContent += &quot;`r`n&quot;<br />
    }<br />
    $newContent | Out-File -FilePath $temporaryModulePath -Force -Confirm:$False -ErrorAction Stop<br />
    $Session | Remove-PSSession -Confirm:$False<br />
    Write-Verbose &quot;Module rewritten, re-importing...&quot;<br />
    if($commandPrefix){<br />
        Import-Module -Name $temporaryModulePath -Prefix $commandPrefix -DisableNameChecking -WarningAction SilentlyContinue -Force<br />
        Write-Verbose &quot;Module imported, you may now use all Exchange Online commands using $commandPrefix as prefix&quot;<br />
    }else{<br />
        Import-Module -Name $temporaryModulePath -DisableNameChecking -WarningAction SilentlyContinue -Force<br />
        Write-Verbose &quot;Module imported, you may now use all Exchange Online commands&quot;<br />
    }<br />
    return $temporaryModulePath<br />
}</p>
<p>

download:ย https://gitlab.com/Lieben/assortedFunctions/blob/master/buildResilientExchangeOnlineSession.ps1

 

CSP delegation on non CSP azure subscriptions

If you’re a Cloud Solution Provider and you supply a CSP azure subscription to that tenant, your AdminAgents will have Owner access to that subscription by default. Lets say the customer also has an existing subscription (maybe a non-profit donation?).

When you add your accounts as Owner to the existing tenant’s (non-csp) subscription, your users are added as Guest accounts in the customer’s Azure AD. Thisย removes the delegated CSP rights on the CSP subscription because the references to foreign accounts break due to the new guest accounts having the same UPN.

So, alternatively, use

Get-AzureRmRoleAssignment -Scope "/subscriptions/<CSP SUBSCRIPTION ID>

on the CSP subscription to get the Foreign Principal ID for your own tenant. Then use

New-AzureRMRoleAssignment -ObjectId &lt;FOREIGN PRINCIPAL ID&gt; -Scope &quot;/subscriptions/<br />
&lt;EXISTING SUBSCRIPTION ID&gt;&quot; -RoleDefinitionName Owner

to add the foreign principal ID to the existing customer subscription to get delegated access ๐Ÿ™‚

 

Exchange Online Reconnect script

I’ve seen and known many scripts that interact with Exchange Online for extended periods of time. After a while, Exchange Online likes it if you reconnect, this can be an Impliciet Authentication popup, or it can simply drop you based on what command you’re using.

If you call the following function every loop in whatever you’re doing, it’ll automatically force a reconnect to Exchange Online every hour (adjustable if you prefer longer):

Edit:ย read v2 of this post ๐Ÿ™‚

Note:ย if you run this script in an Exchange Shell, something in the Exchange Shell modules will still prompt for reconnects every 1-2 days. In a normal PS window, I’ve verified it working for up to a week until it asks for a reconnect.