Revision indexing in progress... (search in this revision will be accurate after indexed)
.github Loading last commit info...
config
docs
input
modules
scripts
tests
tools
.gitignore
CHANGELOG.md
CONTRIBUTING.md
LICENSE
README.md
README.md

O365 User Lifecycle Automation

Scripts and modules to onboard/offboard users with conditional licensing and flexible auth.

Table of Contents

Advanced documentation

Back to TOC

For detailed guidance and deep dives, see the docs/ pages:

What this tool does (plain English)

Back to TOC

  • Onboarding: Creates or updates a Microsoft 365 user, adds them to the right groups, and optionally assigns a license.
    • Groups are the union of: DefaultGroups (config) + mapping by site/title + per-user ExtraGroups (CSV) + CLI -ExtraGroups.
  • Offboarding: Converts the mailbox to shared, can enable an Out‑of‑Office message, optionally grants a delegate, removes direct licenses, removes groups (with configurable skips), disables sign‑in, revokes sessions, and removes the user’s delegate access to other mailboxes (FullAccess, SendAs, SendOnBehalf).
  • You can run it safely first with -WhatIf to see what would happen.

Features

  • User onboarding

    • Create or update users with idempotent checks.
    • Enrich profiles from Sites CSV (address, phones, officeLocation).
    • Add groups from DefaultGroups, site/title mapping, per-user ExtraGroups, and CLI extras.
    • Assign licenses via group-based licensing or direct SKUs.
    • Wait for mailbox provisioning; add EXO DLs/mail-enabled security after the mailbox exists.
    • Optional welcome DOCX generation with placeholders and temp password support.
  • User offboarding

    • Convert to Shared, set OOO from text/HTML templates, manage delegates (FullAccess, SendAs, SendOnBehalf).
    • Remove direct licenses and groups (with configurable skips), disable sign-in, revoke sessions.
    • Remove the user’s delegate access to other mailboxes using a fast permission cache.
  • CSV-driven automation

    • Batch onboarding/offboarding with processed flags and scheduler-friendly semantics.
    • Per-row controls like GenerateWelcome and ResetPasswordForExisting.
    • Support for custom input folders, e.g., input/my/.
  • Authentication options

    • interactive, devicecode, or app (service principal) with certificate-based auth recommended for automation.
    • Multitenant execution guidance for MSP/partners.
  • Configuration and overrides

    • Central config/appsettings.json with clear override order: CLI > env vars > appsettings.json > built-in defaults.
    • Full parameter matrix in the Configuration doc.
  • Templates and documents

    • OOO text/HTML templates with placeholders; welcome DOCX generation with robust placeholders and configurable paths.
  • Permission cache (offboarding)

    • Local mailbox-permissions cache for fast discovery with TTL/rebuild controls; optimized for batch runs.
  • Logging and diagnostics

    • Centralized logging with timestamped files, -Verbose diagnostics, and a comprehensive troubleshooting guide.
  • Safety and idempotency

    • -WhatIf dry-run across all mutating actions; idempotent operations to safely rerun.

Prerequisites (before you run anything)

Back to TOC

  • PowerShell 7.x (PowerShell Core) installed on your machine.
  • Internet access to reach Microsoft Graph and Exchange Online.
  • Permissions: Your account or your app must be allowed to manage users, groups, licenses, and Exchange settings.

Install PowerShell 7 (if you don’t have it)

Install required modules

Run this from the repo directory:

pwsh scripts/install-modules.ps1

Key Concepts

Back to TOC

  • Authentication modes: interactive, devicecode, or app (service principal). Choose based on where/how you run; see Authentication.
  • Configuration precedence: CLI parameters > environment variables > config/appsettings.json > none. See config examples below.
  • Group assignment model: User groups = DefaultGroups + site/title mapped groups + per-user ExtraGroups (CSV) + CLI -ExtraGroups.
  • WhatIf/dry-run: All mutating actions support -WhatIf. Start with dry-runs before applying changes.
  • Idempotency: Reruns are safe—existing users/groups/licenses/mailboxes are checked to avoid duplication.

