#!/usr/bin/python3
"""
-Back up Untangle configurations over HTTPS.
+Back up Untangle configurations via the web admin UI.
"""
from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser
import configparser
-import http.cookiejar
from os import chmod
-import ssl
+from urllib.error import HTTPError, URLError
from sys import stderr
-import urllib.parse
-import urllib.request
+from untangle.untangle import Untangle
# Define a few exit codes.
EXIT_OK = 0
EXIT_BACKUPS_FAILED = 1
-
-class Untangle:
-
- def __init__(self, s):
- """
- Initialize this Untangle object with a ConfigParser section.
- """
- self.name = s.name
- self.host = s['host']
- self.username = s.get('username', 'admin')
- self.password = s['password']
- self.version = int(s.get('version', '11'))
- self.base_url = 'https://' + self.host + '/' # This never changes
-
- # Sanity check the numerical version.
- if self.version not in [9, 11]:
- msg = 'Invalid version "' + str(self.version) + '" '
- msg += 'in section "' + s.name + '"'
- raise configparser.ParsingError(msg)
-
- # Sanity check the boolean verify_cert parameter.
- vc = s.get('verify_cert', 'False')
- if vc == 'True':
- self.verify_cert = True
- elif vc == 'False':
- self.verify_cert = False
- else:
- msg = 'Invalid value "' + vc + '" for verify_cert '
- msg += 'in section "' + s.name + '"'
- raise configparser.ParsingError(msg)
-
- #
- # Finally, create a URL opener to make HTTPS requests.
- #
- # First, create a cookie jar that we'll attach to our URL
- # opener thingy.
- cj = http.cookiejar.CookieJar()
- cookie_proc = urllib.request.HTTPCookieProcessor(cj)
-
- # SSL mumbo jumbo to make it ignore the certificate's hostname
- # when verify_cert = False.
- if self.verify_cert:
- ssl_ctx = ssl.create_default_context()
- else:
- ssl_ctx = ssl._create_unverified_context()
-
- https_handler = urllib.request.HTTPSHandler(context=ssl_ctx)
-
- # Now Create a URL opener, and tell it to use our cookie jar
- # and SSL context. We keep this around for future requests.
- self.opener = urllib.request.build_opener(https_handler, cookie_proc)
-
-
- def login(self):
- login_path = 'auth/login?url=/setup/welcome.do&realm=Administrator'
- url = self.base_url + login_path
- post_vars = {'username': self.username, 'password': self.password }
- post_data = urllib.parse.urlencode(post_vars).encode('ascii')
- self.opener.open(url, post_data)
-
-
- def get_backup(self):
- if self.version == 9:
- return self.get_backup_v9()
- elif self.version == 11:
- return self.get_backup_v11()
-
-
- def get_backup_v9(self):
- url = self.base_url + '/webui/backup'
- post_vars = {'action': 'requestBackup'}
- post_data = urllib.parse.urlencode(post_vars).encode('ascii')
- self.opener.open(url, post_data)
-
- url = self.base_url + 'webui/backup?action=initiateDownload'
- with self.opener.open(url) as response:
- return response.read()
-
-
- def get_backup_v11(self):
- url = self.base_url + '/webui/download?type=backup'
- post_vars = {'type': 'backup'}
- post_data = urllib.parse.urlencode(post_vars).encode('ascii')
- with self.opener.open(url, post_data) as response:
- return response.read()
-
-
-
# Create an argument parser using our docsctring as its description.
parser = ArgumentParser(description = __doc__,
formatter_class = ArgumentDefaultsHelpFormatter)
config.read(args.config_file)
for section in config.sections():
- untangle = Untangle(config[section])
+ u = Untangle(config[section])
try:
- untangle.login()
- backup = untangle.get_backup()
- filename = untangle.name + '.backup'
+ u.login()
+ backup = u.get_backup()
+ filename = u.name + '.backup'
with open(filename, 'wb') as f:
f.write(backup)
chmod(filename, 0o600)
- except urllib.error.URLError as e:
- msg = untangle.name + ': ' + str(e.reason)
- msg += ' from ' + untangle.host
+ except URLError as e:
+ msg = u.name + ': ' + str(e.reason) + ' from ' + u.host
print(msg, file=stderr)
status = EXIT_BACKUPS_FAILED
- except urllib.error.HTTPError as e:
- msg = untangle.name + ': ' + 'HTTP error ' + str(e.code)
- msg += ' from ' + untangle.host
+ except HTTPError as e:
+ msg = u.name + ': ' + 'HTTP error ' + str(e.code) + ' from ' + u.host
print(msg, file=stderr)
status = EXIT_BACKUPS_FAILED
--- /dev/null
+import configparser
+import http.cookiejar
+import ssl
+import urllib.parse
+import urllib.request
+
+class Untangle:
+
+ def __init__(self, s):
+ """
+ Initialize this Untangle object with a ConfigParser section.
+ """
+ self.name = s.name
+ self.host = s['host']
+ self.username = s.get('username', 'admin')
+ self.password = s['password']
+ self.version = int(s.get('version', '11'))
+ self.base_url = 'https://' + self.host + '/' # This never changes
+
+ # Sanity check the numerical version.
+ if self.version not in [9, 11]:
+ msg = 'Invalid version "' + str(self.version) + '" '
+ msg += 'in section "' + s.name + '"'
+ raise configparser.ParsingError(msg)
+
+ # Sanity check the boolean verify_cert parameter.
+ vc = s.get('verify_cert', 'False')
+ if vc == 'True':
+ self.verify_cert = True
+ elif vc == 'False':
+ self.verify_cert = False
+ else:
+ msg = 'Invalid value "' + vc + '" for verify_cert '
+ msg += 'in section "' + s.name + '"'
+ raise configparser.ParsingError(msg)
+
+ #
+ # Finally, create a URL opener to make HTTPS requests.
+ #
+ # First, create a cookie jar that we'll attach to our URL
+ # opener thingy.
+ cj = http.cookiejar.CookieJar()
+ cookie_proc = urllib.request.HTTPCookieProcessor(cj)
+
+ # SSL mumbo jumbo to make it ignore the certificate's hostname
+ # when verify_cert = False.
+ if self.verify_cert:
+ ssl_ctx = ssl.create_default_context()
+ else:
+ ssl_ctx = ssl._create_unverified_context()
+
+ https_handler = urllib.request.HTTPSHandler(context=ssl_ctx)
+
+ # Now Create a URL opener, and tell it to use our cookie jar
+ # and SSL context. We keep this around for future requests.
+ self.opener = urllib.request.build_opener(https_handler, cookie_proc)
+
+
+ def login(self):
+ login_path = 'auth/login?url=/setup/welcome.do&realm=Administrator'
+ url = self.base_url + login_path
+ post_vars = {'username': self.username, 'password': self.password }
+ post_data = urllib.parse.urlencode(post_vars).encode('ascii')
+ self.opener.open(url, post_data)
+
+
+ def get_backup(self):
+ if self.version == 9:
+ return self.get_backup_v9()
+ elif self.version == 11:
+ return self.get_backup_v11()
+
+
+ def get_backup_v9(self):
+ url = self.base_url + '/webui/backup'
+ post_vars = {'action': 'requestBackup'}
+ post_data = urllib.parse.urlencode(post_vars).encode('ascii')
+ self.opener.open(url, post_data)
+
+ url = self.base_url + 'webui/backup?action=initiateDownload'
+ with self.opener.open(url) as response:
+ return response.read()
+
+
+ def get_backup_v11(self):
+ url = self.base_url + '/webui/download?type=backup'
+ post_vars = {'type': 'backup'}
+ post_data = urllib.parse.urlencode(post_vars).encode('ascii')
+ with self.opener.open(url, post_data) as response:
+ return response.read()