Architecture

PatchPilot365 is a single system an MSP runs itself, built to bridge the gap between vulnerability management and remediation across every customer tenant it manages. It doesn’t replace the Microsoft services a customer already pays for — it orchestrates Defender for Endpoint and Intune, using the GDAP relationship the MSP already holds with that customer, with the correct, already-established permissions rather than a new standing credential of its own.

There’s no agent on a customer’s devices and PatchPilot365 installs nothing on them. Every finding it shows and every fix it applies goes through Microsoft Defender for Endpoint and Intune, in the customer’s own tenant — using the access an engineer’s own Microsoft account already has there, for as long as a single request takes and no longer. PatchPilot365 holds no password or standing key for any customer.

This page is a summary aimed at someone deciding whether to adopt PatchPilot365 or explaining it to a colleague. The in-app Setup > Architecture page (visible once signed in) is the maintained source of truth, with interactive diagrams you can click into for detail — see Navigating PatchPilot365: Setup.

How the engineer and PatchPilot365 reach a tenant

An engineer signs in with their own Microsoft account, bringing whatever GDAP roles that account already holds in each customer tenant. Their browser only ever holds a session cookie — never a Graph token. When PatchPilot365 needs to do something in a tenant, it asks Microsoft Entra ID for a short-lived token scoped to that one tenant and nothing else.

  • Home tenant (the MSP’s own): reached via the On-Behalf-Of flow — PatchPilot365 exchanges the engineer’s live sign-in, server-side, for a token. This needs someone actually signed in, which is why an overnight schedule keeps the owning engineer’s renewable credential for up to 90 days; if that engineer stops signing in, their schedules stop with a clear message rather than failing silently.
  • Customer tenants: reached through the GDAP relationship set up during onboarding. The token PatchPilot365 receives inherits exactly the roles the signed-in engineer personally holds in that customer — Microsoft doesn’t allow an application to hold GDAP roles of its own, so there is no mode in which PatchPilot365 acts as itself.
flowchart LR
    Engineer["Engineer"] -->|"signs in with GDAP roles"| PP["PatchPilot365"]
    PP -->|"asks for a token"| Entra["Microsoft Entra ID"]
    Entra -->|"On-Behalf-Of"| MSPHome["MSP home tenant"]
    subgraph Customers["Customer tenants — GDAP"]
        CustA["Customer Tenant A"]
        CustB["Customer Tenant B"]
        CustC["Customer Tenant C"]
    end
    Entra -->|"delegated token"| CustA
    Entra --> CustB
    Entra --> CustC

How PatchPilot365 proves its own identity to Entra

Every token request above is made by PatchPilot365’s own app registration in the MSP’s home tenant, and Entra makes the app prove who it is each time. That app credential never grants access to a tenant by itself — tokens still carry only the engineer’s delegated roles — but it is what stops a stolen refresh token from being redeemed anywhere else.

  • Instance-generated certificate (default). When you download the pairing script, the instance generates a key pair. The script registers only the public certificate on the app; the private key stays on the server, encrypted in its database. It’s valid for a year, and Setup > App Registration warns 30 days before it expires.
  • Client secret. Still supported for instances that paired before certificates, or when you choose it. A secret can be copied and used from anywhere, so it’s the least protective option.
  • Azure VM, by default: the VM’s managed identity, registered on the app as a federated credential, so nothing is stored on the instance at all. The pairing script uses it automatically when the instance finds one in the MSP tenant.
  • Azure VM, opt-in: a certificate or secret kept in Azure Key Vault, where a Key Vault certificate’s key never leaves the vault. The vault is reached with the VM’s managed identity, so this doesn’t work off Azure. Neither Azure option has been verified against a live Azure deployment yet.

The renewable credential an overnight schedule relies on is an engineer’s refresh token, cached in Redis. Each cache entry is encrypted and bound to that engineer’s own cache key, so it can’t be copied under another engineer’s name, and Redis can require a password. To limit where a stolen token would work at all, see Conditional Access.

Remediation options, channels, and catalogs

PatchPilot365 matches every finding against a set of package/script catalogs to work out the actual fix, then dispatches it through one of several Microsoft-owned channels. Which channel runs is picked automatically — Live Response by default — or an engineer can override it from the Run Now dialog.

Four catalogs feed that decision:

  • Winget — the default match for an app finding.
  • Chocolatey and the Microsoft Store — a small hand-curated fallback for apps winget doesn’t cover.
  • Windows Update Catalog — Microsoft’s own live, per-tenant list of quality-update releases.
  • Script Catalog — PatchPilot365’s library of custom PowerShell for findings that map to none of the above; cataloged, but dispatched manually rather than picked automatically.

Of the remediation channels, three are wired end-to-end today:

Channel Latency Use
Defender Live Response Seconds Ad-hoc script on a single device
Win32 app deployment (Intune) 5–15 min Packaged Winget upgrade at scale
Expedited Quality Update (Intune) Hours OS quality patches

A fourth, Intune’s on-demand proactive remediation, is fully modeled in the data layer (selectable, preflight-checked, present in historical job rows) but not actually dispatched by the worker yet — kept modeled deliberately for a future release rather than removed outright.

flowchart LR
    Winget["Winget Catalog"] -->|"match a package"| PP["PatchPilot365"]
    Alt["Chocolatey / Microsoft Store"] -->|"fallback match"| PP
    WUCatalog["Windows Update Catalog"] -->|"match a release/KB"| PP
    Script["Script Catalog"] -->|"manual pick"| PP

    subgraph Customer["Inside the customer tenant"]
        LiveResponse["Defender Live Response"]
        AppDeploy["Intune app deploy (Win32 / Store)"]
        WUPolicies["Intune Windows Update policies"]
        IntuneRemediation["Intune proactive remediation (modeled, not used)"]
        Device["Managed Windows device"]
    end

    PP -->|"seconds"| LiveResponse
    PP -->|"minutes"| AppDeploy
    PP -->|"hours"| WUPolicies
    PP -.->|"modeled — not used"| IntuneRemediation

    LiveResponse -->|"runs the script"| Device
    AppDeploy -->|"installs the app"| Device
    WUPolicies -.->|"installs when due"| Device

How a fix reaches a device

Remediation runs through Defender for Endpoint’s Live Response. The device is already enrolled in Defender and Intune, so there’s no agent for PatchPilot365 to install — it asks Defender to run a script on the machine and waits for the verdict. The script is published to the customer’s Live Response library once, named by a hash of its own contents, and reused after that. Success is decided from a marker the script prints itself rather than trusting Defender’s reported exit code, since a script can exit zero having done nothing.

Windows Update work (feature updates, quality updates, update rings, driver updates) goes through a separate path, described next.

flowchart LR
    PP["PatchPilot365"] -->|"run this script"| Defender["Defender for Endpoint"]
    Defender -.->|"poll for the result"| PP
    PP -->|"sync / expedite update"| Intune["Intune / Microsoft Graph"]

    subgraph Customer["Inside the customer tenant"]
        Defender
        Intune
        Device["Managed Windows device"]
    end

    Defender -->|"runs it on the machine"| Device
    Intune -->|"applies policy"| Device

How Windows updates are identified and delivered

The Windows Updates hub covers four Intune policy types: feature updates and quality updates, which PatchPilot365 can create and delete, plus update rings and driver updates, which it only reads and displays.

  • Quality updates are matched against a real catalog — Microsoft publishes the tenant’s actual list of monthly and out-of-band releases, and PatchPilot365 either matches a Defender-reported missing KB against it or lets an engineer pick a release directly.
  • Feature updates have no such catalog — PatchPilot365 writes the target Windows version label (e.g. “24H2”) straight into the policy.

Delivery for both is the same shape: create an Intune policy and assign it to a real Entra group. Once assigned, delivery is out of PatchPilot365’s hands — the device pulls the policy on its own Windows Update check-in.

flowchart LR
    PP["PatchPilot365"] -->|"read catalog / write policy"| Graph["Microsoft Graph — Windows Update APIs"]
    Graph -.->|"catalog & policy state"| PP

    subgraph Customer["Inside the customer tenant"]
        Graph
        Group["Entra security group"]
        Device["Managed Windows device"]
    end

    Graph -->|"assigns policy"| Group
    Group -.->|"device installs when due"| Device

Microsoft APIs used

Defender calls go to api.securitycenter.microsoft.com; Intune calls go to graph.microsoft.com. Every call is made with a delegated token for a single tenant and recorded in the audit log against the engineer who caused it.

Network requirements at a glance

Two networks matter, and only one is under the MSP’s control:

  • PatchPilot365’s own server needs outbound access to the two Microsoft API hosts above, plus login.microsoftonline.com for auth. On Azure with the managed identity it also needs the VM’s instance metadata endpoint (169.254.169.254), and with Key Vault the vault’s own host (<vault-name>.vault.azure.net). Off Azure, a pairing-script download makes one short (2-second) attempt to reach that metadata endpoint and moves on.
  • Every managed device needs its own outbound access for the Defender sensor and the Intune Management Extension — this is usually the network a remediation job actually stalls or fails on, not PatchPilot365’s server. Full current host lists and AV/whitelisting exclusion paths are on the in-app Architecture page’s “Whitelisting requirements” section, since Microsoft revises these lists independently of PatchPilot365 releases.

See Requirements for licensing and role prerequisites, and Known Issues for what this architecture can’t do yet.