Phased group assignment & mailbox provisioning

  • Graph-based groups (incl. licensing) are added first.
  • The tool waits for the mailbox to provision, then adds Exchange DL/mail-enabled security groups.
  • Timeouts and polling are configurable via Onboarding.MailboxProvisioningTimeoutSeconds and Onboarding.MailboxPollIntervalSeconds.

Quick Start

Back to TOC

1. Install modules

pwsh scripts/install-modules.ps1

2. Create your local config from the example and edit as needed (this file is git-ignored):

cp config/example.appsettings.json config/appsettings.json
# then open config/appsettings.json and adjust defaults (AuthMode, UseGroupLicensing, Onboarding timeouts, etc.)

3. Configure auth (interactive by default). For app auth, set env vars so the scripts can sign in non‑interactively:

# Certificate-based app auth (recommended for automation)
$env:O365_TENANT_ID = '<your-tenant-id>'
$env:O365_CLIENT_ID = '<your-app-client-id>'
$env:O365_CERT_THUMBPRINT = '<your-cert-thumbprint>'
# Then run with: -AuthMode app
# OR: Client secret (simpler, rotate regularly)
$env:O365_TENANT_ID = '<your-tenant-id>'
$env:O365_CLIENT_ID = '<your-app-client-id>'
$env:O365_CLIENT_SECRET = '<your-secret>'
# Then run with: -AuthMode app

4. Onboarding

  • Onboard Example (single — pass the user)
pwsh scripts/onboard.ps1 \
  -UserUpn jdoe@contoso.com \
  -GivenName John -Surname Doe -DisplayName "John Doe" \
  -JobTitle Analyst -Department Finance -UsageLocation US \
  -SiteCode SEA \
  -GroupMapCsv ./input/example-group-mapping.csv \
  -SitesCsv ./input/example-sites.csv \
  -AuthMode devicecode -UseGroupLicensing
  • Onboard Example (batch)
pwsh scripts/onboard.ps1 -UserCsv ./input/example-onboard.csv -GroupMapCsv ./input/example-group-mapping.csv -AuthMode devicecode -UseGroupLicensing

5. Offboarding

  • Offboard Example (single)
pwsh scripts/offboard.ps1 -UserUpn jdoe@contoso.com -AuthMode interactive -EnableOOO -OooTemplatePath ./config/ooo-template.txt
  • Offboard Example (batch)
pwsh scripts/offboard.ps1 -UserCsv ./input/example-offboard.csv -AuthMode interactive -SitesCsv ./input/example-sites.csv

Offboarding: permission cache behavior

Back to TOC

See: Advanced: Permission cache (offboarding)

  • The offboarding step can use a local permission cache to speed discovery of mailbox permissions.
  • Fresh cache (≤ TTL): used automatically.
  • Stale cache (> TTL, ≤ MaxCacheAgeDays):
    • Use as-is if you pass -AllowStaleCache (no prompt).
    • Auto-rebuild if you pass -AutoRefreshStaleCache.
    • Otherwise you will be prompted; choosing No proceeds using the stale cache.
  • Older than -MaxCacheAgeDays: rebuild is forced (no prompt).
  • Related parameters and defaults (config or CLI):
    • -CacheTtlSeconds (default 86400)
    • -MaxCacheAgeDays (default 30)
    • -AutoRefreshStaleCache (default false)
    • -AllowStaleCache (default false)

Dry-run mode (-WhatIf)

Back to TOC

See additional dry-run usage in: docs/examples.md

All mutating operations support PowerShell's -WhatIf for safe dry-runs. You can add -WhatIf at the script level and it will flow through to all actions.

Examples:

# Onboarding dry-run (no changes made)

pwsh scripts/onboard.ps1 -UserCsv ./input/example-onboard.csv -GroupMapCsv ./input/example-group-mapping.csv -AuthMode devicecode -UseGroupLicensing -WhatIf

# Offboarding dry-run for a single user

pwsh scripts/offboard.ps1 -UserUpn jdoe@contoso.com -EnableOOO -OooTemplatePath ./config/ooo-template.txt -AuthMode interactive -WhatIf

WhatIf is implemented via SupportsShouldProcess on all modules for operations like user creation/update, group membership changes, license assignment/removal, mailbox conversion, OOO setup, delegate grants, disabling sign-in, password reset, and session revocation.

Authentication (how the tool signs in)

