Scripted authentication
This documentation does not apply to the most recent version of Splunk. Click here for the latest version.
Scripted authentication
Splunk ships with support for three authentication systems: Splunk's built-in system, LDAP and a new scripted authentication API. With the new scripted authentication system, you can set up Splunk to interface with an authentication system you already have in place.
Known issues with scripted auth
- Scripted authentication does not currently work with distributed search.
- Everybody gets User-level privileges. Map to correct Splunk role via the admin section of Splunk Web.
Configuration
Specify the following settings in authentication.conf to enable your specific script:
authType = Scripted authSettings = script [script] scriptPath = $SPLUNK_HOME/bin/python $SPLUNK_HOME/share/splunk/authScriptSamples/<scriptname> scriptSearchFilters = 1
Optionally add a [cacheTiming] stanza if needed for your script. Use these settings to adjust the frequency at which Splunk calls your application. Each call has its own timeout specified in seconds. Caching does not occur if not specified.
[cacheTiming] userLoginTTL = 1 searchFilterTTL = 1 getUserInfoTTL = 1 getUserTypeTTL = 1 getUsersTTL = 1
Script commands
Scripted authentication includes the following commands to use in your script. Here is a descriptive list of these commands, including their inputs and outputs.
-
userlogin: login with username/password pair- in:
--username=<username> --password=<password>(passed over stdin) - out: --status=<status_bit> --search_filter=<search_filter>(optional) --authToken=<tok> (optional)success (or fail)
- in:
-
getUserType: this command corresponds to the role within Splunk (for example Admin, Power or User)- in:
--username=<username> --authToken=<tok> (optional) - out:
--status=<status_bit> --role=<role> (eg Admin)
- in:
-
getUserInfo: get user information- in:
--username=<username> --authToken=<tok> (optional) - out:
--status=<status_bit> --userInfo=<userId>;<username>;<realname>;<role>
- in:
Supplemental calls:
-
getUsers- in:
--authToken=<tok> (optional) - out:
--status=<status_bit> --userInfo=<userId>;<username>;<realname>;<role> --userInfo1=<userId>;<username>;<realname>;<role>....
- in:
Advanced calls:
-
checkSession- in:
--authToken=<tok> (optional) - out:
--status=<status_bit>
- in:
-
getSearchFilter = <role>- This command corresponds to the role within Splunk (for example Admin, Power or User).
- in:
--username=<username> --authToken=<tok> (optional) - out:
--status=<status_bit> --search_filter=<filter> (you can have one or more --search_filter)
Every out starts with a <status_bit> which is one of the following:
-
success- The command succeeded correctly.
-
tmp_fail- Temporary failure of auth plugin. Attempt to just go on.
-
auth_fail- Failure to authenticate. Terminate the user's session.
Cache timing:
Use these settings to adjust the frequency at which Splunk calls your application. Each call has its own timeout specified in seconds. Caching does not occur if not specified.
-
[cacheTiming]- Start any caching stanza with this name.
-
getUserInfoTTL = <integer>- Timeout for getUserInfo in seconds.
-
getUserTypeTTL = <integer>- Timeout for getUsertype in seconds.
-
getUsersTTL = <integer>- Timeout for getUsers in seconds.
Example
This example uses PAM authentication.
Add the following stanzas to $SPLUNK_HOME/etc/bundles/local/authentication.conf:
[authentication] authType = Scripted authSettings = script [script] scriptPath = $SPLUNK_HOME/bin/python $SPLUNK_HOME/share/splunk/authScriptSamples/pamScripted.py scriptSearchFilters = 1 [cacheTiming] userLoginTTL = 1 searchFilterTTL = 1 getUserInfoTTL = 1 getUserTypeTTL = 1 getUsersTTL = 1
The following is an example script for PAM authentication, located in $SPLUNK_HOME/share/splunk/authScriptSamples/pamScripted.py:
'''
This is a sample script to get you started on scripted Auth.
The splunk system will call this script to obtain several pieces of
information. Responses are parse as anything printed to stdout after
--status=success is seen on stdout. You must return --status==success
for any call that has not errored. If this is not seen the script assumes
an error occured.
Function breakdown
Required:
userLogin : will be called on userLogin into splunk.
getUserInfo : Get information about a particular user. ( userId, username, realname, userType )
getUserType : Get a users Type/Role in splunk. Defaults in the product are Admin, Power & User.
You may return any role here but it must be already defined in splunk. Unknown roles
will result in errors.
Optional Calls :
getSearchFilter : return a search filter for a given user. Called when the user searches.
getUsers : Get a list of all users available. Allows admin fluff to be populated in UI.
N.B.
This script is not fully feature complete. It places all users at the Admin level.
If you wish to place users at different Role level you will have to modify the script
to return the right role on depending on the user.
'''
# commonAuthBase contains constants and a basic mapping framework for users.
# plus any common imports to all scripts.
from commonAuth import *
from userMapping import *
import os
isMac = 0
'''
This function will be called when a user enters their credentials in the login page in UI.
Input:
--username=<user> --password=<pass>
Output:
On Success:
--status=success
On Failuire:
Anyhing but --status=success
Splunk will print everything outputted to stdin if there is an error so you can add debugging info
that will be printed in splunkd.log when the system is in DEBUG mode.
'''
def userLogin( infoIn ):
command = ""
if isMac:
command = "dirt -u " + str(infoIn['username']) + " -p " + str(infoIn['password']) + ''' |grep "Call to checkpw(): Success"'''
else:
command = "/home/boo/splunk/scriptedAuth/pamauth " + str(infoIn['username'])
# our check with pam is done with a setuid program called pamauth
proc = subprocess.Popen( command,
shell=True,
stdin=subprocess.PIPE
)
proc.communicate( infoIn['password'] )
retCode = proc.wait()
retDict = {}
if retCode == 0:
print SUCCESS
else:
print FAILED
'''
This function is to return the user\'s Type/Role in the system.
The role returned must be already defined in splunk. Returning a non-existant role will result in an error.
Input :
--username=<user>
Output:
--status=success --role=<roleName> --role=<roleName> ...
'''
def getUserType( infoIn ):
# put everybody in the three default roles.
# --status=success --role=Admin --role=Power --role=User
roleList = getUsersRole( infoIn['username'] )
outStr = SUCCESS
for roleItem in roleList:
outStr = outStr + " --" + USERTYPE + "=" + roleItem
print outStr
'''
This function prints out the details of the userId supplied.
Input :
--username=<user>
Output:
--status=success --userInfo=<userId>;<username>;<realname>;<role>:<role>:<role> Note roles delimited by :
'''
def getUserInfo( infoIn ):
roleList = getUsersRole( infoIn['username'] )
outStr = SUCCESS + " --userInfo=" + infoIn["username"] + ";" + infoIn["username"] + ";" + infoIn["username"] + ";"
for roleItem in roleList:
outStr = outStr + roleItem + ":"
print outStr
'''
This function gets all the users in the system that scripted auth will work for. This call is optional.
Input :
N/A
Output :
--status=success --userInfo=<userId>:<username>:<realname>:<role>;<role>;<role> --userInfo=<userId>:<username>:<realname>;<role>:<role>:<role> ...
'''
def getUsers( infoIn ):
# just going to use /etc/passwd here but you may use any method you wish.
FILE = open("/etc/passwd" ,"r")
fileLines = FILE.readlines()
outStr = SUCCESS
if isMac:
for line in fileLines:
userBits = line.split( ":" )
if len( userBits ) < 4:
continue
realname = userBits[4]
if realname == "" :
realname = userBits[0]
username = userBits[0]
if not username.startswith( '_' ):
outStr = outStr + " --userInfo=" + str(userBits[2]) + ';' + str(userBits[0]) + ";" + str(realname) + ";"
roleList = getUsersRole( userBits[0] )
for roleItem in roleList:
outStr = outStr + roleItem + ":"
else:
for line in fileLines:
userBits = line.split( ":" )
if userBits[6].find( '/bin/bash' ) != -1:
realname = userBits[4]
if realname == "" :
realname = userBits[0]
# userId username realName
outStr = outStr + " --userInfo=" + str(userBits[2]) + ';' + str(userBits[0]) + ";" + str(realname) + ";"
roleList = getUsersRole( userBits[0] )
for roleItem in roleList:
outStr = outStr + roleItem + ":"
print outStr
'''
Gets the search filter for a given user.
You must have the flag scriptSearchFilters set to 1 on the config for this function to be used.
Input :
--username=<username>
Output:
--search_filter=<filter>
'''
def getSearchFilter( infoIn ):
filters = getUsersFilters( infoIn['username'])
outStr = SUCCESS
for i in filters:
outStr = outStr + " --search_filter=" + str(i)
print outStr
if __name__ == "__main__":
callName = sys.argv[1]
dictIn = readInputs()
returnDict = {}
if callName == "userLogin":
userLogin( dictIn )
elif callName == "checkSession":
checkSession( dictIn )
elif callName == "getUsers":
getUsers( dictIn )
elif callName == "getUserType":
getUserType( dictIn )
elif callName == "getUserInfo":
getUserInfo( dictIn )
elif callName == "getSearchFilter":
getSearchFilter( dictIn )
else:
returnDict.append("ERROR call name no known" )
returnDict.append( callName )
This documentation applies to the following versions of Splunk: 3.2.3 , 3.2.4 , 3.2.5 , 3.2.6 View the Article History for its revisions.