Okta¶
Okta keeps a System Log of what happens in your Okta organization: sign-ins and MFA prompts, sessions, accounts created, locked and deleted, groups and apps changed, admin roles granted, policies and network zones edited, API tokens made, and the threats Okta ThreatInsight sees. Signalith reads it straight from Okta, makes each event searchable and runs the SigmaHQ and Splunk Okta rules on it. Nothing needs to be installed.
How it works¶
Signalith signs in to Okta as an API service app you add in the Okta Admin Console,
with a private key only Signalith holds, and reads the System Log from Okta's System
Log API (GET /api/v1/logs). Every minute it reads the events published since it last
looked, oldest first, in pages of up to 1,000.
The server that runs the background jobs does the reading, and keeps its place in the log in OpenSearch, so a restart or another server taking over carries on where it left off. An event read twice is stored once. Events usually arrive within a minute or two of happening. Okta keeps them for 90 days, so Signalith catches up after being off for less than that; one round reads at most 20 pages, so a long gap is read over a few minutes, leaving room in your organization's rate limit for its other apps.
The app can only read the System Log: it is granted the okta.logs.read scope and
nothing else, and it signs in with a signed token (private_key_jwt), never a shared
secret. When the app requires DPoP, as new Okta apps do, Signalith also proves each
token is its own with a key it makes for itself and never stores.
What you need¶
- An Okta admin who can add apps and assign admin roles: a Super Administrator, or an Application Administrator together with someone who can assign roles.
- The Signalith server must reach your Okta domain (such as
example.okta.com) over HTTPS. SetHTTPS_PROXYif it goes through a proxy. Signalith only connects to internet addresses for Okta, so a domain that leads to this machine or the local network is refused.
Set it up¶
On the Add data page, choose Okta for the same steps:
- Add the app. In the Okta Admin Console, open Applications > Applications and
choose Create App Integration. Pick API Services, name it
Signalith, and save. - Give it a key. On the app's General tab, edit Client Credentials and choose Public key / Private key. Choose Add key, then Generate new key. Okta shows the private key once: copy it, as PEM or as the JSON it shows, before you close the box. Save the app. If Okta asks, keep Require Demonstrating Proof of Possession (DPoP) header in token requests on: Signalith supports it.
- Let it read the System Log. On the Okta API Scopes tab, choose Grant next
to
okta.logs.read. On the Admin roles tab, choose Edit assignments and give the app Read-only Administrator, which may read the System Log and change nothing. - Enter it in Signalith. In Settings, under Okta, enter your Okta domain
(the address of your Okta sign-in page, without
https://), the app's Client ID from its General tab, and the private key. Choose Test: it signs in and reads the last hour of the System Log. Then save.
Reading starts within a minute. The first time, Signalith reads the last 24 hours.
The key is kept encrypted with Signalith's other secrets, and only ever sent to your
Okta domain. It is only used to sign Signalith's sign-in, so Okta never sees it either.
A browser drops the line breaks of a PEM key pasted into the Settings page; Signalith
reads it all the same. If the app has more than one key, also enter the Key ID (the
kid Okta shows next to the key). To keep the key out of the settings entirely, put it
in a file only Signalith can read and set SIGNALITH_OKTA_PRIVATE_KEY_FILE to that
file's path, or store it encrypted in signalith.yaml with
signalith secrets set okta.private_key < key.pem. In signalith.yaml the settings are:
okta:
domain: example.okta.com
client_id: 0oa1b2c3d4e5f6g7h8i9
private_key: ... # or SIGNALITH_OKTA_PRIVATE_KEY_FILE
key_id: "" # only when the app has more than one key
To change the key, add a new one to the app, enter it in Signalith, then deactivate the old one in Okta.
With an API token instead¶
An admin's API token works too, in place of the app: create one in Security > API >
Tokens while signed in as an admin with at least Read-only Administrator, and enter
it as API token with the Okta domain (or set SIGNALITH_OKTA_API_TOKEN). A token has
all of that admin's rights and expires after 30 days without use, so the app is the
better way. When both are set, Signalith uses the app.
Sending events another way¶
Events that come some other way are read the same: send Okta's LogEvent JSON (one event,
or a JSON array of them as the API returns a page) to /api/ingest?tag=okta with an
agent token, or through the OpenTelemetry Collector as a log record
whose body is one event. Don't do this as well as Signalith's own reading, which needs
nothing else.
What you get¶
Each event becomes one event with sourcetype=OktaIM2:log, the sourcetype of Splunk's
add-on for Okta Identity Cloud. Its fields keep Okta's own names, with nested objects
flattened into dotted names:
| Field | Example |
|---|---|
eventType |
user.session.start, user.mfa.factor.deactivate, system.api_token.create |
displayMessage, severity |
User login to Okta, INFO, WARN |
actor.alternateId, actor.displayName |
jo@example.com, Jo Doe |
client.ipAddress, client.userAgent.rawUserAgent |
203.0.113.7, the browser |
outcome.result, outcome.reason |
SUCCESS, FAILURE, INVALID_CREDENTIALS |
authenticationContext.externalSessionId |
the session an event belongs to |
securityContext.isProxy, securityContext.asOrg |
true for an anonymizing proxy, the network's owner |
debugContext.debugData.behaviors, .risk, .threatSuspected |
what Okta's risk engine saw |
target{}.type, target{}.alternateId, target{}.displayName |
each thing the event acted on, as Splunk's add-on names them |
okta_device.name, okta_device.os_platform, okta_device.managed |
the device an Okta Verify or FastPass sign-in came from (Okta's device object, renamed because Signalith's device field holds text) |
Every value is kept as text, because Okta's debug data uses names of its own whose values differ from one event type to the next. Each event also gets the data model fields of what it is:
- A sign-in (
user.session.start,user.authentication.*, opening the Admin Console, a denied app) is an Authentication event, withactionsuccess, failure or pending,user,src,app,reasonandauthentication_method. - A change (users, accounts, MFA factors, groups, apps, policies, network zones, API
tokens, identity providers, devices, admin roles) is a Change event, with
action(created, modified, deleted or lockout),command,objectandobject_category(the first target), andchange_typeAAA. - A threat Okta detected (
security.*,user.risk.*) or suspicious activity a user reported is an Alerts event, withsignature,severityandtype. - Everything else, such as MFA pushes sent and policies evaluated, is an Other event.
All of them have user and src_user (the actor), src (the client's address),
signature (the event type), description, id (the event's ID), app and dest
(the app it was about, or Okta), result and status (success or failure). Some
searches to start with:
sourcetype=OktaIM2:log eventType=user.session.start outcome.result=FAILURE | stats count by user, src
datamodel=Change sourcetype=OktaIM2:log | stats count by signature, user
sourcetype=OktaIM2:log securityContext.isProxy=true | stats count by user, src
Detections¶
The SigmaHQ pack has 19 Okta rules (see Detections): admin roles
assigned, API tokens created or revoked, apps, sign-on policies, policies and policy
rules changed or deleted, identity providers created, MFA reset or deactivated, network
zones deactivated or deleted, accounts locked out, admin functions used through a proxy,
new Admin Console behaviors, sessions started through an anonymizing proxy, FastPass
phishing detections, ThreatInsight threats, unauthorized access to apps and suspicious
activity users reported. Two SigmaHQ Okta rules are left out: okta_user_created is
informational, and okta_password_in_alternateid_field uses a regular expression
Signalith can't read exactly.
The Splunk Security Content pack has 12 Okta rules: failed MFA challenges, MFA turned
off, identity provider changes, many accounts locked out, many failed MFA requests for
one user, many users failing to sign in from one address, new API tokens, new devices
enrolled, sign-ins with only one factor, suspicious activity reported, ThreatInsight
threats and unauthorized access to apps. Of the 21 Splunk rules for Okta, 9 are left out:
4 are experimental, one is a hunting search and one a correlation search, two need
iplocation to name a city (Signalith has no city database), and one uses a command
Signalith doesn't run (REPORT.md in the pack lists each). Turn them on from each pack's
page like any other rules.
When nothing arrives¶
- Look at the Add data page. Choose Okta: below the steps it says how far the System Log has been read, and the last error Okta gave.
- Test the settings. Test in Settings names what is wrong: a client ID Okta
doesn't know, a key that isn't the app's (or the app not set to Public key / Private
key), the
okta.logs.readscope not granted, or no admin role that can read the System Log. - Rate limits. When the organization's rate limit for the System Log is used up, Signalith waits until Okta says it resets, then carries on.
- Read Signalith's log for
could not read the Okta System Log, which carries Okta's own error code (such asE0000011for a token Okta refused).