Back to TOC

Read more: docs/authentication.md

You have three choices. Beginners can start with interactive.

  • Interactive: Opens a browser sign‑in window.
    • Use when running manually on a machine where you can sign in.
  • Device code: Shows a code to enter at https://microsoft.com/devicelogin (good for remote/terminal use).
  • App (service principal): Non‑interactive automation. Uses an Azure AD app with a certificate or secret.

Choosing a mode

  • If unsure, use: -AuthMode interactive
  • For remote shells: -AuthMode devicecode
  • For automation/CI: -AuthMode app (requires one‑time app setup below)

App registration (service principal) — detailed steps

Back to TOC

See detailed steps and screenshots in: docs/authentication.md » App registration (service principal) — detailed steps

  • Tip: scripts/configure-auth.ps1 lists the env vars and a quick setup helper.

Create a certificate (Windows, macOS, Linux)

Back to TOC

For step-by-step certificate creation instructions, see: docs/authentication.md » Create a certificate

Use a certificate for app auth (recommended). You’ll upload the public cert (.cer) to the App Registration and keep the private key (.pfx) securely on the machine that runs the scripts.

  • Upload the public cert to the App Registration

    • Entra ID > App registrations > Your app > Certificates & secrets > Certificates > Upload certificate
    • Select the .cer file (o365-automation.cer)
    • After upload, the portal shows the Thumbprint; use it for O365_CERT_THUMBPRINT
  • Store and reference locally

    • Keep the .pfx securely on the machine/runner (use a secret store or protected path).
    • Set environment variables for app auth:
      $env:O365_TENANT_ID = '<your-tenant-id>'
      $env:O365_CLIENT_ID = '<your-client-id>'
      $env:O365_CERT_THUMBPRINT = '<thumbprint-from-portal>'
      
    • When authenticating with certificates, the scripts will use the certificate from the Windows cert store or from a configured identity depending on your environment; if you need file-based cert loading, use your runner’s secure store to install/import the .pfx before runs.
  • Rotation tips

    • Create a new cert and upload its .cer before the old one expires; update the thumbprint env var.
    • Keep an overlap window where both certificates are valid to avoid downtime.

Quick permissions (app auth)

Back to TOC

See the authoritative list and guidance here: docs/authentication.md » Quick permissions (app auth)

Service providers: authorize your app for multiple tenants

Back to TOC

If you’re a partner/MSP and will run onboarding/offboarding across multiple customer tenants, configure your app as multi‑tenant and obtain admin consent from each customer. High‑level approaches:

See multi‑tenant scheduling guidance here: docs/scheduling.md » Multi-tenant scheduler (service providers)

Configuration defaults

Back to TOC

The configuration file is config/appsettings.json and it controls the default behavior of the scripts. It is not required but recommended to have it in place. You will essentially copy the tempate and rename it to appsettings.json. Change any values you need to match your environment. The table below shows the available settings and their default values, and provides explanations for each setting.

Note: The override order is CLI > environment variables > appsettings.json > built-in default (none).

App settings reference (appsettings.json)

Back to TOC

See the authoritative list and guidance here: docs/configuration.md » App settings reference

Here's a basic example of an appsettings.json file:

{
    "TenantId": "00000000-0000-0000-0000-000000000000",
    "DelegatedOrganization": "contoso.onmicrosoft.com",
    "ClientId": "11111111-1111-1111-1111-111111111111",
    "AuthMode": "app",
    "ReuseSession": true,
    "DefaultSitesCsv": "./input/example-sites.csv",
    "DefaultGroupMapCsv": "./input/example-group-mapping.csv",
    "DefaultOnboardCsv": "./input/example-onboard.csv",
    "DefaultOffboardCsv": "./input/example-offboard.csv",
    "UsePermissionCache": true,
    "PermissionCachePath": "./cache/permissions.json",
    "CacheTtlSeconds": 86400,
    "MaxCacheAgeDays": 30,
    "AutoRefreshStaleCache": false,
    "AllowStaleCache": false,
    "UseGroupLicensing": true,
    "MailboxMode": "group",
    "DefaultGroups": ["All Employees", "Company Portal Users"],
    "DefaultOooTemplatePath": "./config/ooo-template.txt",
    "DefaultEnableOOO": false,
    "DefaultNoConfirm": true,
    "DefaultWelcomeTemplatePath": "./config/welcome-template.docx",
    "DefaultWelcomeOutputDir": "./output/welcome",
    "UserProfile.SiteNameMapsTo": "Department",
    "Logging.LogTempPasswords": false,
    "Onboarding.MailboxProvisioningTimeoutSeconds": 120,
    "Onboarding.MailboxPollIntervalSeconds": 10,
    "Scheduler.BackupEnabled": true,
    "Scheduler.BackupDir": "./backups",
    "Scheduler.OnboardLockFile": "./.scheduler-onboard.lock",
    "Scheduler.OffboardLockFile": "./.scheduler-offboard.lock"
}

