Skip to main content

Set up Maester in GitLab

This guide will walk you through setting up Maester in GitLab and automate the running of tests using GitLab Pipelines (jobs).

Set up your Maester tests project (Group) in GitLab

Pre-requisites

Create a new blank project to always use the latest available public Maester Tests

  • On the left sidebar, at the top, select Create new () and New project/repository.

  • Select Create a blank project

    Visibility Level: Private

There are many ways to authenticate with Microsoft Entra. We currently have tested client secrets, but there are probably more options available.

  • Client secret uses a secret to authenticate with Microsoft Entra protected resources.

Create an Entra Application

  • Open Entra admin center > Identity > Applications > App registrations
  • Select New registration
  • Enter a name for the application (e.g. Maester DevOps Account)
  • Select Register

Grant permissions to Microsoft Graph

  • Open the application you created in the previous step
  • Select API permissions > Add a permission
  • Select Microsoft Graph > Application permissions
  • Search for each of the permissions and check the box next to each permission:
    • Directory.Read.All
    • DirectoryRecommendations.Read.All
    • IdentityRiskEvent.Read.All
    • Policy.Read.All
    • Policy.Read.ConditionalAccess
    • PrivilegedAccess.Read.AzureAD
    • Reports.Read.All
    • RoleEligibilitySchedule.Read.Directory
    • RoleManagement.Read.All
    • SharePointTenantSettings.Read.All
    • UserAuthenticationMethod.Read.All
  • Optionally, search for each of the permissions if you want to allow privileged permissions:
    • RoleEligibilitySchedule.ReadWrite.Directory
      • Required for eligible role assignments (Reference)
  • Select Add permissions
  • Select Grant admin consent for [your organization]
  • Select Yes to confirm

(Optional) Grant permissions to Exchange Online

The Exchange Online Role Based Access Control (RBAC) implementation utilizes service specific roles that apply to an application and the below configuration allows the authorization chain to the App Registration you created in the previous steps.

The Exchange Online permissions are necessary to support tests that validate Exchange Online configurations, such as the CISA tests.

  • Open the application you created in the previous step
  • Select API permissions > Add a permission
  • Select APIs that my organization uses > search for Office 365 Exchange Online > Application permissions
  • Search for Exchange.ManageAsApp
  • Select Add permissions
  • Select Grant admin consent for [your organization]
  • Select Yes to confirm
  • Connect to the Exchange Online Management tools and use the following to set the appropriate permissions:
New-ServicePrincipal -AppId <Application ID> -ObjectId <Object ID> -DisplayName <Name>
New-ManagementRoleAssignment -Role "View-Only Configuration" -App <DisplayName from previous command>

(Optional) Grant permissions to Azure

The Azure Role Based Access Control (RBAC) implementation utilizes Uniform Resource Names (URN) with a "/" separator for heirarchical scoping. There exists resources within the root (e.g., "/") scope that Microsoft retains strict control over by limiting supported interactions. As a Global Administrator you can elevate access to become authorized for these limited interactions.

The Azure RBAC permissions are necessary to support tests that validate Azure configurations, such as the CISA tests.

The following PowerShell script will enable you, with a Global Administrator role assignment, to:

  • Identify the Service Principal Object ID that will be authorized as a Reader and the Subscription ID to authorize for
  • Install the necessary Az module and prompt for connection
  • Elevate your account access to the root scope
  • Create a role assignment for Reader access over the Subscription and objects within
  • Create a role assignment for Reader access over the Entra ID (i.e., aadiam provider)
  • Identify the role assignment authorizing your account access to the root scope
  • Delete the root scope role assignment for your account
$servicePrincipal = "<Object ID of the Entra App>"
$subscription = "<Subscription ID>"
Install-Module Az.Accounts -Force
Install-Module Az.Resources -Force
Connect-AzAccount
#Elevate to root scope access
$elevateAccess = Invoke-AzRestMethod -Path "/providers/Microsoft.Authorization/elevateAccess?api-version=2015-07-01" -Method POST
New-AzRoleAssignment -ObjectId $servicePrincipal -Scope "/subscriptions/$subscription" -RoleDefinitionName "Reader" -ObjectType "ServicePrincipal"
New-AzRoleAssignment -ObjectId $servicePrincipal -Scope "/providers/Microsoft.aadiam" -RoleDefinitionName "Reader" -ObjectType "ServicePrincipal"
#Remove root scope access
$assignment = Get-AzRoleAssignment -RoleDefinitionId 18d7d88d-d35e-4fb5-a5c3-7773c20a72d9|?{$_.Scope -eq "/" -and $_.SignInName -eq (Get-AzContext).Account.Id}
$deleteAssignment = Invoke-AzRestMethod -Path "$($assignment.RoleAssignmentId)?api-version=2018-07-01" -Method DELETE

