Collect Okta logs
This document explains how to ingest Okta logs to Google Security Operations using the Okta API. The parser extracts system logs, handling both single events and batched events within a JSON array. It normalizes the data into the UDM format, mapping Okta fields to UDM equivalents, enriching the data with parsed user agents, geographical information, and authentication details, and generating security result events based on outcomes and risk information.
Before you begin
- Ensure that you have a Google SecOps instance.
- Ensure that you have privileged access to Okta.
Configure Okta
To configure Okta SSO, complete the following tasks:
Create Okta Administrative user with read-only privileges
- Sign in to the Okta administrator console.
Create a Standard User.
- Go to Directory > People.
- Click Add person and complete the required fields.
Select Security > Administrators.
Click Add Administrator.
In the Administrator assignment by admin field, find the Standard User.
In the roles section, select Read-Only Administrator from the list.
Sign out from the administrator account.
Get API Key
- Sign in to the Okta Administrator Console with the read-only administrator user.
- Go to Security > API > Tokens.
- Click Create Token.
- Provide a meaningful name for the token.
- Provide the IP zone, where the API will be used (you can select any IP if you are not sure).
- Click Create Token.
- Copy the API key.
- Click OK, got it.
Configure a feed in Google SecOps to ingest Okta logs
- Go to SIEM Settings > Feeds.
- Click Add new.
- In the Feed name field, enter a name for the feed (for example, Okta Logs).
- Select Third party API as the Source type.
- Select Okta as the Log type.
- Click Next.
- Specify values for the following input parameters:
- Authentication HTTP header: enter Okta API Key in the following format:
Authorization:<API_KEY>
. - API Hostname: specify the domain name of your Okta host (for example,
<your-domain>.okta.com
). - Asset namespace: the asset namespace.
- Ingestion labels: the label applied to the events from this feed.
- Authentication HTTP header: enter Okta API Key in the following format:
- Click Next.
- Review the feed configuration in the Finalize screen, and then click Submit.
UDM Mapping Table
Log Field | UDM Mapping | Logic |
---|---|---|
actor.alternateId |
principal.user.email_addresses |
Extracted from actor.alternateId if it is an email address. If not an email address, used as principal.user.userid . |
actor.displayName |
principal.user.user_display_name |
Directly mapped. |
actor.id |
principal.user.product_object_id |
Directly mapped. |
actor.type |
principal.user.attribute.roles.name |
Directly mapped. |
authenticationContext.authenticationProvider |
security_result.detection_fields.value |
Directly mapped, with key authenticationProvider . |
authenticationContext.credentialProvider |
security_result.detection_fields.value |
Directly mapped, with key credentialProvider . |
authenticationContext.credentialType |
extensions.auth.mechanism |
Used to derive the authentication mechanism (OTP, USERNAME_PASSWORD, LOCAL). |
authenticationContext.externalSessionId |
network.parent_session_id |
Directly mapped. |
client.device |
principal.asset.type / additional.fields.value.string_value |
Mapped to principal.asset.type (WORKSTATION, MOBILE, ROLE_UNSPECIFIED) based on value. Also mapped as string value with key device in additional.fields . |
client.geographicalContext.city |
principal.location.city |
Directly mapped. |
client.geographicalContext.country |
principal.location.country_or_region |
Directly mapped. |
client.geographicalContext.geolocation.lat |
principal.location.region_latitude |
Directly mapped. |
client.geographicalContext.geolocation.lon |
principal.location.region_longitude |
Directly mapped. |
client.geographicalContext.postalCode |
additional.fields.value.string_value |
Directly mapped as string value with key Postal code in additional.fields . |
client.geographicalContext.state |
principal.location.state |
Directly mapped. |
client.ipAddress |
principal.ip , principal.asset.ip |
Directly mapped. |
client.userAgent.browser |
target.resource.attribute.labels.value |
Directly mapped, with key Browser . |
client.userAgent.os |
principal.platform |
Mapped to platform (LINUX, WINDOWS, MAC) based on value. |
client.userAgent.rawUserAgent |
network.http.user_agent , network.http.parsed_user_agent |
Directly mapped and parsed. |
client.zone |
additional.fields.value.string_value |
Directly mapped as string value with key zone in additional.fields . |
debugContext.debugData.behaviors |
security_result.description , security_result.detection_fields |
Directly mapped to description. Individual behaviors are extracted and added as detection fields. |
debugContext.debugData.changedAttributes |
security_result.detection_fields.value |
Directly mapped, with key changedAttributes . |
debugContext.debugData.clientAddress |
principal.ip , principal.asset.ip |
Directly mapped if request.ipChain and client.ipAddress are missing. |
debugContext.debugData.deviceFingerprint |
target.asset.asset_id |
Directly mapped, prefixed with device_finger_print: . |
debugContext.debugData.dtHash |
security_result.detection_fields.value |
Directly mapped, with key dtHash . |
debugContext.debugData.factor |
security_result.detection_fields.value |
Directly mapped, with key factor . |
debugContext.debugData.factorIntent |
security_result.detection_fields.value |
Directly mapped, with key factorIntent . |
debugContext.debugData.logOnlySecurityData.risk.reasons |
security_result.detection_fields.value |
Directly mapped, with key Risk Reasons . |
debugContext.debugData.privilegeGranted |
target.user.attribute.roles |
Split into individual privileges and added as roles with name and description. |
debugContext.debugData.pushOnlyResponseType |
security_result.detection_fields.value |
Directly mapped, with key pushOnlyResponseType . |
debugContext.debugData.pushWithNumberChallengeResponseType |
security_result.detection_fields.value |
Directly mapped, with key pushWithNumberChallengeResponseType . |
debugContext.debugData.requestUri |
extensions.auth.auth_details |
Directly mapped. |
debugContext.debugData.suspiciousActivityEventId |
security_result.detection_fields.value |
Directly mapped, with key suspiciousActivityEventId . |
debugContext.debugData.suspiciousActivityEventType |
security_result.detection_fields.value |
Directly mapped, with key suspiciousActivityEventType . |
debugContext.debugData.threatDetections |
security_result.detection_fields.value |
Directly mapped, with key threatDetections . |
debugContext.debugData.threatSuspected |
security_result.detection_fields.value , security_result.threat_status |
Mapped as a detection field with key threatSuspected . Used to derive threat status (ACTIVE or FALSE_POSITIVE). |
debugContext.debugData.url |
target.url |
Directly mapped. |
displayMessage |
security_result.summary |
Directly mapped. |
eventType |
metadata.product_event_type , metadata.event_type |
Directly mapped to product_event_type . Used to derive event_type (USER_LOGIN, USER_LOGOUT, USER_CHANGE_PASSWORD, USER_CHANGE_PERMISSIONS, USER_DELETION, GROUP_MODIFICATION, SETTING_MODIFICATION, SCHEDULED_TASK_ENABLE, RESOURCE_CREATION, USER_UNCATEGORIZED). |
legacyEventType |
security_result.detection_fields.value |
Directly mapped, with key legacyEventType . |
outcome.reason |
security_result.category_details |
Directly mapped. |
outcome.result |
security_result.action |
Mapped to action (ALLOW, CHALLENGE, BLOCK) based on value. |
published |
metadata.event_timestamp |
Parsed to timestamp. |
request.ipChain.n.geographicalContext |
intermediary.location |
Geographical context of intermediary IPs in the request chain. |
request.ipChain.n.ip |
intermediary.ip |
IP addresses of intermediaries in the request chain. |
securityContext.asNumber |
security_result.detection_fields.value |
Directly mapped, with key asNumber . |
securityContext.asOrg |
security_result.detection_fields.value |
Directly mapped, with key asOrg . |
securityContext.domain |
security_result.detection_fields.value |
Directly mapped, with key domain . |
securityContext.isp |
security_result.detection_fields.value |
Directly mapped, with key isp . |
securityContext.isProxy |
security_result.detection_fields.value |
Directly mapped, with key anonymized IP . |
target.n.alternateId |
target.user.email_addresses / target.user.userid |
If it is an email address, mapped to target.user.email_addresses . If not an email address, used as target.user.userid . |
target.n.detailEntry.clientAppId |
target.asset_id |
Directly mapped, prefixed with Client_app_id: . |
target.n.detailEntry.methodTypeUsed |
target.resource_ancestors.attribute.labels.value |
Directly mapped, with key methodTypeUsed when target type is AuthenticatorEnrollment. |
target.n.detailEntry.methodUsedVerifiedProperties |
target.resource_ancestors.attribute.labels.value |
Directly mapped, with key methodUsedVerifiedProperties when target type is AuthenticatorEnrollment. |
target.n.detailEntry.policyType |
target.resource_ancestors.attribute.labels.value |
Directly mapped, with key Policy Type . |
target.n.detailEntry.signOnModeType |
security_result.detection_fields.value |
Directly mapped, with key signOnModeType . |
target.n.displayName |
target.user.user_display_name / target.application / target.resource.name |
Mapped based on target type. |
target.n.id |
target.user.product_object_id / target.resource.product_object_id / target.resource_ancestors.product_object_id |
Mapped based on target type. |
target.n.type |
target.user.attribute.roles.name / target.resource.resource_subtype / target.resource_ancestors.resource_subtype |
Mapped based on target type. |
transaction.id |
network.session_id |
Directly mapped. |
transaction.type |
additional.fields.value.string_value |
Directly mapped as string value with key type in additional.fields . |
uuid |
metadata.product_log_id |
Directly mapped. |
N/A | metadata.vendor_name |
Set to Okta . |
N/A | metadata.product_name |
Set to Okta . |
N/A | extensions.auth.type |
Set to SSO . |
N/A | is_alert |
Set to true for security.threat.detected and user.account.report_suspicious_activity_by_enduser events. |
N/A | is_significant |
Set to true for security.threat.detected and user.account.report_suspicious_activity_by_enduser events. |
Changes
2024-05-16
- If
is_alert
is true andis_significant
is true, then setsecurity_result.alert_state
asALERTING
.
2024-03-05
- Updated
security_result.action
field to reflect whether the traffic was allowed or blocked.
2024-02-16
Bug fix:
- When
target.0.type
isUser
orAppUser
, then mappedtarget.0.alternateId
totarget.user.userid
. - When
target.1.type
isUser
orAppUser
, then mappedtarget.1.alternateId
totarget.user.userid
.
2023-12-14
- Mapped
securityContext.asNumber
tosecurity_result.detection_fields
. - Mapped
legacyEventType
tosecurity_result.detection_fields
. - Added
conditional_check
before settingmetadata.event_type
.
2023-06-28
- Mapped complete value of
debugContext.debugData.suspiciousActivityEventType
tosecurity_result.detection_fields
. - Mapped complete value of
debugContext.debugData.logOnlySecurityData.behaviors.New Device
tosecurity_result.detection_fields
.
2023-06-09
- The field
debugContext.debugData.deviceFingerprint
is mapped totarget.asset.asset_id
. - Mapped complete value of
debugContext.debugData.risk.reasons
tosecurity_result.detection_fields
.
2023-05-17
- The field 'authenticationContext.externalSessionId' is mapped to 'network.parent_session_id'.
- The field 'debugContext.debugData.pushOnlyResponseType' is mapped to 'security_result.detection_fields.key/value'.
- The field 'debugContext.debugData.factor' is mapped to 'security_result.detection_fields.key/value'.
- The field 'debugContext.debugData.factorIntent' is mapped to 'security_result.detection_fields.key/value'.
- The field 'debugContext.debugData.pushWithNumberChallengeResponseType' is mapped to 'security_result.detection_fields.key/value'.
- The field 'debugContext.debugData.dtHash' is mapped to 'security_result.detection_fields.key/value'.
- The field 'client.userAgent.rawUserAgent' is mapped to 'network.http.user_agent'.
- Changed the mapping from 'ALLOW_WITH_MODIFICATION' to enum value 'CHALLENGE' under 'security_result.action'.
- For the eventType 'system.api_token.create', changed metadata.event_type from 'USER_UNCATEGORIZED' to 'RESOURCE_CREATION'.
2023-04-28
Bug fix:
- Modified mapping for
security_result.threat_status
toACTIVE
whendebugContext.debugData.threatSuspected
istrue
else mapped toFALSE_POSITIVE
.
2023-03-24
- Mapped
logOnlySecurityData
fields tosecurity_result.detection_fields
. - Additionally, resolved parsing error by adding
DEFERRED
to action list.
2023-04-11
- Remapped the fields which are mapped to
http.user_agent
tohttp.parsed_user_agent
. - Mapped
target.displayName
totarget.resource_ancestors.name
. - Mapped
targetfield.detailEntry.methodTypeUsed
totarget.resource_ancestors.attribute.labels
. - Mapped
targetfield.detailEntry.methodUsedVerifiedProperties
totarget.resource_ancestors.attribute.labels
.
2023-02-20
- Changed
metadata.event_type
fromUSER_LOGIN
toSTATUS_UPDATE
whereeventType
isuser.authentication.auth_via_AD_agent
2022-12-14
- Mapped
debugContext.debugData.changedAttributes
tosecurity_result.detection_fields
. - Added null check for
detail.actor.alternateId
.
2022-11-17
- The field
target[n].alternateId
is mapped totarget.resource.attribute.labels
. - The field
detail.target.0.alternateId
is mapped totarget.resource.attribute.labels
.
2022-11-08
Bug fix:
- Added condition for proper email check for field
user_email
. - Added check for field
Action1
not inRATE_LIMIT
. - Added null, unknown check for
actor.displayName
.
2022-11-04
- Added support for logs having multiple events.
2022-10-15
signOnModeType
mapped tosecurity_result.detection_fields
.authenticationProvider
mapped tosecurity_result.detection_fields
.credentialProvider
mapped tosecurity_result.detection_fields
.device
mapped toadditional.fields
.zone
mapped toadditional.fields
.type
mapped toadditional.fields
.
2022-10-14
Bug fix:
- Added conditional check for 'principal.user.email_addresses' and 'target.user.email_addresses'.
- Added grok to check for valid ip_address for the field 'request.ipChain.0.ip' mapped to 'principal.ip'.
- Added on_error condition for the field 'debugContext.debugData.url' mapped to 'target.url'.
2022-10-03
- Mapped
client.userAgent.os
toprincipal.platform
. - Mapped
client.device
toprincipal.asset.type
. - Mapped
anonymized IP
(hardcoded string) to security_result.detection_fields.key where 'securityContext.isProxy' value to corresponding security_result.detection_fields.value.
2022-09-16
- 'securityContext.asOrg' mapped to 'security_result.category_details'.
- 'securityContext.isProxy' mapped to 'security_result.detection_fields'.
- 'securityContext.domain' mapped to 'security_result.detection_fields'.
- 'securityContext.isp' mapped to 'security_result.detection_fields'.
- 'debugContext.debugData.risk.level' mapped to 'security_result.severity'.
- 'debugContext.debugData.risk.reasons' mapped to 'security_result.detection_fields'.
2022-08-12
- the newly ingested logs have been parsed and mapped to following fields:
- 'detail.uuid' mapped to 'metadata.product_log_id'.
- 'detail.eventType' mapped to 'metadata.product_event_type'
- 'detail.actor.id' mapped to 'principal.user.product_object_id'.
- if 'detail.actor.alternateId' mapped to 'principal.user.userid' else
- 'detail.actor.alternateId' mapped to 'principal.user.email_addresses'.
- 'detail.actor.displayName' mapped to 'principal.user.user_display_name'.
- 'detail.actor.type' mapped to '.principal.user.attribute.roles'.
- 'detail.client.ipChain.0.ip' mapped to 'principal.ip'.
- 'detail.client.ipChain.0.geographicalContext.state' mapped to 'principal.location.state'.
- 'detail.client.ipChain.0.geographicalContext.city' mapped to 'principal.location.city'.
- 'detail.client.ipChain.0.geographicalContext.country' mapped to 'principal.location.country_or_region'.
- 'detail.debugContext.debugData.requestUri' mapped to 'target.url'.
- 'detail.target.0.type' mapped to 'target.resource.resource_subtype'.
- 'detail.target.0.id' mapped to 'target.resource.resource.product_object_id'.
- 'detail.target.0.displayName' mapped to 'target.resource.resource_subtype'.
- 'detail.target.0.detailEntry.policyType' mapped to 'target.resource_ancestors.attribute.labels'.
- 'detail.outcome.reason' mapped to 'security_result.category_details'.
- 'detail.debugContext.debugData.threatSuspected' mapped to 'security_result.detection_fields'.
- 'detail.displayMessage' mapped to 'security_result.summary'.
- 'detail.outcome.result' mapped to 'security_result.action'.
- 'detail.severity' mapped to 'security_result.severity'.
- 'detail.transaction.id' mapped to 'network.session_id'.
- 'detail.debugContext.debugData.requestUri' mapped to 'extensions.auth.auth_details'.
2022-07-08
- Modified mapping for
actor.type
fromprincipal.user.role_name
toprincipal.user.attribute.roles
. - Modified mapping for
target.0.type
fromtarget.user.role_name
totarget.user.attribute.roles
. - Modified mapping for
target.1.type
fromtarget.user.role_name
totarget.user.attribute.roles
.
2022-06-15
Enhancement:
- for
target.0.type
==Token
. - Mapped
target.0.detailEntry.clientAppId
totarget.asset_id
. - Added conditional check for the field 'transaction.id' mapped to the UDM field 'network.session_id'.
2022-06-03
Enhancement:
- Mapped debugContext.debugData.privilegeGranted to target.user.attribute.roles.name additionally.
- Mapped debugContext.debugData.requestUri to extensions.auth.auth_details.
- Mapped debugContext.debugData.suspiciousActivityEventId, debugContext.debugData.threatDetections, debugContext.debugData.threatSuspected to security_result.detection_fields.
2022-03-22
Enhancement:
- debugContext.debugData.behaviors mapped to security_result.description.
- debugContext.debugData.threatSuspected mapped to security_result.threat_status.
- debugContext.debugData.risk mapped to security_result.severity.
Need more help? Get answers from Community members and Google SecOps professionals.