Script Parameters

Back to TOC

For the authoritative and latest matrix, see: docs/configuration.md » Script parameter matrix

Here are a few common parameters that are available in the scripts:

  • AuthMode: The authentication mode to use. Can be interactive, devicecode, or app.
  • TenantId: The tenant ID to use for authentication. This is required for app authentication.
  • ClientId: The client ID to use for authentication. This is required for app authentication.
  • SitesCsv: Path to Sites CSV used for profile enrichment and for resolving OOO placeholders like <SiteName>, <SitePhone>, <SiteEmail>.
  • GroupMapCsv: Path to group-mapping CSV (maps Site/Title to groups) used to determine group membership during onboarding.
  • CertThumbprint: The certificate thumbprint to use for authentication. This is required for app authentication.
  • ReuseSession: Reuse existing sessions to reduce prompts.
  • WhatIf: Run in WhatIf mode to see what would happen without making changes.
  • Help: Show help and exit.

Notes

  • Make sure to use quotes around multi-word arguments, e.g., -ExtraGroups "VPN Users","BI Viewers".
  • Single-user onboarding fields can be provided via CLI or in the Users CSV using a single row. In batch mode, they come from the Users CSV.
  • SitesCsv and GroupMapCsv can default from config/appsettings.json via DefaultSitesCsv and DefaultGroupMapCsv.
  • WhatIf is a PowerShell common parameter and works across all mutating actions.

See full per-setting reference and the script parameter matrix in: docs/configuration.md

  • DefaultGroups

    • What: Groups that every onboarded user will be added to.
    • Type: array of group display names or IDs.
    • Default: none.
    • Merged with: site/title mapping + per-user ExtraGroups (CSV) + CLI -ExtraGroups.
  • Default groups example: Define DefaultGroups to assign to all users during onboarding.

    {
      "DefaultGroups": ["All Employees", "Company Portal Users"]
    }
    

Back to TOC

  • AuthMode: use app for automation/CI; devicecode for cross‑platform interactive; interactive if GUI prompts are fine.
  • UseGroupLicensing: set true if your tenant uses Azure AD group‑based licensing; otherwise leave false and pass -LicenseSkuIds when needed.
  • MailboxMode: keep group unless your org provisions mailboxes via a separate process, then set manual.
  • DefaultGroups: start small (e.g., "All Employees") and expand later; prefer group names that are stable across environments.

Security notes

Back to TOC

  • Do not commit secrets in config/appsettings.json. This repo ignores config/appsettings.json by default; use config/example.appsettings.json as a template.
  • For AuthMode=app:
    • Prefer certificate authentication (rotate certs and protect private keys). Use env vars: O365_TENANT_ID, O365_CLIENT_ID, O365_CERT_THUMBPRINT.
    • If using client secrets, store in a secure secret store and expose at runtime via O365_CLIENT_SECRET only.
  • Grant the least privileges required to the app registration (see Permissions overview below).

Full example: config/appsettings.json

Back to TOC

For a full example see Configuration AppSettings

Row selection and processed flags (onboarding)

Back to TOC

  • The scheduler treats a row as already processed when either:
    • ProcessedOnboard is true/yes/1/y, or
    • ProcessedOnboardAt is a non‑empty timestamp.
  • Due rows are those with OnboardDate <= today and not already processed.
  • The scheduler ensures the ProcessedOnboard and ProcessedOnboardAt columns exist in memory and writes them after successful processing.
  • Password reset gating:
    • The -ResetPasswordForExisting CLI switch acts as a default for the run.
    • A per‑row CSV column ResetPasswordForExisting can enable/disable resets for specific rows.
    • Even when the switch/column is true, resets are skipped for rows already marked as processed.

