Skip to content

satorisage/console-pwsh

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MSP Console

A menu-driven PowerShell cockpit for Microsoft 365 administration — built for MSP techs who live in Exchange Online and Entra ID all day. One launch, connect once, and drive mailboxes, permissions, mail flow, anti-spam, users, groups, licenses, MFA, and reporting from a single keyboard-friendly menu. Every tenant-changing action confirms first and is written to an audit log.

Modern stack only. Uses ExchangeOnlineManagement v3+ (REST-based, no basic-auth/WinRM) and Microsoft.Graph. The retired AzureAD and MSOnline modules are intentionally not used.

Requirements

  • PowerShell 7+ (brew install powershell on macOS, winget install Microsoft.PowerShell on Windows)
  • Modules (the console can install them for you from Tools → Install modules):
    • ExchangeOnlineManagement ≥ 3.4.0
    • Microsoft.Graph ≥ 2.15.0
    • Az.Accounts, Az.Resources, Az.Compute, Az.Storage, Az.Billing, Az.App, Az.OperationalInsights (optional — only for the Azure infrastructure / Container Apps suite; install with the "include Azure" prompt)

Quick start

pwsh ./Start-MSPConsole.ps1
  1. Press C → connect Exchange / Graph / Azure (browser sign-in).
  2. Pick a platform hub — E Exchange Online, N Entra ID, A Azure — then a feature area. Reads are instant; writes confirm and log.
  3. Reports export timestamped CSVs into exports/.

First run with no modules? Open Tools → Install modules and let it pull them.

Configure

Copy the sample and edit to taste (the live file is git-ignored):

cp config/settings.sample.json config/settings.json
Setting Purpose
DefaultTenantId Tenant to target on Graph connect
DefaultDomain Auto-completes bare usernames → user@domain
AntiSpamPolicyName Hosted content filter policy to edit (usually Default)
DefaultUsageLocation Required before assigning licenses
PageSize Rows per page in long listings
ConfirmDestructive Master confirm gate for changes (keep true)
GraphScopes Delegated scopes requested at Graph sign-in

Settings are editable live from Tools → Edit settings.

Feature map

The home screen is three platform hubs plus Connect and Tools.

Connect — Exchange / Graph / Azure sign-in, status, module install/check.

E Exchange Online

Area Highlights
Mailboxes list/search, details+stats, create shared, convert type, forwarding, OOO, archive, litigation hold
Permissions FullAccess, SendAs, Send-on-Behalf, calendar delegation
Anti-Spam / Allow-Block policy allow/block lists, Tenant Allow/Block List, quarantine list & release
Mail Flow transport rules, SCL -1 allowlist rule, block rule, message trace, connectors
Groups / DLs distribution & security groups, M365 groups, membership
Reports mailbox sizes, forwarding audit (BEC), shared-mailbox perms, inactive mailboxes

N Entra ID

Area Highlights
Users list, details, create, reset password, enable/disable, revoke sessions, attributes
Groups list, members, add/remove, create
Licenses SKU availability, assign/remove, per-user report
Security & MFA MFA registration report, Conditional Access, risky users, admin roles
Directory Reports sign-ins, audit log, inactive users, tenant overview

A Azure

Area Highlights
App Registrations & Secrets list/create apps, mint/rotate client secrets, request Graph API permissions, grant admin consent, create SP, delete
Domains list, add custom domain, show DNS verification (TXT/MX) records, verify, remove
Infrastructure (Az) subscriptions + switch, resource groups (create/delete), resources, VMs (start/stop/restart), storage accounts, month-to-date cost summary
Container Apps + logs list apps by resource group, details (image/ingress/replicas), revisions, pull console/system logs from Log Analytics, restart a revision

T Tools

Install modules, edit settings, CSV bulk runner, log viewer, exports, session summary.

Whitelisting an email — pick the right mechanism

The console exposes all three because they are not equivalent:

  1. Anti-Spam → Add allowed sender — a spam-scoring hint. Convenient, but Defender can still quarantine high-confidence phish/malware. ("Almost never spam.")
  2. Mail Flow → Allowlist rule (SCL -1) — hard bypass of spam filtering, keyed on the envelope sender. The reliable "guarantee delivery" option.
  3. Anti-Spam → Tenant Allow/Block List — false-positive remediation for a spoofed/blocked sender, URL, or file hash.

Audit & exports

  • Logs: logs/msp-console-YYYY-MM-DD.log — one line per operation, with the acting admin and target. Every change is tagged ACTION.
  • Exports: exports/<report>-<timestamp>.csv.

Architecture

