How do I write MultiFactor Powershell scripts for Exchange Online - powershell

I have a powershell script that MS provided and I have edited. True to form MS has provided a script using old code. Since we have MFA enabled, I can no longer use Get-Credential to authenticate as we use Modern Auth instead of Basic. How can I edit the code to support MFA? We do not use Auzer MFA we use Duo.
Old Code:
$adminCredential = Get-Credential
Write-Output "Connecting to Exchange Online Remote Powershell Service"
$ExoSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $adminCredential -Authentication Basic -AllowRedirection
if ($null -ne $ExoSession) {
Import-PSSession $ExoSession -AllowClobber
} else {
Write-Output " No EXO service set up for this account"
}
Write-Output "Connecting to EOP Powershell Service"
$EopSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.compliance.protection.outlook.com/powershell-liveid/ -Credential $adminCredential -Authentication Basic -AllowRedirection
if ($null -ne $EopSession) {
Import-PSSession $EopSession -AllowClobber
} else {
Write-Output " No EOP service set up for this account"
}
The new commands should be Connect-IPPSSession instead of New-PSSession but I have to somehow change Get-Credential to pass the credentials and MFA I just have no idea how to do this.

Full disclosure, neither I nor any the customers I support use Duo.
That being said, there are no docs from MS regarding PowerShell and MFA using DUO as the source for O365.
As per MS...
Connect to Office 365 services with multifactor authentication (MFA) and PowerShell
Connect to Exchange Online PowerShell using multi-factor authentication
You can't use the Exchange Online Remote PowerShell Module to connect to Exchange Online PowerShell and Security & Compliance Center PowerShell in the same session (window). You need to use separate sessions of the Exchange Online Remote PowerShell Module.
If you want to use multi-factor authentication (MFA) to connect to Exchange Online PowerShell, you can't use the instructions at Connect to Exchange Online PowerShell
https://learn.microsoft.com/en-us/powershell/exchange/exchange-online/connect-to-exchange-online-powershell/connect-to-exchange-online-powershell?view=exchange-ps
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
to use remote PowerShell to connect to Exchange Online.
MFA requires you to install the Exchange Online Remote PowerShell Module, and use the Connect-EXOPSSession cmdlet to connect.
Connect-EXOPSSession -UserPrincipalName <UPN> [-ConnectionUri <ConnectionUri> -AzureADAuthorizationEndPointUri <AzureADUri>]
Multi-Factor Authentication (MFA) Setup and End-User Experience with Office 365 and PowerShell
See also, if you have not already.
How do I change the username format sent to Duo?

If you want to use OAuth authentication, you need to have Access Token
Once the application has an access token, it may use the token to access the user's account via the API, limited to the scope of access, until the token expires or is revoked.
Here is an example of an API request, using curl. Note that it includes the access token:
curl -X POST -H "Authorization: Bearer ACCESS_TOKEN""https://api.digitalocean.com/v2/$OBJECT"
You can Authenticate Against OAuth refer the below link:
Using PowerShell to Authenticate Against OAuth

Upon reading the answers I realize that I did not structure my question in a detailed enough manner for the answer I need. I am leaving the question live and marking one of the answers as the answer because it does answer the question I asked, just not what I was hoping to learn.

The Connect-ExchangeOnline supports login with 2FA. You can run it as is without any arguments.

Related

Connect to Office 365 powershell is failing when password begins with blank space

I'm trying to connect to PowerShell through the script with username and password. When Password begins with space-like
passwordherebeginwithspace, Authentication is failed.
Session creation line is as below:
$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $credential -Authentication Basic -AllowRedirection -ErrorAction Stop;
error:
WARNING: Your connection has been redirected to the following URI:
"https://ps.outlook.com/PowerShell-LiveID?PSVersion=5.1.17763.771 "
New-PSSession : [ps.outlook.com] Connecting to remote server
ps.outlook.com failed with the following error message : Access is
denied.
According to the Office 365 Password Policy, cloud only users are not allowed to have a space in the password.
This is something I've encountered in the past where one part of the service will work(such as Outlook) yet another part will fail(like Sharepoint). The requirement isn't always strictly enforced. It can vary depending on what method was used to set the password(web login form vs. admin assigned it using PowerShell).