How to use

CLI (batch):

pwsh scripts/onboard.ps1 -UserCsv ./input/my/posse-onboard.csv -SitesCsv ./input/my/PosseSites.csv -GenerateWelcome -ResetPasswordForExisting

Effect: New users get temp passwords as before; existing users have their password reset and included in the welcome doc; rows marked “processed” will skip resets.

CLI (single user):

pwsh scripts/onboard.ps1 -UserUpn user@contoso.com -GenerateWelcome -ResetPasswordForExisting

Effect: The generated temporary CSV row will include ResetPasswordForExisting=true.

Per-row CSV control:

Add ResetPasswordForExisting column with values true/yes/1 (or false/no/0) to control resets for specific users. Even if enabled, resets are skipped for rows already marked processed.

Troubleshooting configuration

Back to TOC

See troubleshooting steps for auth, config, CSVs, and logs in: docs/troubleshooting.md

Input files (CSV) you’ll prepare

Back to TOC

For per-column schemas of each CSV, see: docs/templates.md » CSV input templates

Custom input folders

You can create a "my" folder in input to store your own custom files, e.g., input/my/example-onboard.csv. This is to use your own custom files separate from the default files in the repository and will not affect updates to the repository

Note: The "my" folder is not committed to the repository

Default input files

Back to TOC

  • Users CSV (input/example-onboard.csv): one row per user. Common columns:

    • UserPrincipalName, DisplayName, GivenName, Surname, JobTitle, Department
    • Office, SiteCode, Country, UsageLocation, optional ManagerUPN, etc.
    • The SiteCode is used to fill the user’s address/phone info from the Sites CSV (below).
    • Optional scheduler/welcome columns:
      • OnboardDate, ProcessedOnboard, ProcessedOnboardAt
      • GenerateWelcome — set to true/yes/1 per row to produce a welcome DOCX for that user
      • ResetPasswordForExisting — set to true/yes/1 to reset password for existing users for this row (CLI -ResetPasswordForExisting acts as a default)
  • Group mapping CSV (input/example-group-mapping.csv): tells the tool which groups to add based on site and/or title.

    • Columns: mappingType (Site or Title), mappingKey (e.g., NYC, Analyst), groups (separate multiple with ; or :).
  • Sites CSV (input/example-sites.csv): authoritative list of sites and their contact info; used to enrich users.

    • Columns: SiteCode, SiteName, Street, City, State, PostalCode, Country, Phone, Fax, SiteEmail.
    • When you specify -SitesCsv, the tool will set the user’s officeLocation, address fields, and businessPhones from the matching site.
  • Extra groups (per user): Add an ExtraGroups column to input/example-onboard.csv with ; or : separated values.

    • Example: VPN Users; BI Viewers
    • These are merged with DefaultGroups and any groups from the group mapping for that user.
  • Offboarding CSV (input/example-offboard.csv): drives bulk offboarding.

    • Columns: UserUpn, DelegateUpn, SiteCode, EnableOOO, OooTemplatePath, EnableLitigationHold, HoldDurationDays, PreserveGroupLicenses, SkipGroups, DeleteUser, GrantSendAs, GrantSendOnBehalf, HideFromGal
    • Notes:
      • SkipGroups: comma or semicolon separated display names of groups to skip during removal (e.g., All Users; Everyone).
      • DeleteUser: true/false. If true, the user is soft-deleted after cleanup. Default is not deleting (account is disabled and locked out).
      • Delegate cleanup includes removal of the user’s FullAccess, SendAs, and SendOnBehalf permissions to other mailboxes.
      • EnableOOO: true/false. When true, OooTemplatePath is required. Template supports placeholders described in the OOO Templates section.
      • DelegateUpn: Optional. If provided, used in OOO placeholders and delegate logic.
      • EnableLitigationHold and HoldDurationDays: Optional legal hold controls.
      • PreserveGroupLicenses: When true, skips removing licenses assigned via group membership.
      • SiteCode: Optional. If provided, the OOO placeholders <SiteName>, <SitePhone>, and <SiteEmail> are resolved from the Sites CSV by matching this code.
      • HideFromGal: Optional true/false. When true, hides the user from the Global Address List.
    • Example usage:
      pwsh scripts/offboard.ps1 -UserCsv ./input/example-offboard.csv -AuthMode interactive -WhatIf
      

