Skip to content

Commit 8b7d949

Browse files
committed
Now tested on Windows and Splunk Cloud (note this version of the app is not installed on SplunkCloud, the VersionControl for SplunkCloud is the app to install on the SplunkCloud instance, this variation of the app includes only what is required to remotely backup/restore a SplunkCloud instance
This app is still used for SplunkCloud instances, but this app is installed on-prem Updates include: - Updated python SDK to 1.6.13 - New options in both backup & restore so that you can specify the location of the git / SSH command - The ability to only backup particular apps by default rather than to backup all and rely on an exclusion list (appsList) - Support for passwords.conf instead of plain text passwords - Proxy support - Re-wrote the runOSProcess function so that it works on Windows as expected The README.md has had various updates including more details around setup and how this was tested on Windows
1 parent 3d9e44b commit 8b7d949

20 files changed

+570
-176
lines changed

README.md

Lines changed: 134 additions & 10 deletions
Large diffs are not rendered by default.

README/inputs.conf.spec

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@ python.version = python3
55
srcURL = <value>
66
* This the URL to be used for the REST API access of the Splunk instance, https://localhost:8089/ for example (does not have to be localhost)
77
srcUsername = <value>
8-
* username to use for REST API of srcURL argument (only required if not using useLocalAuth)
8+
* username to use for REST API of srcURL argument (required if not using useLocalAuth)
99
srcPassword = <value>
10-
* password to use for REST API of srcURL argument (only required if not using useLocalAuth)
10+
* password to use for REST API of srcURL argument (required if not using useLocalAuth), use 'password:<name in passwords.conf>' and the app will attempt to find the password in your passwords.conf file
1111
gitTempDir = <value>
12-
* location where to store the output of the script on the filesystem
12+
* 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)
1313
gitRepoURL = <value>
1414
* git repository URL to store the objects (SSH URL only)
1515
noPrivate = <boolean>
16-
* disable the backup of user level / private objects (true/false)
16+
* disable the backup of user level / private objects (true/false), default false
1717
noDisabled = <boolean>
18-
* disable the backup of objects with a disabled status in Splunk (true/false)
18+
* disable the backup of objects with a disabled status in Splunk (true/false), default false
1919
includeEntities = <value>
2020
* comma separated list of object values to include
2121
excludeEntities = <value>
@@ -25,32 +25,44 @@ includeOwner = <value>
2525
excludeOwner = <value>
2626
* comma separated list of owners objects that should be transferred
2727
debugMode = <boolean>
28-
* turn on DEBUG level logging (defaults to INFO) (true/false)
28+
* turn on DEBUG level logging (defaults to INFO) (true/false), default false
2929
useLocalAuth = <boolean>
30-
* do not use the srcUsername/srcPassword, use the session_key of the user running the modular input instead (works on localhost only) (true/false)
30+
* do not use the srcUsername/srcPassword, use the session_key of the user running the modular input instead (works on localhost only) (true/false), default false
3131
remoteAppName = <value>
32-
* defaults to SplunkVersionControl, this app needs to contain the savedsearches and potentially the splunkversioncontrol_globalexclusionlist
32+
* defaults to SplunkVersionControl, this app needs to contain the savedsearches and potentially the splunkversioncontrol_globalexclusionlist, use SplunkVersionControlCloud on a cloud-based instance
3333
appsList = <value>
34-
* Comma separated list of apps, this changes Splunk Version Control to not list all applications and instead only runs a backup on the specified apps. Useful for Splunk Cloud where you cannot access the apps REST endpoint
34+
* Comma separated list of apps, this changes Splunk Version Control to not list all applications and instead only runs a backup on the specified apps
35+
git_command = <value>
36+
* defaults to 'git', can be overriden (for example on a Windows server) to use a full path to the git command
37+
ssh_command = <value>
38+
* defaults to 'ssh', can be overriden (for example on a Windows server) to use a full path to the ssh command
39+
proxy = <value>
40+
* If supplied provides a proxy setting to use to access the srcURL (https proxy). Use https://user:password:passwordinpasswordsconf@10.10.1.0:3128 and the application will obtain the password for the entry 'passwordinpasswordsconf'. If password: is not used the password is used as per a normal proxy setting, for example https://user:password@10.10.1.0:3128
3541

