Skip to content
Sponsor
3.0 preview2.3.0 stable

These docs describe the preview. Pick the version you run and every page marks what it doesn't have yet. Get the preview →
Maester 2.x docs (archived) →

Configuration overview

Maester uses a configuration file called maester-config.json to customize how tests are run and to define global settings for your environment. This guide explains the basics; the run configuration reference lists every section and key.

From Maester 3.0 the tests carry their own defaults (severity, parameters), and the module no longer ships a configuration file with a row per test. Your configuration only holds what you want to change.

Maester reads these files from the folder you pass with -Path (or the current folder), each one optional:

  1. maester-config.json - your main configuration. Maester looks in -Path, -Path/tests and up to five parent folders.
  2. custom/maester-config.json - an overlay on the main file, for example settings owned by a different team.
  3. maester-config.<tenantId>.json - settings for one tenant, merged over the other two once Maester knows which tenant you are connected to.

Each file merges over the one before, so a tenant file only needs the values that differ for that tenant.

Instead of files next to your tests, you can pass a configuration with Invoke-Maester -Config (a path, an object, or several merged left to right) or the MAESTER_CONFIG environment variable. Then the files next to your tests are not read.

The configuration file has two main sections:

{
"GlobalSettings": {
// Organization-wide settings that apply to multiple tests
},
"TestSettings": [
// Test-specific settings like severity levels
]
}

The GlobalSettings section contains organization-wide configuration that can be used by multiple tests. For example, you can define your emergency access accounts here so that all related tests use the same accounts.

A test receives a global setting as one of its parameters, so Get-MtTest shows which tests use it and the result shows the value each test ran with. To give one test a different value, set the parameter in that test’s TestSettings row; it wins over GlobalSettings:

{
"GlobalSettings": { "ParkedDomains": ["contoso-old.com"] },
"TestSettings": [ { "Id": "CIS.M365.2.1.9", "Parameters": { "ParkedDomains": [] } } ]
}

Maester checks GlobalSettings once, before any test runs:

  • A value of the wrong type, or one the setting does not allow, stops the run with a message that names the setting.
  • A key Maester does not know gives a warning that names the closest setting, so a typo such as ParkedDomain is not silently ignored.
  • A setting marked sensitive is written to the results as [redacted].

Your own custom tests can have settings too. Name them Namespace.Key, for example Contoso.Regions, so they cannot collide with a setting of Maester or of a pack. A Maester Pack declares the settings it reads, and they are checked the same way when the pack runs. The run configuration reference lists every setting Maester knows.

The XSPM unified identity query uses Advanced Hunting externaldata sources to enrich identity results. You can override these sources with HTTPS mirrors by adding XspmExternalDataUris to the GlobalSettings section of your custom configuration:

{
"GlobalSettings": {
"XspmExternalDataUris": {
"EntraDirectoryRoles": "https://mirror.contoso.com/Classification_EntraIdDirectoryRoles.json",
"MicrosoftApps": "https://mirror.contoso.com/MicrosoftApps.json",
"ApiPermissions": "https://mirror.contoso.com/Classification_ApiPermissions.json",
"ArmApiRequests": "https://mirror.contoso.com/ArmApiRequest.csv"
}
}
}

All values must be absolute HTTPS URIs. Because externaldata is evaluated by Defender Advanced Hunting, the mirror must be reachable by that service, not only by the computer running Maester. See Microsoft’s Advanced Hunting best practices for details.

Omitted keys retain their built-in defaults. A mirror must preserve the original JSON or CSV schema. Use an immutable commit URL or a versioned mirror object when reproducible classification is required; the default URLs still track upstream branches. User information and fragments in URIs are rejected. Signed query strings are supported, but treat the configuration file as a secret and grant only read access to the mirrored data. Maester suppresses verbose configuration/query logging on this path and redacts configured query strings in its diagnostic message. This does not control logging by the service or by external instrumentation.

The TestSettings section changes individual tests by ID: severity, turning a test off, parameter values and timeouts.

{
"TestSettings": [
{ "Id": "MT.1005", "Severity": "Critical" },
{ "Id": "MT.1089", "Enabled": false, "Reason": "Not relevant for this tenant" },
{ "Id": "MT.1198", "Parameters": { "MaximumValidityDays": 180 } }
]
}

A disabled test is not run and appears in the report as Not run with the reason you gave. See Severity Levels and the run configuration reference.

Selection (which tests run), Environment (facts about the tenant and which applicability checks are enforced), Execution (timeouts), Output (CI test result files) and Metadata (labels echoed in the results) are described in the run configuration reference.

Maester runs with its default settings when there is no config file, so you only need one to change something. Create maester-config.json in a folder and run Invoke-Maester -Path <folder> (or run Maester from that folder), or pass the file with Invoke-Maester -Config <file> or the MAESTER_CONFIG environment variable. Only include the settings you want to change. Here’s a complete example:

{
"GlobalSettings": {
"EmergencyAccessAccounts": [
{
"UserPrincipalName": "[email protected]",
"Type": "User"
},
{
"Id": "00000000-0000-0000-0000-000000000000",
"Type": "Group"
}
]
},
"TestSettings": [
{
"Id": "MT.1005",
"Severity": "Critical"
}
]
}

The following global settings are available for customization:

SettingDescriptionDocumentation
EmergencyAccessAccountsDefine your break glass accounts and groupsEmergency Access Accounts
ParkedDomainsAccepted domains that never send email; the email authentication checks expect them to deny all mailThis page
DefenderEndpointPolicyFilteringWhich Defender for Endpoint policies the Defender checks read: All, IncludeUnassigned or OnlyAssigned (default)This page
DefenderEndpointComplianceLogicHow the Defender for Endpoint checks combine policies: EffectivePolicy (default), AllPolicies or AnyPolicyThis page
XspmExternalDataUrisOverride the HTTPS sources used by XSPM Advanced Hunting queriesThis page

The GitHub and Dataverse settings are listed in the run configuration reference.

When several files are found, each one merges over the one before:

  • TestSettings rows are matched by Id, and each property you set replaces the same property in the lower file.
  • Other sections are merged key by key.
  • Lists replace lists: an empty list in a higher file clears the lower one.

This means you only need to include the settings you want to change or add.

Run Maester without running any test to see which configuration it used and what it would do:

$plan = Invoke-Maester -DryRun -PassThru
$plan.MaesterConfig.ConfigSource # the files that were read
$plan.Tests | Group-Object Result, ReasonCode

See Applicability and reason codes for what each reason means.