Templates

Back to TOC

Custom input folders

You can create a "my" folder in config to store your own custom files, e.g. config/my/ooo-template.txt. This is to allow you to keep your own custom files separate from the default files in the repository and will not affect updates to the repository

Note: The "my" folder is not committed to the repository

Overview

Back to TOC

Looking for the full templates guide (CSV schemas, OOO, Welcome DOCX)? See: docs/templates.md

Out-of-Office (OOO) templates

You can provide a text or HTML file as the Out‑of‑Office template (e.g., config/ooo-template.txt or config/ooo-template.html). Placeholders below will be replaced during offboarding:

  • <userFullName>: Display name of the user being offboarded
  • <delegateFullName>: Display name of the delegate user specified by -DelegateUpn (blank if not provided)
  • <delegateEmail>: The email/UPN passed via -DelegateUpn (blank if not provided)
  • <SiteName>: Resolved using SiteCode if provided; otherwise based on UserProfile.SiteNameMapsTo (Department or OfficeLocation) matched against the Sites CSV keys.
  • <SitePhone>: Looked up from the Sites CSV for the resolved site
  • <SiteEmail>: Looked up from the Sites CSV for the resolved site

Notes:

  • Provide -SitesCsv ./input/example-sites.csv to enable <SitePhone>/<SiteEmail> lookup and ensure SiteName matches.
  • If a value cannot be found, it is replaced with an empty string.

Example OOO template:

Hello, thank you for your email <userFullName> is no longer with us. Please contact <delegateFullName> at <delegateEmail> for assistance.

Alternatively you can call <SitePhone> to speak to a member of the <SiteName> team.

Example command (text template):

pwsh scripts/offboard.ps1 \
  -UserUpn jdoe@contoso.com \
  -DelegateUpn manager@contoso.com \
  -EnableOOO -OooTemplatePath ./config/ooo-template.txt \
  -SitesCsv ./input/example-sites.csv \
  -AuthMode interactive -WhatIf

HTML OOO template example

Back to TOC

  • Rich formatting is supported by Exchange auto‑replies. This repo includes config/ooo-template.html you can customize.
  • Use the same placeholders (e.g., <userFullName>, <delegateEmail>, <SiteName>, <SitePhone>, <SiteEmail>).

Example command (HTML template):

pwsh scripts/offboard.ps1 \
  -UserUpn jdoe@contoso.com \
  -DelegateUpn manager@contoso.com \
  -EnableOOO -OooTemplatePath ./config/ooo-template.html \
  -SitesCsv ./input/example-sites.csv \
  -AuthMode interactive -WhatIf

Welcome document (DOCX)

Back to TOC

  • Generate a welcome document from a DOCX template with placeholders. The template is copied and placeholders in word/document.xml are replaced with user/site values.
  • A sample text template is provided at config/welcome-template.txt to help you draft content; copy its contents into your DOCX template at ./config/welcome-template.docx (or your custom path).

See full placeholder reference and authoring guidance: docs/templates.md » Welcome DOCX authoring guidelines

  • Template and output defaults (configurable in config/appsettings.json):

    • DefaultWelcomeTemplatePath: ./config/welcome-template.docx
    • DefaultWelcomeOutputDir: ./output/welcome
  • Usage

    • Single user (generate directly):
      pwsh scripts/onboard.ps1 -UserUpn jdoe@contoso.com -GenerateWelcome -SitesCsv ./input/example-sites.csv -SiteCode SEA
      
    • Batch (per‑row control via CSV):
      • Add a GenerateWelcome column to input/example-onboard.csv and set to true/yes/1 for rows that should receive a welcome doc.
      pwsh scripts/onboard.ps1 -UserCsv ./input/example-onboard.csv -GenerateWelcome
      
    • Override paths explicitly:
      pwsh scripts/onboard.ps1 -UserCsv ./input/example-onboard.csv -GenerateWelcome \
        -WelcomeTemplatePath ./config/welcome-template.docx -WelcomeOutputDir ./output/welcome
      
    • For existing users, the welcome document is generated even if a temp password is not available. If no temp password is available, the <TempPassword> placeholder is blank. To generate a new temp password for existing users and include it in the doc, pass -ResetPasswordForExisting (or set ResetPasswordForExisting per row in the CSV). The reset forces change at next sign‑in. The password is not logged.

