Skip to main content
Applies to BloodHound Enterprise only Creating a Microsoft Entra ID application registration is a prerequisite for AzureHound Enterprise data collection and involves the following steps: Some steps are required before you can complete the AzureHound configuration. At minimum, you must create the application registration because AzureHound requires an Entra ID Directory (tenant) ID and Application (client) ID. For managed identity authentication, you must first create the identity in Azure and configure the app registration to use it because AzureHound requires the Managed Identity Client ID. For certificate authentication, you must also upload the certificate to the app registration if you’re using the AzureHound Enterprise CLI tool to create the certificate.

Create a new app registration

This section guides you through the minimum steps to create a new application registration in Microsoft Entra ID for AzureHound Enterprise data collection.
See the Microsoft documentation for more information.
1

Navigate to Entra ID

Log into the Microsoft Entra admin center as a user with the Global Administrator role, or the following less privileged roles:
2

Create a new app registration

  1. In the left menu, click Entra ID > App registrations > New registration.
  2. In the Name field, enter a name for the application to identify it in your organization. Make sure the supported account type is set to the Accounts in this organizational directory only (Single tenant) option. A URI is not required.
    A view of the Azure portal showing the New registration page with fields to enter the application name and supported account types.
  3. Click Register to create the application registration.
3

Retrieve details for AzureHound configuration

In the Overview menu, copy the Application (client) ID and Directory (tenant) ID.
You will need this information later to configure AzureHound Enterprise.
A view of the Azure portal showing the application registration details page with the Application (client) ID and Directory (tenant) ID fields highlighted.
Continue to the Grant Microsoft Graph Permissions section.

Assign required API permissions

This section describes how to assign the required Microsoft Graph API permissions to the AzureHound Enterprise application registration.
See the Microsoft documentation for more information.
1

Navigate to API permissions

On the Overview page of the app registration, click API Permissions.
2

Remove default permission

Remove the default User.Read delegated permission. It is not required for AzureHound Enterprise data collection.
A view of the Azure portal showing the API permissions page with the User.Read permission highlighted for removal.
3

Add Microsoft Graph API permissions

  1. Click Add a permission > Microsoft Graph.
  2. Select Application permissions.
    A view of the Microsoft Graph API permission selection page with the Application permissions option highlighted.
  3. Search for the Directory.Read.All permission and check the box next to it.
    A view of the Microsoft Graph API permission selection page with the Directory.Read.All permission highlighted.
  4. Search for the RoleManagement.Read.All permission and check the box next to it.
    A view of the Microsoft Graph API permission selection page with the RoleManagement.Read.All permission highlighted.
  5. Click Add permissions.
4

Grant admin consent

After adding the required permissions, you must grant admin consent for the application to use them.
  1. Click Grant admin consent for <your_tenant_name>.
    A view of the Azure portal showing the API permissions page with the Grant admin consent button highlighted.
  2. Click Yes in the confirmation dialog.
  3. After being redirected to API Permissions again, you should see both permissions as Granted.
    A view of the Azure portal showing the API permissions page with the Directory.Read.All and RoleManagement.Read.All permissions marked as Granted.
    Continue to the Configure authentication section.

Configure authentication

This section describes how to configure authentication methods for the AzureHound Enterprise application registration. AzureHound Enterprise supports the following authentication methods:
  • Azure Managed Identity (recommended)
  • Certificate
  • Client Secret
  • Username and Password
This section provides instructions for configuring the Azure Managed Identity and Certificate authentication methods. For information on other methods, see the Microsoft documentation.
Managed identities provide the most secure authentication method by eliminating credential management entirely. Microsoft Entra ID automatically manages the identity lifecycle, but you must properly configure the identity-to-host assignment and federated trust. This section describes how to configure Azure Managed Identity authentication for the AzureHound Enterprise application registration.
You will need the managed identity Client ID to complete AzureHound configuration later.
Microsoft recommends the User-Assigned Managed Identity for Microsoft services, so the following example shows the User-Assigned type.
1

Navigate to Azure Managed Identities

Sign in to the Azure portal and search for Managed Identities in the top search bar.
2

Create a user-assigned managed identity

Click Create and enter the required information to create a new user-assigned managed identity.
See the Microsoft documentation for more information.
3