Start-MSPConsole.ps1     # entry point: load order, init, run loop
src/Core/                # engine — never changes when you add features
  Config.ps1             #   $Global:MSP shared state + settings
  UI.ps1                 #   banners, tables, prompts, confirm gate
  Logging.ps1            #   audit log + Invoke-Safely wrapper
  Helpers.ps1            #   CSV import/export, pickers, size parsing
  Connections.ps1        #   EXO / Graph / Az connect + Assert-Connection
  MenuEngine.ps1         #   declarative menu renderer/dispatcher
src/Features/*.ps1       # one file per area; each exports a Get-*Menu builder
  Exchange*.ps1          #   Mailbox, Permissions, AntiSpam, MailFlow, Groups, Reporting
  Entra*.ps1             #   Users, Groups, Licenses, Security, Reporting
  Azure*.ps1             #   AppRegistrations, Domains, Infra (Az)
src/Menus/MainMenu.ps1   # platform hubs (Exchange/Entra/Azure) wired into the tree
tests/                   # Run-Tests.ps1 (no deps), TenantMocks.ps1, Pester specs

Adding a feature = write an Invoke-* function and add a New-MenuItem to the relevant Get-*Menu. The engine never changes. Menu keys are case-insensitive; avoid B and Q (reserved for Back/Quit).

Tests

Everything runs offline — no tenant, no network.

pwsh ./tests/Run-Tests.ps1                              # full harness (4 layers)
pwsh -c 'Invoke-Pester ./tests/Tenant.Tests.ps1 -Output Detailed'   # just the mocked behavioural tests

Run-Tests.ps1 layers:

  1. Syntax — every .ps1 parses.
  2. Load — all modules load and every menu builds (-SelfTest).
  3. Conventions — no duplicate/reserved menu keys, every item wired.
  4. Tenant-mock behaviour (Pester 5+, auto-skips if absent) — runs Tenant.Tests.ps1.

Tenant mocks

tests/TenantMocks.ps1 stubs every external cmdlet (Exchange / Graph / Az) so the real Invoke-* action functions execute with no live connection. tests/Tenant.Tests.ps1 then mocks the interactive prompts, invokes a function, and asserts the correct cmdlet fired with the right arguments — e.g. that adding an allowlisted sender calls Set-HostedContentFilterPolicy -AllowedSenders @{Add=...}, that the SCL -1 rule sets -SetSCL -1, and that container-app logs resolve the Log Analytics workspace and query ContainerAppConsoleLogs_CL.

To add a test: mock the prompts (Read-Input, Select-FromList, Confirm-Action, Read-YesNo), mock the target cmdlet, invoke, then Should -Invoke <Cmdlet> -ParameterFilter { ... }. If you call a cmdlet not yet in TenantMocks.ps1, add its name to the catch-all list (or give it a small param-block stub if you need to filter on its arguments).

Install Pester once: Install-Module Pester -Scope CurrentUser -Force.

Live smoke test (read-only)

Mocks prove the console calls the right cmdlet with the right arguments — they can't prove a real cmdlet/property name is correct against the live API. That's what tests/Invoke-LiveSmokeTest.ps1 is for.

# already connected in your session:
pwsh ./tests/Invoke-LiveSmokeTest.ps1

# sign in first, test only Azure, target one app's log path:
pwsh ./tests/Invoke-LiveSmokeTest.ps1 -Connect -Azure -ResourceGroup rg-apps -ContainerApp web

# or fold it into the full harness as layer 5:
pwsh ./tests/Run-Tests.ps1 -Live

It is strictly read-only. Only Get-* and Log Analytics query cmdlets run — no New/Set/Remove/Add/Update/Start/Stop/Restart/Revoke. It reads a couple of objects per service and, for container apps, resolves the managed-environment Log Analytics workspace and runs a take 1 KQL query. It cannot create, change, or delete anything; the worst case is a probe prints FAIL (which is the point — it catches a mistyped cmdlet, a renamed property, or a missing permission). Each probe reports PASS / FAIL / SKIP; the run exits non-zero only if a probe on a connected service fails.

Safety notes

  • Destructive actions gate behind Confirm-Action (respect ConfirmDestructive).
  • The forwarding audit and admin-role reports exist specifically to catch BEC / privilege creep — run them on any tenant you inherit.
  • config/settings.json and logs/ are git-ignored; never commit tenant data.

Disclaimer

Community project — not affiliated with or endorsed by Microsoft. It calls the official ExchangeOnlineManagement, Microsoft.Graph, and Az PowerShell modules on your behalf. You are responsible for what you run against your tenants; every change confirms and is logged, but review before you execute.

License

MIT — see LICENSE. Contributions welcome.

About

Menu-driven PowerShell console for Microsoft 365 admin — Exchange Online, Entra ID & Azure (app registrations, custom domains, Container Apps + logs). MSP-friendly, every change audit-logged, offline + read-only-safe tests.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors