Skip to content

Commit 1ede611

Browse files
author
me
committed
Add sslVerify variable
1 parent 0e1022c commit 1ede611

10 files changed

+103
-63
lines changed

README/inputs.conf.spec

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ gitTempDir = <value>
99
* location where to store the output of the script on the filesystem (note this directory will be deleted/re-created but the parent dir must exist)
1010
gitRepoURL = <value>
1111
* git repository URL to store the objects (SSH URL only)
12+
sslVerify = <boolean>
13+
* Set to 'true' or 'false' to enable/disable SSL verification for REST requests to `srcUrl`. Set to a path to specify a file with valid CA. (https://2.python-requests.org/en/master/user/advanced/#ssl-cert-verification)
1214
noPrivate = <boolean>
1315
* disable the backup of user level / private objects (true/false), default false
1416
noDisabled = <boolean>
@@ -47,6 +49,9 @@ gitTempDir = <value>
4749
* location where to store the output of the script on the filesystem (note this directory will be deleted/re-created but the parent dir must exist)
4850
gitRepoURL = <value>
4951
* git repository URL to store the objects (SSH URL only)
52+
sslVerify = <boolean>
53+
* Set to 'true' or 'false' to enable/disable SSL verification for REST requests to `srcUrl`. Set to a path to specify a file with valid CA. (https://2.python-requests.org/en/master/user/advanced/#ssl-cert-verification)
54+
5055
auditLogsLookupBackTime = <value>
5156
* This is how far back the audit logs will be checked to ensure that a restore entry is valid, this should be set to your interval time or slightly more, defaults to -1h (use Splunk format)
5257
debugMode = <boolean>

bin/postversioncontrolrestore.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class SVCPostRestore(GeneratingCommand):
6060
restoreAsUser = Option(require=True)
6161
scope = Option(require=True)
6262
timeout = Option(require=True)
63+
sslVerify = Option(require=False, default=False)
6364

6465
def generate(self):
6566
"""
@@ -94,7 +95,7 @@ def generate(self):
9495

9596
logger.debug("Using token %s" % (body['Authorization']))
9697

97-
attempt = requests.post(url, verify=False, data=body)
98+
attempt = requests.post(url, verify=self.sslVerify, data=body)
9899
if attempt.status_code != 200:
99100
logger.error("POST request failed with status_code=%s, reason=%s, text=%s on url=%s" % (attempt.status_code, attempt.reason, attempt.text, url))
100101
yield {'result': 'Unknown failure, received a non-200 response code of %s on the url %s, reason %s, text result is %s' % (attempt.status_code, url, attempt.reason, attempt.text)}

bin/splunkversioncontrol_backup.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@
4747
<title>gitRepoURL</title>
4848
<description>git repository URL to store the objects (SSH URL only)</description>
4949
</arg>
50+
<arg name="sslVerify">
51+
<title>sslVerify</title>
52+
<description>Set to 'true' or 'false' to enable/disable SSL verification for REST requests to `srcUrl`. Set to a path to specify a file with valid CA. (https://2.python-requests.org/en/master/user/advanced/#ssl-cert-verification)</description>
53+
<validation>is_bool('sslVerify')</validation>
54+
<required_on_create>false</required_on_create>
55+
</arg>
5056
<arg name="noPrivate">
5157
<title>noPrivate</title>
5258
<description>disable the backup of user level / private objects (true/false), default false</description>
@@ -203,10 +209,13 @@ def validate_arguments():
203209
else:
204210
ssh_command = "ssh"
205211

212+
sslVerify = False
213+
if 'sslVerify' in val_data:
214+
sslVerify = val_data['sslVerify']
215+
206216
#Run a sanity check and make sure we can connect into the remote Splunk instance
207217
if not useLocalAuth:
208218
url = val_data['srcURL'] + "/servicesNS/nobody/%s/search/jobs/export?search=makeresults" % (appName)
209-
#Verify=false is hardcoded to workaround local SSL issues
210219
srcUsername = val_data['srcUsername']
211220
srcPassword = val_data['srcPassword']
212221
if srcPassword.find("password:") == 0:
@@ -224,7 +233,7 @@ def validate_arguments():
224233

225234
try:
226235
logger.debug("Running query against URL %s with username %s proxies_length=%s" % (url, srcUsername, len(proxies)))
227-
res = requests.get(url, auth=(srcUsername, srcPassword), verify=False, proxies=proxies)
236+
res = requests.get(url, auth=(srcUsername, srcPassword), verify=self.sslVerify, proxies=proxies)
228237
logger.debug("End query against URL %s with username %s" % (url, srcUsername))
229238

230239
if (res.status_code != requests.codes.ok):

bin/splunkversioncontrol_backup_class.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class SplunkVersionControlBackup:
7777
gitRepoURL = None
7878
stanzaName = None
7979
lastRunEpoch = None
80+
sslVerify = False
8081

8182
# read XML configuration passed from splunkd
8283
def get_config(self):
@@ -136,8 +137,7 @@ def getAllAppsList(self):
136137
else:
137138
auth = HTTPBasicAuth(self.srcUsername, self.srcPassword)
138139

139-
#Verify=false is hardcoded to workaround local SSL issues
140-
res = requests.get(url, auth=auth, headers=headers, verify=False, proxies=self.proxies)
140+
res = requests.get(url, auth=auth, headers=headers, verify=self.sslVerify, proxies=self.proxies)
141141
if (res.status_code != requests.codes.ok):
142142
logger.fatal("i=\"%s\" Could not obtain a list of all apps, URL=%s statuscode=%s reason=%s, response=\"%s\"" % (self.stanzaName, url, res.status_code, res.reason, res.text))
143143
sys.exit(-1)
@@ -190,8 +190,7 @@ def runQueries(self, app, endpoint, type, fieldIgnoreList, aliasAttributes={}, v
190190
else:
191191
auth = HTTPBasicAuth(self.srcUsername, self.srcPassword)
192192

193-
#Verify=false is hardcoded to workaround local SSL issues
194-
res = requests.get(url, auth=auth, headers=headers, verify=False, proxies=self.proxies)
193+
res = requests.get(url, auth=auth, headers=headers, verify=self.sslVerify, proxies=self.proxies)
195194
if (res.status_code != requests.codes.ok):
196195
logger.error("i=\"%s\" URL=%s in app=%s statuscode=%s reason=%s response=\"%s\"" % (self.stanzaName, url, app, res.status_code, res.reason, res.text))
197196

@@ -433,8 +432,7 @@ def macros(self, app):
433432
else:
434433
auth = HTTPBasicAuth(self.srcUsername, self.srcPassword)
435434

436-
#Verify=false is hardcoded to workaround local SSL issues
437-
res = requests.get(url, auth=auth, headers=headers, verify=False, proxies=self.proxies)
435+
res = requests.get(url, auth=auth, headers=headers, verify=self.sslVerify, proxies=self.proxies)
438436
if (res.status_code != requests.codes.ok):
439437
logger.error("i=\"%s\" Type macro in app=%s, URL=%s statuscode=%s reason=%s, response=\"%s\"" % (self.stanzaName, app, url, res.status_code, res.reason, res.text))
440438

@@ -749,7 +747,7 @@ def runSearchJob(self, query):
749747
headers = {'Authorization': 'Splunk %s' % self.session_key }
750748
else:
751749
auth = HTTPBasicAuth(self.srcUsername, self.srcPassword)
752-
res = requests.post(url, auth=auth, headers=headers, verify=False, data=data, proxies=self.proxies)
750+
res = requests.post(url, auth=auth, headers=headers, verify=self.sslVerify, data=data, proxies=self.proxies)
753751
if (res.status_code != requests.codes.ok):
754752
logger.error("i=\"%s\" URL=%s statuscode=%s reason=%s response=\"%s\"" % (self.stanzaName, url, res.status_code, res.reason, res.text))
755753
res = json.loads(res.text)
@@ -1022,6 +1020,9 @@ def run_script(self):
10221020

10231021
self.proxies = proxies
10241022

1023+
if 'sslVerify' in config:
1024+
self.sslVerify = config['sslVerify']
1025+
10251026
#From server
10261027
self.splunk_rest = config['srcURL']
10271028
excludedList = [ "srcPassword", "session_key" ]
@@ -1035,9 +1036,8 @@ def run_script(self):
10351036

10361037
headers={'Authorization': 'Splunk %s' % config['session_key']}
10371038

1038-
#Verify=false is hardcoded to workaround local SSL issues
10391039
url = 'https://localhost:8089/services/shcluster/captain/info?output_mode=json'
1040-
res = requests.get(url, headers=headers, verify=False)
1040+
res = requests.get(url, headers=headers, verify=self.sslVerify)
10411041
if (res.status_code == 503):
10421042
logger.debug("i=\"%s\" Non-shcluster / standalone instance, safe to run on this node" % (self.stanzaName))
10431043
elif (res.status_code != requests.codes.ok):

bin/splunkversioncontrol_rest_restore.py

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,26 @@
5959

6060
class SVCRestore(splunk.rest.BaseRestHandler):
6161

62+
def query_back_for_user_and_permissions(self, authorization_token, remoteAddr,*, sslVerify):
63+
headers = { "Authorization" : authorization_token }
64+
65+
#Run a query back against the source system to check the username/role
66+
remoteAddr = self.request['remoteAddr']
67+
url = "https://" + remoteAddr + ":8089/services/authentication/current-context?output_mode=json"
68+
logger.info("Received remote request checking username and role related to the token on url=%s" % (url))
69+
logger.debug("token=%s" % (authorization_token))
70+
71+
res = self.runHttpRequest(url, headers, None, "get", "checking username with token (based on incoming ip address)", sslVerify=sslVerify)
72+
if not res:
73+
return
74+
75+
json_dict = json.loads(res.text)
76+
#self.response.write(str(json_dict) + "\n\n\n")
77+
username = json_dict['entry'][0]['content']['username']
78+
roles = json_dict['entry'][0]['content']['roles']
79+
return username, roles
80+
81+
6282
def handle_POST(self):
6383
starttime = calendar.timegm(time.gmtime())
6484
payload = six.moves.urllib.parse.parse_qs(self.request['payload'])
@@ -75,26 +95,6 @@ def handle_POST(self):
7595
self.response.write("Received remote call but attr=%s was missing from arguments, received=\"%s\"" % (attr, payload))
7696
return
7797

78-
headers = { "Authorization" : payload['Authorization'][0] }
79-
80-
#Run a query back against the source system to check the username/role
81-
remoteAddr = self.request['remoteAddr']
82-
url = "https://" + remoteAddr + ":8089/services/authentication/current-context?output_mode=json"
83-
logger.info("Received remote request checking username and role related to the token on url=%s" % (url))
84-
logger.debug("token=%s" % (payload['Authorization'][0]))
85-
86-
res = self.runHttpRequest(url, headers, None, "get", "checking username with token (based on incoming ip address)")
87-
if not res:
88-
return
89-
90-
json_dict = json.loads(res.text)
91-
#self.response.write(str(json_dict) + "\n\n\n")
92-
username = json_dict['entry'][0]['content']['username']
93-
roles = json_dict['entry'][0]['content']['roles']
94-
95-
#self.response.write(username + "\n")
96-
#self.response.write(str(roles) + "\n")
97-
logger.info("username=%s roles=%s" % (username, roles))
9898

9999
splunk_vc_name = payload['splunk_vc_name'][0]
100100
#self.response.write(splunk_vc_name + "\n\n\n")
@@ -104,7 +104,7 @@ def handle_POST(self):
104104
url = "https://localhost:8089/servicesNS/-/-/data/inputs/splunkversioncontrol_restore/" + six.moves.urllib.parse.quote(splunk_vc_name) + "?output_mode=json"
105105
logger.debug("Now running query against url=%s to obtain config information" % (url))
106106

107-
res = self.runHttpRequest(url, headers, None, "get", "querying the inputs for splunkversioncontrol_restore with name %s" % (splunk_vc_name))
107+
res = self.runHttpRequest(url, headers, None, "get", "querying the inputs for splunkversioncontrol_restore with name %s" % (splunk_vc_name), sslVerify=sslVerify)
108108
if not res:
109109
return
110110

@@ -134,6 +134,10 @@ def handle_POST(self):
134134

135135
destURL = json_dict['destURL']
136136

137+
sslVerify = False
138+
if 'sslVerify' in json_dict:
139+
sslVerify = json_dict['sslVerify']
140+
137141
headers = {}
138142
auth = None
139143

@@ -156,6 +160,9 @@ def handle_POST(self):
156160
else:
157161
time_wait = 600
158162

163+
username, roles = self.query_back_for_user_and_permissions(payload['Authorization'][0], remoteAddr)
164+
logger.info("username=%s roles=%s" % (username, roles))
165+
159166
app = payload['app'][0]
160167
type = payload['type'][0]
161168
obj_name = payload['obj_name'][0]
@@ -178,7 +185,7 @@ def handle_POST(self):
178185

179186
starttime = starttime-60-timeout
180187

181-
json_res = self.runSearchJob(destURL, remoteAppName, headers, auth, username, starttime)
188+
json_res = self.runSearchJob(destURL, remoteAppName, headers, auth, username, starttime, sslVerify=sslVerify)
182189

183190
if 'error' in json_res:
184191
self.response.write("An error occurred: %s" % (json_res['error']))
@@ -200,7 +207,7 @@ def handle_POST(self):
200207
headers = { "Authorization" : "Splunk " + self.request['systemAuth'] }
201208
curtime = calendar.timegm(time.gmtime())
202209
url = "https://localhost:8089/servicesNS/nobody/SplunkVersionControl/storage/collections/data/splunkversioncontrol_rest_restore_status"
203-
res = self.runHttpRequest(url, headers, None, "get", "checking kvstore collection splunkversioncontrol_rest_restore_status")
210+
res = self.runHttpRequest(url, headers, None, "get", "checking kvstore collection splunkversioncontrol_rest_restore_status", sslVerify=sslVerify)
204211
if not res:
205212
return
206213

@@ -209,14 +216,14 @@ def handle_POST(self):
209216
if not len(res) == 0:
210217
if not 'start_time' in res[0]:
211218
logger.warn("Warning invalid kvstore data, will wipe it and continue in collection splunkversioncontrol_rest_restore_status on url=%s, value returned res=\"%s\"" % (url, payload))
212-
self.runHttpRequest(url, headers, None, 'delete', 'wiping kvstore splunkversioncontrol_rest_restore_status')
219+
self.runHttpRequest(url, headers, None, 'delete', 'wiping kvstore splunkversioncontrol_rest_restore_status', sslVerify=sslVerify)
213220
else:
214221
kvstore_start_time = res[0]['start_time']
215222
target_time = curtime - time_wait
216223
if kvstore_start_time < target_time:
217224
logger.warn("Found existing entry from %s but time is %s, this is past the limit of current time minus %s (%s)" % (kvstore_start_time, curtime, time_wait, target_time))
218225
#More than 10 minutes ago, delete the entry and move on
219-
self.runHttpRequest(url, headers, None, "delete", "wiping kvstore splunkversioncontrol_rest_restore_status due to record %s older than %s time period" % (kvstore_start_time, target_time))
226+
self.runHttpRequest(url, headers, None, "delete", "wiping kvstore splunkversioncontrol_rest_restore_status due to record %s older than %s time period" % (kvstore_start_time, target_time), sslVerify=sslVerify)
220227
else:
221228
removal_target = kvstore_start_time + time_wait + 1
222229
logger.warn("Attempted to run but found a running restore instance with time=%s and current_time=%s, will delete and move on after current_time_minus=%s seconds (override_time=%s)" % (kvstore_start_time, curtime, time_wait, removal_target))
@@ -227,7 +234,7 @@ def handle_POST(self):
227234
payload = json.dumps({ 'start_time': curtime })
228235
headers['Content-Type'] = 'application/json'
229236
#update kvstore with runtime
230-
res = self.runHttpRequest(url, headers, payload, 'post', 'updating kvstore collection splunkversioncontrol_rest_restore_status')
237+
res = self.runHttpRequest(url, headers, payload, 'post', 'updating kvstore collection splunkversioncontrol_rest_restore_status', sslVerify=sslVerify)
231238
if not res:
232239
return res
233240

@@ -239,16 +246,16 @@ def handle_POST(self):
239246
self.response.write("Restore has failed to complete successfully in app %s, object of type %s, with name %s, from tag %s, scope %s with restoreAsUser %s and your username of %s. Message is %s" % (app, type, obj_name, tag, scope, restoreAsUser, username, message))
240247
logger.warn("Restore has failed to complete successfully in app=%s, object of type=%s, with name=%s, from tag=%s, scope=%s with restoreAsUser=%s and requested by username=%s, message=%s" % (app, type, obj_name, tag, scope, restoreAsUser, username, message))
241248

242-
self.runHttpRequest(url, headers, None, 'delete', 'wiping kvstore splunkversioncontrol_rest_restore_status after completed run')
249+
self.runHttpRequest(url, headers, None, 'delete', 'wiping kvstore splunkversioncontrol_rest_restore_status after completed run', sslVerify=sslVerify)
243250

244251
#Run a Splunk query via the search/jobs endpoint
245-
def runSearchJob(self, url, appname, headers, auth, username, earliest_time):
252+
def runSearchJob(self, url, appname, headers, auth, username, earliest_time, *, sslVerify=False):
246253
url = url + "/servicesNS/-/%s/search/jobs" % (appname)
247254
query = "savedsearch \"Splunk Version Control Audit Query POST\" username=\"%s\" | stats count | where count>0" % (username)
248255
logger.debug("Running requests.post() on url=%s query=\"%s\"" % (url, query))
249256
data = { "search" : query, "output_mode" : "json", "exec_mode" : "oneshot", "earliest_time" : earliest_time }
250257

251-
res = requests.post(url, auth=auth, headers=headers, verify=False, data=data)
258+
res = requests.post(url, auth=auth, headers=headers, verify=sslVerify, data=data)
252259
if (res.status_code != requests.codes.ok):
253260
logger.error("url=%s status_code=%s reason=%s, response=\"%s\"" % (url, res.status_code, res.reason, res.text))
254261
return { "error": "url=%s status_code=%s reason=%s, response=\"%s\"" % (url, res.status_code, res.reason, res.text) }
@@ -264,17 +271,17 @@ def runSearchJob(self, url, appname, headers, auth, username, earliest_time):
264271
logger.warn("messages from query=\"%s\" were messages=\"%s\"" % (query, res["messages"]))
265272
return res
266273

267-
def runHttpRequest(self, url, headers, data, type, text):
274+
def runHttpRequest(self, url, headers, data, type, text, *, sslVerify=False):
268275
if type == "delete":
269-
res = requests.delete(url, headers=headers, verify=False)
276+
res = requests.delete(url, headers=headers, verify=sslVerify)
270277
elif type == "post":
271-
res = requests.post(url, headers=headers, verify=False, data=data)
278+
res = requests.post(url, headers=headers, verify=sslVerify, data=data)
272279
elif type == "get":
273-
res = requests.get(url, headers=headers, verify=False)
280+
res = requests.get(url, headers=headers, verify=sslVerify)
274281

275282
if (res.status_code != requests.codes.ok and res.status_code != 201):
276-
logger.error("Unexpected response code while %s, on url=%s, statuscode=%s reason=%s, response=\"%s\", payload=\"%s\"" % (text, url, res.status_code, res.reason, res.text, data))
277-
self.response.write("Error unexpected response code while %s, on url %s, statuscode %s reason %s, response \"%s\", payload=\"%s\"" % (text, url, res.status_code, res.reason, res.text, data))
283+
logger.error("Unexpected response code while %s, on url=%s, statuscode=%s reason=%s, response=\"%s\", payload=\"%s\", verify=\"%s\"" % (text, url, res.status_code, res.reason, res.text, data, sslVerify))
284+
self.response.write("Error unexpected response code while %s, on url %s, statuscode %s reason %s, response \"%s\", payload=\"%s\", verify=\"%s\"" % (text, url, res.status_code, res.reason, res.text, data, sslVerify))
278285
return
279286

280287
return res

0 commit comments

Comments
 (0)