Configure the app registration to use the managed identity

  1. Sign in to the Microsoft Entra admin center and navigate to the previously created AzureHound Enterprise application registration.
  2. In the left menu, click Certificates & secrets > Federated credentials > Add credential.
  3. From the Federated credential scenario drop-down menu, select Managed Identity and enter the required information.
    See the Microsoft documentation for more information.
  4. Click Add.

Certificate

Certificates provide stronger authentication than client secrets or username and password combinations, but you must manage and rotate them properly. This section describes how to add an authentication certificate to the AzureHound Enterprise application registration.
If you have not already created a certificate, see Create an AzureHound Configuration before proceeding.
1

Navigate to Entra ID Certificates & secrets

  1. On the Overview page of the app registration, click Certificates & secrets.
  2. Click Certificates.
2

Upload certificate

  1. Click Upload certificate.
  2. Locate the cert.pem file that you created during AzureHound configuration.
  3. Click the folder icon, select the cert.pem file, and add a description (optional).
  4. Click Add.

Assign required access roles

This section describes how to assign the required access roles to the AzureHound Enterprise application registration for data collection.

Assign Directory Readers role on the Entra ID tenant

The AzureHound Enterprise application registration requires the Directory Readers role to read Entra ID data. Follow the steps below to assign this role.
1

Navigate to Entra ID Roles & admins

In the left menu, click Entra ID > Roles & admins.
2

Assign Directory Readers role

  1. Search for the Directory Readers role and click the role name or description.
    Clicking the checkbox sometimes prevents clicking on the role itself.
  2. Click Add assignments.
  3. Click No member selected to open the search window.
  4. Search for the previously created service principal with either its name, application ID, or object ID. Select it by clicking on it.
  5. Click Select.
  6. Validate that your principal is displayed and click Next.
  7. Ensure that the Assignment type is Active and the Permanently assigned box is checked. Enter a justification and click Assign.
  8. Confirm that the service principal is a Directory Reader by refreshing the view.

Grant Reader role on all Azure subscriptions

If you do not have any management groups, you may either create your Tenant Root Group following the prompts in the middle of the screen to ensure future visibility if another administrator begins use of subscriptions, or you may skip this section altogether.
If you skip this section, you will see a warning in the logs for each collection indicating the lack of ability to collect this data accordingly.
1

Navigate to Management Groups

  1. Log into the Azure portal as a user with the User Access Administrator role.
  2. Search for and select the Management groups item in the top search bar.
  3. Select Tenant Root Group.
2

Add the Reader role assignment

  1. Select Access control (IAM).
  2. Select Role assignments.
  3. Click Add, then Add role assignment.
  4. Find the Reader role and select it.
  5. Click Members.
  6. Click Select members.
  7. Search for and click on your previously created service principal.
  8. Validate the principal selected, then click Select.
3

Review role assignment

  1. Click the tab Review + Assign.
  2. Click Review + Assign at the bottom of the page.
  3. Confirm the role is present by refreshing this view. You may need to alter the filter to see this role.

Scripted app registration

As an alternative to the manual app registration process described in this document, you can use PowerShell to achieve the same. Below is a sample PowerShell script that performs all the required steps, with the exception of configuring the authentication certificate.
<#
.SYNOPSIS
Registers the Azure Data Exporter for BloodHound Enterprise (AzureHound)
as an application in Entra ID.

.DESCRIPTION
This script registers the Azure Data Exporter for BloodHound Enterprise (AzureHound)
as an on-prem application in Microsoft Entra ID and Azure,
including all the necessary read permissions.

The required PowerShell modules can be installed
from the PowerShell Gallery using the following command:

Install-Module -Scope AllUsers -Repository PSGallery -Force -Name @(
    Microsoft.Graph.Applications,
    Microsoft.Graph.Authentication,
    Microsoft.Graph.Identity.DirectoryManagement,
    Az.Resources,
    Az.Accounts
)

.NOTES
Version: 1.1
#>

#Requires -Version 5
#Requires -Modules Microsoft.Graph.Applications,Microsoft.Graph.Authentication
#Requires -Modules Microsoft.Graph.Identity.DirectoryManagement
#Requires -Modules Az.Resources,Az.Accounts

#region Entra ID

# Connect to Microsoft Entra ID through the Microsoft Graph API
# Note: The -TenantId parameter is also required when using an External ID.
Connect-MgGraph -NoWelcome -ContextScope Process -Scopes @(
   'User.Read',
   'Application.ReadWrite.All',
   'AppRoleAssignment.ReadWrite.All',
   'RoleManagement.ReadWrite.Directory'
)

