Connecting to Microsoft 365 data requires:
- creating one Microsoft Entra ID (former Azure Active Directory, AAD) application per Microsoft 365 data source (eg,
msft-entra-id
,outlook-mail
,outlook-cal
, etc). - configuring an authentication mechanism to permit each proxy instance to authenticate with the Microsoft Graph API. (since Sept 2022, the supported approach is federated identity credentials)
- granting admin consent to each Entra ID enterprise application to specific scopes of Microsoft 365 data the connection requires.
Steps (1) and (2) are handled by the terraform
examples. To perform them, the machine running
terraform
must be authenticated with Azure CLI as
a Microsoft Entra ID user with, at minimum, the following role in your Microsoft 365 tenant:
- Cloud Application Administrator to create/update/delete Entra ID applications and its settings during Terraform apply command.
Please note that this role is the least-privileged role sufficient for this task (creating a Microsoft Entra ID Application), per Microsoft's documentation. See Least privileged roles by task in Microsoft Entra ID.
This role is needed ONLY for the initial terraform apply
. After each Azure AD enterprise
application is created, the user will be set as the owner
of that application, providing ongoing
access to read and update the application's settings. At that point, the general role can be
removed.
Step (3) is performed via the Microsoft Entra ID web console through an user with administrator permissions.
Running the terraform
examples for steps (1)/(2) will generate a document with specific
instructions for this administrator. This administrator must have, at minimum, the following role in
your Microsoft 365 tenant:
- Privileged Role Administrator to Consent to application permissions to Microsoft Graph
Again, this is the least-privileged role sufficient for this task, per Microsoft's documentation. See Least privileged roles by task in Microsoft Entra ID.
Psoxy uses Federated Identity Credentials to authenticate with the Microsoft Graph API. This approach avoids the need for any secrets to be exchanged between your Psoxy instances and your Microsoft 365 tenant. Rather, each API request from the proxy to Microsoft Graph API is signed by an identity credential generated in your host cloud platform. You configure your Azure AD application for each connection to trust this identity credential as identifying the application, and Microsoft trusts your host cloud platform (AWS/GCP) as an external identity provider of those credentials.
Neither your proxy instances nor Worklytics ever hold any API key or certificate for your Microsoft 365 tenant.
See Microsoft Workload Identity Federation docs for details. Specifically, the relevant scenario is workload running in either GCP or AWS (your proxy host platform)
The video below explains the general idea for identity federation for Azure AD-gated resources more generally, of which your Graph API is an example: {% embed url="https://www.youtube.com/watch?v=WIs3IRCJhEo" %}
The following Scopes are required for each connector. Note that they are all READ-only scopes.
Source | Examples | Application Scopes |
---|---|---|
Entra ID | data - rules | User.Read.All Group.Read.All MailboxSettings.Read |
Calendar | data - rules | User.Read.All Group.Read.All Calendars.Read MailboxSettings.Read |
data - rules | User.Read.All Group.Read.All Mail.ReadBasic.All MailboxSettings.Read |
|
Teams (beta) | data - rules | User.Read.All Team.ReadBasic.All Channel.ReadBasic.All Chat.Read.All ChannelMessage.Read.All CallRecords.Read.All OnlineMeetings.Read.All |
NOTE: the above scopes are copied from infra/modules/worklytics-connector-specs. They are accurate as of 2023-04-12. Please refer to that module for a definitive list.
NOTE: that Mail.ReadBasic
affords only access to email metadata, not content/attachments.
NOTE: These are all 'Application' scopes, allowing the proxy itself data access as an application, rather than on behalf of a specific authenticated end-user ('Delegated' scopes).
If you do not have the 'Cloud Application Administrator' role, someone with that or an alternative role that can create Azure AD applications can create one application per connection and set you as an owner of each.
You can then import
these into your Terraform configuration.
First, try terraform plan | grep 'azuread_application'
to get the Terraform addresses for each
application that your configuration will create.
Second, ask your Microsoft admin to create an application for each of those, set you as the owner,
and send you the Object ID
for each.
Third, use terraform import <address> <object-id>
to import each application into your Terraform
state.
At that point, you can run terraform apply
and it should be able to update the applications with
the settings necessary for the proxy to connect to Microsoft Graph API. After that apply, you will
still need a Microsoft 365 admin to perform the admin consent step for each application.
See https://registry.terraform.io/providers/hashicorp/azuread/latest/docs/resources/application#import for details.
DEPRECATED - will be removed in v0.5; this is not recommended approach, for a variety of
reasons, since Microsoft released support for
federated credentials
in ~Sept 2022. See our module azuread-federated-credentials
for preferred alternative.
Psoxy's terraform modules create certificates on your machine, and deploy these to Azure and the keys to your AWS/GCP host environment. This all works via APIs.
Sometimes Azure is a bit finicky about certificate validity dates, and you get an error message like this:
│ Error: Adding certificate for application with object ID "350c0b06-10d4-4908-8708-d5e549544bd0"
│
│ with module.msft-connection-auth["azure-ad"].azuread_application_certificate.certificate,
│ on ../../modules/azuread-local-cert/main.tf line 27, in resource "azuread_application_certificate" "certificate":
│ 27: resource "azuread_application_certificate" "certificate" {
│
│ ApplicationsClient.BaseClient.Patch(): unexpected status 400 with OData
│ error: KeyCredentialsInvalidEndDate: Key credential end date is invalid.
╵
Just running terraform apply
again (and maybe again) usually fixes it. Likely it's something with
with Azure's clock relative to your machine, plus whatever flight time is required between cert
generation and it being PUT to Azure.