Skip to main content

Getting Started

This guide walks you through setting up the Entra ID scraper — from Azure Portal configuration to a working access audit.

Prerequisites
  • Azure AD tenant with Global Administrator or Application Administrator access
  • Mission Control installed via Helm
Azure App Registration Setup
  1. In the Azure Portal, go to Microsoft Entra ID > App registrations > New registration
  2. Set the Name (e.g. mission-control-scraper)
    • Set Supported account types to "Accounts in this organizational directory only"
    • Leave Redirect URI blank and click Register
  3. Note the Application (client) ID and Directory (tenant) ID from the overview page
  4. Go to Certificates & secrets > Client secrets > New client secret
    • Add a description and choose an expiry (recommended: 12 months)
    • Click Add and copy the secret Value immediately (it won't be shown again)
  5. Go to API permissions > Add a permission > Microsoft Graph > Application permissions
  6. Click Grant admin consent for {tenant} (requires Global Administrator or Privileged Role Administrator)
  7. Create a Connection

Permissions

PermissionTypeUsed ForFunctionality Enabled
User.Read.AllApplicationRead all user profilesScrape users; alias resolution for access log matching
Group.Read.AllApplicationRead group propertiesDiscover groups in tenant; enable group-based role mapping in Application CRD
GroupMember.Read.AllApplicationRead group membershipsMap users to groups; required for role-based access audit
Application.Read.AllApplicationRead app registrations and enterprise appsCatalog app registrations, client secrets/certificates, enterprise applications
Directory.Read.AllApplicationBroad directory read accessService principal metadata, directory roles, additional attributes
AuditLog.Read.AllApplicationSign-in and audit logsOnly needed for HTTP scraper sign-in log ingestion (requires P1/P2 license)
Policy.Read.AllApplicationAuthentication method policiesScrape tenant-level MFA, FIDO2, passwordless, and other auth method configs
Note
  • All permissions must be Application type (not Delegated)
  • Admin consent is required for all permissions
  • Sign-in log access requires an Entra ID P1 or P2 license on the tenant
  • Directory.Read.All is a broad permission; if you only need users and groups, User.Read.All + Group.Read.All is sufficient

Connection

Store the credentials as a Kubernetes secret and reference them in a Connection:

azure-entra-connection.yaml
apiVersion: v1
kind: Secret
metadata:
name: azure-entra-credentials
namespace: mc
type: Opaque
stringData:
AZURE_CLIENT_ID: "<your-client-id>"
AZURE_CLIENT_SECRET: "<your-client-secret>"
AZURE_TENANT_ID: "<your-tenant-id>"
---
apiVersion: mission-control.flanksource.com/v1
kind: Connection
metadata:
name: entra
namespace: mc
spec:
azure:
clientID:
valueFrom:
secretKeyRef:
name: azure-entra-credentials
key: AZURE_CLIENT_ID
clientSecret:
valueFrom:
secretKeyRef:
name: azure-entra-credentials
key: AZURE_CLIENT_SECRET
tenantID:
valueFrom:
secretKeyRef:
name: azure-entra-credentials
key: AZURE_TENANT_ID

Configuration

The Azure scraper uses the include array to control which Entra ID resource sets are scraped:

ValueDescription
entraUsers, groups, app registrations, enterprise applications
appRolesApp role assignments — creates ConfigAccess records linking users/groups to enterprise apps
authMethodsTenant-level authentication method policies (MFA, FIDO2, passwordless)

Within the entra block, each resource type uses resource selectors to filter what gets scraped. An empty selector ({}) scrapes all items of that type.

Users and Groups

entra-users-groups.yaml
apiVersion: configs.flanksource.com/v1
kind: ScrapeConfig
metadata:
name: azure-entra-users-groups
spec:
schedule: "@every 1h"
azure:
- connection: connection://mc/entra
include:
- entra
entra:
users:
- {}
groups:
- {}

Requires: User.Read.All, Group.Read.All

Apps and Roles

entra-apps-roles.yaml
apiVersion: configs.flanksource.com/v1
kind: ScrapeConfig
metadata:
name: azure-entra-apps-roles
spec:
schedule: "@every 1h"
azure:
- connection: connection://mc/entra
include:
- entra
- appRoles
entra:
users:
- {}
groups:
- {}
appRegistrations:
- {}
enterpriseApps:
- {}
appRoleAssignments:
- {}

Requires: User.Read.All, Group.Read.All, Application.Read.All, Directory.Read.All

With Authentication Methods

entra-full.yaml
apiVersion: configs.flanksource.com/v1
kind: ScrapeConfig
metadata:
name: azure-entra-full
spec:
schedule: "@every 1h"
azure:
- connection: connection://mc/entra
include:
- entra
- appRoles
- authMethods
entra:
users:
- {}
groups:
- {}
appRegistrations:
- {}
enterpriseApps:
- {}
appRoleAssignments:
- {}

Requires: all permissions above + Policy.Read.All for auth method policies.

Filtering with Resource Selectors

You can filter scraped resources using resource selectors:

entra:
users:
- name: "John*" # Only users matching name pattern
groups:
- name: "app-*" # Only groups starting with "app-"
enterpriseApps:
- name: "Payments*"
appRoleAssignments:
- name: "Payments*" # Assignments for matching enterprise apps

Filter for a single enterprise app and its role assignments:

entra:
enterpriseApps:
- name: "Payments API"
appRoleAssignments:
- name: "Payments API"

Filter users by domain pattern:

entra:
users:
- name: "*@engineering.contoso.com"
groups:
- {}

End-to-End: Audit an Application

This walkthrough shows how to go from zero to a working access audit for an application.

Step 1: Deploy the connection and scraper (see Configuration above)

Step 2: Verify resources appear in the catalog. After the first scrape cycle, you should see Azure::AppRegistration and Azure::EnterpriseApplication items in the catalog, and users/groups in the access views.

Step 3: Create an Application that maps Entra resources to your app:

my-app-audit.yaml
apiVersion: mission-control.flanksource.com/v1
kind: Application
metadata:
name: my-app
namespace: mc
spec:
type: Application
description: My application
mapping:
logins:
- search: type=Azure::EnterpriseApplication name="My App"
roles:
- search: type=Azure::Group name=my-app-users
role: User
- search: type=Azure::Group name=my-app-admins
role: Admin

The Application automatically surfaces:

  • All users and groups that have access via the enterprise application
  • Their assigned roles (User, Admin)
  • Authentication method policies from the tenant

See Applications for the full spec and more examples.

Verification

After deploying your scraper, verify that resources are being scraped correctly.

Check Scraper Status

kubectl get scrapeconfigs -n mc
kubectl describe scrapeconfig azure-entra-full -n mc

Look for:

  • Status: should show Healthy or Succeeded
  • Last Scrape Time: should be recent (within your schedule interval)
  • Events: no error events like 403 Forbidden or Authentication failed

Verify Config Items

Open the Mission Control catalog and filter by type:

  • Azure::AppRegistration — app registrations from your tenant
  • Azure::EnterpriseApplication — enterprise applications (service principals)
  • Azure::AuthenticationMethod — tenant-level auth method policies (if authMethods is enabled)

If these types don't appear, check that include contains entra and that Application.Read.All permission is granted.

Verify Users and Groups

Navigate to any Application's Access Control tab to see users and groups. Alternatively, verify via the API:

kubectl exec -n mc deploy/mission-control -- curl -s localhost:8080/api/db/external_users | jq '.[0:3]'
kubectl exec -n mc deploy/mission-control -- curl -s localhost:8080/api/db/external_groups | jq '.[0:3]'

Verify App Role Assignments

If appRoles is in your include list, navigate to an enterprise application's Access tab in the catalog. You should see users and groups with their assigned roles.

Performance & Scheduling

Schedule Recommendations

Tenant SizeRecommended ScheduleNotes
< 1,000 users@every 1hDefault, suitable for most tenants
1,000 – 10,000 users@every 2hReduces API call volume
10,000+ users@every 4hUse resource selectors to narrow scope

Rate Limits

Microsoft Graph API enforces per-tenant rate limits. If you encounter 429 Too Many Requests errors:

  1. Increase the schedule interval — scrape less frequently
  2. Narrow resource selectors — scrape only the users, groups, and apps you need
  3. Stagger scrapers — if running multiple ScrapeConfigs against the same tenant, offset their schedules
info

The built-in Azure scraper handles pagination automatically. You do not need to worry about page sizes or @odata.nextLink tokens — the scraper follows all pages until the collection is fully scraped.

Example: reduced-scope config for large tenants:

entra-large-tenant.yaml
apiVersion: configs.flanksource.com/v1
kind: ScrapeConfig
metadata:
name: azure-entra-scoped
spec:
schedule: "@every 4h"
azure:
- connection: connection://mc/entra
include:
- entra
- appRoles
entra:
users:
- name: "*@engineering.contoso.com"
groups:
- name: "app-*"
enterpriseApps:
- name: "Payments*"
appRoleAssignments:
- name: "Payments*"

Troubleshooting

"Insufficient privileges" or "Authorization_RequestDenied"

Admin consent has not been granted. In the Azure Portal, go to App registrations > your app > API permissions and click Grant admin consent.

Empty results / no users or groups

  • Verify the entra block has at least one resource selector (use - {} to select all)
  • Ensure include contains entra
  • Check that admin consent has been granted (a green checkmark should appear next to each permission)

"Application not found" or authentication errors

  • Verify the tenant ID, client ID, and client secret are correct
  • Ensure the secret has not expired (check Certificates & secrets in the Azure Portal)

Client secret expired

  1. Go to App registrations > your app > Certificates & secrets
  2. Create a new client secret
  3. Update the Kubernetes secret with the new value
  4. The scraper will use the new secret on the next cycle

No app registrations or enterprise apps

Ensure Application.Read.All and Directory.Read.All permissions are granted and consented. The app registration must have Application type permissions, not Delegated.

Authentication methods not appearing

Ensure authMethods is in the include list and Policy.Read.All permission is granted.

Rate limiting / 429 errors

Microsoft Graph API enforces per-tenant rate limits. Increase the schedule interval, reduce scope with resource selectors, or stagger multiple scrapers. See Performance & Scheduling for details.

Next Steps