Sentinel-As-Code - Build and Test Guide

July 10, 2026 · View on GitHub

Running and validating without a local PowerShell install

Prepared forAny organisation adopting Sentinel-As-Code
Version1.0
Applies toThe Sentinel-As-Code repository

Contents


Executive summary

Your organisation needs to build, test and deploy the Sentinel-As-Code solution, which requires full end-to-end testing of every configuration item locally in PowerShell before it is promoted. Because PowerShell 7, the Az modules and related tooling often cannot be installed on managed end-user devices, this guide sets out sanctioned methods that provide that same local PowerShell testing in a controlled Azure or cloud-hosted environment.

The work divides into two activities. End-to-end testing runs the full Pester test suite, the PR-validation gate and a deployment dry-run that exercises every analytics rule, playbook, workbook and automation rule. It must be carried out locally in PowerShell 7 against a test workspace so that all configuration is validated before promotion. Deployment authenticates to Azure and is normally carried out by the CI/CD pipeline rather than by a person, so it does not depend on any individual workstation.

The recommended primary method is a Windows 365 Cloud PC: a persistent, Intune-managed desktop on which IT installs PowerShell 7, the required modules and the full developer toolchain once. It gives engineers a governed environment in which to run the complete end-to-end tests locally in PowerShell, with nothing installed on their own device. Four alternatives are documented - Azure Cloud Shell, GitHub Codespaces, CI/CD-only and a container image - so each team can adopt the approach that best fits its security posture. All requirements in this guide are derived from the repository's own scripts, module manifests and CI configuration, which remains the single source of truth.

At a glance

  • Constraint: no local install of PowerShell, the Az modules or related tooling on managed devices.
  • Test (validate): full end-to-end testing of every configuration item, run locally in PowerShell 7 - the Pester suite, the PR-validation gate and a deployment dry-run against a test workspace.
  • Use (deploy): PowerShell 7.2 or later, the Az and Microsoft.Graph modules and the right Azure permissions; normally pipeline-driven.
  • Recommended method: a Windows 365 Cloud PC with all tools pre-installed, giving a governed place to run the local PowerShell end-to-end tests; Azure Cloud Shell, GitHub Codespaces, CI/CD-only and a container image are alternatives.
  • Baseline runtime: PowerShell 7.2 or later; Windows PowerShell 5.1 is not supported.

1 Purpose and audience

This guide explains everything your organisation needs to build, run and test the Sentinel-As-Code solution, and gives a practical method to do so without installing PowerShell, the Az modules, or any other tooling on a local workstation.

It is written for the platform, security and DevOps engineers who will own the Sentinel-As-Code pipeline. It assumes familiarity with Azure and Microsoft Sentinel, but not with the specifics of this repository.

1.1 The constraint

Local installation of PowerShell 7, the Az PowerShell modules and supporting binaries is often not permitted on managed end-user devices. Rather than treat this as a blocker, this guide positions a set of sanctioned, zero-local-install execution methods that run the same tooling in a controlled Azure or cloud-hosted context.

1.2 What this guide gives you

  • The complete list of requirements - runtime, PowerShell modules, external binaries and permissions - split by what you need to validate (test) the project versus use (deploy) it.
  • A comparison of smart execution options that need nothing installed locally, with a recommended primary and several fallbacks.
  • Step-by-step run and test instructions for the recommended method and the main alternatives.

Source of truth. Requirements in this document are derived from the repository's own scripts, module manifests and CI configuration. If a script changes its dependencies, the repository documentation is updated in the same change - treat the repository as authoritative.

2 What you are building and testing

Sentinel-As-Code is a CI/CD solution that deploys Microsoft Sentinel and Defender XDR content from a Git repository. It provisions infrastructure (Bicep) and deploys Content Hub solutions, custom analytical rules, hunting queries, watchlists, playbooks, workbooks, parsers, automation rules, summary rules and Defender XDR custom detections.

There are two distinct activities, and they have very different requirements:

ActivityWhat it meansWhere it runs
Validate (test)Run the Pester test suite and the PR-validation gate to prove content and scripts are correct, before anything touches a live tenant.Any host with PowerShell 7 - no Azure access required for the core suite.
Use (deploy)Authenticate to Azure and deploy infrastructure and content to a real Sentinel workspace and Defender XDR tenant.A host with PowerShell 7, the Az/Graph modules, and the right Azure permissions.

The good news for a no-local-install scenario: validation needs almost nothing, and deployment is normally done by the pipeline, not by a person. The execution methods in Section 4 cover both cases.

3 Requirements

3.1 Baseline runtime

  • PowerShell 7.2 or later - required by every script and declared in the Sentinel.Common module manifest (PowerShellVersion = '7.2'). Windows PowerShell 5.1 is not supported.

3.2 Modules required to validate the project

This is all you need to run the Pester suite and the PR-validation gate via Tools/Invoke-PRValidation.ps1. CI pins exact versions; the local minimums are looser.

ModulePinned (CI)Local minimumWhy
Pester5.7.15.0.0Runs every Tests/*.Tests.ps1 suite
powershell-yaml0.4.12anyYAML schema tests, dependency-manifest gate, content parsing
Az.Accounts2.0.0+2.0.0Hard dependency of Sentinel.Common, imported transitively by the module-unit tests

Why so little? All other Az and Microsoft.Graph cmdlets used by the deploy scripts are mocked in the test suite, so they are not needed to validate the project. This is what makes browser-based validation in Cloud Shell practical.

3.3 Modules required to use (deploy) the project

ModuleRequired byDeclared via
Az.AccountsSentinel.Common manifest; the Deploy-* content scripts; Export-DefenderDetections; Export-SentinelWorkbooks; Invoke-DCRWatchlistSync#Requires / manifest
Az.ResourcesDeploy-CustomContent (playbook ARM deploy); Set-PlaybookPermissions; Setup-ServicePrincipalcmdlet usage / header
Az.LogicAppSet-PlaybookPermissionsRequires: header
Az.KeyVaultPlaybook permissions / Key Vault referencesdocs
Az.ManagedServiceIdentityService-principal / managed-identity setupdocs
Az.OperationalInsightsDeploy pipeline and nightly workflow; Documenter collectorcmdlet usage
Microsoft.Graph.ApplicationsSetup-ServicePrincipalInstall-Module (auto)
Microsoft.Graph.Identity.DirectoryManagementSetup-ServicePrincipalInstall-Module (auto)
powershell-yamlDeploy-CustomContent; Deploy-DefenderDetections; Export-DefenderDetections; Import-CommunityRules; Build-DependencyManifestInstall-Module (auto)
Sentinel.Common (local)Every deploy script plus Build-DependencyManifestImport-Module from Modules/

Scripts marked (auto) install the module on first run if it is missing. Pre-installing avoids interactive prompts in non-interactive contexts such as pipelines.

3.4 Sentinel Documenter modules

The read-only Documenter pins its own module set. The collector imports the Az modules; the renderer only needs powershell-yaml.

ModulePinned versionModulePinned version
Az.Accounts3.0.4Az.Resources7.4.0
Az.SecurityInsights3.1.2Az.LogicApp1.7.0
Az.OperationalInsights3.2.0powershell-yaml0.4.12
Az.Monitor5.2.1

3.5 External (non-module) dependencies

These are only needed for specific optional tools, not for the core validate-or-deploy path. Note that some are not present in Azure Cloud Shell (see Section 6).

DependencyRequired by
git (2.x+ on PATH)Import-CommunityRules; Migrate-ForkLayout (and cloning the repo)
pandoc (on PATH)Convert-MarkdownToWord; Convert-FolderToWordReport
Node.js + @mermaid-js/mermaid-cliConvert-MermaidToImage (Documenter diagrams)
Azure CLI + Bicep (az bicep build)PR-validation bicep-build job
ImportExcel (module)Standalone SDL migration workbook export only

3.6 Permissions

Modules get you the cmdlets; you still need the right Azure RBAC roles, Entra ID directory roles and Microsoft Graph application permissions for the scripts to do anything against a live tenant. None of this is needed to validate the project - only to deploy.

Authoritative references: Azure built-in roles, Microsoft Sentinel roles and permissions, Azure RBAC conditions (ABAC) and the Microsoft Graph permissions reference. Each role and permission below links to its Microsoft Learn page.

3.6.1 Pipeline service principal (deploy + content)

Granted once by Setup-ServicePrincipal.ps1, run by a user who holds Owner on the subscription and at least Privileged Role Administrator in Entra ID. After it runs once, the pipeline is autonomous.

PermissionTypeScopePurpose
ContributorAzure RBACSubscriptionResource group, workspace, Bicep, content, summary rules. Implies Reader.
User Access Administrator (ABAC-conditioned)Azure RBACSubscriptionPlaybook managed-identity role assignments, restricted by ABAC to five named roles.
Security AdministratorEntra ID roleTenantUEBA and Entity Analytics settings. Optional (-SkipEntraRole).
CustomDetection.ReadWrite.AllGraph app permissionTenantDefender XDR custom detection rules. Optional (-SkipGraphPermission); needs admin consent.

3.6.2 Playbook managed identities

Assigned by Set-PlaybookPermissions.ps1 as a post-deployment step, run by a separate identity holding User Access Administrator or Owner (the pipeline's ABAC-conditioned role cannot assign Sentinel-tier roles). Roles are derived per playbook from its connectors and HTTP actions.

RoleScopeTriggered by
Microsoft Sentinel ResponderSentinel RGazuresentinel / microsoftsentinel connector
Microsoft Sentinel ContributorSentinel RGPlaybook modifies incidents/watchlists, or HTTP PUT to management.azure.com
Key Vault Secrets UserKey Vaultkeyvault connector
Log Analytics ReaderSentinel RGazuremonitorlogs connector or api.loganalytics.io HTTP action

3.6.3 DCR Watchlist Sync automation account

Assigned by Set-RunbookPermissions.ps1, run once by a user with Owner or User Access Administrator on the subscription (the pipeline SPN lacks roleAssignments/write).

RoleScopePurpose
Monitoring ReaderSubscriptionList DCRs and their associations via ARM
Microsoft Sentinel ContributorSentinel RGCreate and update the Sentinel watchlist

3.6.4 Defender XDR export tool

3.6.5 Resource providers

4 Choosing a no-local-install execution method

Every option below runs PowerShell 7 and the required modules somewhere other than the user's managed device. They differ in where the compute lives, how much setup they need, and what they are best suited for. None require any software to be installed on the user's machine beyond a web browser (or, for managed workstations, the standard remote-desktop client your organisation already uses).

OptionHow it runsBest suited forKey trade-offs
Windows 365 Cloud PC (recommended)A persistent, per-user cloud desktop managed through Intune, with PowerShell 7, the modules and developer tooling in the image.The recommended default: a governed, persistent desktop with everything pre-installed.Per-user licensing and run-cost; managed by IT like any endpoint.
Azure Cloud ShellBrowser-based shell in the Azure Portal, pre-loaded with PowerShell 7 and Az.Validation, ad-hoc deploys, quick onboarding - zero setup.Ephemeral; pandoc / Node not present; idle timeout.
GitHub Codespaces / dev containerCloud dev container opened in the browser or VS Code, tooling baked into the image.Active development and full local-like testing.Needs a devcontainer definition; consumes Codespaces quota.
CI/CD only (GitHub Actions / Azure DevOps)Hosted runners execute every stage; no human runs PowerShell at all.Production deployment and gated validation.Not interactive; slower feedback loop for experiments.
Container image (Docker / MCR PowerShell base)A pre-built image with PowerShell, Az and the repo dependencies, run on any container host.Reproducible, portable execution and self-hosted runners.Requires a container host and image maintenance.

4.1 Recommendation

Lead with a Windows 365 Cloud PC as the primary method: IT installs PowerShell 7, the modules and the full developer toolchain once on the image, so engineers get a governed, persistent desktop with nothing to install on their own device. Use Azure Cloud Shell as a lightweight browser alternative for quick validation, CI/CD as the path to production so people rarely deploy by hand, Codespaces for engineers doing heavy development, and a container image where a fully self-hosted environment is required.

A Windows 365 Cloud PC is a persistent, per-user cloud desktop managed through Microsoft Intune. IT builds the image once with PowerShell 7, the validate and deploy modules and the full developer toolchain, then assigns a Cloud PC to each engineer. Users connect from a browser or the Windows App, so the machine and everything on it stays in Azure and nothing is installed on the user's own device. For most organisations this is the recommended default: it is governed like any other managed endpoint, supports Conditional Access and Defender for Endpoint, and gives engineers a consistent environment where the project is ready to build, test and deploy.

5.1 What IT installs on the Cloud PC image

Because the Cloud PC is IT-built and governed, installation happens once on the image, not on the user's device. Alongside the runtime and modules from Section 3, bake in the standard Windows developer toolchain so engineers can author, clone and run the project directly on the Cloud PC. On the image, install:

  • PowerShell 7.2 or later - the baseline runtime for every script (see 3.1). Windows PowerShell 5.1 is not sufficient; install PowerShell 7 side-by-side as pwsh.
  • Git for Windows - provides git 2.x on PATH (required to clone the repository and by Import-CommunityRules and Migrate-ForkLayout), plus Git Bash and Git Credential Manager for authentication.
  • The Az and Microsoft.Graph modules from Section 3 - the validate and deploy modules (Pester, powershell-yaml, and the Az and Sentinel modules), installed for all users so engineers never need a per-session Install-Module step.
  • The external binaries from Section 3.5 - git, plus pandoc and Node.js where the Sentinel Documenter Word export and mermaid diagrams are required, so the full validation and documentation flow runs on the host.
  • Visual Studio Code - the recommended editor for authoring rules, scripts, Bicep and pipeline changes, and the desktop client for the dev container / Codespaces flow in Section 7. Add the Bicep and PowerShell extensions; it also runs the repository's shipped GitHub Copilot customisations (path-scoped instructions, custom agents and reusable prompts under .github/).

5.2 Provision and connect

IT assigns a Cloud PC from the Windows 365 experience in Intune and applies the same Conditional Access, compliance and update policies as any managed device. Engineers sign in at windows365.microsoft.com or through the Windows App on Windows, macOS, iOS or the web. The connection is brokered, so there is no inbound RDP to the user's device and nothing is installed locally. Because the Cloud PC is persistent, clones, modules and settings are retained between sessions.

5.3 Get the code and run the tests

Open a terminal or Visual Studio Code on the Cloud PC, clone the repository and run the validation gate. The modules and binaries are already present from the image, so there is no setup step:

# Clone the repository (git is pre-installed on the image)
git clone https://github.com/noodlemctwoodle/Sentinel-As-Code.git
Set-Location Sentinel-As-Code

# Modules are already installed - run the full PR-validation gate
./Tools/Invoke-PRValidation.ps1 -RepoPath .

5.4 Deploy interactively (optional)

Unlike Cloud Shell, a Cloud PC is not automatically signed in to Azure, so authenticate once with the account that holds the permissions from Section 3.6, select the subscription, and preview every change with -WhatIf before applying it:

# Sign in and select the subscription
Connect-AzAccount
Set-AzContext -Subscription '<subscription-id>'

# Example: deploy custom content (see Docs/Deploy for parameters)
./Deploy/content/Deploy-CustomContent.ps1 -WhatIf

Use -WhatIf first. Always preview changes with a -WhatIf pass before applying them, then route production deployments through the CI/CD pipeline (Section 8) rather than deploying by hand.

5.5 Other managed-desktop variants

A Windows 365 Cloud PC is the recommended flavour because it is per-user, persistent and managed through Intune. Where an organisation already operates a different managed-desktop estate, the same image and commands apply to the alternatives below:

Workstation optionWhat it isGood fit when
Azure VM (jump box)A locked-down Windows or Linux VM with PowerShell 7 and the modules pre-installed, reached over Bastion or RDP.You want a single shared, auditable admin host.
Azure Virtual Desktop (AVD)A pooled or personal virtual desktop delivered from Azure, with the tooling in the image.Several engineers need a consistent managed desktop.
Windows 365 Cloud PCA persistent, per-user Cloud PC managed through Intune.You prefer a per-user device managed like any other endpoint.
Remote Desktop Services (RDS)Session-host based remote desktops or published apps on Windows Server.You already operate an RDS estate and want to extend it.

6 Alternative: Azure Cloud Shell

Azure Cloud Shell is a browser-based shell, launched from the Azure Portal or shell.azure.com, that already includes PowerShell 7, the Az modules, git and the Azure CLI. Nothing is installed on the user's device. It is a fast, zero-setup way to validate the project or run an interactive deployment when a full Cloud PC is not needed.

6.1 One-time setup

  1. Sign in to the Azure Portal and select the Cloud Shell icon in the top toolbar (or browse to shell.azure.com).
  2. Choose PowerShell (not Bash) when prompted. If this is the first launch, accept the prompt to create the backing storage account for your Cloud Shell profile.
  3. Confirm the environment:
$PSVersionTable.PSVersion   # expect 7.x
Get-Module Az.Accounts -ListAvailable | Select-Object -First 1

6.2 Get the code and validation modules

# Clone the repository (git is pre-installed)
git clone https://github.com/noodlemctwoodle/Sentinel-As-Code.git
Set-Location Sentinel-As-Code

# Install the three modules needed to validate
Install-Module Pester -RequiredVersion 5.7.1 -Scope CurrentUser -Force -SkipPublisherCheck
Install-Module powershell-yaml -RequiredVersion 0.4.12 -Scope CurrentUser -Force

# Az.Accounts is already present in Cloud Shell

6.3 Run the tests

  1. Run the full PR-validation entry point:

    ./Tools/Invoke-PRValidation.ps1 -RepoPath .
    
  2. Or run a single suite while iterating:

    Invoke-Pester -Path Tests/Test-AnalyticalRuleYaml.Tests.ps1
    

Cloud Shell limitations. Cloud Shell does not include pandoc or the Node-based mermaid-cli, so the Word-conversion and diagram-rendering helpers will not run there. The core Pester suite and YAML/schema gates - which is what validation means here - run cleanly. For the bicep-build gate, the Azure CLI and Bicep are pre-installed.

6.4 Deploy interactively (optional)

Cloud Shell is already authenticated as your portal identity, so for an interactive deploy you only need the relevant Azure permissions from Section 3.6:

# Confirm context / select subscription
Get-AzContext
Set-AzContext -Subscription '<subscription-id>'

# Example: deploy custom content (see Docs/Deploy for parameters)
./Deploy/content/Deploy-CustomContent.ps1 -WhatIf

Use -WhatIf first. Always run a -WhatIf pass before a live deployment to preview changes. Production deployments should normally go through the pipeline (Section 8), not interactive Cloud Shell.

7 Alternative: GitHub Codespaces / dev container

A Codespace is a cloud-hosted development container, opened in the browser or in desktop VS Code, with all tooling baked into the image. It gives a full local-like experience - including pandoc and Node - without installing anything on the user's device.

7.1 When to use it

  • Engineers actively authoring rules, scripts or pipeline changes who want editor, terminal and tests in one place.
  • Scenarios that need the optional tooling (Documenter Word export, mermaid diagrams) that Cloud Shell lacks.

7.2 Setup outline

  1. Add a devcontainer definition to the repository (.devcontainer/devcontainer.json) based on the Microsoft PowerShell image, installing Pester, powershell-yaml and the Az/Graph modules during the post-create step.
  2. Add the optional binaries (pandoc, Node + @mermaid-js/mermaid-cli, Azure CLI + Bicep) as devcontainer features or post-create commands.
  3. Open the repository in a Codespace from GitHub (Code → Codespaces → Create), then run the same validation commands as Section 5.3 inside the integrated terminal.

Governance. Codespaces run under your GitHub organisation's policies and billing. Confirm Codespaces is enabled for the organisation and that the repository is permitted before relying on this method.

8 Alternative: CI/CD only (no interactive PowerShell)

In normal operation, no person needs to run PowerShell at all. The repository ships equivalent pipelines for both GitHub Actions and Azure DevOps; the hosted runners install the pinned modules and execute every stage. This is the recommended path to production.

8.1 How validation runs

  • Every pull request triggers a five-job gate: validate (Pester suites), bicep-build, arm-validate, kql-validate and dependency-manifest.
  • The runner installs the pinned modules via the setup-pwsh-modules composite action, so the result is reproducible and independent of any developer's machine.
  • A failing gate blocks merge - engineers get pass/fail feedback in the PR without ever opening a shell.

8.2 How deployment runs

  • Authentication uses OIDC federated credentials - there are no stored secrets and no interactive sign-in.
  • The deploy pipeline provisions infrastructure (Bicep) and deploys content using the service principal permissions from Section 3.6.
  • This means the entire build-test-deploy lifecycle can be operated with only a browser and Git access - the strongest fit for a no-local-install policy.

Recommended pairing. Use a Cloud PC or Cloud Shell for interactive work and the CI/CD pipeline for anything that reaches a shared or production workspace. Together they cover the full lifecycle with nothing installed locally.

9 Alternative: container image

A container image bundles PowerShell, the Az and Graph modules, and the repository's external dependencies into a single reproducible artifact. It runs on any container host - a developer's container runtime, an Azure Container Instance, or a self-hosted pipeline runner - and guarantees everyone uses an identical toolset.

9.1 Setup outline

  1. Base the image on the official Microsoft PowerShell image (mcr.microsoft.com/powershell).
  2. In the Dockerfile, install the pinned modules (Pester 5.7.1, powershell-yaml 0.4.12, the Az and Microsoft.Graph modules) and the external binaries (git, pandoc, Node + mermaid-cli, Azure CLI + Bicep) as needed.
  3. Run the container and execute the same validation and deploy commands as Section 5. For unattended use, drive it from a self-hosted Actions or Azure DevOps runner.

Best fit. Use a container image when you need bit-for-bit reproducibility or a self-hosted runner, and you already operate a container host. Otherwise the managed services in Sections 5 to 8 need less maintenance.

10 Quick reference: install commands

The same commands work in any of the methods above. Run them once per environment (or bake them into the image / devcontainer).

10.1 Minimum to validate (run the test suite)

Install-Module Pester -RequiredVersion 5.7.1 -Scope CurrentUser -Force -SkipPublisherCheck
Install-Module powershell-yaml -RequiredVersion 0.4.12 -Scope CurrentUser -Force
Install-Module Az.Accounts -MinimumVersion 2.0.0 -Scope CurrentUser -Force

10.2 Full runtime (deploy content + run the tooling)

Install-Module Az.Resources, Az.KeyVault, Az.ManagedServiceIdentity, `
  Az.LogicApp, Az.OperationalInsights, Az.SecurityInsights, Az.Monitor `
  -Scope CurrentUser -Force

Install-Module Microsoft.Graph.Applications, `
  Microsoft.Graph.Identity.DirectoryManagement -Scope CurrentUser -Force

10.3 Only for the standalone SDL workbook export

Install-Module ImportExcel -Scope CurrentUser -Force

10.4 Run the validation gate

./Tools/Invoke-PRValidation.ps1 -RepoPath .

For deployment parameters, pipeline configuration and content-authoring conventions, refer to the repository documentation under Docs/ (start with Docs/README.md), which remains the authoritative reference.

11 Microsoft Learn references

Every requirement in this guide links to its Microsoft Learn page inline (PowerShell Gallery is used for the two community modules that are not on Learn). The list below groups the authoritative pages by topic for quick access, including the API schemas the tooling depends on.

11.1 Runtime, modules and testing

11.2 Local developer tooling

11.3 Execution environments

11.4 Permissions, roles and identity

11.5 API schemas and resource definitions