SecureAuth Splunk Dashboard Sample Queries
Use this guide to create queries in the Splunk Dashboard, which generate a visual representation of SecureAuth® Identity Platform logon activity, threat activity, realm utilization, and overall system health.
If using Splunk Enterprise or Splunk Cloud, then download the SecureAuth Splunk Dashboard App, which provides unprecedented user access visibility into enterprise resources such as VPN and ADC, cloud application access as well as on-premises applications out-of-the-box.
Prerequisites
Have SecureAuth IdP 8.1.1+
NOTE: SecureAuth IdP 8.2+ supports the use of the application, while version 8.1.1 supports only the manually-entered sample queries
Have Splunk (on-premises or cloud version)
NOTE: SecureAuth IdP queries were tested against Splunk version 6.2.3
Configure the Logs Tab to enable Syslog
Logs tab configuration
In the Identity Platform Classic Experience, go to the Logs tab.
In the Log Options section, set the log configurations.
Log Instance ID
Set an identifiable name. This is displayed on Splunk.
Audit Logs
Select the Syslog check box.
In the Syslog section, set the following configurations.
Syslog Server
Set to the Syslog IP address.
Syslog Port
Set to the port in use.
For example, 514.
Syslog RFC Spec
Set to RFC5424.
Prviate Enterprise Number (PEN)
Set to the PEN of the Syslog server.
The number for Splunk is 27389.
Save your changes.
Sample Queries
Manual Field Extractions were not used for these examples
Exclude debug logs if they are logged to Syslog (NOT Category>DEBUG)
Images are sample / recommended visual outputs, but can be designed as preferred
Base Queries
- successful_api_logins
EventID=60503 ApiResponseStatus=Authenticated
- successful_user_logins
((EventID=20990 TrxResult=*Success*) OR EventID=91220) NOT DestinationSiteUrl="Authorized/WSFedProvider.aspx"
- successful_ws_logins
("Password is validated" Version="8.*" [search EventID="40601" WSTrustUserNameSecurityTokenHandler Version="8.*" | fields RequestID])) OR (DestinationSiteUrl="Authorized/WSFedProvider.aspx" EventID=20990)
- successful_logins
secureauth_successful_api_logins OR secureauth_successful_user_logins OR secureauth_successful_ws_logins
- failed_api_logins
(EventID=60202 OR EventID=60502 OR EventID=60602 OR (EventID=60102 NOT ApiResponseStatus="found"))
- failed_user_logins
(EventID=20990 (TrxResult!=*Success* OR Succeed=False) NOT DestinationSiteUrl="Authorized/WSFedProvider.aspx")
- failed_logins
secureauth_failed_user_logins OR secureauth_failed_api_logins
Login Activity
- logins_by_external_location
secureauth_successful_user_logins | stats count by UserHostAddress | iplocation UserHostAddress | eval Country=if(Country=="", "N/A", Country) | eval Region=if(Region=="", Country, Region) | eval City=if(City=="",Country, City)
- frequent_user_logins
secureauth_successful_user_logins | eval lower_user_id = lower(UserID) | stats count by lower_user_id | sort -count | eventstats sum(count) as total | eval percent=round(count*100/total,2) | fields - total | rename count as Logins, lower_user_id as "User ID", percent as Percent
- admin_console_logins
EventID=19501 | stats count by UserID | sort -count | eventstats sum(count) as total | eval percent=round(count*100/total,2) | fields - total | rename count as Logins, UserID as "User ID", percent as Percent
- logins_by_operating_system
secureauth_successful_user_logins | lookup user_agents http_user_agent as UserAgent | stats count by ua_os_family | sort -count | eventstats sum(count) as total | eval percent=round(count*100/total,2) | fields - total | rename count as Logins, ua_os_family as "Operating System", percent as Percent
- logins_by_browser
secureauth_successful_user_logins | lookup user_agents http_user_agent as UserAgent | stats count by ua_family | sort -count | eventstats sum(count) as total | eval percent=round(count*100/total,2) | fields - total | rename count as Logins, ua_family as Browser, percent as Percent
- logins_by_realm
secureauth_successful_user_logins | stats count by Realm | sort -count | eventstats sum(count) as total | eval percent=round(count*100/total,2) | fields - total | rename count as Logins, percent as Percent
- logins_by_ip_address
secureauth_successful_user_logins | stats count by UserHostAddress | sort -count | eventstats sum(count) as total | eval percent=round(count*100/total,2) | fields - total | rename count as Logins, UserHostAddress as "Source IP", percent as Percent
- orphaned_second_factor_logins
EventID=20100 BrowserSession=* BROWSER_REGISTRATION_METHOD | stats count by BrowserSession UserID UserHostAddress Realm | search count=1 | fields - count BrowserSession | stats count by UserID, UserHostAddress, Realm | sort -count | rename UserID as "User ID", count as "Logins", UserHostAddress as "Source IP"
Login Failures
- failed_counts
EventID=20990 (TrxResult="SecurityViolation_ExceededMaxOTPAttempts" OR TrxResult="Incorrect_FingerPrint_Check_Password" OR TrxResult="Incorrect_Kiosk_Check_Password" OR TrxResult="Incorrect_Standard_Check_Password" OR TrxResult="Incorrect_User" OR TrxResult="Incorrect_UserPassword" OR TrxResult="SECURITYVIOLATION_*") | rex field=TrxResult "(?[^_]+)$" | stats count(UserID) as total, dc(eval(if(reason=="Password" OR reason=="UserPassword",UserID,NULL))) as Password, dc(eval(if(reason=="User",UserID,NULL))) as User, dc(eval(if(reason=="ExceededMaxOTPAttempts" OR reason=="ExceededMaxPasswordAttempts",UserID,NULL))) as ExceededMaxAttempts
- failed_logins_by_external_location
secureauth_failed_user_logins | stats count by UserHostAddress | iplocation UserHostAddress | eval Country=if(Country=="", "N/A", Country) | eval Region=if(Region=="", Country, Region) | eval City=if(City=="",Country, City)
- login_attempts_from_blocked_countries
(EventID=92310 OR EventID=92320) (whitelisted_ip=false OR blacklisted_ip=true) | fillnull value=NULL UserID | rename whitelisted_country as country blacklisted_country as country | stats count by UserHostAddress, UserID | iplocation UserHostAddress | eval Country=if(Country=="", "N/A", Country) | eval Region=if(Region=="", Country, Region) | eval City=if(City=="",Country, City)
- failed_login_reasons_over_time
secureauth_failed_user_logins | lookup trx_lookup TrxResult | eval reason=coalesce(Definition, TrxResult) | timechart count by reason
- denied_login_requests_by_user
secureauth_failed_user_logins TrxResult=Denied_Browser_RegistrionMethod_AcceptDeny_LoginRequest | stats count by UserID, Realm | sort -count
- failed_passwords
EventID=20990 (TrxResult="SecurityViolation_ExceededMaxOTPAttempts" OR TrxResult="Incorrect_FingerPrint_Check_Password" OR TrxResult="Incorrect_Kiosk_Check_Password" OR TrxResult="Incorrect_Standard_Check_Password" OR TrxResult="Incorrect_User" OR TrxResult="Incorrect_UserPassword" OR TrxResult="SECURITYVIOLATION_*") | rex field=TrxResult "(?[^_]+)$" | stats count(eval(reason=="Password")) as Password count(eval(reason=="User")) as User count(eval(if(reason=="ExceededMaxOTPAttempts" OR reason=="ExceededMaxPasswordAttempts",UserID,NULL))) as ExceededMaxAttempts by UserID
- invalid_user_ids
EventID=20990 (TrxResult="SecurityViolation_ExceededMaxOTPAttempts" OR TrxResult="Incorrect_FingerPrint_Check_Password" OR TrxResult="Incorrect_Kiosk_Check_Password" OR TrxResult="Incorrect_Standard_Check_Password" OR TrxResult="Incorrect_User" OR TrxResult="Incorrect_UserPassword" OR TrxResult="SECURITYVIOLATION_*") | rex field=TrxResult "(?[^_]+)$" | stats count(eval(reason=="Password")) as Password count(eval(reason=="User")) as User count(eval(if(reason=="ExceededMaxOTPAttempts" OR reason=="ExceededMaxPasswordAttempts",UserID,NULL))) as ExceededMaxAttempts by UserID
- exceeded_max_login_attempts
EventID=20990 (TrxResult="SecurityViolation_ExceededMaxOTPAttempts" OR TrxResult="Incorrect_FingerPrint_Check_Password" OR TrxResult="Incorrect_Kiosk_Check_Password" OR TrxResult="Incorrect_Standard_Check_Password" OR TrxResult="Incorrect_User" OR TrxResult="Incorrect_UserPassword" OR TrxResult="SECURITYVIOLATION_*") | rex field=TrxResult "(?[^_]+)$" | stats count(eval(reason=="Password")) as Password count(eval(reason=="User")) as User count(eval(if(reason=="ExceededMaxOTPAttempts" OR reason=="ExceededMaxPasswordAttempts",UserID,NULL))) as ExceededMaxAttempts by UserID
- top_browsers
secureauth_failed_user_logins | stats count by UserAgent | lookup user_agents http_user_agent as UserAgent | fields + ua_family count | stats sum(count) as count by ua_family | sort -count | eventstats sum(count) as total | eval percent = round(count*100/total,2) | table ua_family count percent | rename count as Failures UserID as "User ID" percent as Percent ua_family as Browser
- geovelocity_violations
EventID=92300 UserHostAddress=* "geo-velocity" UserHostAddress!="10.0.0.0/8" UserHostAddress!="172.16.0.0/12" UserHostAddress!="192.168.0.0/16" UserHostAddress!="169.254.0.0/16" | streamstats current=f last(UserHostAddress) as new_addr last(_time) as time_of_change by UserID | where UserHostAddress!=new_addr | rename UserHostAddress as prev_addr | search "result: false" | iplocation prefix=prev_ prev_addr | iplocation prefix=new_ new_addr | table time_of_change, UserID, prev_addr, prev_Country, new_addr, new_Country | sort - time_of_change | convert ctime(time_of_change) as Time | table Time UserID prev_addr prev_Country new_addr new_Country | rename prev_addr as "Previous IP" prev_Country as "Previous Country" new_addr as "New IP" new_Country as "New Country" UserID as "User ID"
- threats
"Check IP Risk 'ge" AE_IP_threatType=* AE_IP_threatType!=0 AE_IP_RiskScore!=0 | stats count by UserHostAddress, UserID, Realm, AE_IP_threatType, AE_IP_threatCategory | lookup threatType_lookup threatScore AS AE_IP_threatType OUTPUT threatType | lookup threatCategory_lookup AE_IP_threatCategory OUTPUT threatCategory | sort -count | table UserHostAddress, UserID, Realm, threatType, threatCategory, count | rename UserHostAddress as "Source IP", UserID as "User ID", threatType as "Source", threatCategory as "Category", count as Failures
Realm Utilization
- total_logins
EventID=20990 TrxResult=*Success* | stats count sparkline(count) as utilization by Realm | eventstats sum(count) as total | eval Percent=round(count*100/total,2) | fields - total | sort -count | table Realm utilization count Percent | rename Realm as "Realm Name" utilization as "Utilization Over Time" count as "Total Logins"
- second_factor_utilization
EventID=20990 | eval auth_type=case(AuthRegMethod=="NONE" AND AllowedTokens=="BROWSERFINGERPRINT" AND (AuthGuiMode=="0" OR AuthGuiMode=="2" OR AuthGuiMode=="3" OR AuthGuiMode=="4" OR AuthGuiMode=="5" OR AuthGuiMode=="6" OR AuthGuiMode=="9"), "DFP", AuthRegMethod!="NONE", AuthRegMethod) | chart count by auth_type | sort -count | rename count as Count auth_type as Authentication
- digital_fingerprint_utilization
EventID=20990 (AuthRegMethod="NONE" AND AllowedTokens="BROWSERFINGERPRINT" AND (AuthGuiMode="0" OR AuthGuiMode="2" OR AuthGuiMode="3" OR AuthGuiMode="4" OR AuthGuiMode="5" OR AuthGuiMode="6" OR AuthGuiMode="9")) | stats count by Realm | sort -count | rename count as Count
- top_realms_with_long_page_response_times
EventID=90040 | timechart avg(duration) as Seconds by Realm
- data_store_response_time
((EventID=52010 "Retrieved user profile data") OR (EventID=52020 "Found the user for retrieving user's profile")) | stats min(_time) as min_time max(_time) as max_time by RequestID Realm | eval duration=(max_time-min_time )| rename min_time to _time | timechart max(duration) as Seconds by Realm
- page_response_time_in_seconds
EventID=90040 Realm=* | stats min(duration) as Minimum, avg(duration) as Average, max(duration) as Maximum by Realm | sort -Average
Appliance Utilization
- total_logins
EventID=90010 | stats count by host | sort -count | eventstats sum(count) as total | eval percent=round(count*100/total,2) | fields - total | rename host as Appliance count as Logins percent as Percent
- average_page_load_time
EventID=90040 | timechart avg(duration) by host
- page_load_time
EventID=90040 | stats min(duration) as Minimum, avg(duration) as Average, max(duration) as Maximum by host
- appliance_errors_over_time
Category=ERROR NOT EventID=51102 NOT EventID=51003 NOT EventID=52001 | fillnull value=NULL Realm | search $realm$ | timechart useother=f count by host
API Activity
- api_requests
(EventID=60203 OR EventID=60301 OR EventID=60201) ApiResponseStatus=Valid | stats count | lookup int2word int as count | fields word
- api_requests_by_realm
EventID=60203 ApiResponseStatus=Valid | stats count sparkline(count) as utilization by Realm | eventstats sum(count) as total | eval Percent=round(count*100/total,2) | fields - total | sort -count | table Realm utilization count Percent | rename Realm as "Realm Name" utilization as "Utilization Over Time" count as "Total Logins"
- failed_login_reasons_over_time
EventID=60203 ApiResponseStatus=Invalid ApiResponseMessage=* | rex field=ApiResponseMessage "^(?P.+?)( '|.$)" | timechart count by reason
- request_types
(EventID=60201 OR EventID=60301) | chart count by AuthRequestType | sort -count | eval AuthRequestType=upper(AuthRequestType) | rename AuthRequestType as Request
- adaptive_engine_api_responses
EventID=60503 ApiResponseStatus=* | timechart count by ApiResponseStatus
- device_recognition_responses
((EventID=60402 Message=*) OR (EventID=60603 ApiResponseStatus=*)) | eval tmp=case(EventID=60402 AND Message="ok", "Mobile DFP Pass",EventID=60402 AND Message!="ok", "Mobile DFP Failed",EventID=60603,ApiResponseStatus) | stats count by tmp | eval tmp=replace(upper(tmp),"_"," ") | rename tmp as "Device Recognition Responses" count as Count | sort -Count
- threats
EventID=60302 | stats count by UserHostAddress, UserID, Realm, AE_IP_threatType, AE_IP_threatCategory | lookup threatType_lookup threatScore AS AE_IP_threatType OUTPUT threatType | lookup threatCategory_lookup AE_IP_threatCategory OUTPUT threatCategory | sort -count | table UserHostAddress, UserID, Realm, threatType, threatCategory, count | rename UserHostAddress as "Source IP", UserID as "User ID", threatType as "Source", threatCategory as "Category", count as Failures