3642
[splunkversioncontrol_restore://<name>]
3743
destURL = <value>
3844
* This the URL to be used for the REST API access of the Splunk instance, https://localhost:8089/ for example (does not have to be localhost)
3945
destUsername = <value>
4046
* username to use for REST API of srcURL argument (only required if not using useLocalAuth)
4147
destPassword = <value>
42-
* password to use for REST API of srcURL argument (only required if not using useLocalAuth)
48+
* password to use for REST API of srcURL argument (only required if not using useLocalAuth), use 'password:<name in passwords.conf>' and the app will attempt to find the password in your passwords.conf file
4349
gitTempDir = <value>
44-
* location where to store the output of the script on the filesystem
50+
* 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)
4551
gitRepoURL = <value>
4652
* git repository URL to store the objects (SSH URL only)
4753
auditLogsLookupBackTime = <value>
4854
* 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)
4955
debugMode = <boolean>
50-
* turn on DEBUG level logging (defaults to INFO) (true/false)
56+
* turn on DEBUG level logging (defaults to INFO) (true/false), default false
5157
useLocalAuth = <boolean>
52-
* do not use the srcUsername/srcPassword, use the session_key of the user running the modular input instead (works on localhost only) (true/false)
58+
* do not use the srcUsername/srcPassword, use the session_key of the user running the modular input instead (works on localhost only) (true/false), default false
5359
remoteAppName = <value>
54-
* defaults to SplunkVersionControl, this app needs to contain the savedsearches and potentially the splunkversioncontrol_globalexclusionlist
60+
* defaults to SplunkVersionControl, this app needs to contain the savedsearches and potentially the splunkversioncontrol_globalexclusionlist, use SplunkVersionControlCloud on a cloud-based instance
5561
timewait = <value>
5662
* defaults to 600, if the kvstore contains an entry advising there is a restore running, how many seconds should pass before the entry is deleted and the restore happens anyway?
63+
git_command = <value>
64+
* defaults to 'git', can be overriden (for example on a Windows server) to use a full path to the git command
65+
ssh_command = <value>
66+
* defaults to 'ssh', can be overriden (for example on a Windows server) to use a full path to the ssh command
67+
proxy = <value>
68+
* If supplied provides a proxy setting to use to access the destURL (https proxy). Use https://user:password:passwordinpasswordsconf@10.10.1.0:3128 and the application will obtain the password for the entry 'passwordinpasswordsconf'. If password: is not used the password is used as per a normal proxy setting, for example https://user:password@10.10.1.0:3128

SplunkVersionControl.tgz

5.89 KB
Binary file not shown.

bin/splunkversioncontrol_backup.py

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import sys
88
import xml.dom.minidom, xml.sax.saxutils
99
from splunkversioncontrol_backup_class import SplunkVersionControlBackup
10-
from splunkversioncontrol_utility import runOSProcess
10+
from splunkversioncontrol_utility import runOSProcess, get_password
1111

