Collect Microsoft Azure AD Context logs
This document describes how you can collect Microsoft Azure Active Directory (AD) logs by setting up a Google Security Operations feed.
Azure Active Directory (AZURE_AD) is now called Microsoft Entra ID. Azure AD audit logs
(AZURE_AD_AUDIT) are now Microsoft Entra ID audit logs.
For more information, see Data ingestion to Google Security Operations.
An ingestion label identifies the parser which normalizes raw log data to structured UDM format.
Before you begin
Ensure you have the following prerequisites:
- An Azure subscription that you can sign in to
- A global administrator or Azure AD administrator role
- An Azure AD (tenant) in Azure
How to configure Azure AD
- Sign in to the Azure portal.
- Go to Home > App registration, select a registered application or register an application if you haven't created an application yet.
- To register an application, in the App registration section, click New registration.
- In the Name field, provide the display name for your application.
- In the Supported account types section, select the required option to specify who can use the application or access the API.
- Click Register.
- Go to the Overview page and copy the application (client) ID and the directory (tenant) ID, which are required to configure the Google Security Operations feed.
- Click API permissions.
- Click Add a permission, and then select Microsoft Graph in the new pane.
- Click Application permissions.
- Select AuditLog.Read.All, Directory.Read.All, and SecurityEvents.Read.All permissions. Ensure that the permissions are Application permissions and not Delegated permissions.
- Click Grant admin consent for default directory. Applications are authorized to call APIs when they are granted permissions by users or administrators as part of the consent process.
- Go to Settings > Manage.
- Click Certificates and secrets.
- Click New client secret. In the Value field, the client secret appears.
- Copy the client secret value. The value is displayed only at the time of creation and it is required for the Azure app registration and to configure the Google Security Operations feed.
Set up feeds
There are two different entry points to set up feeds in the Google SecOps platform:
- SIEM Settings > Feeds > Add New Feed
- Content Hub > Content Packs > Get Started
How to set up the Microsoft Azure AD Context feed
- Click the Azure Platform pack.
- Locate the Azure AD Organizational Context log type.
- Specify values for the following fields: - Source Type: Third party API (recommended)
- OAUTH client ID: Specify the client ID that you obtained previously.
- OAUTH client secret: Specify the client secret that you obtained previously.
- Tenant ID: Specify the tenant ID that you obtained previously.
- Retrieve Devices: Whether to retrieve device information within user context.
- Retrieve Groups: Whether to retrieve group membership information within user context.
- API Full path: Microsoft Graph REST API endpoint URL.
- API Authentication Endpoint: Microsoft Active Directory Authentication Endpoint.
 - Advanced options - Feed Name: A prepopulated value that identifies the feed.
- Asset Namespace: Namespace associated with the feed.
- Ingestion Labels: Labels applied to all events from this feed.
 
