Repository navigation
Exchange Online certificate authentication on Linux
o365-connect-exo-cert-linux.ps1 creates a certificate for app-only Exchange
Online authentication, can provision the corresponding Entra application and
Exchange permissions, and connects to Exchange Online from the current
PowerShell session.
The script is intended for Linux and requires PowerShell 7.4 or later. On
Windows, use o365-connect-exo-cert.ps1 instead.
Choose exactly one of these modes for each invocation:
| Mode | Operation |
|---|---|
-GenerateLocalCertificate |
Creates a self-signed RSA-2048/SHA-256 certificate, exports the public certificate as a .cer, and exports the private key as a password-protected .pfx. Does not require PowerShell modules unless provisioning is also requested. |
-UseCertificateAuth |
Loads a PFX into memory, validates it, and connects to Exchange Online using app-only certificate authentication. The connection is available in the PowerShell process that ran the script. |
-ProvisionEntraApp can be combined with certificate generation to perform
one-time tenant setup. It creates or reuses an Entra application, uploads the
public certificate, assigns the Exchange Exchange.ManageAsApp application
role, creates the application's service principal if necessary, and adds that
principal to the Exchange Organization Management role group. This grants
full Exchange administration; use it only when that level of access is
intended.
Provisioning requires an administrator who can consent to the requested Microsoft Graph application-management permissions and manage Exchange role groups. It uses device-code sign-in for Microsoft Graph and Exchange Online and is not available in headless mode. The script checks that the Graph and Exchange sign-ins are for the same tenant and that the supplied organization domain is an accepted domain before changing Exchange RBAC.
- Linux and PowerShell 7.4 or later.
- For connection and provisioning,
ExchangeOnlineManagement3.5.0 or later. - For
-ProvisionEntraApp,Microsoft.Graph.Authentication2.0.0 or later, plus an administrator able to complete both device-code sign-ins and authorize the setup operations. - Network access to the PowerShell Gallery when required modules need to be installed, and to Microsoft Graph and Exchange Online.
When prompts are enabled, missing modules are installed for the current user;
sudo is not needed. Headless runs require the modules to be installed already.
By default, the script stores certificate files in:
$XDG_DATA_HOME/ciaops/exo
If XDG_DATA_HOME is not set to an absolute path, it uses
~/.local/share/ciaops/exo. The default profile map is:
$XDG_CONFIG_HOME/ciaops/exo/o365-exo-cert-auth.json
If XDG_CONFIG_HOME is not set to an absolute path, it uses
~/.config/ciaops/exo/o365-exo-cert-auth.json.
Storage directories are restricted to owner-only mode 700; files created by
the script are restricted to owner read/write mode 600, independent of the
umask. Symbolic links are rejected in storage paths. Custom output and profile
directories must be dedicated to this script because their permissions are
also restricted to 700.
The PFX is encrypted with a nonempty password. The password is not saved in
the profile. Supply it interactively, pass a SecureString, or provide the
name of a process environment variable containing the password. Environment
variables are not a secret vault and may be accessible to other processes
running as the same user; prefer retrieving a SecureString from a secret
vault in automation. Do not treat ConvertFrom-SecureString output on Linux
as equivalent to Windows DPAPI protection.
During connection, the script rejects a PFX that is a symbolic link or has
permissions broader than owner read/write, checks its private key and
validity, and imports it with an ephemeral key-storage setting. It disposes of
the in-memory certificate when the script finishes. Keep the PFX private and
store a backup securely; the .cer contains only the public certificate.
-enableLog writes a transcript under the private certificate data directory.
Provisioning transcripts may contain short-lived device codes, so protect and
remove logs according to your organization's handling policy.
Run these commands in a PowerShell session on Linux. Replace the tenant domain
with the primary .onmicrosoft.com domain for your tenant:
./o365-connect-exo-cert-linux.ps1 `
-GenerateLocalCertificate `
-ProvisionEntraApp `
-Tenant contoso.onmicrosoft.comThe script prompts for a PFX password and for administrator device-code
sign-ins. -Organization defaults to -Tenant for this provisioning flow;
provisioning requires the primary .onmicrosoft.com organization domain. The
app display name defaults to the generated certificate subject, and the saved
profile name defaults to the app display name.
The script prints the .cer and .pfx paths and thumbprint. When provisioning
completes, it saves a profile containing the tenant, organization, app ID,
certificate thumbprint, and PFX path. It does not save the PFX password. New
application permissions and Exchange RBAC changes can take 15–30 minutes to
replicate.
./o365-connect-exo-cert-linux.ps1 -GenerateLocalCertificateThe defaults are subject O365-EXO-AppAuth, a two-year lifetime, and the
default certificate directory. Use -GeneratedCertSubject,
-GeneratedCertYearsValid (1–100), -GeneratedCertOutputPath, and
-GeneratedPfxPassword to customize generation. The public .cer must be
registered with an Entra application that has the appropriate Exchange
application permission and Exchange RBAC assignment before it can be used to
connect.
After provisioning and allowing time for permission replication, run:
./o365-connect-exo-cert-linux.ps1 `
-UseCertificateAuth `
-Tenant contoso.onmicrosoft.comThe script selects the matching profile and prompts for its PFX password. If
there is more than one matching profile, specify -ProfileName. -Tenant
filters profiles by their tenant or organization value.
To bypass profile lookup, supply all three connection values:
$pfxPassword = Read-Host 'PFX password' -AsSecureString
./o365-connect-exo-cert-linux.ps1 `
-UseCertificateAuth `
-Organization contoso.onmicrosoft.com `
-AppId 11111111-2222-3333-4444-555555555555 `
-CertificateFilePath "$HOME/.local/share/ciaops/exo/certificate.pfx" `
-CertificatePassword $pfxPasswordThe PFX path must identify an owner-only file. Optionally pass
-CertificateThumbprint to require that the PFX thumbprint matches an
expected value.
For a noninteractive connection, first provision the application and profile
interactively and ensure the required modules are installed. Then retrieve the
password from your secret manager as a SecureString in the same PowerShell
job and use:
./o365-connect-exo-cert-linux.ps1 `
-UseCertificateAuth `
-ProfileName 'EXO automation' `
-CertificatePassword $pfxPassword `
-noprompt `
-noupdate-noprompt also has the alias -Headless. In this mode the script cannot
install missing modules, prompt for a password, check for module updates, or
run provisioning. If a SecureString is not passed, set
-CertificatePasswordEnvironmentVariable to the name of an environment
variable injected into the process by the scheduler or secret manager. The
value is read from the process environment and is not printed or stored.
The Exchange connection does not persist across processes. Run this script in the same PowerShell process or job that will execute Exchange cmdlets, for example:
./o365-connect-exo-cert-linux.ps1 -UseCertificateAuth -ProfileName 'EXO automation' -CertificatePassword $pfxPassword -noprompt -noupdate
Get-EXOMailbox -ResultSize 10| Parameter | Purpose |
|---|---|
-GenerateLocalCertificate |
Generate a certificate and export .cer and encrypted .pfx files. |
-UseCertificateAuth |
Connect to Exchange Online using certificate authentication. |
-ProvisionEntraApp |
During generation, provision the Entra application and Exchange access. Requires interactive administrator sign-in. |
-GeneratedCertSubject |
Generated certificate common name; default O365-EXO-AppAuth. |
-GeneratedCertYearsValid |
Certificate lifetime in years; default 2, allowed range 1–100. |
-GeneratedCertOutputPath |
Dedicated certificate output directory. |
-GeneratedPfxPassword |
SecureString password for a generated PFX. If omitted, the script prompts unless headless mode is active. |
-CertificateFilePath |
Existing encrypted PFX path for connection; takes precedence over the path in a profile. |
-CertificatePassword |
SecureString PFX password. |
-CertificatePasswordEnvironmentVariable |
Name of a process environment variable to use when a password parameter is omitted. |
-CertificateThumbprint |
Optional expected certificate thumbprint; also checked when provided by a profile. |
-CertificateMapPath |
Profile JSON path. The file may be an array or an object with a profiles property. |
-Tenant |
Tenant ID/domain for provisioning, or a tenant/organization filter for profile lookup. |
-Organization |
Organization's primary .onmicrosoft.com domain for provisioning; can also be supplied explicitly for connection. |
-AppId |
Entra application client ID for an explicit connection. |
-ProfileName |
Profile name to select. |
-AppDisplayName |
Application display name during provisioning; defaults to the generated certificate subject. |
-SetupClientId |
Optional tenant-approved public client ID for Microsoft Graph device sign-in. |
-noprompt / -Headless
|
Disable prompts; requires passwords and modules to be supplied/preinstalled and cannot be combined with provisioning. |
-noupdate |
Skip the Exchange module Gallery update check. |
-enableLog |
Write a timestamped transcript in the private certificate data directory. |
-
No matching profile: check the
-Tenant,-Organization, and-ProfileNamefilters, or provide-Organization,-AppId, and-CertificateFilePathtogether for an explicit connection. -
Headless password or module error: pass a
SecureStringor configure-CertificatePasswordEnvironmentVariable, and install the required modules for the current user before running the script. -
PFX permission error: set the PFX permissions to owner read/write only,
for example
chmod 600 -- /path/to/certificate.pfx. - Certificate thumbprint or validity error: confirm the selected PFX, expected thumbprint, and certificate dates.
- Provisioned app cannot connect immediately: allow 15–30 minutes for Entra permissions and Exchange RBAC changes to replicate.
- Connection disappears: run the connection script and Exchange cmdlets in the same PowerShell process; the connection ends when that process exits.