# Register the AzureHound application
[string] $appName = 'BloodHound Enterprise Collector'
[string] $appDescription =
  'Azure Data Exporter for BloodHound Enterprise (AzureHound)'
# TODO: Optionally provide the actual URL your BloodHound Enterprise tenant
[string] $homePage = 'https://specterops.io/bloodhound-enterprise'
[hashtable] $infoUrls = @{
    MarketingUrl      = 'https://specterops.io/bloodhound-enterprise'
    TermsOfServiceUrl = 'https://specterops.io/terms-of-service'
    PrivacyStatementUrl = 'https://specterops.io/privacy-policy'
    SupportUrl = 'https://support.bloodhoundenterprise.io/'
}
[hashtable] $webUrls = @{
    HomePageUrl = $homePage
}

[Microsoft.Graph.PowerShell.Models.IMicrosoftGraphApplication] $registeredApp =
   New-MgApplication -DisplayName $appName `
                     -Description $appDescription `
                     -Info $infoUrls `
                     -Web $webUrls `
                     -SignInAudience 'AzureADMyOrg'

# Configure the application logo
[string] $logoUrl =
  'https://bloodhound.specterops.io/assets/icons/entra-bhe-app-icon.png'
[string] $tempLogoPath = New-TemporaryFile

Invoke-WebRequest -Uri $logoUrl `
                  -OutFile $tempLogoPath `
                  -UseBasicParsing `
                  -ErrorAction Stop
try {
    Set-MgApplicationLogo -ApplicationId $registeredApp.Id `
                          -ContentType 'image/png' `
                          -InFile $tempLogoPath
}
finally {
    # Delete the local copy of the logo from temp
    Remove-Item -Path $tempLogoPath
}

# Make sure the app instance property lock is enabled
Update-MgApplication `
  -ApplicationId $registeredApp.Id `
  -ServicePrincipalLockConfiguration @{
    IsEnabled = $true
    AllProperties = $true
}

# Create the associated service principal object
[Microsoft.Graph.PowerShell.Models.IMicrosoftGraphServicePrincipal] $servicePrincipal =
   New-MgServicePrincipal -DisplayName $appName `
                          -AppId $registeredApp.AppId `
                          -AccountEnabled `
                          -ServicePrincipalType Application `
                          -Notes $appDescription `
                          -Homepage $homePage `
                          -Tags 'WindowsAzureActiveDirectoryIntegratedApp','HideApp'

# Fetch the Microsoft Graph applicaton ID,
# which should be 00000003-0000-0000-c000-000000000000
[Microsoft.Graph.PowerShell.Models.IMicrosoftGraphServicePrincipal] $microsoftGraph =
    Get-MgServicePrincipal -Filter "DisplayName eq 'Microsoft Graph'"

# Fetch the Directory.Read.All scope ID,
# which should be 7ab1d382-f21e-4acd-a863-ba3e13f7da61
[Microsoft.Graph.PowerShell.Models.IMicrosoftGraphAppRole] $readDirectoryScope =
    $microsoftGraph.AppRoles | Where-Object Value -eq 'Directory.Read.All'

# Fetch the RoleManagement.Read.All scope ID,
# which should be c7fbd983-d9aa-4fa7-84b8-17382c103bc4
[Microsoft.Graph.PowerShell.Models.IMicrosoftGraphAppRole] $readRolesScope =
    $microsoftGraph.AppRoles | Where-Object Value -eq 'RoleManagement.Read.All'

# Delegate the required API permissions
Update-MgApplication -ApplicationId $registeredApp.Id -RequiredResourceAccess @{
    ResourceAppId = $microsoftGraph.AppId # 00000003-0000-0000-c000-000000000000
    ResourceAccess = @(@{
        id = $readDirectoryScope.Id       # 7ab1d382-f21e-4acd-a863-ba3e13f7da61
        type = 'Role'
    },@{
        id = $readRolesScope.Id           # c7fbd983-d9aa-4fa7-84b8-17382c103bc4
        type = 'Role'
    })
}

# Approve the permissions on the tenant
[Microsoft.Graph.PowerShell.Models.IMicrosoftGraphAppRoleAssignment] $readRolesAdminConsent =
    New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $servicePrincipal.Id `
                                            -PrincipalId $servicePrincipal.Id `
                                            -ResourceId $microsoftGraph.Id `
                                            -AppRoleId $readRolesScope.Id

