Skip to main content
Who is this for? IT administrators, security teams, and change advisory board (CAB) reviewers who need to independently verify the permissions granted to ContraForce enterprise applications before or after onboarding.

Overview

ContraForce provides two audit scripts that enumerate the permissions granted to ContraForce enterprise applications in your Microsoft Entra ID tenant. Both scripts produce an identical JSON output that you can compare against the Enterprise Applications Reference to verify that only the documented permissions are in place. Choose the script that fits your environment:
These scripts are read-only. They do not create, modify, or delete any objects in your tenant. All API calls are HTTP GET requests to Microsoft Graph.

What the Scripts Access

Both scripts make read-only queries to the Microsoft Graph REST API. The specific endpoint depends on your cloud environment: No other endpoints are contacted beyond the Microsoft identity platform for token acquisition.

Data in the Output File

The output JSON contains:
  • Application names and app IDs for each ContraForce enterprise application
  • Permission names and descriptions resolved to human-readable values
  • The resource API each permission targets (Microsoft Graph, WindowsDefenderATP, etc.)
  • Metadata: timestamp, tenant ID, cloud environment, authenticated operator, and tool version
The output does not contain secrets, tokens, or user data beyond the operator identifier. In government cloud environments, the operator’s UPN is automatically redacted and replaced with their Entra object ID (an opaque GUID). See Output File Access Control for handling guidance.

Directory Role Assignments

The scripts on this page report Microsoft Graph permission grants — delegated (oauth2PermissionGrants) and application (appRoleAssignments). They do not enumerate Entra directory role memberships, which are a separate authorization mechanism that Graph permission audits do not surface. One ContraForce capability uses a directory role. If you enable the optional service-provider password reset add-on on the Identity module, the ContraForce Gamebooks for Identity service principal is assigned the Authentication Administrator role so the Reset Password Gamebook can run app-only (see the Enterprise Applications Reference). Review that assignment directly with the same read-only access the audit scripts already use (Directory.Read.All):
An empty result means the add-on is not enabled (or has been turned off). When it is enabled, the expected assignment is Authentication Administrator — a role scoped to non-administrator users that cannot reset passwords for Global Administrators or other higher-privileged roles.

Applications Audited

In commercial (AzureCloud) environments, both scripts use built-in app IDs that match the Quick Reference table: You can verify these app IDs in the Microsoft Entra Admin Center under Enterprise Applications before running the scripts.
Government cloud environments use different app IDs. Contact support@contraforce.com to obtain the app IDs for your environment. Pass them to the script via -AppsFile (PowerShell) or --apps-file (Python) — a JSON file containing an array of objects with Name/AppId (PowerShell) or name/app_id (Python) fields.

Prerequisites

Runtime: PowerShell 7.0+ (pwsh, not Windows PowerShell 5.1)Microsoft Graph modules:
Required Graph scopes: Application.Read.All and Directory.Read.AllAuthenticate before running:
For environments without a browser, use device code flow:

Minimum Permissions

The account running the script needs read access to service principals and their permission grants. The minimum Microsoft Entra ID role is Directory Reader, or you can grant the following Microsoft Graph API permissions directly: These are read-only permissions. They do not grant the ability to modify applications, permissions, or any other tenant objects.

Running the Scripts

The -Cloud parameter value must match the cloud you authenticated to with Connect-MgGraph -Environment. The script validates this and exits with an error if there is a mismatch. Government environments require -AppsFile because app IDs differ from commercial.
Both scripts display progress as they resolve permissions and will report a summary when complete. A non-zero exit code means one or more applications were not found in the tenant — this is expected if you haven’t consented all ContraForce applications (for example, Sentinel Hunting is only required for XDR + SIEM deployments).

Government Cloud Environments (GCC High / DoD)

Both scripts support Microsoft Azure Government cloud environments used by public sector organizations subject to CMMC, FedRAMP, or ITAR requirements. Both scripts use the same -Cloud / -c parameter values, which match the az cloud set --name values: When running in a government cloud environment, the scripts automatically:
  1. Use the correct Graph endpointgraph.microsoft.us instead of graph.microsoft.com
  2. Redact the operator’s UPN — Records the Entra object ID (an opaque GUID) instead of the User Principal Name in the generatedBy metadata field
  3. Restrict output file permissions — Limits file access to the current user only (PowerShell: Windows ACL; Python: POSIX chmod 600)
