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.
Create a new app registration
-
In the left menu, click Entra ID > App registrations > New registration.
-
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.
-
Click Register to create the application registration.
Retrieve details for AzureHound configuration
Assign required API permissions
This section describes how to assign the required Microsoft Graph API permissions to the AzureHound Enterprise application registration.
Navigate to API permissions
On the Overview page of the app registration, click API Permissions.
Remove default permission
Remove the default User.Read delegated permission. It is not required for AzureHound Enterprise data collection. Add Microsoft Graph API permissions
-
Click Add a permission > Microsoft Graph.
-
Select Application permissions.
-
Search for the Directory.Read.All permission and check the box next to it.
-
Search for the RoleManagement.Read.All permission and check the box next to it.
-
Click Add permissions.
Grant admin consent
After adding the required permissions, you must grant admin consent for the application to use them.
-
Click Grant admin consent for <your_tenant_name>.
-
Click Yes in the confirmation dialog.
-
After being redirected to API Permissions again, you should see both permissions as Granted.
Continue to the Configure authentication section.
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 identity (recommended)
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.
Microsoft recommends the User-Assigned Managed Identity for Microsoft services, so the following example shows the User-Assigned type.
Navigate to Azure Managed Identities
Sign in to the Azure portal and search for Managed Identities in the top search bar. Create a user-assigned managed identity
Click Create and enter the required information to create a new user-assigned managed identity. Configure the app registration to use the managed identity
-
Sign in to the Microsoft Entra admin center and navigate to the previously created AzureHound Enterprise application registration.
-
In the left menu, click Certificates & secrets > Federated credentials > Add credential.
-
From the Federated credential scenario drop-down menu, select Managed Identity and enter the required information.
-
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.
Navigate to Entra ID Certificates & secrets
-
On the Overview page of the app registration, click Certificates & secrets.
-
Click Certificates.
Upload certificate
-
Click Upload certificate.
-
Locate the
cert.pem file that you created during AzureHound configuration.
-
Click the folder icon, select the
cert.pem file, and add a description (optional).
-
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.
Navigate to Entra ID Roles & admins
In the left menu, click Entra ID > Roles & admins.
Assign Directory Readers role
-
Search for the Directory Readers role and click the role name or description.
Clicking the checkbox sometimes prevents clicking on the role itself.
-
Click Add assignments.
-
Click No member selected to open the search window.
-
Search for the previously created service principal with either its name, application ID, or object ID. Select it by clicking on it.
-
Click Select.
-
Validate that your principal is displayed and click Next.
-
Ensure that the Assignment type is Active and the Permanently assigned box is checked. Enter a justification and click Assign.
-
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.
Navigate to Management Groups
Add the Reader role assignment
-
Select Access control (IAM).
-
Select Role assignments.
-
Click Add, then Add role assignment.
-
Find the Reader role and select it.
-
Click Members.
-
Click Select members.
-
Search for and click on your previously created service principal.
-
Validate the principal selected, then click Select.
Review role assignment
-
Click the tab Review + Assign.
-
Click Review + Assign at the bottom of the page.
-
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)