Skip to main content

Pipeline Configuration

Configure scan schedule, commit behavior, inventory storage, module versions, and more.

Quick Reference

SettingFileDefaultPurpose
Schedule (cron)monitor-pipeline.yml / .github/workflows/scan.yml0 */6 * * *How often scan runs
Inventory pathsrc/Scan-PimState.ps1./inventory/Where state is stored
Commit messagemonitor-pipeline.yml / .github/workflows/scan.ymlISO 8601 timestampGit commit format
Git authorsrc/git.ps1"PIM Monitor"Author name
Module versionmonitor-pipeline.yml / .github/workflows/scan.yml2.35.1PowerShell module version
HTML reportPipeline variableUnsetGenerate scan report artifact
Expiring windowPipeline variable14 daysExpiring assignment detection

Schedule & Triggers

Change the scan schedule

Edit the cron expression in monitor-pipeline.yml (Azure DevOps) or .github/workflows/scan.yml (GitHub Actions):

Azure DevOps:

schedules:
- cron: "0 */6 * * *"
displayName: "PIM Change Scan (4x daily)"
branches:
include: [main]
always: true

GitHub Actions:

on:
schedule:
- cron: '0 */6 * * *'

Cron Pattern Guide

0 */6 * * * = Every 6 hours (default)
0 * * * * = Every hour
0 */3 * * * = Every 3 hours
0 9 * * * = Daily at 9 AM UTC
0 9 * * 1-5 = Weekdays at 9 AM UTC
0 0 * * 0 = Weekly (Sunday midnight UTC)
*/30 * * * * = Every 30 minutes

Why not every minute?

  • Graph API throttling (429 errors on frequent requests)
  • Noise reduction (PIM changes rarely occur every minute)
  • Cost efficiency (fewer pipeline runs = lower compute costs)

Allow manual triggers

Azure DevOps:

trigger: none
pr: none

schedules:
- cron: "0 */6 * * *"
displayName: "PIM Change Scan"
branches:
include: [main]
always: true

Users can then click Run in the Azure DevOps UI without waiting for schedule.

GitHub Actions (enabled by default):

on:
schedule:
- cron: '0 */6 * * *'
workflow_dispatch: # Manual trigger

Commit & Repository

Change the commit message format

Edit the git step in monitor-pipeline.yml (Azure DevOps) or .github/workflows/scan.yml (GitHub Actions):

Current format (ISO 8601 timestamp):

git commit -m "scan: $(date -u +%Y-%m-%dT%H:%M:%SZ)"

Example commit messages:

scan: 2026-04-27T18:42:15Z
chore: pim scan at 2026-04-27
feat: pim changes on 2026-04-27
SCAN: Daily security check

Any format works as long as it's unique enough to identify scans in git log.

Customize git commit author

Edit src/git.ps1 (lines ~33-34):

git config user.name "PIM Monitor"
git config user.email "pim-monitor@pipeline"

Change to:

git config user.name "Azure Security Team"
git config user.email "[email protected]"

The name and email appear in git history and commit metadata.

Store inventory in a subfolder

Edit src/Scan-PimState.ps1 (line ~51):

$inventoryRoot = Join-Path -Path (Get-Location) -ChildPath "inventory"

Change to:

$inventoryRoot = Join-Path -Path (Get-Location) -ChildPath "security/pim-inventory"

Then update the git add step to match:

Azure DevOps monitor-pipeline.yml:

git add security/pim-inventory/ expected-changes.json 2>/dev/null || true

GitHub Actions .github/workflows/scan.yml:

git add security/pim-inventory/ expected-changes.json

Module & Dependencies

Pin Microsoft.Graph module version

The PowerShell pipeline uses Microsoft.Graph for Azure AD queries. You can pin a specific version.

Current default: 2.35.1

Edit in monitor-pipeline.yml (Azure DevOps, line ~14) or .github/workflows/scan.yml (GitHub Actions, line ~17):

variables:
MSGRAPH_VERSION: "2.35.1"

Change to:

variables:
MSGRAPH_VERSION: "2.36.0"

When to change:

  • New Graph API features required
  • Critical security patch released
  • Compatibility issue with current version
  • Microsoft deprecates the version

What happens:

  • Pipeline cache key includes version
  • Changing version automatically invalidates cache
  • Module is re-downloaded on next run
  • Previous version cache is kept for 7 days

How to check latest:

Find-Module Microsoft.Graph | Select-Object Version

Reporting & Artifacts

Enable HTML scan report artifact

Set REPORT_ARTIFACT=true in your pipeline variables.

Azure DevOps:

  1. PipelinesPIM MonitorEditVariables
  2. Add: REPORT_ARTIFACT = true

GitHub Actions:

  1. SettingsSecrets and variablesActionsVariables
  2. Add: REPORT_ARTIFACT = true

The scan generates scan-report.html and publishes it as an artifact.

Report includes:

  • Severity summary with counts
  • All detected changes organized by severity
  • Before/after diffs
  • Tenant info and timestamp
  • Commit SHA (if available)

See Reporting & Artifacts for details.

Expiring assignments window

Set EXPIRING_WINDOW_DAYS in your pipeline variables to control early warning for expiring PIM assignments.

Default: 14 days

Examples:

  • 7 = 1 week advance notice
  • 14 = 2 weeks (default)
  • 30 = 1 month

Assignments expiring within this window are flagged as Informational severity changes.

See Expiring Assignments for details.

Environment-Specific Configuration

Staging vs. Production

If you have multiple Azure AD tenants or want different schedules per environment, create separate pipeline files:

Azure DevOps:

# monitor-pipeline-prod.yml
schedules:
- cron: "0 */6 * * *"

# monitor-pipeline-staging.yml
schedules:
- cron: "0 0 * * 0" # Weekly

Then configure two pipelines in Azure DevOps UI pointing to different files.

GitHub Actions:

# .github/workflows/scan-prod.yml
# .github/workflows/scan-staging.yml

Platform Comparison

SettingAzure DevOpsGitHub Actions
Schedule locationmonitor-pipeline.yml.github/workflows/scan.yml
Manual triggerBuilt-in (click Run)workflow_dispatch: in YAML
Module cacheVia pipeline cacheactions/cache@v4
ArtifactsBuild artifacts storageArtifact storage
Cron syntaxSame cron formatSame cron format

Troubleshooting

Pipeline not running on schedule

Check:

  • Is the main branch the default branch? Scheduled runs only on default branch
  • Are workflows enabled? (GitHub Actions)
  • Check pipeline run history for errors
  • Verify cron syntax (test at https://crontab.guru/)

Module cache not working

Check:

  • Did you change MSGRAPH_VERSION? Cache is invalidated on version change
  • Is cache size exceeded? Pipelines have cache limits
  • Try manually clearing cache and re-running

Inventory not committing

Check:

  • Are there any changes to commit? No-change scans skip commit
  • Verify git config is correct (user.name, user.email set in src/git.ps1)
  • Check pipeline permissions: must have write access to repository

Artifact not generating

Check:

  • Is REPORT_ARTIFACT=true set in variables?
  • Were changes detected? Report only generates on changes
  • Check pipeline logs for permission errors