Notes

  • The welcome DOCX contains a temporary password; restrict access to the output directory.
  • The password is not logged unless Logging.LogTempPasswords is set to true in config.

Step‑by‑step: Onboarding (beginner)

More examples (full/minimal/common): docs/examples.md » Onboarding

  1. Fill in your CSVs:
    • input/example-onboard.csv (copy and edit)
    • input/example-group-mapping.csv (copy and edit)
    • input/example-sites.csv (copy and edit)
  2. Do a safe dry‑run to preview actions:
    pwsh scripts/onboard.ps1 \
      -UserCsv ./input/example-onboard.csv \
      -GroupMapCsv ./input/example-group-mapping.csv \
      -SitesCsv ./input/example-sites.csv \
      -ExtraGroups "VPN Users","BI Viewers" \
      -AuthMode interactive -UseGroupLicensing -WhatIf
    
  3. If it looks good, remove -WhatIf to apply changes.

Step‑by‑step: Offboarding (beginner)

More examples (full/minimal/common): docs/examples.md » Offboarding

  1. Identify the user’s UPN (email) to offboard.
  2. Dry‑run first:
    pwsh scripts/offboard.ps1 \
      -UserUpn jdoe@contoso.com \
      -EnableOOO -OooTemplatePath ./config/ooo-template.txt \
      -AuthMode interactive -WhatIf
    
  3. Remove -WhatIf to perform the actions.

Bulk offboarding (CSV)

You can offboard multiple users from a CSV using -UserCsv. For details see Offboarding (CSV) and examples in docs/examples.md.

Permissions overview (quick)

Back to TOC

  • Microsoft Graph: User.ReadWrite.All, Group.ReadWrite.All, Directory.ReadWrite.All (as applicable), AuditLog.Read.All (optional for diagnostics)
  • Exchange Online: Mailbox permissions to convert to shared, set OOO, add delegates (typically Exchange Admin role)
  • Use least privilege; app-based auth requires admin consent for application permissions.

Permissions Matrix

See the full, maintained matrix here: docs/authentication.md » Permissions Matrix

Sample outputs

Back to TOC

Onboarding (WhatIf excerpt)

What if: Performing the operation "Create user" on target "jdoe@contoso.com".
What if: Performing the operation "Add to groups" on target "jdoe@contoso.com -> [Grp A, Grp B]".
What if: Performing the operation "Assign licenses" on target "jdoe@contoso.com -> [SPE_E5]".

Offboarding (WhatIf excerpt)

What if: Performing the operation "Convert mailbox to Shared" on target "jdoe@contoso.com".
What if: Performing the operation "Disable sign-in and revoke sessions" on target "jdoe@contoso.com".

Performance tips (offboarding mailbox discovery)

  • Use -SharedOnly when you only need to revoke access on Shared Mailboxes. This reduces discovery time significantly in large tenants.
  • Watch elapsed timing: After target computation you’ll see a log like Discovery completed in N.N seconds (scope: ...) to quantify runtime.
  • Future option: We plan to expose a generalized -RecipientTypeDetails filter (keeping -SharedOnly as shorthand) for precise scoping (e.g., SharedMailbox, UserMailbox).
  • Advanced (optional):
    • Provide a curated list of candidate mailboxes via a future -MailboxCsv to limit search space.
    • Opt‑in parallel discovery with a throttle may help in some tenants but can hit EXO throttling; default will remain serial for reliability.

Permission cache (offboarding)

Back to TOC

For the comprehensive guide (flags, behavior, performance tips), see: docs/permission-cache.md

Logging

Back to TOC

  • Default location: logs/ at the repo root. Each run creates a UTF-8 log: run-YYYYMMDD_HHmmss.log.
  • Initialization: Initialize-Logging sets $global:O365_LogFile and creates the directory/file if missing.
  • Writing: Write-Log -Level Info|Warn|Error|Debug -Message <text> writes to console and appends to the current log file.

