Repository navigation
SharePoint Online certificate authentication on Linux
o365-connect-pnp-cert-linux.ps1 generates a file-based certificate, can
provision an Entra application for it, and connects PnP.PowerShell to a
SharePoint Online site using certificate authentication.
The script is intended to run on Linux in PowerShell 7.4.6 or later. It is not the Windows certificate-store workflow; the private key is kept in an encrypted PFX file and loaded ephemerally when connecting.
- Linux and PowerShell 7.4.6 or later.
- For connections, PnP.PowerShell 3.0.0 or later.
- To provision an Entra app, Microsoft.Graph.Authentication 2.0.0 or later, plus an administrator who can sign in and grant the requested application permissions.
- Network access to the PowerShell Gallery when a required module needs to be installed or updated, and to Microsoft Graph and SharePoint Online.
When allowed to install a missing module, the script installs it for the
current user (CurrentUser scope); it does not require sudo. Certificate
generation by itself uses .NET and does not require either module.
Exactly one of -GenerateLocalCertificate and -UseCertificateAuth must be
specified.
./o365-connect-pnp-cert-linux.ps1 -GenerateLocalCertificateThe script prompts for a nonempty PFX password unless
-GeneratedPfxPassword or -CertificatePasswordEnvironmentVariable supplies
it. It creates:
- An RSA-2048, SHA-256 self-signed certificate.
- A public DER-encoded
.cerfile. - An encrypted private-key
.pfxfile.
Both files are named using the certificate thumbprint. The script prints their paths, the thumbprint, and the expiry date. The private key is not imported into a persistent certificate store.
Useful generation options:
| Parameter | Purpose | Default |
|---|---|---|
-GeneratedCertSubject |
Certificate common name; also the default app display name when provisioning. | O365-PNP-AppAuth |
-GeneratedCertYearsValid |
Certificate lifetime, from 1 through 100 years. | 2 |
-GeneratedCertOutputPath |
Dedicated directory for the generated files. | XDG data path described below |
-GeneratedPfxPassword |
Nonempty SecureString password for the generated PFX. |
Prompted interactively |
Generation can be combined with one-time app provisioning:
./o365-connect-pnp-cert-linux.ps1 `
-GenerateLocalCertificate `
-ProvisionEntraApp `
-Tenant contoso.onmicrosoft.com `
-SiteUrl https://contoso.sharepoint.comProvisioning requires an absolute HTTPS -SiteUrl, -Tenant, and an
interactive administrator sign-in. The script uses Microsoft Graph device-code
authentication. -noprompt/-Headless cannot be used with provisioning.
The script creates an Entra app or reuses the single app with the requested display name, adds the public certificate credential, and ensures the app has these application permissions:
- SharePoint:
Sites.FullControl.All— full control of all SharePoint sites. - Microsoft Graph:
Application.Read.All— read access to directory applications.
It creates the service principal and role assignments if needed, then saves a
connection profile containing the tenant, site URL, app ID, certificate
thumbprint, and PFX path. The default profile name is the app display name;
-ProfileName can override it. Set -AppDisplayName to choose a different app
name. If multiple apps already have that name, provisioning stops rather than
choosing one arbitrarily.
The administrator sign-in requests Graph delegated scopes
Application.ReadWrite.All and AppRoleAssignment.ReadWrite.All to carry out
provisioning. These are setup permissions for the signed-in administrator; the
two application permissions listed above are granted to the app being
provisioned. Review and approve these privileges according to your
organization's policy. New permissions may take time to replicate, so connect
from a fresh PowerShell session after provisioning.
-SetupClientId optionally selects a tenant-approved public client ID for
Graph device sign-in. Without it, the script uses the Microsoft Graph
PowerShell client.
Connect from a saved profile:
./o365-connect-pnp-cert-linux.ps1 `
-UseCertificateAuth `
-Tenant contoso.onmicrosoft.comIf more than one saved profile matches the supplied filters, select one explicitly:
./o365-connect-pnp-cert-linux.ps1 `
-UseCertificateAuth `
-ProfileName ContosoAlternatively, supply all connection values directly:
./o365-connect-pnp-cert-linux.ps1 `
-UseCertificateAuth `
-Tenant contoso.onmicrosoft.com `
-SiteUrl https://contoso.sharepoint.com `
-AppId 11111111-2222-3333-4444-555555555555 `
-CertificateFilePath /home/admin/auth.pfxFor an interactive connection, the script prompts for the PFX password. The
site URL must be an absolute HTTPS URL. The PFX must contain a private key, be
currently valid, and must not grant permissions to group or other users
(0600 is the normal setting). The script
checks the certificate thumbprint if -CertificateThumbprint is supplied or
stored in the selected profile, and warns when the certificate expires in
fewer than 30 days.
Profiles are filtered by exact -ProfileName, -Tenant, and -SiteUrl
values. The script requires exactly one match. If a profile stores a relative
PFX path, it is resolved relative to the profile file's directory. A
Windows-style profile containing only a certificate thumbprint is not
sufficient on Linux: provide a PFX through -CertificateFilePath or add a
certificateFilePath value to that profile.
For automation, pass a SecureString password from a secret vault:
./o365-connect-pnp-cert-linux.ps1 `
-UseCertificateAuth `
-Tenant contoso.onmicrosoft.com `
-SiteUrl https://contoso.sharepoint.com `
-AppId 11111111-2222-3333-4444-555555555555 `
-CertificateFilePath /home/admin/auth.pfx `
-CertificatePassword $vaultPassword `
-noprompt `
-noupdateAlternatively, name an environment variable populated by the scheduler or secret manager:
./o365-connect-pnp-cert-linux.ps1 `
-UseCertificateAuth `
-ProfileName Contoso `
-CertificatePasswordEnvironmentVariable PNP_PFX_PASSWORD `
-Headless `
-noupdate-noprompt is an alias-compatible spelling of -Headless. In this mode, the
relevant password must be passed as a SecureString or provided through the
named process environment variable, and required modules must already be
installed. Passwords are not saved in profiles or printed. Environment
variables can be read by processes running as the same user, so a secret vault
and a SecureString are preferable where practical.
-noupdate skips the PnP.PowerShell Gallery version check. Without it, the
script checks for a newer version when interactive; installing an update
requires confirmation. Update-check failures are warnings, not connection
success guarantees. Headless mode skips update checks.
The script connects in the current PowerShell process and leaves the PnP
connection active when it completes successfully. Run it in the same
PowerShell session or job that will execute PnP cmdlets; a separate pwsh -File
process exits when the script finishes, ending that process's connection. If
previously loaded module assemblies conflict with the required version, use a
fresh pwsh session.
By default, certificate files and transcript logs use:
-
$XDG_DATA_HOME/ciaops/pnpwhenXDG_DATA_HOMEis set to an absolute path; otherwise~/.local/share/ciaops/pnp.
The profile map defaults to:
-
$XDG_CONFIG_HOME/ciaops/pnp/o365-pnp-cert-auth.jsonwhenXDG_CONFIG_HOMEis set to an absolute path; otherwise~/.config/ciaops/pnp/o365-pnp-cert-auth.json.
The profile file can be a JSON array or an object with a profiles array. Each
profile records a name, tenant, site URL, app ID, certificate thumbprint, and
certificate file path. Passwords are never included. -CertificateMapPath
selects a different profile map; custom output and profile directories must be
dedicated to this script because it restricts their permissions.
The script sets its storage directories to owner-only permissions (0700) and
creates private files with owner read/write permissions (0600), independent
of the process umask. It rejects symbolic links in storage paths and rejects a
symbolic-link PFX. A PFX with any group/other permissions is refused; correct
an existing file with, for example:
chmod 600 -- /home/admin/auth.pfx-enableLog writes a uniquely named transcript under the private certificate
data directory. Provisioning transcripts may include short-lived device codes;
protect and remove logs according to your security and retention policies.
| Parameter | Description |
|---|---|
-GenerateLocalCertificate |
Generate the certificate files. |
-UseCertificateAuth |
Load a PFX and connect to SharePoint Online. |
-ProvisionEntraApp |
During generation, provision the Entra app and save a profile. Requires -Tenant, -SiteUrl, and interactive sign-in. |
-Tenant |
Tenant ID or domain for provisioning/connection and profile filtering. |
-SiteUrl |
Absolute HTTPS SharePoint site URL; required for provisioning and explicit connection. |
-AppId |
Entra application (client) ID for an explicit connection. |
-CertificateFilePath |
PFX path; overrides the path from a profile. |
-CertificatePassword |
PFX password as a SecureString for connection. |
-CertificatePasswordEnvironmentVariable |
Process environment variable name containing the password, used only when the relevant secure-string parameter is omitted. |
-CertificateThumbprint |
Optional expected thumbprint to verify against the PFX. |
-CertificateMapPath |
JSON profile map path. |
-ProfileName |
Exact profile name to select; during provisioning, also overrides the saved profile name. |
-AppDisplayName |
App display name for provisioning; defaults to -GeneratedCertSubject. |
-SetupClientId |
Optional public client ID for Microsoft Graph device sign-in. |
-noprompt / -Headless
|
Disable prompts; requires passwords and modules to be prepared, and skips update checks. |
-noupdate |
Skip the PnP.PowerShell Gallery version check. |
-enableLog |
Save a transcript in the private certificate data directory. |
| Symptom | Resolution |
|---|---|
| “Specify exactly one…” | Use exactly one of -GenerateLocalCertificate or -UseCertificateAuth. |
| Headless mode requires a password | Pass the appropriate password as a SecureString, or configure the named environment variable in the process before running. |
| Required module is missing in headless mode | Install the required module for the current user before running; headless mode does not install modules. |
| A module is loaded below the required version | Start a fresh pwsh session after installing the required version. |
| No unique matching profile | Specify -ProfileName, refine the tenant/site filters, or supply all four explicit connection values. |
| PFX permissions are rejected | Remove group/other access (for example, chmod 600 -- /path/to/file.pfx) and retry. |
| PFX is rejected as a certificate without a private key | Supply the encrypted .pfx, not the public .cer. |
| Expected thumbprint does not match | Verify that the PFX and profile/parameter thumbprint refer to the same certificate. |
| Connection fails soon after provisioning | Allow Entra permission replication time and retry from a fresh PowerShell session. |
For cmdlet details, see the Connect-PnPOnline documentation.