From 3b4b57c081bc768cc5856d90b6b229e219670679 Mon Sep 17 00:00:00 2001 From: Joshua Tauberer Date: Sun, 9 Aug 2015 18:25:26 +0000 Subject: [PATCH] switching between backup options in the admin wasn't working at all * going from s3 to file target wasn't working * use 'local' in the config instead of a file: url, for the local target, so it is not path-specific * break out the S3 fields since users can't be expected to know how to form a URL * use boto to generate a list of S3 hosts * use boto to validate that the user input for s3 is valid * fix lots of html errors in the backup admin --- management/backup.py | 50 +++++++++++++++++- management/daemon.py | 6 +++ management/templates/system-backup.html | 70 ++++++++++++++++--------- 3 files changed, 101 insertions(+), 25 deletions(-) diff --git a/management/backup.py b/management/backup.py index 8f51127d..c85d04c2 100755 --- a/management/backup.py +++ b/management/backup.py @@ -297,6 +297,42 @@ def run_duplicity_verification(): env["STORAGE_ROOT"], ], get_env(env)) +def validate_target(config): + import urllib.parse + try: + p = urllib.parse.urlparse(config["target"]) + except ValueError: + return "invalid target" + + if p.scheme == "s3": + import boto.s3 + from boto.exception import BotoServerError + + # match to a Region + for region in boto.s3.regions(): + if region.endpoint == p.hostname: + break + else: + raise ValueError("Invalid S3 region/host.") + + bucket = p.path[1:].split('/')[0] + path = '/'.join(p.path[1:].split('/')[1:]) + '/' + if bucket == "": + raise ValueError("Enter an S3 bucket name.") + + # connect to the region & bucket + try: + conn = region.connect(aws_access_key_id=config["target_user"], aws_secret_access_key=config["target_pass"]) + bucket = conn.get_bucket(bucket) + except BotoServerError as e: + if e.status == 403: + raise ValueError("Invalid S3 access key or secret access key.") + elif e.status == 404: + raise ValueError("Invalid S3 bucket name.") + elif e.status == 301: + raise ValueError("Incorrect region for this bucket.") + raise ValueError(e.reason) + def backup_set_custom(env, target, target_user, target_pass, min_age): config = get_backup_config(env, for_save=True) @@ -309,6 +345,15 @@ def backup_set_custom(env, target, target_user, target_pass, min_age): config["target_user"] = target_user config["target_pass"] = target_pass config["min_age_in_days"] = min_age + + # Validate. + try: + if config["target"] != "local": + # "local" isn't supported by the following function, which expects a full url in the target key, + # which is what is there except when loading the config prior to saving + validate_target(config) + except ValueError as e: + return str(e) write_backup_config(env, config) @@ -320,7 +365,7 @@ def get_backup_config(env, for_save=False): # Defaults. config = { "min_age_in_days": 3, - "target": "file://" + os.path.join(backup_root, 'encrypted'), + "target": "local", } # Merge in anything written to custom.yaml. @@ -338,6 +383,9 @@ def get_backup_config(env, for_save=False): # helper fields for the admin config["file_target_directory"] = os.path.join(backup_root, 'encrypted') config["enc_pw_file"] = os.path.join(backup_root, 'secret_key.txt') + if config["target"] == "local": + # Expand to the full URL. + config["target"] = "file://" + config["file_target_directory"] return config diff --git a/management/daemon.py b/management/daemon.py index 355e0662..932a967f 100755 --- a/management/daemon.py +++ b/management/daemon.py @@ -90,13 +90,19 @@ def json_response(data): def index(): # Render the control panel. This route does not require user authentication # so it must be safe! + no_users_exist = (len(get_mail_users(env)) == 0) no_admins_exist = (len(get_admins(env)) == 0) + + import boto.s3 + backup_s3_hosts = [(r.name, r.endpoint) for r in boto.s3.regions()] + return render_template('index.html', hostname=env['PRIMARY_HOSTNAME'], storage_root=env['STORAGE_ROOT'], no_users_exist=no_users_exist, no_admins_exist=no_admins_exist, + backup_s3_hosts=backup_s3_hosts, ) @app.route('/me') diff --git a/management/templates/system-backup.html b/management/templates/system-backup.html index ed9f26f3..03eeb2c2 100644 --- a/management/templates/system-backup.html +++ b/management/templates/system-backup.html @@ -11,15 +11,15 @@
- +
- +
-
+
Backups are stored on this machine’s own hard disk. You are responsible for periodically using SFTP (FTP over SSH) to copy the backup files from to a safe location. These files are encrypted, so they are safe to store anywhere.
@@ -30,27 +30,37 @@
- +
- +
- +
- +
- +
- +
- +
- + +
+
+
+ +
+
@@ -79,8 +89,8 @@