Baseline Repository Setup
The baseline repository is a configuration-only store of JSON policy files deployed to every managed tenant. This guide covers how to create it, populate it, and keep it maintained.
What Is the Baseline Repository?
No pipeline execution. Purely JSON policy files.
Every tenant pipeline checks out baseline at runtime.
All changes tracked in Git with descriptive commit messages.
Important: The baseline repo does not connect to any tenant and never runs deployments. It is purely a store for configuration files. Tenant pipelines check it out and apply the configs.
Step 1: Create the Repository
- 1. Go to Repos → New repository
- 2. Name:
baseline - 3. Project:
{YourProject} - 4. Click Create
Step 2: Populate Baseline Configurations
Option A: Export from Reference Tenant (Recommended)
If you have a reference M365 tenant with your standard policies, back it up and copy the JSON files into baseline.
Create a reference tenant
Onboard a reference tenant in the CONFIG365 portal. This creates a tenant-reference Gitea repo with the reference tenant's credentials.
Run the backup pipeline
Run the pipeline with "Run Backup Stage" enabled. JSON files are committed to backups/ in the repo.
Copy to baseline
Copy backups/groups/*.json → baseline/groups/, backups/conditional-access/* → baseline/conditional-access/, etc.
Placeholders are already applied
The backup pipeline automatically outputs files with {{GROUP:name}}, {{LOCATION:name}}, and {{TENANTID}} instead of hardcoded IDs. No manual replacement needed.
Option B: Create JSON Files Manually
In Gitea, navigate to the baseline repository → Files → the appropriate subfolder → ⋯ → New File, or push directly via Git. Example group file:
{
"displayName": "Baseline - Emergency Access",
"description": "Emergency access accounts excluded from CA policies",
"mailEnabled": false,
"securityEnabled": true,
"mailNickname": "baseline-emergency-access"
} Step 3: Verify Repository Structure
baseline/ ├── baseline/ │ ├── authentication-policies/ │ │ ├── microsoft-authenticator.json │ │ └── passkeys-fido2.json │ ├── conditional-access/ │ │ ├── named-locations/ │ │ │ └── AVD.json │ │ ├── policies/ │ │ │ └── Baseline - *.json (30+ policies) │ │ └── optional-applications.json │ ├── custom-attributes/ │ │ ├── attribute-definitions/ │ │ │ └── BaselineCSAAppExclusions_CAExclusion.json │ │ └── attribute-sets/ │ │ └── BaselineCSAAppExclusions.json │ ├── enterprise-apps/ │ ├── entra-id-consentpermissions/ │ │ ├── permissionClassifications/ │ │ │ └── low.json │ │ └── policies/ │ │ ├── admin-consent-request-policy.json │ │ └── authorization-policy.json │ ├── entra-id-device-settings/ │ │ ├── device-registration-policy.json │ │ └── entra-id-settings.json │ ├── exchange/ │ │ └── transport-rules/ │ │ └── Baseline - *.json (3 rules) │ ├── groups/ │ │ └── Baseline - *.json (50+ groups) │ ├── intune/ │ │ ├── app-protection/ │ │ │ └── Android_Baseline - *.json / iOS_Baseline - *.json │ │ ├── autopilot/ │ │ ├── compliance-policies/ │ │ │ └── Baseline - *.json / *.assignment.json │ │ ├── platform-scripts-powershell/ │ │ │ └── Baseline - *.json / *.ps1 / *.assignment.json │ │ ├── platform-scripts-bash/ │ │ │ └── Baseline - *.json / *.sh / *.assignment.json │ │ ├── settings-catalog/ │ │ │ └── Baseline - *.json / *.assignment.json │ │ ├── windows-driver-updates/ │ │ ├── windows-feature-updates/ │ │ ├── windows-quality-updates/ │ │ └── windows-updates/ │ ├── sharepoint-settings/ │ │ └── sharepoint-sharingCapability.json │ └── teams/ ├── baseline-remove/ └── README.md
Step 4: Maintenance
Updating Baseline Configurations
Edit the JSON file directly in Gitea or via Git, commit with a descriptive message:
git commit -m "Baseline update: Enable MFA policy (was report-only)"
Always test baseline changes with a single tenant pipeline before rolling out to all tenants.
Removing Resources from Tenants
To remove a resource from all tenants, add a minimal JSON file to baseline-remove/ matching the subfolder type:
{
"displayName": "Old Deprecated Policy"
} Cross-Tenant Placeholders
Use placeholders for values that differ per tenant. The deployment scripts resolve them by querying the target tenant before applying the configuration.
{{GROUP:Baseline - Emergency Access}} Replaced with the group's object ID in the target tenant
Used in: excludeGroups or groupId fields
{{LOCATION:Corporate Offices}} Replaced with the named location ID in the target tenant
Used in: includeLocations fields
{{TENANTID}} Replaced with the tenant's Tenant ID
Used in: Cross-tenant references
{
"displayName": "Baseline - Require MFA",
"state": "enabledForReportingButNotEnforced",
"conditions": {
"users": {
"includeUsers": ["All"],
"excludeGroups": ["{{GROUP:Baseline - Emergency Access}}"]
}
}
} Common Issues
Baseline files not loading in tenant pipeline
Solution: Check the pipeline resources section — the baseline repository must be referenced as a repository resource with ref: refs/heads/main
Group not found error
Solution: Groups must be deployed before policies that reference them. Check the group displayName matches exactly (case-sensitive). Use {{GROUP:displayname}} placeholder syntax.
Changes not taking effect
Solution: Verify changes are committed and pushed to baseline, then re-run the tenant pipeline. Check the Plan output shows expected changes.