Remote powershell sessions can only be established with interactively entered credentials?

I'm trying to automate a powershell script which gathers data from O365. I've got a special limited user setup with the privileges required on O365 and also with local logon allowed on the server so that I can "run-as" that user (which I do for all the scripts below. I have verified different, expected errors when running as other users).
The script works fine interactively when credentials are set like this and the session opened:
$cred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $cred -Authentication Basic –AllowRedirection
However, if I create the credentials file for automation with:
Get-Credential | Export-Clixml -Path C:\batch\${env:USERNAME}_cred.xml
And then access from the script via:
$cred = Import-Clixml -Path C:\batch\${env:USERNAME}_cred.xml
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $cred -Authentication Basic –AllowRedirection
The credential file load appears to succeed. I then get "Access Denied" on the session open, and then of course the rest of the script fails due to the session being null. I'm cutting and pasting the password in all cases (plus have tried many, MANY times including hand typing) so I don't think it's a simple typo issue. Seems more like something I'm fundamentally misunderstanding about powershell. Ultimately I'd like to not just have the credentials automated, but also have it run from task scheduler if there's any special settings above and beyond that I also need.
I don't see anything wrong from your code from PowerShell perspective. I have tested the way you are creating credentials within a company domain and I was able to create new session by importing credential XML file that was created by exporting the credentials the way you did. I then assume it might be MS Exchange related.
I can suggest alternatives for you to try:
# First we need to get the encrypted password:
$TempCred = Get-Credential
# provide credentials to the prompt
# now the encryption to be saved in a file
$TempCred.Password | ConvertFrom-SecureString | Set-Content C:\mypass.txt
This was the encrypted version of your password is saved as a text.
In your automation script you can now do this:
$username = "yourusername"
$password = Get-Content C:\mypass.txt | ConvertTo-SecureString
$cred = New-Object System.Management.Automation.PsCredential($username, $password)
$session = New-PSSession -Credential $cred .....
I am not sure if this works in your case, it worked in my company domain. Once again it worked for me the XML version too. I am just providing alternatives to try if you are not keen to find out as to why the XML way did not work.
I was able to get this working, in my environment at least, by including a call to Import-PSSession:
$Credential = Import-Clixml -Path D:\Modules\O365Credentials.xml
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $Credential -Authentication Basic -AllowRedirection
Import-PSSession $Session -DisableNameChecking
Get-Mailbox
Does the account in question have MFA enabled? If so, you might try this.
This script:
Downloads Exchange Online Remote PowerShell Module
Installs Exchange Online PowerShell Module
Connects Exchange Online PowerShell using MFA
Or, you can perform these manually. More information, including a detailed walk-through, is available here:
https://o365reports.com/2019/04/17/connect-exchange-online-using-mfa/

Using invoke-command scriptblock with exchange management shell