You can also redact the UPN in commercial environments using the -RedactUPN switch (PowerShell) or --redact-upn flag (Python).
The script validates that the connected session matches the requested cloud environment. If you specify -Cloud AzureUSGovernment but are connected to a commercial Graph session, the script will exit with an error and instructions to reconnect.

Audit Scripts

Understanding the Output

Both scripts produce a JSON file with the same structure. Here’s an abbreviated example:
Output Schema

Key Fields

Internal Scope Resolution

You may notice the output includes delegated permissions where the api field shows a ContraForce application name (e.g., "ContraForce Portal") and "internal": true. These are cross-application delegations where one ContraForce app delegates to another via custom OAuth2 scopes. To resolve these internal scopes to human-readable names instead of raw GUIDs, the scripts query for all service principals whose display name starts with ContraForce — not just the seven applications listed in the audit table. This broader query:
  • Does not grant additional access — it reads public service principal metadata that any authenticated directory reader can see
  • Is clearly tagged — all permissions from internal apps are marked "internal": true in the output
  • Improves readability — without this, internal scopes would appear as opaque GUIDs that are difficult to review

Comparing Against Documentation

To verify your tenant’s permissions match the documented permissions:
  1. Run the audit script to produce enterprise-apps-audit.json
  2. Open the Enterprise Applications Reference
  3. For each application in the JSON output, compare its delegatedPermissions and applicationPermissions against the corresponding tables in the reference
  4. Permissions marked "internal": true are ContraForce-to-ContraForce delegations and are not listed in the reference tables

Comparing Across Audit Runs

To track permission changes over time, save each audit output with a date-stamped filename:
Because the scripts sort all permissions alphabetically and produce deterministic JSON output, standard text diff tools (diff, VS Code’s built-in compare, or Compare-Object in PowerShell) will surface only actual permission changes — not ordering noise. Store audit outputs alongside your change management records. The metadata.generatedAt and metadata.toolVersion fields provide traceability for each snapshot.

Output File Access Control

The audit output reveals your tenant’s permission surface for ContraForce applications. While it does not contain secrets or tokens, it should be treated as internal documentation. Government cloud environments: Both scripts automatically restrict the output file so only the current user can read or write it:
  • PowerShell (Windows): Removes inherited ACL entries and grants FullControl only to the current user via Set-Acl
  • Python (POSIX): Sets file mode to 600 (chmod u=rw,go=) via os.chmod
Commercial environments: File permissions are not restricted automatically. If you are running the audit on a shared workstation or jump box, consider restricting access manually:

Using This Output as Audit Evidence

The audit output is designed to serve as evidence in change advisory board (CAB) reviews, compliance audits, and periodic access reviews. For CAB / Change Management:
  • Run the audit before and after onboarding a new ContraForce module
  • Include both snapshots in your change record to show exactly which permissions were added
  • The toolVersion field ensures reviewers know which version of the script produced the output
For Periodic Access Reviews (CMMC, SOC 2, FedRAMP):
  • Schedule monthly or quarterly audit runs and archive the output alongside your review documentation
  • Use date-stamped filenames (e.g., audit-2026-Q1.json) for easy retrieval
  • Compare successive outputs using diff to identify any permission drift
For Incident Response:
  • If you suspect unauthorized permission changes, run an immediate audit and compare against your most recent baseline
  • The generatedAt timestamp provides a verifiable point-in-time snapshot
Store audit outputs in a version-controlled repository or a tamper-evident storage location (such as an Azure Storage account with immutable blob policies) to maintain an auditable chain of custody.

Troubleshooting


Enterprise Applications Reference

Complete reference for all ContraForce enterprise applications and their permissions

Azure Resources Deployed

All Azure resources provisioned during ContraForce onboarding

Roles & Permissions

ContraForce platform roles and what each can do

Platform Onboarding

Step-by-step guide to onboarding your parent workspace
Questions about the audit scripts or enterprise application permissions? Contact us at support@contraforce.com.