From d7530357279ff8daeac6052d7dcd1908c15e8b81 Mon Sep 17 00:00:00 2001 From: Brett Hacker Date: Wed, 29 Aug 2018 02:19:19 -0500 Subject: [PATCH] psh-exo-encrypted-mailsend-script Added encrypted email script sample --- psh-exo-encrypted-mailsend-script/README.md | 29 +++++++ .../SendEXOMailTest1.ps1 | 86 +++++++++++++++++++ .../SendEXOMailTest2.ps1 | 78 +++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100644 psh-exo-encrypted-mailsend-script/README.md create mode 100644 psh-exo-encrypted-mailsend-script/SendEXOMailTest1.ps1 create mode 100644 psh-exo-encrypted-mailsend-script/SendEXOMailTest2.ps1 diff --git a/psh-exo-encrypted-mailsend-script/README.md b/psh-exo-encrypted-mailsend-script/README.md new file mode 100644 index 0000000..7fc0d0e --- /dev/null +++ b/psh-exo-encrypted-mailsend-script/README.md @@ -0,0 +1,29 @@ +## Sending Encrypted Mail From a Script + +Eventually, you're going to want to send an email from a script. This is really straightforward using Exchange Online and the Microsoft Graph API. But what if you want those emails to be encrypted? Sometimes, log information may be put in an email, and there may be something sensitive in that log. + +Azure Information Protection enables encryption, and it's also easy. But how to activate it from a script? There’s no apparent way to specify encryption in the Graph call, but you CAN setup default rules as an Exchange admin, that apply to a given user account. So the API call is over TLS, and once it gets to EXO through Graph, EXO will encrypt it before storing it or sending it. + +There are two approaches to accomplishing this: + +1. In both cases: + + a. create a new user account and assign it a mailbox in EXO (limit its permissions all you want, as long as it can send email) + + b. Create an app registration. Get the AppID and create an app secret + + c. Case A - Assign it Application permissions to the Microsoft Graph, allowing it to send email on behalf of anyone in the org (This requires GA approval.) + + d. Case B – Assign it delegated permissions to the Microsoft Graph, allowing it to send on behalf of the logged-in user (Doesn’t require admin approval.) +2. Case A – Sending on behalf of this user + + a. The script authenticates in as the application, using the client_credential grant type. It calls https://graph.microsoft.com/v1.0/users/{0}/sendMail, filling in the UPN of the sending account mailbox. +3. Case B – Sending AS the user + + a. The script authenticates in as the user, using the password grant type. It calls https://graph.microsoft.com/v1.0/me/sendMail + +Here’s the REST reference: +https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/user_sendmail + +Here’s the EXO mail flow encryption doc: +https://docs.microsoft.com/en-us/office365/securitycompliance/define-mail-flow-rules-to-encrypt-email diff --git a/psh-exo-encrypted-mailsend-script/SendEXOMailTest1.ps1 b/psh-exo-encrypted-mailsend-script/SendEXOMailTest1.ps1 new file mode 100644 index 0000000..bda17ad --- /dev/null +++ b/psh-exo-encrypted-mailsend-script/SendEXOMailTest1.ps1 @@ -0,0 +1,86 @@ +function getAuthHeader() { + Param( + [Parameter(Mandatory=$true, Position=0)] + [string]$ClientID, + [Parameter(Mandatory=$true, Position=1)] + [string]$ClientKey, + [Parameter(Mandatory=$true, Position=2)] + [string]$TenantID, + [Parameter(Mandatory=$true, Position=3)] + [string]$UserName, + [Parameter(Mandatory=$true, Position=4)] + [SecureString]$Password + ) + + $pw = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)) + + $AADURI = "https://login.microsoftonline.com/$TenantID/oauth2/token" + $GrantBody = "grant_type=password&username=$UserName&password=$pw&resource=https://graph.microsoft.com&client_id=$ClientID&client_secret=$ClientKey" + + $AADTokenResponse = Invoke-RestMethod -Uri $AADURI -ContentType "application/x-www-form-urlencoded" -Body $GrantBody -Method Post + return $AADTokenResponse.access_token +} + +function SendMessage() { + Param( + [Parameter(Mandatory=$true, Position=0)] + [string]$Subject, + [Parameter(Mandatory=$true, Position=1)] + [string]$Body, + [Parameter(Mandatory=$true, Position=2)] + [string]$Recipient, + [Parameter(Mandatory=$true, Position=3)] + [string]$ClientID, + [Parameter(Mandatory=$true, Position=4)] + [string]$ClientKey, + [Parameter(Mandatory=$true, Position=5)] + [string]$TenantID, + [Parameter(Mandatory=$true, Position=6)] + [string]$SenderEmail, + [Parameter(Mandatory=$true, Position=7)] + [SecureString]$SenderPassword + ) + + $AADToken = getAuthHeader -ClientID $ClientID -ClientKey $ClientKey -TenantID $TenantID -UserName $SenderEmail -Password $SenderPassword + $Headers = @{Authorization = "Bearer $AADToken"} + + $message = @{ + "message" = @{ + "subject" = $Subject; + "body" = @{ + "contentType" = "text"; + "content" = $Body; + }; + "toRecipients" = @( + @{ + "emailAddress" = @{ + "address" = $Recipient; + }; + }; + ); + }; + "savedToSentItems" = "false" + } + $body = ConvertTo-Json $message -Depth 5 + $SendMail="https://graph.microsoft.com/v1.0/me/sendMail" + $res = Invoke-WebRequest -Uri $SendMail -Method Post -Headers $Headers -Body $body -ContentType "application/json" +} + +#variables +$SenderAccountName = "[Sending Account Email]" +$ClientID = "[Azure AD App Registration]" +$ClientKey = "[App Registration Secret]" +$TenantID = "[Azure AD Tenant ID]" +$PW = ConvertTo-SecureString "[Clear text password of sending user account]" -AsPlainText -Force +$Recipient = "[Email Recipient]" + +#execute +SendMessage ` + -Subject "Testing Encryption 2" ` + -Body "Sending this one also from powershell, but authenticating DIRECTLY as the sending user." ` + -Recipient $Recipient ` + -ClientID $ClientID ` + -TenantID $TenantID ` + -ClientKey $ClientKey ` + -SenderEmail $SenderAccountName ` + -SenderPassword $PW diff --git a/psh-exo-encrypted-mailsend-script/SendEXOMailTest2.ps1 b/psh-exo-encrypted-mailsend-script/SendEXOMailTest2.ps1 new file mode 100644 index 0000000..5c14a3b --- /dev/null +++ b/psh-exo-encrypted-mailsend-script/SendEXOMailTest2.ps1 @@ -0,0 +1,78 @@ +function getAuthHeader() { + Param( + [Parameter(Mandatory=$true, Position=0)] + [string]$ClientID, + [Parameter(Mandatory=$true, Position=1)] + [string]$ClientKey, + [Parameter(Mandatory=$true, Position=2)] + [string]$TenantID + ) + + $AADURI = "https://login.microsoftonline.com/$TenantID/oauth2/token" + $GrantBody = "grant_type=client_credentials&client_id=$ClientID&client_secret=$ClientKey&resource=https://graph.microsoft.com" + + $AADTokenResponse = Invoke-RestMethod -Uri $AADURI -ContentType "application/x-www-form-urlencoded" -Body $GrantBody -Method Post + return $AADTokenResponse.access_token +} + +function SendMessage(){ + Param( + [Parameter(Mandatory=$true, Position=0)] + [string]$Subject, + [Parameter(Mandatory=$true, Position=1)] + [string]$Body, + [Parameter(Mandatory=$true, Position=2)] + [string]$Recipient, + [Parameter(Mandatory=$true, Position=3)] + [string]$ClientID, + [Parameter(Mandatory=$true, Position=4)] + [string]$ClientKey, + [Parameter(Mandatory=$true, Position=5)] + [string]$TenantID, + [Parameter(Mandatory=$true, Position=6)] + [string]$SenderEmail + ) + + $AADToken=getAuthHeader -ClientID $ClientID -ClientKey $ClientKey -TenantID $TenantID + $Headers = @{Authorization = "Bearer $AADToken"} + + $message = @{ + "message" = @{ + "subject" = $Subject; + "body" = @{ + "contentType" = "text"; + "content" = $Body; + }; + "toRecipients" = @( + @{ + "emailAddress" = @{ + "address" = $Recipient; + }; + }; + ); + }; + "savedToSentItems" = "false" + } + $message.message.toRecipients + $body = ConvertTo-Json $message -Depth 5 + $SendMail="https://graph.microsoft.com/v1.0/users/{0}/sendMail" -f [uri]::EscapeDataString($senderAccountName) + $res = Invoke-WebRequest -Uri $SendMail -Method Post -Headers $Headers -Body $body -ContentType "application/json" +} + +#variables +$SenderAccountName = "[Sending Account Email]" +$ClientID = "[Azure AD App Registration]" +$ClientKey = "[App Registration Secret]" +$TenantID = "[Azure AD Tenant ID]" +$Recipient = "[Email Recipient]" + +#execute +SendMessage ` + -Subject "Testing Encryption" ` + -Body "Sending this from Powershell via EXO, using a service principal with app permissions to send behalf of, and specifying an email account I created in my demo O365 subscription." ` + -Recipient $Recipient ` + -ClientID $ClientID ` + -ClientKey $ClientKey ` + -TenantID $TenantID ` + -SenderEmail $SenderAccountName +