Create a client secret

  • Select Certificates & secrets > Client secrets > New client secret
  • Enter a description for the secret (e.g. Maester DevOps Secret)
  • Select Add
  • Copy the value of the secret, we will use this value in the Azure Pipeline

Create GitLab variables

  • Open your maester-tests GitLab project and go to Settings
  • Select CI/CD > Variables > CI/CD Variables
  • Add the three secrets listed below by selecting Add variable
  • To look up these values you will need to use the Entra portal, open the application you created earlier and copy the following values from the Overview page:
    • Visibility: Visible, Key: AZURE_TENANT_ID, Value: The Directory (tenant) ID of the Entra tenant
    • Visibility: Visible, Key: AZURE_CLIENT_ID, Value: The Application (client) ID of the Entra application you created
    • Visibility: Masked and hidden, Key: AZURE_CLIENT_SECRET, Value: The client secret you copied in the previous step
  • Save each secret by selecting Add variable at the bottom.

Create .gitlab-ci.yml file (or use Pipeline editor)

stages:
- test

run_maester_tests_inline:
stage: test
image: mcr.microsoft.com/microsoftgraph/powershell:latest
variables:
TENANTID: $AZURE_TENANT_ID
CLIENTID: $AZURE_CLIENT_ID
CLIENTSECRET: $AZURE_CLIENT_SECRET
before_script:
- mkdir test-results
- mkdir public-tests
- pwsh -c 'Write-host "Running in project $env:CI_PROJECT_NAME with results at $env:CI_JOB_URL ($env:CI_JOB_URL)."'
script:
- |
pwsh -Command '
# Connect to Microsoft Graph
$clientSecret = ConvertTo-SecureString -AsPlainText $env:AZURE_CLIENT_SECRET -Force
[pscredential] $clientSecretCredential = New-Object System.Management.Automation.PSCredential($env:AZURE_CLIENT_ID, $clientSecret)
Connect-MgGraph -TenantId $env:AZURE_TENANT_ID -ClientSecretCredential $clientSecretCredential -NoWelcome

# Install Maester
#Install-Module Maester -AllowPrerelease -Force
Install-Module Maester -Force

# Latest public tests
cd public-tests
Install-MaesterTests
cd ..

# Configure test results
$PesterConfiguration = New-PesterConfiguration
$PesterConfiguration.Output.Verbosity = "None"
Write-Host "Pester verbosity level set to: $($PesterConfiguration.Output.Verbosity.Value)"

$MaesterParameters = @{
Path = "public-tests"
PesterConfiguration = $PesterConfiguration
OutputFolder = "test-results"
OutputFolderFileName = "test-results"
PassThru = $true
}

#$MaesterParameters.Add("DisableTelemetry", $true )
Write-Host "Pester telemetry set to: $($MaesterParameters.DisableTelemetry)"

# Run Maester tests
#$results = Invoke-Maester -Path public-tests -PesterConfiguration $PesterConfiguration -OutputFolder test-results -OutputFolderFileName "test-results" -PassThru
$results = Invoke-Maester @MaesterParameters

# View summary report
$results | fl Result, FailedCount, PassedCount, SkippedCount, TotalCount, TenantId, TenantName, CurrentVersion, LatestVersion

# Flag status to GitLab
if ($results.Result -ne "Passed") {
Write-Warning "Status = $($results.Result): see Maester Test Report for details."
}
'
after_script:
- pwsh -c 'Write-host "Report can be opened at ($env:CI_JOB_URL/artifacts/external_file/test-results/test-results.html)."'
artifacts:
when: on_success
paths:
- test-results/
expire_in: 1 week

rules:
- if: '$CI_PIPELINE_SOURCE == "schedule" && $CI_PIPELINE_SOURCE == "web"'

Manually running the Maester tests

To manually run the Maester tests workflow

  • Open your maester-tests GitLab project and go to Build
  • Select Piplines from the left pane
  • Select New pipline on the right top button
  • And again New pipline to run new pipeline

Viewing the test results

  • Open your maester-tests GitLab project and go to Build
  • Select Artifacts from the left pane
  • Search a artifact to view the results e.g. run_maester_tests_*
  • Select browse on the right to open the folder test-results

Summary view A summary view is not available with GitLab in comparison to GitHub.