1212
"""
1313
@@ -31,31 +31,31 @@
3131
</arg>
3232
<arg name="srcUsername">
3333
<title>srcUsername</title>
34-
<description>username to use for REST API of srcURL argument (only required if not using useLocalAuth)</description>
34+
<description>username to use for REST API of srcURL argument (required if not using useLocalAuth)</description>
3535
<required_on_create>false</required_on_create>
3636
</arg>
3737
<arg name="srcPassword">
3838
<title>srcPassword</title>
39-
<description>password to use for REST API of srcURL argument (only required if not using useLocalAuth)</description>
39+
<description>password to use for REST API of srcURL argument (required if not using useLocalAuth). If started with password: the name after the : symbol (password:mypass) is searched for in passwords.conf</description>
4040
<required_on_create>false</required_on_create>
4141
</arg>
4242
<arg name="gitTempDir">
4343
<title>gitTempDir</title>
44-
<description>location where to store the output of the script on the filesystem</description>
44+
<description>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)</description>
4545
</arg>
4646
<arg name="gitRepoURL">
4747
<title>gitRepoURL</title>
4848
<description>git repository URL to store the objects (SSH URL only)</description>
4949
</arg>
5050
<arg name="noPrivate">
5151
<title>noPrivate</title>
52-
<description>disable the backup of user level / private objects (true/false)</description>
52+
<description>disable the backup of user level / private objects (true/false), default false</description>
5353
<validation>is_bool('noPrivate')</validation>
5454
<required_on_create>false</required_on_create>
5555
</arg>
5656
<arg name="noDisabled">
5757
<title>noDisabled</title>
58-
<description>disable the backup of objects with a disabled status in Splunk (true/false)</description>
58+
<description>disable the backup of objects with a disabled status in Splunk (true/false), default false</description>
5959
<validation>is_bool('noDisabled')</validation>
6060
<required_on_create>false</required_on_create>
6161
</arg>
@@ -81,24 +81,39 @@
8181
</arg>
8282
<arg name="debugMode">
8383
<title>debugMode</title>
84-
<description>turn on DEBUG level logging (defaults to INFO) (true/false)</description>
84+
<description>turn on DEBUG level logging (defaults to INFO) (true/false), default false</description>
8585
<validation>is_bool('debugMode')</validation>
8686
<required_on_create>false</required_on_create>
8787
</arg>
8888
<arg name="useLocalAuth">
8989
<title>useLocalAuth</title>
90-
<description>Instead of using the srcUsername/srcPassword, use the session_key of the user running the modular input instead (works on localhost only) (true/false)</description>
90+
<description>Instead of using the srcUsername/srcPassword, use the session_key of the user running the modular input instead (works on localhost only) (true/false), default false</description>
9191
<validation>is_bool('useLocalAuth')</validation>
9292
<required_on_create>false</required_on_create>
9393
</arg>
9494
<arg name="remoteAppName">
9595
<title>remoteAppName</title>
96-
<description>defaults to SplunkVersionControl, this app needs to contain the savedsearches and potentially the splunkversioncontrol_globalexclusionlist</description>
96+
<description>defaults to SplunkVersionControl, this app needs to contain the savedsearches and potentially the splunkversioncontrol_globalexclusionlist, use SplunkVersionControlCloud on a cloud-based instance</description>
9797
<required_on_create>false</required_on_create>
9898
</arg>
9999
<arg name="appsList">
100100
<title>appsList</title>
101-
<description>Comma separated list of apps, this changes Splunk Version Control to not list all applications and instead only runs a backup on the specified apps. Useful for Splunk Cloud where you cannot access the apps REST endpoint</description>
101+
<description>Comma separated list of apps, this changes Splunk Version Control to not list all applications and instead only runs a backup on the specified apps</description>
102+
<required_on_create>false</required_on_create>
103+
</arg>
104+
<arg name="git_command">
105+
<title>git_command</title>
106+
<description>defaults to 'git', can be overriden (for example on a Windows server) to use a full path to the git command</description>
107+
<required_on_create>false</required_on_create>
108+
</arg>
109+
<arg name="ssh_command">
110+
<title>ssh_command</title>
111+
<description>defaults to 'ssh', can be overriden (for example on a Windows server) to use a full path to the ssh command</description>
112+
<required_on_create>false</required_on_create>
113+
</arg>
114+
<arg name="proxy">
115+
<title>proxy</title>
116+
<description>If supplied provides a proxy setting to use to access the srcURL (https proxy). Use https://user:password:[email protected]:3128 and the application will obtain the password for the entry 'passwordinpasswordsconf'. If password: is not used the password is used as per a normal proxy setting, for example https://user:[email protected]:3128</description>
102117
<required_on_create>false</required_on_create>
103118
</arg>
104119
</args>
@@ -116,6 +131,8 @@ def get_validation_data():
116131
# parse the validation XML
117132
doc = xml.dom.minidom.parseString(val_str)
118133
root = doc.documentElement
134+
session_key = root.getElementsByTagName("session_key")[0].firstChild.data
135+
val_data['session_key'] = session_key
119136

120137
logger.debug("XML: found items")
121138
item_node = root.getElementsByTagName("item")[0]
@@ -143,6 +160,14 @@ def print_error(s):
143160
#Validate the arguments to the app to ensure this will work...
144161
def validate_arguments():
145162
val_data = get_validation_data()
163+
164+
if 'debugMode' in val_data:
165+
debugMode = val_data['debugMode'].lower()
166+
if debugMode == "true" or debugMode == "t":
167+
logging.getLogger().setLevel(logging.DEBUG)
168+
169+
session_key = val_data['session_key']
170+
146171
useLocalAuth = False
147172
if 'useLocalAuth' in val_data:
148173
useLocalAuth = val_data['useLocalAuth'].lower()
@@ -166,16 +191,39 @@ def validate_arguments():
166191
if 'remoteAppName' in val_data:
167192
appName = val_data['remoteAppName']
168193

194+
if 'git_command' in val_data:
195+
git_command = val_data['git_command']
196+
logger.debug("Overriding git command to %s" % (git_command))
197+
else:
198+
git_command = "git"
199+
if 'ssh_command' in val_data:
200+
ssh_command = val_data['ssh_command']
201+
logger.debug("Overriding ssh command to %s" % (ssh_command))
202+
else:
203+
ssh_command = "ssh"
204+
169205
#Run a sanity check and make sure we can connect into the remote Splunk instance
170206
if not useLocalAuth:
171207
url = val_data['srcURL'] + "/servicesNS/nobody/%s/search/jobs/export?search=makeresults" % (appName)
172208
#Verify=false is hardcoded to workaround local SSL issues
173209
srcUsername = val_data['srcUsername']
174210
srcPassword = val_data['srcPassword']
175-
211+
if srcPassword.find("password:") == 0:
212+
srcPassword = get_password(srcPassword[9:], session_key, logger)
213+
214+
proxies = {}
215+
if 'proxy' in val_data:
216+
proxies["https"] = val_data['proxy']
217+
if proxies['https'].find("password:") != -1:
218+
start = proxies['https'].find("password:") + 9
219+
end = proxies['https'].find("@")
220+
logger.debug("Attempting to replace proxy=%s by subsituting=%s with a password" % (proxies['https'], proxies['https'][start:end]))
221+
temp_password = get_password(proxies['https'][start:end], session_key, logger)
222+
proxies['https'] = proxies['https'][0:start-9] + temp_password + proxies['https'][end:]
223+
176224
try:
177-
logger.debug("Running query against URL %s with username %s" % (url, srcUsername))
178-
res = requests.get(url, auth=(srcUsername, srcPassword), verify=False)
225+
logger.debug("Running query against URL %s with username %s proxies_length=%s" % (url, srcUsername, len(proxies)))
226+
res = requests.get(url, auth=(srcUsername, srcPassword), verify=False, proxies=proxies)
179227
logger.debug("End query against URL %s with username %s" % (url, srcUsername))
180228

181229
if (res.status_code != requests.codes.ok):
@@ -186,12 +234,11 @@ def validate_arguments():
186234
sys.exit(5)
187235

188236
gitRepoURL = val_data['gitRepoURL']
189-
(stdout, stderr, res) = runOSProcess(["git ls-remote %s" % (gitRepoURL) ], logger)
190-
237+
(stdout, stderr, res) = runOSProcess("%s ls-remote %s" % (git_command, gitRepoURL), logger)
191238
#If we didn't manage to ls-remote perhaps we just need to trust the fingerprint / this is the first run?
192239
if res == False:
193-
(stdout, stderrout, res) = runOSProcess("ssh -n -o \"BatchMode yes\" -o StrictHostKeyChecking=no " + gitRepoURL[:gitRepoURL.find(":")], logger)
194-
(stdout, stderr, res) = runOSProcess(["git ls-remote %s" % (gitRepoURL) ], logger)
240+
(stdout, stderrout, res) = runOSProcess(ssh_command + " -n -o \"BatchMode yes\" -o StrictHostKeyChecking=no " + gitRepoURL[:gitRepoURL.find(":")], logger)
241+
(stdout, stderr, res) = runOSProcess("%s ls-remote %s" % (git_command, gitRepoURL), logger)
195242

196243
if res == False:
197244
print_error("Failed to validate the git repo URL, stdout of '%s', stderr of '%s'" % (stdout, stderr))

0 commit comments

Comments
 (0)