# Default to success, change it if anything fails.
status = EXIT_OK
+# Parse the configuration file...
config = configparser.ConfigParser()
config.read(args.config_file)
+# And loop through each section.
for section in config.sections():
+ # For each section, we create an Untangle object based on that
+ # section's configuration.
u = Untangle(config[section])
try:
+ # And then try to log in and retrieve a backup.
u.login()
backup = u.get_backup()
+
+ # If that worked, we save the backup file and make it
+ # accessible only to its owner.
filename = u.name + '.backup'
with open(filename, 'wb') as f:
f.write(backup)
chmod(filename, 0o600)
+ # If it didn't work, but in a predictable way (some host is down),
+ # then we report that error and keep going.
except URLError as e:
msg = u.name + ': ' + str(e.reason) + ' from ' + u.host
print(msg, file=stderr)
import urllib.request
class Untangle:
-
+ """
+ This class wraps one instance of Untangle. It gets initialized with
+ some configuration information, and then provides the methods to
+ retreive a backup.
+ """
def __init__(self, s):
"""
Initialize this Untangle object with a ConfigParser section.
def login(self):
+ """
+ Perform the HTTPS request to log in to the Untangle web admin
+ UI. The resulting session cookie is stored by our ``self.opener``.
+ """
login_path = 'auth/login?url=/setup/welcome.do&realm=Administrator'
url = self.base_url + login_path
post_vars = {'username': self.username, 'password': self.password }
def get_backup(self):
+ """
+ Version-agnostic get-me-a-backup method. Dispatches to the
+ actual implementation based on ``self.version``.
+ """
if self.version == 9:
return self.get_backup_v9()
elif self.version == 11:
def get_backup_v9(self):
+ """
+ Retrieve a backup from Untangle version 9. This requires two
+ requests; the first just hits the page, and the second actually
+ retrieves the backup file.
+
+ Returns the binary HTTPS response (i.e. the file).
+ """
url = self.base_url + '/webui/backup'
post_vars = {'action': 'requestBackup'}
post_data = urllib.parse.urlencode(post_vars).encode('ascii')
def get_backup_v11(self):
+ """
+ Retrieve a backup from Untangle version 11.
+
+ Returns the binary HTTPS response (i.e. the file).
+ """
url = self.base_url + '/webui/download?type=backup'
post_vars = {'type': 'backup'}
post_data = urllib.parse.urlencode(post_vars).encode('ascii')