Splunk Custom Endpoints Part 4: GETting the Data

In the previous part of this series, we finished setting up our POSTing of data to our custom endpoint. Now we are going to work on making a GET request.



In the previous part of this series, we finished setting up our POSTing of data to our custom endpoint. Now we are going to work on making a GET request. As usual, feel free to follow along with the blog or I've included the screencasts for you as well:

GETing

Following a similar pattern to POSTing. We will now cover getting our data – specifically permissions around a user. You can view the Handle the Get Request In Python screencast here.

The first thing we will do is add an additional panel to our dashboard that will contain our GET form. Our form will contain one field called ‘Username’. This form will send a GET request to a custom endpoint and return information surrounding permission information for a particular user.

First, go into your dashboard’s simple XML and add the following right below the first panel we created that contains our POST form:

created that contains our POST form:
    <panel>
      <title>GET Form</title>
      <html>
        <form id="userGETForm">
          <div>
            <label for="Username">Username</label>
            <input type="text" name="Username"/>
          </div>
          <div>
            <button id="getButton">Get Data!</button>
          </div>
        </form>
        <div id="getResponseBox"/>
      </html>
    </panel>  

Below you will see a dashboard with the additional GET form:

Next we need to modify our custom_endpoint.py file. We are going to create a new class called "Receive". We will tie this class to a custom endpoint of /receive and from there we will be able to query for a specific Username using the following query parameter /receive?Username=batman

Querying the user will then pull the user data from /services/admin/users/<username>.

In the custom_endpoint.py file add the following below the Send class:

class Receive(splunk.rest.BaseRestHandler):

def handle_GET(self):
      	sessionKey = self.sessionKey

        	try:
            	queried_user = self.request['query']['Username']

            	get_path = '/services/admin/users/' + queried_user + '?output_mode=json'
            
serverResponse, serverContent = splunk.rest.simpleRequest(get_path, sessionKey=sessionKey, method='GET', raiseAllErrors=True)
            	self.response.write(serverContent)
        	except Exception, e:
            	self.response.write(e)

Here's what we're doing:

  1. First thing, we pull in the sessionKey.
  2. In our try statement, we set a variable called queried_user to self.request[‘query’][<query_parameter>], which gives us access to any query parameters that are passed and in our case will be Username=<user>.
  3. Next, we define the path for accessing the user’s information with the get_path variable.
  4. Important to note is that we will append ?output_mode=json to the end to ensure our data is returned in a JSON format. The default format returned is XML.
  5. We then set serverResponse and serverContent to the splunk.rest.simpleRequest() method.
  6. We return the serverContent so that we can handle the response and eventually display it in our dashboard.
  7. If anything goes wrong, errors will be thrown in our except statement.

Next, we need to modify our restmap.conf and web.conf files in order to tie our custom endpoint Receive class to /receive and to allow for the GET requests. You can view the related screencast here.

restmap.conf Additions

[script:custom_endpoint_receive]
match=/receive
handler=custom_endpoint.Receive

web.conf Additions

Open that up and below the custom_endpoint_post stanza we added earlier, add the following:

[expose:custom_endpoint_receive]
pattern=receive
methods=GET

Once you make changes to your restmap.conf and web.conf files, restart Splunk.

Sending GET Requests From Our Dashboard

Let’s hook up our GET request from the dashboard so when we request information about a specific user we will be provided with the roles that are tied to that specific user.

First, we will listen for our click event on our #getButton. This is very similar to the process we have in place for sending POST requests.

$(document.body).on('click', '#getButton', function(e) {

    e.preventDefault();

    var service = mvc.createService();
    var get_data = $('#userGETForm').serializeArray();
    var cleaned_data = {};

    cleanData = function(data) {
        _.each(data, function(field) {
            var key = field['name'];
            var value = field['value'];

            cleaned_data[key] = value;
        });
    }

    cleanData(get_data);

    service.get('/services/receive', cleaned_data, function(err, response) {

        if(err) {
            console.log('error: ', err);
        }
        else if(response.status === 200) {
            console.log('Response: ', response.data);
            var response_data = JSON.parse(response.data);
            $('#getResponseBox').empty();
            $('#getResponseBox').append('Roles: ' + response_data.entry[0].content.roles

            $('#userGETForm')[0].reset();
        }

    });

});

Here is what we are doing:

  1. For the most part we following the same process for our POST request. The difference here is we are using service.get() instead of service.post().
  2. We have a cleanData function that we are using to make sure the GET request is formatted correctly e.g. { “Username” : “batman” }.
  3. The cleanData function takes the serialized form data, cleans it up and returns back a new object that we can then pass to our service.get() function.
  4. If everything is successful (i.e. status === 200) then we take the data we get back (response_data) and narrow it down to only give us the role information (response_data.entry[0].content.roles).
  5. The $(‘#getResponseBox’).empty() is to empty out the div so that it doesn’t append new data to told data on any follow-up requests.
  6. $('#userGETForm')[0].reset(); will clear all the form fields once it successfully returns the data.

If you’re curious to see what else is returned you could console.log(response_data) and it would give you all the information surrounding the specific user. This will give you an idea of all the information you could potentially pull in for a user.

At this point you should be able to post a comma-delimited list of roles to a user which will update the roles that are tied to a specific user. You should then be able to GET a user’s role information from your GET form.

Final Words

You’re done - congratulations!

As discussed in the first part of this series, there are some real-world reasons to use a custom endpoint that may include pulling data from Splunk into a third party service. You may also need to develop a custom endpoint to do some additional modifications to data that Splunk may not do out of the box.

If you followed along through this whole series, hopefully it helped in making sense of how to set up custom endpoints in Splunk.

Happy Splunking!




Close off Canvas Menu