Powershell, EWS, OAuth2 и автоматизация - PullRequest
1 голос
/ 30 сентября 2019

Я пытаюсь найти документацию о том, как внедрить неинтерактивную аутентификацию Oauth2 в EWS с помощью PowerShell, но, вероятно, я не использую правильные условия поиска, потому что не могу найти ничего полезного. Документация Microsoft, которую я могу найти на OAuth2, содержит только документацию на C #.

Итак, кто-нибудь знает, как это реализовать?

  • Нет ввода пользователя, должен работать с вводом, который может быть предоставлен. как сценарий ввода
  • Должно быть в PowerShell, а не в C #
  • Подробнее! Подробности! Не «Теперь сгенерируйте токен для входа», а фактический код для генерации этого токена.

1 Ответ

1 голос
/ 01 октября 2019

Это действительно хороший обзор этого блога: https://ingogegenwarth.wordpress.com/2018/08/02/ews-and-oauth/#more-5139

Я использовал этот блог, чтобы заставить его работать в наших скриптах PowerShell - с большим количеством проб и ошибок. В следующем примере сценария используется ClientID приложения, зарегистрированный в Azure AD. Если у вас еще нет приложения, зарегистрированного в Azure AD, вы должны сделать это в первую очередь. В Интернете доступны различные руководства по регистрации нового приложения в Azure AD. Чтобы использовать EWS с OAuth, ваше зарегистрированное приложение должно иметь правильные разрешения в Azure AD. У EWS есть два варианта:

  1. Использовать делегированные разрешения и запрашивать разрешение API «EWS.AccessAsUser.All» в Azure AD - Устаревшие API |Обмен |Делегированные разрешения |EWS.AccessAsUser.All (Доступ к почтовым ящикам как зарегистрированному пользователю через веб-службы Exchange). Это разрешение дает вашему зарегистрированному приложению такой же доступ к почтовым ящикам Exchange, как и вошедшему в систему пользователю. Если вы используете это разрешение, то в первый раз, когда ClientID вашего приложения используется какой-либо службой или учетной записью пользователя для доступа к Exchange Online, соответствующая учетная запись должна подтвердить ClientID посредством интерактивного всплывающего уведомления. Поэтому, прежде чем использовать этот сценарий в автоматическом режиме, вы должны в интерактивном режиме получить доступ к Exchange Online Service, используя ClientID вашего зарегистрированного приложения, и одобрить всплывающее окно авторизации. Самый простой способ сделать это - войти в почтовый ящик с помощью бесплатного приложения Microsoft «EWS Editor» и указать ClientID вашего приложения. Как только ClientID вашего приложения будет утвержден, ваш сценарий может работать полностью автоматически без какого-либо взаимодействия.
  2. Используйте разрешения приложения и запросите разрешение API «full_access_as_app» в Azure AD - Устаревшие API |Обмен |Делегированные разрешения |EWS.AccessAsUser.All (Доступ к почтовым ящикам как зарегистрированному пользователю через веб-службы Exchange). Это разрешение дает вашему зарегистрированному приложению полный доступ через веб-службы Exchange ко всем почтовым ящикам без зарегистрированного пользователя. Этот тип разрешений дает приложению полный доступ к любому почтовому ящику в службе Exchange Online и должен быть одобрен глобальным администратором Azure AD, предоставляющим «согласие администратора». Затем ваш сценарий будет проходить проверку подлинности в Exchange Online с использованием зарегистрированного идентификатора клиента приложения Azure AD (фактически это имя пользователя) и Client Secret (фактически пароль).

В приведенном ниже примере используется вариант 1. У меня нетпроверенный вариант 2. Какой бы вариант вы ни выбрали, вам нужно будет обработать запрос токена OAuth (пример в приведенном ниже коде) из Azure AD и регулярно проверять и обновлять токен (без примера). Я не сделал этого, так как все наши сценарии EWS просты, быстро запускают сценарии, которые завершаются до обновления токена (обычно в течение 60 минут). Если это то, что вам нужно, вам нужно будет попросить других о помощи. Надеюсь, что это поможет вам выбрать правильный путь ...

Вот пример сценария (основная часть сценария вызывает функцию Get-EWSOAuthToken):

#Variables
$UserPrincipalName = "Enter the UPN of your Service Account ID"
$Password = "Password of your Service Account ID - store this securely"
$ClientIDfromAzureAD = "Client ID of your registered application in Azure AD"
$errRecip = "Email address of recipients to notify via email if errors occur"
$script = "Name of script"
$sender = "Email address of sender - normally the server name where your script runs"
$logfile = "Path and filename to log file"
$smtpServer = "Your SMTP server"