- Click Create feed. 
For more information about configuring multiple feeds for different log types within this product family, see Configure feeds by product.
For more information about Google Security Operations feeds, see Google Security Operations feeds documentation. For information about requirements for each feed type, see Feed configuration by type. If you encounter issues when you create feeds, contact Google Security Operations support.
Field mapping reference
This parser code transforms raw JSON formatted logs from Azure Active Directory into a unified data model (UDM). It extracts user and manager information, including attributes, roles, relations, and labels, while handling various data inconsistencies and enriching the output with standardized fields.
UDM Mapping Table
| Log Field | UDM Mapping | Logic | 
|---|---|---|
| businessPhones | user.phone_numbers | Directly mapped from the businessPhonesfield in the raw log. Multiple phone numbers are extracted and mapped as separate entries. | 
| city | user.personal_address.city | Directly mapped from the cityfield in the raw log. | 
| companyName | user.company_name | Directly mapped from the companyNamefield in the raw log. | 
| country | user.personal_address.country_or_region | Directly mapped from the countryfield in the raw log. Ifcountryis empty, the value is taken fromusageLocation. | 
| createdDateTime | user.attribute.creation_time | Converted to a timestamp from the createdDateTimefield in the raw log using the RFC 3339 format. | 
| department | user.department | Directly mapped from the departmentfield in the raw log. Multiple departments are extracted and mapped as separate entries. | 
| displayName | user.user_display_name | Directly mapped from the displayNamefield in the raw log. | 
| employeeId | user.employee_id | Directly mapped from the employeeIdfield in the raw log. IfemployeeIdis empty, the value is taken fromextension_employeeNumber. | 
| employeeType | user.attribute.labels.value (key: employeeType) | Directly mapped from the employeeTypefield in the raw log and added as a label with the keyemployeeType. | 
| extension_employeeNumber | user.employee_id | Mapped to user.employee_idifemployeeIdis empty. | 
| extension_wfc_AccountType | event.idm.entity.entity.labels.value (key: wfc_AccountType) | Directly mapped from the extension_wfc_AccountTypefield in the raw log and added as a label with the keywfc_AccountType. | 
| extension_wfc_AccountingUnitName | event.idm.entity.entity.labels.value (key: extension_wfc_AccountingUnitName) | Directly mapped from the extension_wfc_AccountingUnitNamefield in the raw log and added as a label with the keyextension_wfc_AccountingUnitName. | 
| extension_wfc_execDescription | event.idm.entity.entity.labels.value (key: extension_wfc_execDescription) | Directly mapped from the extension_wfc_execDescriptionfield in the raw log and added as a label with the keyextension_wfc_execDescription. | 
| extension_wfc_groupDescription | event.idm.entity.entity.labels.value (key: extension_wfc_groupDescription) | Directly mapped from the extension_wfc_groupDescriptionfield in the raw log and added as a label with the keyextension_wfc_groupDescription. | 
| extension_wfc_orgDescription | event.idm.entity.entity.labels.value (key: extension_wfc_orgDescription) | Directly mapped from the extension_wfc_orgDescriptionfield in the raw log and added as a label with the keyextension_wfc_orgDescription. | 
| givenName | user.first_name | Directly mapped from the givenNamefield in the raw log. | 
| gopher-devices | event.idm.entity.relations | Each device in the gopher-devicesarray is mapped to a separate relation entry. ThedeviceIdis mapped toproduct_object_id,operatingSystemandoperatingSystemVersionare combined to formplatform_version,modelis directly mapped, andcreatedDateTimeis converted to a timestamp and mapped tocreated_timestamp. The relationship is set toOWNSand the direction is set toUNIDIRECTIONAL. | 
| gopher-groups | event.idm.entity.relations | Each group in the gopher-groupsarray is mapped to a separate relation entry. Theidis mapped toproduct_object_id, anddisplayNameis mapped togroup_display_name. The relationship is set toMEMBERand the direction is set toUNIDIRECTIONAL. | 
| gopher-manager.businessPhones | empmanager.phone_numbers | Mapped to empmanager.phone_numbersifmanageris empty. | 
| gopher-manager.country | empmanager.personal_address.country_or_region | Mapped to empmanager.personal_address.country_or_regionifmanageris empty. If bothgopher-manager.countryandgopher-manager.usageLocationare empty, the field is left empty. | 
| gopher-manager.department | empmanager.department | Mapped to empmanager.departmentifmanageris empty. | 
| gopher-manager.displayName | empmanager.user_display_name | Mapped to empmanager.user_display_nameifmanageris empty. | 
| gopher-manager.employeeId | empmanager.employee_id | Mapped to empmanager.employee_idifmanageris empty andgopher-manager.employeeIdis not empty. | 
| gopher-manager.extension_employeeNumber | empmanager.employee_id | Mapped to empmanager.employee_idifmanagerandgopher-manager.employeeIdare empty, andgopher-manager.extension_employeeNumberis not empty. | 
| gopher-manager.givenName | empmanager.first_name | Mapped to empmanager.first_nameifmanageris empty. | 
| gopher-manager.id | empmanager.product_object_id | Mapped to empmanager.product_object_idifmanageris empty. | 
| gopher-manager.jobTitle | empmanager.title | Mapped to empmanager.titleifmanageris empty. | 
| gopher-manager.mail | empmanager.email_addresses | Mapped to empmanager.email_addressesifmanageris empty. | 
| gopher-manager.onPremisesImmutableId | user.attribute.labels.value (key: gopher-manager onPremisesImmutableId) | Mapped as a label with the key gopher-manager onPremisesImmutableId. | 
| gopher-manager.onPremisesSamAccountName | empmanager.userid | Mapped to empmanager.useridifmanageris empty. | 
| gopher-manager.onPremisesSecurityIdentifier | empmanager.windows_sid | Mapped to empmanager.windows_sidifmanageris empty. | 
| gopher-manager.proxyAddresses | empmanager.email_addresses, empmanager.group_identifiers | If manageris empty, each address in thegopher-manager.proxyAddressesarray is mapped to eitherempmanager.email_addressesorempmanager.group_identifiersbased on whether it starts with "smtp" or "SMTP". | 
| gopher-manager.refreshTokensValidFromDateTime | empmanager.attribute.labels.value (key: refreshTokensValidFromDateTime) | Mapped as a label with the key refreshTokensValidFromDateTimeifmanageris empty. | 
| gopher-manager.streetAddress | empmanager.personal_address.name | Mapped to empmanager.personal_address.nameifmanageris empty. | 
| gopher-manager.surname | empmanager.last_name | Mapped to empmanager.last_nameifmanageris empty. | 
| gopher-manager.usageLocation | user.attribute.labels.value (key: manager_src_usageLocation) | Mapped as a label with the key manager_src_usageLocation. | 
| gopher-manager.userType | empmanager.attribute.roles.name | Mapped to empmanager.attribute.roles.nameifmanageris empty. | 
| id | user.product_object_id | Directly mapped from the idfield in the raw log. | 
| identities | user.attribute.labels.value (key: signInType), user.attribute.labels.value (key: userPrincipalName) | The signInTypeis mapped as a label with the keysignInType. IfsignInTypeanduserPrincipalNameare not empty, they are combined and mapped as a label with the keyuserPrincipalName. | 
| jobTitle | user.title | Directly mapped from the jobTitlefield in the raw log. | 
| user.email_addresses | Directly mapped from the mailfield in the raw log. Ifmailstarts with "svc-", theuser_role.typeis set toSERVICE_ACCOUNT. | |
| mailNickname | user.attribute.labels.value (key: mailNickname) | Directly mapped from the mailNicknamefield in the raw log and added as a label with the keymailNickname. | 
| manager.businessPhones | empmanager.phone_numbers | Mapped to empmanager.phone_numbersifgopher-manageris empty. | 
| manager.city | empmanager.personal_address.city | Mapped to empmanager.personal_address.cityifgopher-manageris empty. | 
| manager.companyName | empmanager.company_name | Mapped to empmanager.company_nameifgopher-manageris empty. | 
| manager.country | empmanager.personal_address.country_or_region | Mapped to empmanager.personal_address.country_or_regionifgopher-manageris empty. If bothmanager.countryandmanager.usageLocationare empty, the field is left empty. | 
| manager.department | empmanager.department | Mapped to empmanager.departmentifgopher-manageris empty. | 
| manager.displayName | empmanager.user_display_name | Mapped to empmanager.user_display_nameifgopher-manageris empty. | 
| manager.employeeId | empmanager.employee_id | Mapped to empmanager.employee_idifgopher-manageris empty andmanager.employeeIdis not empty. | 
| manager.extension_employeeNumber | empmanager.employee_id | Mapped to empmanager.employee_idifgopher-managerandmanager.employeeIdare empty, andmanager.extension_employeeNumberis not empty. | 
| manager.givenName | empmanager.first_name | Mapped to empmanager.first_nameifgopher-manageris empty. | 
| manager.id | empmanager.product_object_id | Mapped to empmanager.product_object_idifgopher-manageris empty. | 
| manager.jobTitle | empmanager.title | Mapped to empmanager.titleifgopher-manageris empty. | 
| manager.mail | empmanager.email_addresses | Mapped to empmanager.email_addressesifgopher-manageris empty. | 
| manager.onPremisesSamAccountName | empmanager.userid | Mapped to empmanager.useridifgopher-manageris empty. | 
| manager.onPremisesSecurityIdentifier | empmanager.windows_sid | Mapped to empmanager.windows_sidifgopher-manageris empty. | 
| manager.proxyAddresses | empmanager.email_addresses, empmanager.group_identifiers | If gopher-manageris empty, each address in themanager.proxyAddressesarray is mapped to eitherempmanager.email_addressesorempmanager.group_identifiersbased on whether it starts with "smtp" or "SMTP". | 
| manager.refreshTokensValidFromDateTime | empmanager.attribute.labels.value (key: refreshTokensValidFromDateTime) | Mapped as a label with the key refreshTokensValidFromDateTimeifgopher-manageris empty. | 
| manager.state | empmanager.personal_address.state | Mapped to empmanager.personal_address.stateifgopher-manageris empty. | 
| manager.streetAddress | empmanager.personal_address.name | Mapped to empmanager.personal_address.nameifgopher-manageris empty. | 
| manager.surname | empmanager.last_name | Mapped to empmanager.last_nameifgopher-manageris empty. | 
| manager.usageLocation | user.attribute.labels.value (key: manager_src_usageLocation), empmanager.personal_address.country_or_region | Mapped as a label with the key manager_src_usageLocation. Ifmanager.countryis empty, the value is also mapped toempmanager.personal_address.country_or_region. | 
| manager.userType | empmanager.attribute.roles.name | Mapped to empmanager.attribute.roles.nameifgopher-manageris empty. | 
| onPremisesDistinguishedName | user.attribute.labels.value (key: onPremisesDistinguishedName), user.attribute.labels.value (key: onPremisesDistinguishedName-OU data) | The full distinguished name is mapped as a label with the key onPremisesDistinguishedName. The OU portion of the distinguished name is extracted and mapped as a label with the keyonPremisesDistinguishedName-OU data. If the OU portion contains "Admin", theuser_role.typeis set toADMINISTRATOR. If it contains "Service Accounts", theuser_role.typeis set toSERVICE_ACCOUNT. | 
| onPremisesDomainName | user.group_identifiers, user.attribute.labels.value (key: onPremisesDomainName) | Directly mapped to user.group_identifiersand added as a label with the keyonPremisesDomainName. | 
| onPremisesImmutableId | user.attribute.labels.value (key: onPremisesImmutableId) | Directly mapped from the onPremisesImmutableIdfield in the raw log and added as a label with the keyonPremisesImmutableId. | 
| onPremisesSamAccountName | user.userid, user.attribute.labels.value (key: onPremisesSamAccountName) | Mapped to user.useridifsAMAccountNameis empty. Also added as a label with the keyonPremisesSamAccountName. | 
| onPremisesSecurityIdentifier | user.windows_sid | Directly mapped from the onPremisesSecurityIdentifierfield in the raw log. | 
| proxyAddresses | user.email_addresses, user.group_identifiers | Each address in the proxyAddressesarray is mapped to eitheruser.email_addressesoruser.group_identifiersbased on whether it starts with "smtp" or "SMTP". If the address starts with "smtp" or "SMTP", the "smtp:" or "SMTP:" prefix is removed and the remaining email address is extracted and mapped touser.email_addresses. | 
| refreshTokensValidFromDateTime | user.attribute.labels.value (key: refreshTokensValidFromDateTime) | Directly mapped from the refreshTokensValidFromDateTimefield in the raw log and added as a label with the keyrefreshTokensValidFromDateTime. | 
| sAMAccountName | user.userid | Directly mapped from the sAMAccountNamefield in the raw log. | 
| state | user.personal_address.state | Directly mapped from the statefield in the raw log. | 
| streetAddress | user.personal_address.name | Directly mapped from the streetAddressfield in the raw log. | 
| surname | user.last_name | Directly mapped from the surnamefield in the raw log. | 
| usageLocation | user.personal_address.country_or_region | If countryis empty, the value is mapped touser.personal_address.country_or_region. | 
| userPrincipalName | user.email_addresses | Directly mapped from the userPrincipalNamefield in the raw log. IfuserPrincipalNamestarts with "svc-", theuser_role.typeis set toSERVICE_ACCOUNT. | 
| userType | user.attribute.roles.name | Directly mapped from the userTypefield in the raw log and added touser.attribute.roles.name. | 
| Parser Logic | UDM Mapping | Logic | 
| N/A | event.idm.entity.metadata.vendor_name | Set to "Microsoft". | 
| N/A | event.idm.entity.metadata.product_name | Set to "Azure Active Directory". | 
| N/A | event.idm.entity.metadata.entity_type | Set to "USER". | 
| N/A | event.idm.entity.metadata.collected_timestamp | Set to the create_timefield from the raw log. | 
| accountEnabled | user.user_authentication_status, user.attribute.labels.value (key: accountEnabled) | If accountEnabledis true,user.user_authentication_statusis set to "ACTIVE" and a label with the keyaccountEnabledand value "true" is added. Otherwise, a label with the keyaccountEnabledand value "false" is added. | 
| empmanager-src.accountEnabled | user.user_authentication_status, user.attribute.labels.value (key: accountEnabled) | If manageris empty andempmanager-src.accountEnabledis "true",user.user_authentication_statusis set to "ACTIVE" and a label with the keyaccountEnabledand value "true" is added. Otherwise, a label with the keyaccountEnabledand value "false" is added. | 
| onPremisesDistinguishedName | user_role.type | If the OU portion of the distinguished name contains "Admin", the user_role.typeis set toADMINISTRATOR. If it contains "Service Accounts", theuser_role.typeis set toSERVICE_ACCOUNT. | 
| userPrincipalName | user_role.type | If userPrincipalNamestarts with "svc-", theuser_role.typeis set toSERVICE_ACCOUNT. | 
| empmanager-src.onPremisesDistinguishedName | manager_role.type | If gopher-manageris empty and the OU portion of the manager's distinguished name contains "Users", themanager_role.typeis set toADMINISTRATOR. If it contains "Service Accounts", themanager_role.typeis set toSERVICE_ACCOUNT. | 
| empmanager-src.userPrincipalName | manager_role.type | If gopher-manageris empty andempmanager-src.userPrincipalNamestarts with "svc-", themanager_role.typeis set toSERVICE_ACCOUNT. | 
| user_role.type | If mailstarts with "svc-", theuser_role.typeis set toSERVICE_ACCOUNT. | 
Need more help? Get answers from Community members and Google SecOps professionals.