From Splunk Wiki
login.html
<%!
import time, json
import splunk.appserver.mrsparkle.lib.i18n as i18n
# TRANS: This is the title for the account login page
title = _('Login')
%>
<%inherit file="//layout/base.html" />
<%namespace name="lib" file="//lib.html" import="*" />
<%
year = time.strftime('%Y')
# Added by for SSO
# These headers will be set by the Access Manager agent
splunkuid = cherrypy.request.headers['SPLUNK-ID'].lower()
splunkroles = cherrypy.request.headers['SPLUNK-ROLES']
splunkname = cherrypy.request.headers['SPLUNK-NAME']
# Check that the form is valid with the headers
if cherrypy.request.params:
splunkroles_name = splunkroles + "|" + splunkname
# Just set these to the right values from the header
# Fixes bug with getlinks and more secure
cherrypy.request.params['username'] = splunkuid
cherrypy.request.params['password'] = splunkroles_name
#
# build all of the nagware parameters
#
# determine if UI has an error message displayed
hasErrorMessage = False
if invalid_password or logged_out or session_expired:
hasErrorMessage = True
# assemble dict to serialize into JSON for update checker
checkerConfig = {
'locale': i18n.current_lang_url_component(),
'licenseType': 'free' if serverInfo['is_free_license'] else 'pro',
'versionNumber': serverInfo['version_label'],
'installType': 'trial' if serverInfo['is_trial_license'] else 'prod',
'skin': 'basic',
'updateCheckerBaseURL': updateCheckerBaseURL,
'tipsCheckerCannotConnectBannerPath': make_url('/static/img/nagware/updater_free_cannot_connect.gif'),
'updateCheckerCannotConnectBannerPath': make_url('/static/img/nagware/updater_pro_paid_login_cannot_connect.gif'),
'hasErrorMessage': hasErrorMessage
}
# add harness for testing
debugPrefix = 'test.'
for k in checkerConfig:
if (debugPrefix + k) in cherrypy.request.params:
checkerConfig[k] = cherrypy.request.params[debugPrefix + k]
# determine CSS class on container
layoutClass = []
if checkerConfig['licenseType'] == 'free':
layoutClass.append('licenseIsFree')
if checkerConfig['installType'] == 'trial':
layoutClass.append('licenseIsTrial')
# output messaging
user_message = None
enable_login_form = True
# TRANS: Sign in button on the account login page
login_button_text = _('Sign in')
if serverInfo['license_state'] == 'PREVIOUS_KEYED_LICENSE':
# the enums for license state are from SPL-24850
user_message = _('Splunk has detected that you are using a license for an older version of Splunk. <a href="http://www.splunk.com/r/my_licenses" target="_blank">Get an updated license</a>.')
enable_login_form = False
# TRANS: Sign in button on the account login page when license is from previous version
login_button_text = _('N/A')
# handle expired licenses for all non admin users SPL-26253
elif serverInfo['license_state'] == 'EXPIRED':
user_message = _("%(openSpan1)s Your license is expired. %(closeSpan)s %(openSpan2)s Please login as an administrator to update the license. %(closeSpan)s") % { 'openSpan1': '<span class="licenseError">', 'closeSpan': "</span>", 'openSpan2':'<span class="licenseErrorText">'}
elif invalid_password:
user_message = _('You are not a member of any splunk roles. You must request access.')
elif bad_cookies:
user_message = _('Failed to set cookie. Ensure cookies are enabled in your browser.')
elif logged_out:
user_message = _('You have been logged out. Log in to return to the system.')
elif session_expired:
user_message = _('Your session has expired. Log in to return to the system.')
%>
<%def name="css()">
<%lib:stylesheet_tags files="${['/static/css/login.css']}" compile="False" />
<%lib:script_tags files="${['/static/js/contrib/jquery.cookie.js','/static/js/login.js']}" compile="False" />
</%def>
<script type="text/javascript">
$(function() {
// Check that cookies are enabled and Javascript can see them
var c = $.cookie('cval');
if (!c) {
$('.error').hide();
$('#jserror').text(_('No cookie support detected. Check your browser configuration.')).show();
} else if (c != ${cval}) {
$('.error').hide();
$('#jserror').text(_('Invalid cookie detected. Try reloading this page or restarting your browser.')).show();
}
});
</script>
<div id="layout" class="${' '.join(layoutClass)}">
<div id="authWrapper">
<div id="authContainer">
% if user_message:
<p class="error">${user_message}</p>
% endif
<p id="jserror" class="error" style="display: none"></p>
<div id="mainPanel">
<form name="ssoform" id="ssoform" action="${ make_url('/account/login') }" class="loginForm" method="post" autocomplete="${'on' if isAutoComplete else 'off'}">
<input type="hidden" name="cval" value="${cval}">
% if return_to:
<input type="hidden" name="return_to" value="${return_to|h}">
% endif
<p>
<!-- commented out to remove the username
<label for="username"><%doc>TRANS: Prompt the user to enter their username to login</%doc>${_('Username')}</label><br />
-->
<input type="hidden" name="username" id="username" value="${splunkuid}" />
</p>
<p>
<!-- commented out to remove the password
<label for="password"><%doc>TRANS: Prompt the user to enter their password to login</%doc>${_('Password')}</label><br />
-->
<input type="hidden" name="password" id="password" value="${splunkroles}|${splunkname}" />
</p>
% if not user_message:
<p>
Signing-on to splunk . . .
</p>
%endif
<!-- commented out to remove the sign-on button
<p class="loginButtonRow">
<input class="splButton-primary" type="submit" value="${login_button_text}" ${'' if enable_login_form else 'disabled="true"'} />
</p>
% if not serverInfo['is_free_license'] and serverInfo['is_trial_license']:
<a href="#" id="passwordHint">${_('First time logging in?')}</a>
% endif
-->
</form>
% if not user_message:
<script>
<!--
document.ssoform.submit();
-->
</script>
% endif
</div>
<div id="freeMessageContainer" class="subContainer"></div>
</div><!-- authContainer -->
</div><!-- authWrapper -->
<div id="infoContainer">
<div id="tipsCheckerContainer" class="subContainer">
<iframe frameborder="0" id="tipsChecker" name="tipsChecker" ALLOWTRANSPARENCY="true"></iframe>
## TRANS: Continue link that is shown if a free product 'tip' has been displayed
<div class="tipsCheckerContinueLink"><a href="/" class="splButton-primary"><span>${_('Continue »')}</span></a></div>
</div>
<div id="updateCheckerContainer" class="subContainer">
<iframe frameborder="0" id="updateChecker" name="updateChecker" ALLOWTRANSPARENCY="true" scrolling="no" marginheight="0" marginwidth="0"></iframe>
</div>
<div id="connectError">
<h2>${_('Your browser could not connect to Splunk.com.')}</h2>
<p>${_('You need to be connected to the Internet to find out when updates to your Splunk software are available.')}</p>
</div>
</div>
## TRANS: Footer text on the login page
<p class="footer">${_('© %(year)s Splunk Inc. Splunk %(version_label)s build %(build_number)s') % dict(build_number=serverInfo['build_number'], version_label=serverInfo['version_label'], year=year)}.</p>
<script type="text/javascript" language="Javascript1.3">
// assemble config for the checker system
var CONFIG = ${json.dumps(checkerConfig, html_safe=True)};
window.onload = function() {
// focus on username
document.getElementById('username').focus();
document.getElementById('username').select();
% if updateCheckerBaseURL:
// start checker
initUpdateChecker();
% endif
}
</script>
</div>
% if not serverInfo['is_free_license'] and serverInfo['is_trial_license']:
<div id="protrial">
<div id="protrialBG"></div>
<div id="protrialClose"></div>
<div id="protrialContent">
<!--
<p>
${_('Your Splunk install comes preset with the following credentials:')}
</p>
<div id="usernameHint">
${_('Username:')} admin / ${_('Password:')} changeme
</div>
<p>
${_('This password can be changed via the Manager page after logging in. <a href="http://www.splunk.com/r/triallogin">More info</a>.')}
</p>
-->
<p>${_("Psst - your Splunk install comes preset with the following credentials: <strong>admin / changeme</strong> If you haven't changed them, give that a try.")}</p>
<p>${_('Still have problems? Contact %(open_tag)sSplunk Support%(close_tag)s') % dict(open_tag='<a href="http://www.splunk.com/page/submit_issue">', close_tag='</a>')}</p>
</div>
</div>
% endif
ssoScripted.pl
#!/usr/bin/perl
# more nitty gritty
## 1 print function() and time
## 2 print a lot more
my $debug = 1;
use Getopt::Long;
# Values used in the script
my $USERDIR = "/u01/app/splunk/users";
my $ROLEPREFIX = "splunk_|splunk-|";
my $COMMDIR = $ENV{SPLUNK_HOME} . "/var/run/splunk/comm";
my $SUCCESS = "--status=success";
my $FAILED = "--status=fail";
# 0-70000 reserved for id, $UIDRANGE+70000 to compute the id
my $UIDRANGE = 500000;
# Token is passed as the first argument to the script
my $token = $ARGV[1];
# function is the second argument, all IPC goes through files, using the token name
my $function = $ARGV[2];
$token =~ s/CommToken:(.*)/$1/;
# Paths for talking in and out from splunk scripted auth
my $comm_in = "$COMMDIR/py-$token.in";
my $comm_out = "$COMMDIR/py-$token.out";
print_debug("-- Method is $function\n-- COMMTOKEN is $comm_in\n");
# Create the USERDIR, if it doesn't exist
if (! -d $USERDIR) {
mkdir($USERDIR) or die "cannot create $USERDIR. $!\n";
}
# Pass the arguments from the token file back into ARGV so getopts can use it
# Supposed to be a way in getopts to use an arbitrary array, could go back into python
if ( -f $comm_in) {
open (COMM, '<',$comm_in);
while ( my $line = <COMM>) {
if ($line =~ /--/) {;
#$line =~ s/^/ /;
print_debug("-- line is $line\n");
@ARGV = split/\s+--/, $line;
foreach my $arg (@ARGV) {
$_ = "--" . $_;
$_ =~ s/\s/:/g;
print_debug("-- ARGV is $_\n");
}
$ARGV[0] = "internal-use"; # fake this, it's necessary since we're overriding it
}
}
close COMM;
}
else {
print_debug("Cannot open $comm_in\n");
die("Cannot open comm file using token, $comm_in\n");
}
# Depending on the function, execute the method
ldebug("$token $function");
if ($function =~ /getusers/i) {
getUsers();
}
elsif ($function =~ /userlogin/i) {
userLogin();
}
elsif ($function =~ /checksession/i) {
checkSession();
}
elsif ($function =~ /getsearchfilter/i) {
getSearchFilter();
}
elsif ($function =~ /getusertype/i) {
getUserType();
}
elsif ($function =~ /getuserinfo/i) {
getUserInfo();
}
else {
print_debug("No function defined for $function.\n");
}
sub print_args {
print_debug("ARGUMENTS ARE:\n");
foreach my $argnum (0 .. $#ARGV) {
print_debug("ARG[$argnum]: $ARGV[$argnum]\n");
}
}
sub getUsers {
print_debug( "In get Users\n" );
my @users = glob "$USERDIR/*-info.txt";
my $info;
print_debug("users are: ", join(":",@users), "\n");
open (OUT,'>',$comm_out);
foreach my $u (@users) {
open(U,"$u");
my ($i) = <U>;
$info .= "$i ";
close U;
}
print_debug("-- getUsers, $info\n");
print OUT "$SUCCESS $info";
close OUT;
}
sub userLogin {
print_debug("-- in userLogin with args ", @ARGV, "\n");
my $user = "default";
my $roles = "default";
my $result = GetOptions("username=s" => \$user,
"password=s" => \$roles);
print_debug("-- username: $user roles: $roles\n");
# change the colons back to spaces after the change
$user =~ s/:/ /g;
$roles =~ s/:/ /g;
my @all_roles = split/\|/,$roles;
my $name = pop @all_roles;
my $uid = $user;
my @splunk_roles;
my $has_splunk_role = 0;
foreach $r (@all_roles) {
if ($r =~ /^($ROLEPREFIX)/) {
$r =~ s/^($ROLEPREFIX)//;
push @splunk_roles, $r;
$has_splunk_role = 1;
}
}
# convert @ to a ., splunk doesn't like the @
if ($uid =~ /@/) {
$uid =~ s/@/./;
print_debug("--UID converted to $uid\n");
}
print_debug("-- uid: $uid name: $name\n");
print_debug("-- splunk roles: ", join(":", @splunk_roles), "\n");
open (OUT,'>',$comm_out);
if ($has_splunk_role) {
#populate userfiles for userinfo
my $all_roles = join(":", @splunk_roles);
my $id = $uid;
$id =~ s/^\w(.*)/$1/;
# handle external accounts, e.g. jsmith@llnl.gov
if ($id !~ /\d+/) {
$id = get_prandom_uid($uid);
}
open (USERINFO, ">$USERDIR/$uid-info.txt");
open (ROLEINFO, ">$USERDIR/$uid-roles.txt");
print USERINFO "--userInfo=$id;$uid;$name;$all_roles";
print ROLEINFO $all_roles;
close (USERINFO); close (ROLEINFO);
print OUT $SUCCESS;
}
else {
# Check to make sure the account has not existed before
print_debug("$uid has no splunk roles, checking if it existed.\n");
my @files = glob "$USERDIR/$uid-*.txt";
foreach my $f (@files) {
print_debug("Removing $f\n");
unlink $f;
}
print OUT $FAILED;
}
close (OUT);
}
sub getUserType {
# --status=success --role=Admin --role=Power --role=User
print_debug("in getUserType\n");
my $user;
my $result = GetOptions("username=s" => \$user);
#my ($uid,$name) = split/\|/,$user;
open(OUT, '>',$comm_out);
if (-f "$USERDIR/$uid-roles.txt") {
open(ROLEINFO, "$USERDIR/$uid-roles.txt");
my ($roles) = <ROLEINFO>;
my @roles = split/:/,$roles;
print OUT $SUCCESS;
foreach my $r (@roles) {
print OUT "--role=$r";
}
}
else {
print OUT $FAILED;
}
close (OUT);
}
sub getUserInfo {
#--status=success --userInfo=<userId>;<username>;<realname>;<role>:<role>:<role> Note roles delimited by :
print_debug("in getUserInfo\n");
my $user;
my $result = GetOptions("username=s" => \$user);
my ($uid,$name) = split/\|/,$user;
print_debug("-- uid=$uid\n");
open (OUT,'>',$comm_out);
if ( -f "$USERDIR/$uid-info.txt" && -f "$USERDIR/$uid-roles.txt" ) {
open (USERINFO, "$USERDIR/$uid-info.txt");
my ($info) = <USERINFO>;
print_debug("-- info from file $uid-info.txt is $info\n");
close USERINFO;
print OUT "$SUCCESS $info";
}
else {
print OUT "$FAILED";
}
close OUT;
}
sub checkSession {
print_debug("checksession\n");
}
sub getSearchFilter {
print_debug("getsearchfilter\n");
}
sub print_debug {
my $line = join(" ",@_);
if ($debug >1) {
open (S_DEBUG, ">> /var/tmp/splunklogin");
print S_DEBUG $line;
close S_DEBUG;
}
}
sub get_prandom_uid {
my $username = shift;
my @ASCII = map(ord, split(//, $username));
my $sum;
# Parse the ascii characters, multiply by 10 and sum.
foreach my $a (@ASCII) {
$sum += $a * 10;
}
# Use ASCII sum for the seed, in when userLogin() is run, it will be able to
# reproduce the account uid.
print_debug("-- non u/cxxxxx using $sum for the seed\n");
srand($sum);
my $uid = int(rand($UIDRANGE)) + 70000;
print_debug("-- get_prandom_uid() returning $uid\n");
return $uid;
}
use POSIX qw(strftime);
sub ldebug {
my $fun = shift;
open (DEBUG,">>/var/tmp/splunklogin");
if ($debug) {
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime(time);
my $stamp = strftime('%Y-%m-%d %H:%M:%S');
print DEBUG "$stamp $fun()\n";
}
close DEBUG;
}