I've written some scripts to automate some user add and user modifications functions. But there is one last piece to the puzzle I can't figure out.
I need to run some commands in exchange management shell on the exchange server from a local powershell session, like an invoke-command scriptblock.
Is this possible?
Will adding Add-PSSnapin Microsoft.Exchange.Management.PowerShell.SnapIn
to the beginning of my script block accomplish this?
As for this...
Will adding Add-PSSnapin
Microsoft.Exchange.Management.PowerShell.SnapIn
You can't do this natively, without installing the EMC directly on your host.
Secondly, there is no real reason to. You can use PSRemoting to proxy the Exchange cmdlets to your host. The cmdlets are only available during the session
This process is the same whether you are using Exchange on-prem or Exchange online, though Exchange Online points to the O365 URI.
This has been documented in several places via the MS provided docs as noted here:
Connect to Exchange servers using remote PowerShell
Connect to a remote Exchange server
1.On your local computer, open Windows PowerShell, and run the following command:
$UserCredential = Get-Credential
In the Windows PowerShell Credential Request dialog box that opens, enter your user principal name (UPN) (for example, chris#contoso.com) and password, and then click OK.
2.Replace with the fully qualified domain name of your Exchange server (for example, mailbox01.contoso.com) and run the following command:
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://<ServerFQDN>/PowerShell/ -Authentication Kerberos -Credential $UserCredential
Note: The ConnectionUri value is http, not https.
3.Run the following command:
Import-PSSession $Session -DisableNameChecking
https://learn.microsoft.com/en-us/powershell/exchange/exchange-server/connect-to-exchange-servers-using-remote-powershell?view=exchange-ps
Remote PowerShell in Exchange 2013
1.On your local computer, open Windows PowerShell and execute the following command:
$UserCredential = Get-Credential
2.After entering the credentials prompted when you executed the above command, execute the following:
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://<FQDN of Exchange 2013 Client Access server>/PowerShell/ -Authentication Kerberos -Credential $UserCredential
3.Finally, import the session established above with the following:
Import-PSSession $Session
https://blogs.technet.microsoft.com/nathanscott/2015/06/14/remote-powershell-in-exchange-2013/
Yes you can, some commands have to be run locally, below is an example. You can do the same with Exchange.
Invoke-Command -ComputerName $srv -ScriptBlock{Add-PSSnapin Microsoft.Forefront.Filtering.Management.Powershell;
Get-EngineUpdateInformation}

How to set up a service principle account in azure automation

I'm using azure automation to automate a process with a Powershell Workflow Runbook. In that process I connect to MSOnline and Exchange with a Credential:
# Pull credential from Automation assets
$cred = Get-AutomationPSCredential -Name "CredentialName"
# Connect To Microsoft online
Connect-MsolService -Credential $cred
# Connect to Exchange Online
$ExchangeOnlineSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $cred -Authentication Basic -AllowRedirection -Name $ConnectionName
Import-Module (Import-PSSession -Session $ExchangeOnlineSession -AllowClobber -DisableNameChecking) -Global
This works but I don't want to save credentials of an account with permissions, the $cred.
I read and (thought I) understood that this could be done with a Service Principle Account. The problem is that I don't find it good described in order for me to make it work, although I have tried many times.
Any information is welcome
When you say you're using "Azure Automation" to automate a process, I believe you must have provisioned an Azure Automation Account to hold the PS Runbook & authenticate to Azure resources.
When you setup an Azure Automation Account, there's a built-in feature "Run As Accounts". It creates a Run-As account which takes care of the following tasks for the user:
Create a Service Principal in Azure AD
Create a Certificate
Assigns the Contributor Role-Based Access Control (RBAC), which manages Azure Resource Manager resources by using runbooks
One point to note here is that, the Service Principal for a Run as Account does not have permissions to read Azure AD by default. If you want to add permissions to read or manage Azure AD, you'll need to grant the permissions on the service principal under API permissions.
Once you're all set with Run As Account, you can use the account and retrieve the connection with Get-AzAutomationConnection
You can refer this documentation for more details: Manage Azure Automation Run As Accounts
Hope this helps!

Set-UMMailbox not listed in Exchange Powershell session?

When creating a new PS Session to our Exchange 2010 server:
$session = New-PSSession -ConfigurationName microsoft.exchange -ConnectionURI http://exchange.domain.com/powershell -Credential $cred
And importing the newly created session:
Import-PSSession $session
This would give me a slew of Exchange cmdlets that I can now use locally within my Powershell session. Unfortunately, it seems to be missing a few cmdlets that I need to automate some mailbox actions. Specifically -- Set-UMMailbox, which would allow me to change the operator's phone number on the mailbox.
Is this a bug with this particular configuration? Or am I missing something else?
If there is another way go to about doing this, I'm all ears. Thanks.
I found out the issue here is related to permissions. The service account I was using had a majority of the rights, but not rights to unified messaging. I tested this by using my domain admin account credentials (which I won't be using in my script).