Developing for Splunk Enterprise

Why is access to Splunk API via Python generating an "Unauthorized" error?

Robbie1194
Communicator

Using some of the python code provided by Splunk:

Step 3: Get the search status

httplib2.Http(disable_ssl_certificate_validation=True).add_credentials(username, password)
servicessearchstatusstr = '/services/search/jobs/%s/' % sid
isnotdone = True
while isnotdone:
    searchstatus = httplib2.Http(disable_ssl_certificate_validation=True).request(baseurl + servicessearchstatusstr, 'GET')[1]
    print searchstatus
    isdonestatus = re.compile('isDone">(0|1)')
    isdonestatus = isdonestatus.search(searchstatus).groups()[0]
    if (isdonestatus == '1'):
        isnotdone = False
print "====>search status:  %s  <====" % isdonestatus

Error message produced:

====>search result:  [{"messages":[{"type":"ERROR","text":"Unauthorized"}]}]  <====

I have read many questions about people having the same issue and have tried all of the solutions but the error still persists. I've tried changing the password to something that's only alphanumeric (no special characters) so nothing needs to be escaped. I've changed the password from default, I've made a new account with admin access for api calls and I've even tried printing out the password and username in the script at multiple points so that I can see that it doesn't change values etc.

Any POST requests I make (running the search for example) will work fine, it's as soon as it comes to retrieving the information (GET requests) that there is a problem! Can anyone please provide any additional solutions that may help with this issue?

0 Karma

micahkemp
Champion

On lines 32 and 41 you're issuing GET requests but did not include the authorization header like you did on line 23.

0 Karma

Robbie1194
Communicator

Yeah i see what you mean!

I'm new to Python so it might take me a while to work out how but I'll attempt to add the authorisation headers in the same way the POST commands did.

0 Karma

Robbie1194
Communicator

Although I did think the script looked okay at first because I was of the understanding that you don't typically use headers in get requests.

0 Karma

Robbie1194
Communicator
    import urllib
    import httplib2
    import time
    import re
    from time import localtime,strftime
    from xml.dom import minidom
    import json

    baseurl = 'splunkserver:8089'
    username = 'user'
    password = 'password'

   # Step 1: Get a session key
    servercontent = httplib2.Http(disable_ssl_certificate_validation=True).request(baseurl + '/services/auth/login', 'POST',
    headers={}, body=urllib.urlencode({'username':username, 'password':password}))[1]
    sessionkey = minidom.parseString(servercontent).getElementsByTagName('sessionKey')[0].childNodes[0].nodeValue
    print "====>sessionkey:  %s  <====" % sessionkey

   # Step 2: Create a search job
    searchquery = 'search index=notable | top limit=5 _time unique_id'

    searchjob = httplib2.Http(disable_ssl_certificate_validation=True).request(baseurl + '/services/search/jobs','POST',
    headers={'Authorization': 'Splunk %s' % sessionkey},body=urllib.urlencode({'search': searchquery}))[1]
    sid = minidom.parseString(searchjob).getElementsByTagName('sid')[0].childNodes[0].nodeValue
    print "====>sid:  %s  <====" % sid

    #Step 3: Get the search status
    httplib2.Http(disable_ssl_certificate_validation=True).add_credentials(username, password)
    servicessearchstatusstr = '/services/search/jobs/%s/' % sid
    isnotdone = True
    while isnotdone:
        searchstatus = httplib2.Http(disable_ssl_certificate_validation=True).request(baseurl + servicessearchstatusstr, 'GET')[1]
        isdonestatus = re.compile('isDone">(0|1)')
        isdonestatus = isdonestatus.search(searchstatus).groups()[0]
        if (isdonestatus == '1'):
            isnotdone = False
    print "====>search status:  %s  <====" % isdonestatus

   # Step 4: Get the search results
    services_search_results_str = '/services/search/jobs/%s/results?output_mode=json&count=0' % sid
    searchresults = httplib2.Http(disable_ssl_certificate_validation=True).request(baseurl + services_search_results_str, 'GET')[1]
    print "====>search result:  [%s]  <====" % searchresults
0 Karma

micahkemp
Champion

Can you format the code using the code button (the 101010 icon) so that it's easier to read?

0 Karma

Robbie1194
Communicator

Okay, done 🙂

0 Karma

micahkemp
Champion

Can you paste your full script? It seems you didn't include the section that prints the search result.

I wonder if your call to get the search results is lacking the authentication component, either using the same httplib2 object that you added credentials to, or by passing the session ID from a previous request.

0 Karma

Robbie1194
Communicator

I've posted the full script in the answers.

0 Karma
Take the 2021 Splunk Career Survey

Help us learn about how Splunk has
impacted your career by taking the 2021 Splunk Career Survey.

Earn $50 in Amazon cash!