[Microsoft.Graph.PowerShell.Models.IMicrosoftGraphAppRoleAssignment] $readDirectoryAdminConsent =
    New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $servicePrincipal.Id `
                                            -PrincipalId $servicePrincipal.Id `
                                            -ResourceId $microsoftGraph.Id `
                                            -AppRoleId $readDirectoryScope.Id

# Fetch the template ID of the Directory Readers role,
# which should be 88d8e3e3-8f55-4a1e-953a-9b9898b8876b
[Microsoft.Graph.PowerShell.Models.MicrosoftGraphDirectoryRole] $directoryReadersRole =
    Get-MgDirectoryRole -Filter "displayName eq 'Directory Readers'"

# Get the environment-specific Microsoft Graph API endpoint
# Azure Global: https://graph.microsoft.com
# Azure USGov:  https://graph.microsoft.us
[string] $graphEndpoint =
    (Get-MgEnvironment -Name (Get-MgContext).Environment).GraphEndpoint

# OData IDs need to be used when assigning role membership,
# e.g., https://graph.microsoft.com/v1.0/serviceprincipals/{46615ae4-da39-4403-8de2-606e10774ae0}
[string] $servicePrincipalOdataId =
  "$graphEndpoint/v1.0/serviceprincipals/{$($servicePrincipal.Id)}"

# Assign the Directory Readers Entra ID Role to the service principal
New-MgDirectoryRoleMemberByRef -DirectoryRoleId $directoryReadersRole.Id `
                               -OdataId $servicePrincipalOdataId

# Fetch the info about the current user
[Microsoft.Graph.PowerShell.Models.IMicrosoftGraphDirectoryObject] $currentUser =
    Invoke-MgGraphRequest -Method GET -Uri '/v1.0/me'

# OData IDs need to be used when assigning application ownership,
# e.g., https://graph.microsoft.com/v1.0/users/{bca3617a-4c54-45eb-9a32-744c1938242e}
[string] $currentUserOdataId = "$graphEndpoint/v1.0/users/{$($currentUser.Id)}"

# Assign the current user as the application object owner
New-MgApplicationOwnerByRef -ApplicationId $registeredApp.Id `
                            -OdataId $currentUserOdataId

# Assign the current user as the service principal owner
New-MgServicePrincipalOwnerByRef -ServicePrincipalId $servicePrincipal.Id `
                                 -OdataId $currentUserOdataId

# Sign out from Microsoft Graph
Disconnect-MgGraph | Out-Null

#endregion Entra ID

#region Azure (Optional)

# Optionally enable browser-based login on Windows 10 and later
Update-AzConfig -EnableLoginByWam $false

# Authenticate against Azure Resource Manager
Connect-AzAccount -Environment AzureCloud -Scope Process

# Fetch the identifier of the Reader role
[string] $rootScope = '/'
[Microsoft.Azure.Commands.Resources.Models.Authorization.PSRoleDefinition] $azureReaderRole =
    Get-AzRoleDefinition -Scope $rootScope -Name 'Reader'

if (-not (Test-Path -Path 'variable:servicePrincipal')) {
    # Fetch the service principal if the Azure part of the script is executed independently
    [Microsoft.Azure.PowerShell.Cmdlets.Resources.MSGraph.Models.ApiV10.IMicrosoftGraphServicePrincipal] $servicePrincipal =
        Get-AzADServicePrincipal -DisplayName 'BloodHound Enterprise Collector'
}

# Fetch the Tenant Root Group
[guid] $currentTenantId = (Get-AzContext).Tenant.Id
[Microsoft.Azure.Commands.Resources.Models.ManagementGroups.PSManagementGroup] $rootManagementGroup =
    Get-AzManagementGroup -GroupName $currentTenantId

# Assign the Reader role on all Azure subscriptions to AzureHound
[Microsoft.Azure.Commands.Resources.Models.Authorization.PSRoleAssignment] $readerRoleAssignment =
    New-AzRoleAssignment -ObjectId $servicePrincipal.Id `
                         -Scope $rootManagementGroup.Id `
                         -RoleDefinitionId $azureReaderRole.Id

# Sign out from Azure Resource Manager
Disconnect-AzAccount -Scope Process

#endregion Azure (Optional)