Read more: docs/logging.md

Frequently asked questions

  • Back to TOC
  • Do I need admin rights? Yes. Your signed‑in identity (or app) must have permissions to manage users, groups, licenses, and Exchange mailboxes.
  • What if a user already exists? The tool updates only the fields you provide or derive from the site; it won’t duplicate users or groups.
  • How are licenses applied? If -UseGroupLicensing is set, license assignment is done by Azure AD group membership policies. If not, you can pass -LicenseSkuIds for direct assignment.
  • Where are logs? By default these logs are located at logs/ at the repo root. Each run creates a UTF-8 log: run-YYYYMMDD_HHmmss.log. See Logging section below for more details.

Troubleshooting

Back to TOC

For a structured troubleshooting guide (auth, config, CSV/scheduler, templates, cache, logging), see: docs/troubleshooting.md

  • Common topics in the guide:
    • Distribution group ambiguity and remediation steps
    • Auth errors, module issues, and license/group troubleshooting
    • Provisioning/replication delays and how to verify state
    • CSV/scheduler issues, templates/welcome generation, and permission cache behavior
    • Ensure usageLocation is set before direct license assignment; otherwise Graph will reject license changes.
  • Unknown SiteCode: The tool will warn and continue; fix the SiteCode or add the site to the Sites CSV.
  • Ensure PowerShell 7.x and required modules are available.
  • Use -Verbose and/or -WhatIf to inspect actions.
  • Logs are written to UTF-8 timestamped files via Initialize-Logging.

Contributing

Back to TOC

We welcome contributions! Please read CONTRIBUTING.md for:

  • How to report bugs and request features
  • Development setup (PowerShell 7, modules, local config)
  • Coding guidelines (approved verbs, -WhatIf, help docs)
  • Git workflow and PR checklist

Issues

Back to TOC

Before opening a new issue, search existing ones. When filing a bug, include:

  • Exact command(s) run and parameters
  • Relevant CSV snippets (with sensitive info redacted)
  • Expected vs actual behavior (include error text/output)
  • Environment: OS, $PSVersionTable.PSVersion, module versions

Scripts

Back to TOC

  • scripts/onboard.ps1 — batch onboarding; supports group-based licensing or direct license assignment.
    • Optional: -SitesCsv ./input/example-sites.csv to validate/enrich from SiteCode.
  • scripts/offboard.ps1 — safe offboarding sequence (convert to shared, OOO, delegate, cleanup, disable, revoke).
  • scripts/install-modules.ps1 — installs required modules.
  • scripts/configure-auth.ps1 — guidance for setting auth environment variables.

Roadmap

Back to TOC

  • Master dispatcher script (e.g., scripts/manage.ps1) providing a single entry point with -Mode onboard|offboard, central auth, and shared logging, while delegating to existing scripts.
  • Add screenshots/GIFs for auth flows and CSV examples.
  • Add Pester tests for critical functions and batch processing.
  • Add GitHub issue/PR templates and CI checks.
  • Add Update User functionality, e.g., move user site, update group membership based on title, add groups, remove groups, update license, etc.
  • Add Exchange Online functionality for additional properties, e.g., set mailbox quota, set mailbox retention policy, addressbook policy, etc.
  • Add Azure AD functionality, e.g., set user properties, update user photo, etc.
  • Add OneDrive functionality, e.g., offboarding archive, grant access to onedrive for delegate, etc.
  • Improve offboarding mailbox permissions discovery performance:
    • Generalize scope filter to -RecipientTypeDetails (keep -SharedOnly as shorthand).
    • Optional parallel discovery with configurable -ThrottleLimit (opt-in; default off to avoid EXO throttling).
    • Optional curated candidate list input (e.g., -MailboxCsv) to limit search space.
    • Add discovery elapsed timing logs to quantify improvements.
  • Refactor documentation: break out advanced topics into docs/ (scheduling, authentication deep-dive, templates, permission cache), and keep README as a concise entry point with links.

License

Back to TOC

This project is licensed under the MIT License. See LICENSE for details.

Please wait...
Connection lost or session expired, reload to recover
Page is in error, reload to recover