Function Get-EWSOAuthToken
{
    <#
        .SYNOPSIS
            Request an OAuth EWS token from Azure AD using supplied Username and Password

        .DESCRIPTION
            Request an OAuth EWS token from Azure AD using supplied Username and Password

        .PARAMETER UserPrincipalName
            The UPN of the user that will authenticate to Azure AD to request the OAuth Token

        .PARAMETER Password
            The Password (SecureString) of the user that will authenticate to Azure AD to request the OAuth Token

        .PARAMETER ADALPath
            The full path and filename on the local file system to the ADAL (Active Directory Authentication Library) DLL. This library is installed as part of various modules such as Azure AD, Exchange Online, etc.

        .PARAMETER ClientId
            Identifier of the client application that is requesting the token. You must register your calling application in Azure AD. This will provide you with a ClientID and RedirectURI

        .PARAMETER ConnectionUri
            The URI of the Exchange Online EWS endpoint. Default URI of 'https://outlook.office365.com/EWS/Exchange.asmx' is used

        .PARAMETER RedirectUri
            Address to return to upon receiving a response from the authority. You must register your calling application in Azure AD. This will provide you with a ClientID and RedirectURI

        .EXAMPLE
            $token = Get-EWSOAuthtokenFromCredential -UserPrincipalName "ABC123@mydomain.com" -Password $mySecurePassword -ClientId "123444454545454767687878787" -RedirectUri "https://dummyredirectdomain.com"
            $ews = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService -ArgumentList Exchange2013_SP1 -ErrorAction Stop
            $ews.UseDefaultCredentials = $False
            $ews.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$token
    #>

    [CmdletBinding()]
    Param
    (
        [System.String]$UserPrincipalName,
        [System.Security.SecureString]$Password,
        [System.String]$ADALPath,
        [System.String]$ClientId = "123444454545454767687878787",
        [System.Uri]$ConnectionUri = "https://outlook.office365.com/EWS/Exchange.asmx",
        [System.Uri]$RedirectUri = "https://dummyredirectdomain.com"
    )

    Begin
    {
        Write-Host "Starting Get-EWSOAuthTokenFromCredential function..." -ForegroundColor Yellow
        #Determine ADAL location based on Azure AD module installation path
        If([System.String]::IsNullOrEmpty($ADALPath)) 
        {
            Write-Host "Attempting to locate ADAL library..." -ForegroundColor Yellow

            $ADALPath = (Get-InstalledModule -Name "AzureAD" -ErrorAction SilentlyContinue | Select-Object InstalledLocation).InstalledLocation
            $ADALPath = Join-Path -Path $ADALPath -ChildPath "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
            Write-Host "Located library @ '$ADALPath'" -ForegroundColor Yellow
            If([System.String]::IsNullOrEmpty($ADALPath))
            {
                #Get List of installed modules and check Azure AD DLL is available
                $tmpMods = Get-Module -ListAvailable | Where-Object {$_.Name -eq "AzureAD"}

                If($tmpMods)
                {
                    $ADALPath = Split-Path $tmpMods.Path
                    $ADALPath = Join-Path -Path $ADALPath -ChildPath "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
                    Write-Host "Located library @ '$ADALPath'" -ForegroundColor Yellow
                }
                Else
                {
                    $err = "$($myinvocation.mycommand.name) requires the ADAL Library DLL files ('Microsoft.IdentityModel.Clients.ActiveDirectory.dll') that are installed as part of the 'AzureAD' module! Please install the AzureAD module from the Powershell Gallery. See: 'https://www.powershellgallery.com/packages/AzureAD' for more information"
                    Throw "$err"
                }
            }
        }

        #Load 'Microsoft.IdentityModel.Clients.ActiveDirectory' DLL
        Try
        {
            Import-Module $ADALPath -DisableNameChecking -Force -ErrorAction Stop
            Write-Host "Successfully imported ADAL Library" -ForegroundColor Yellow
        }
        Catch
        {
            $err = "$($myinvocation.mycommand.name): Could not load ADAL Library DLL '$ADALPath'. Error: $_"
            Throw "$err"
        }
    }
    Process
    {
        try
            {
            $resource = $connectionUri.Scheme + [System.Uri]::SchemeDelimiter + $connectionUri.Host
            $azureADAuthorizationEndpointUri = "https://login.windows.net/common/oauth2/authorize/"
            $AuthContext = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext($azureADAuthorizationEndpointUri) -ErrorAction Stop
            $AuthCredential = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential($UserPrincipalName, $Password) -ErrorAction Stop
            Write-Host "$($myinvocation.mycommand.name): Requesting a new OAuth Token..." -ForegroundColor Yellow
            $authenticationResult = ([Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync($AuthContext, $resource, $clientId, $AuthCredential))

            If ($authenticationResult.Status.ToString() -ne "Faulted") {
                Write-Host "$($myinvocation.mycommand.name): Successfully retrieved OAuth Token" -ForegroundColor Yellow
            }
            else {
                $err = "$($myinvocation.mycommand.name): Error occurred calling ADAL 'AcquireTokenAysnc' : $authenticationResult.Exception.ToString()"
                Throw "$err"
            }
        }
        catch
        {
            #create object
            $returnValue = New-Object -TypeName PSObject

            #get all properties from last error
            $ErrorProperties =$Error[0] | Get-Member -MemberType Property

            #add existing properties to object
            foreach ($Property in $ErrorProperties)
            {
                if ($Property.Name -eq 'InvocationInfo')
                {
                    $returnValue | Add-Member -Type NoteProperty -Name 'InvocationInfo' -Value $($Error[0].InvocationInfo.PositionMessage)
                }
                else
                {
                    $returnValue | Add-Member -Type NoteProperty -Name $($Property.Name) -Value $($Error[0].$($Property.Name))
                }
            }
            #return object
            $returnValue
            break
        }
    }
    End
    {
        return $authenticationResult
    }
}


###### Main script

#Ensure TLS 1.2 protocol is enabled
try {
    If ([Net.ServicePointManager]::SecurityProtocol -notmatch 'Tls12') {
        [Net.ServicePointManager]::SecurityProtocol += [Net.SecurityProtocolType]::Tls12
        Write-Host "Enabled Tls1.2 in '[Net.ServicePointManager]::SecurityProtocol'" -ForegroundColor Yellow
    }
    else {
        Write-Host "Tls1.2 is enabled in '[Net.ServicePointManager]::SecurityProtocol'" -ForegroundColor Yellow
    }
}
Catch {
    $err = "An error occurred enabling TLS1.2. Error: $_"
    Write-Host "`n$err" -ForegroundColor Red
    Send-MailMessage -To $errRecip -Subject "$script - Error occurred during processing" -Body $err -From $sender -Attachment $logfile -SmtpServer $smtpServer
    Exit
}

#CHECK FOR EWS MANAGED API, IF PRESENT IMPORT THE HIGHEST VERSION EWS DLL, ELSE EXIT
$EWSDLL = (($(Get-ItemProperty -ErrorAction SilentlyContinue -Path Registry::$(Get-ChildItem -ErrorAction SilentlyContinue -Path 'Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\Web Services'|Sort-Object Name -Descending | Select-Object -First 1 -ExpandProperty Name)).'Install Directory') + "Microsoft.Exchange.WebServices.dll")
If (Test-Path $EWSDLL)
{
    Try
    {
        Import-Module $EWSDLL -DisableNameChecking -ErrorAction Stop
    }
    Catch 
    {
        $err = "An error occurred importing the Exchange Web Services DLL '$EWSDLL'. Error: $_"
        Write-Host "`n$err" -ForegroundColor Red
        Send-MailMessage -To $errRecip -Subject "$script - Error occurred during processing" -Body $err -From $sender -Attachment $logfile -SmtpServer $smtpServer
        Exit
    }
}
Else
{
    $err = "This script requires the EWS Managed API 1.2 or later. Please download and install the current version of the EWS Managed API from http://go.microsoft.com/fwlink/?LinkId=255472"
    Write-Host "`n$err" -ForegroundColor Red
    Send-MailMessage -To $errRecip -Subject "$script - Error occurred during processing" -Body $err -From $sender -Attachment $logfile -SmtpServer $smtpServer
    Exit
}


#Create EWS Object
$ews = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService -ArgumentList "Exchange2013_SP1" -ErrorAction Stop

#Authenticate EWS using OAuth
Try {
    $ews.UseDefaultCredentials = $False
    Write-Host "Requesting EWS OAuth Token using registered Client ID" -ForegroundColor Yellow

    $OAuthResult = Get-EWSOAuthToken -UserPrincipalName $UserPrincipalName -Password $Password -ClientId "$ClientIDfromAzureAD" -ErrorAction Stop
    $token = $OAuthResult.Result.AccessToken

#Check if we successfully retrieved an Oauth Token
If ([System.String]::IsNullOrEmpty($token))
        {
            $err = "Get-EWSOAuthtoken returned an empty Auth Token. Aborted. Latest error details:`n$_error $($OAuthResult.Exception)"
            Write-Host "`n$err" -ForegroundColor Red
            $OAuthResult | Format-List -Force
            $OAuthResult.Result | Format-List -Force
            Send-MailMessage -To $errRecip -Subject "$script - Error occurred during processing" -Body "$err" -From $sender -Attachment $logfile -SmtpServer $smtpServer
            Exit
        }
        else
        {
            $OAuthchk = $true
            $ews.Credentials = [Microsoft.Exchange.WebServices.Data.OAuthCredentials]$token
            Write-Host "Set EWS credentials to OAuth token" -ForegroundColor Yellow
        }
    }
Catch
{
    $err = "An error occurred creating a new EWS object. Error:`n $_"
    write-host "`n$err" -ForegroundColor Red
    Send-MailMessage -To $errRecip -Subject "$script - Error occurred during processing" -Body "$err" -From $sender -Attachment $logfile -SmtpServer $smtpServer
    Exit
}

# Do your processing using EWS
....
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...