REST API Example Application: iPad App

Developers: Zach Archer

What does our application do?

Our project was a simple iOS app that checked a log file for suspicious activity, as defined by various search criteria. By saving a search query, you can set it to run on a schedule, and email the results if they meet certain conditions—*bam*, you have created an alert.

What REST endpoints are we calling?

We use four endpoints:

  1. We need to login, obviously.
  2. Kick of a search
  3. Check if a search is done
  4. Get the search results

Login

static const NSString * LOGIN_ACTION = @"services/auth/login";
...
-(void) CZ_authenticateNow {	
	[self CZ_destroyRequest];
	
	NSLog(@"Starting authenticateNow");
	reqPhase = kPhaseAuthentication;
	NSDictionary * authVars = [NSDictionary dictionaryWithObjectsAndKeys:
							   [Settings login], @"username",
							   [Settings password], @"password",
							   nil];
	request = [self CZ_newRequest:[APIRequest urlFromAction:(NSString*)LOGIN_ACTION] formVars:authVars];
	[request retain];
	[request setValidatesSecureCertificate:FALSE];
	[request startAsynchronous];
}

Search

static const NSString * SEARCH_ACTION = @"services/search/jobs";
...
-(id) initWithSearch:(NSString*)inQuery {
	self = [super init];
	if( self ) {
		action = (NSString*)SEARCH_ACTION;
		NSString * fullQuery = [NSString stringWithFormat:@"search %@", inQuery];
		formVars = [[NSDictionary dictionaryWithObjectsAndKeys: fullQuery, @"search", nil] retain];
		reqType = kRequestSearch;
	}
	return self;
}

Check Search isDone

static const NSString * SEARCH_MONITOR_ACTION = @"services/search/jobs";
...
-(void) CZ_startSearchMonitorAction:(NSTimer*)theTimer {
	[self CZ_destroyRequest];
	
	NSLog(@"Checking if the search has completed...");
	reqPhase = kPhaseSearchMonitor;
	NSString * monitorAction = [NSString stringWithFormat:@"%@/%@", (NSString*)SEARCH_MONITOR_ACTION, searchId];
	request = [self CZ_newRequest:[APIRequest urlFromAction:monitorAction] formVars:nil];
	[request retain];
	[request startAsynchronous];
}

Get Search Results

static const NSString * SEARCH_RESULTS_ACTION = @"services/search/jobs/^/results";
...
-(void) CZ_startSearchResultsAction {
	[self CZ_destroyRequest];
	
	NSLog(@"Checking search results...");
	reqPhase = kPhaseSearchResults;
	NSString * searchAction = [((NSString*)SEARCH_RESULTS_ACTION) stringByReplacingOccurrencesOfString:@"^" withString:searchId];
	request = [self CZ_newRequest:[APIRequest urlFromAction:searchAction] formVars:nil];
	[request retain];
	[request startAsynchronous];
}

Any problems encountered

The most important thing to remember about the Splunk REST API is that you must change the login/password before you can authenticate. The defaults are "admin"/"changeme". I'm glad that Splunk forced us to change the login credentials to something less hackable, yet this blocked our progress a couple times during development, so be mindful of it!

Splunk is deep, very deep. I learned a tiny fraction of Splunk's search language, but it was sufficient to cast powerful magic—applying filters to several columns, while averaging CPU activity over a range of time, for example.

I would gladly use Splunk again. I have a new project on the way, involving monitoring Apache access logs, and I expect that Splunk will be an indispensable asset.