Wednesday, June 12, 2019

Parsing and Displaying Okta Data in Splunk - Part I - User Lookup Tool

By Tony Lee

If you are reading this page chances are good that you have both Splunk and Okta. The good news is that there is a pre-built TA (https://splunkbase.splunk.com/app/2806/) to help with the data ingest and parsing, plus an app (https://splunkbase.splunk.com/app/2821/) to help with the visualizations. However, there is always room to improve and thus we created and are sharing some additional lookup dashboards to make the data more actionable.

Figure 1:  At the time of this article, an Okta TA and App exists

In this first article, we will show how to create a user lookup tool using the information contained within the Okta logs. As a bonus, we will provide our dashboard board at the bottom. Since Okta has quite a bit of user information, the existing data makes a useful Rolodex (yes, that paper-based wheel of information--ask your parents if still unclear) that is available to Splunk. This is especially useful to a SOC analyst who might be tracking down a user or group.

Figure 2:  Okta User Lookup dashboard with useful filters!


Data Categorization

Okta data brought in via the TA is easily distinguishable via the source field.  For example:
  • okta:user
  • okta:event
  • okta:group
  • okta:app
Thus, for user data, we will use source=okta:user 


Raw Log

A sample user event is shown below. Notice how much useful data is contained within the event:

[
  {
    "id": "00ub0oNGTSWTBKOLGLNR",
    "status": "STAGED",
    "created": "2013-07-02T21:36:25.344Z",
    "activated": null,
    "statusChanged": null,
    "lastLogin": null,
    "lastUpdated": "2013-07-02T21:36:25.344Z",
    "passwordChanged": "2013-07-02T21:36:25.344Z",
    "profile": {
      "firstName": "Isaac",
      "lastName": "Brock",
      "email": "isaac.brock@example.com",
      "login": "isaac.brock@example.com",
      "mobilePhone": "555-415-1337"
    },
    "credentials": {
      "provider": {
        "type": "OKTA",
        "name": "OKTA"
      }
    },
    "_links": {
      "self": {
        "href": "https://{yourOktaDomain}/api/v1/users/00ub0oNGTSWTBKOLGLNR"
      }
    }
  },
  {
    "id": "00ub0oNGTSWTBKOLGLNR",
    "status": "ACTIVE",
    "created": "2013-06-24T16:39:18.000Z",
    "activated": "2013-06-24T16:39:19.000Z",
    "statusChanged": "2013-06-24T16:39:19.000Z",
    "lastLogin": "2013-06-24T17:39:19.000Z",
    "lastUpdated": "2013-07-02T21:36:25.344Z",
    "passwordChanged": "2013-07-02T21:36:25.344Z",
    "profile": {
      "firstName": "Eric",
      "lastName": "Judy",
      "email": "eric.judy@example.com",
      "secondEmail": "eric@example.org",
      "login": "eric.judy@example.com",
      "mobilePhone": "555-415-2011"
    },
    "credentials": {
      "password": {},
      "recovery_question": {
        "question": "The stars are projectors?"
      },
      "provider": {
        "type": "OKTA",
        "name": "OKTA"
      }
    },
    "_links": {
      "self": {
        "href": "https://{yourOktaDomain}/api/v1/users/00ub0oNGTSWTBKOLGLNR"
      }
    }
  }
]


Source:  https://developer.okta.com/docs/api/resources/users#list-users

Fields we need to parse

Fortunately, the available TA already parses the data for us, but the fields that we are most interested in for this lookup dashboard are the following:
  • title
  • firstName
  • middleName
  • lastName
  • email
  • primaryPhone
  • created
  • passwordChanged
  • lastLogin
  • status
Feel free to modify the search and replace fields as needed.

Search String

A simple search string that gets us the table needed is shown below. We deduplicated the results by id since it is a unique field. Now just add filters such as the ones we provided in our dashboard code at the end of the article and you are in business! 

index=okta source=okta:user | dedup id | table credentials.provider.type, profile.title, profile.firstName, profile.middleName, profile.lastName, profile.email, profile.primaryPhone, created, passwordChanged, lastLogin, status

Conclusion

Even though we had a Splunk TA and App to perform the parsing and help create visibility, we extended the usefulness of the data to build a user lookup tool. We hope this article helps others gain additional insight into their user data via Okta logs. Happy Splunking!

Dashboard Code

The following dashboard assumes that the appropriate logs are being collected and sent to Splunk. Additionally, the dashboard code assumes an index of okta. Feel free to adjust as necessary. Splunk dashboard code provided below:


<form>
  <label>Okta User Lookup</label>
  <description>index=okta source=okta:user   (First try last 24 hours, then try a longer time range)</description>
  <fieldset autoRun="true" submitButton="true">
    <input type="time" token="time">
      <label>Time Range</label>
      <default>
        <earliest>-24h@h</earliest>
        <latest>now</latest>
      </default>
    </input>
    <input type="text" token="wild">
      <label>Wildcard Search</label>
      <default>*</default>
      <initialValue>*</initialValue>
    </input>
    <input type="text" token="first">
      <label>First Name</label>
      <default>*</default>
      <initialValue>*</initialValue>
    </input>
    <input type="text" token="last">
      <label>Last Name</label>
      <default>*</default>
      <initialValue>*</initialValue>
    </input>
    <input type="text" token="email">
      <label>Email Address</label>
      <default>*</default>
      <initialValue>*</initialValue>
    </input>
  </fieldset>
  <row>
    <panel>
      <table>
        <title>Details</title>
        <search>
          <query>index=okta source=okta:user $wild$ profile.firstName=$first$ profile.lastName=$last$ profile.email=$email$ | dedup id | table credentials.provider.type, profile.title, profile.firstName, profile.middleName, profile.lastName, profile.email, profile.primaryPhone, created, passwordChanged, lastLogin, status</query>
          <earliest>$time.earliest$</earliest>
          <latest>$time.latest$</latest>
          <sampleRatio>1</sampleRatio>
        </search>
        <option name="count">10</option>
        <option name="dataOverlayMode">none</option>
        <option name="drilldown">none</option>
        <option name="percentagesRow">false</option>
        <option name="rowNumbers">false</option>
        <option name="totalsRow">false</option>
        <option name="wrap">true</option>
      </table>
    </panel>
  </row>
</form>

No comments:

Post a Comment