backupscript/backup.py

175 lines
6.6 KiB
Python

from Crypto.Cipher import AES
import base64
import json
import argparse
import sys
import string
import random
import datetime
import os
windows = False
if sys.platform == "win32":
windows = True
print("")
print("####################################")
print("Program does not run on Windows!")
print("Falling back to Testing Mode!")
print("####################################")
print("")
def encrypt_val(clear_text, master):
enc_secret = AES.new(master[:32])
tag_string = (str(clear_text) +
(AES.block_size -
len(str(clear_text)) % AES.block_size) * "\0")
cipher_text = base64.b64encode(enc_secret.encrypt(tag_string))
return cipher_text
def decrypt_val(cipher_text, master):
dec_secret = AES.new(master[:32])
raw_decrypted = dec_secret.decrypt(base64.b64decode(cipher_text))
clear_val = raw_decrypted.rstrip("\0".encode())
return clear_val
parser = argparse.ArgumentParser(description="Backup Script")
parser.add_argument("-c", "--config", help="config file", default="settings.json")
parser.add_argument("-t", "--test", help="Start in testing mode", action='store_true', default=False)
args = parser.parse_args()
if args.test:
print("")
print("####################################")
print("Program is now running in testing Mode!")
print("####################################")
print("")
windows = True
try:
json_data=open(args.config).read()
except Exception as e:
sys.exit("Cant open Config File:\n{0}".format(e))
try:
data = json.loads(json_data)
except Exception as e:
sys.exit("Parser Error in JSON File {0}:\n{1}".format(args.config, e))
def save_json():
global data
global args
with open(args.config, 'w') as outfile:
json.dump(data, outfile, sort_keys=True, indent=4, separators=(',', ': '))
MASTER_KEY = ""
if not "option" in data or not "masterpassword" in data["option"] or data["option"]["masterpassword"] == "":
master_pw = ''.join(random.choice(string.ascii_uppercase + string.digits + string.ascii_lowercase) for _ in range(16))
data["option"]["masterpassword"] = base64.b64encode(master_pw.encode()).decode("utf-8")
print("MASTER PASSWORD automaticly generated. !!!DO NOT REMOVE IT FROM THE SETTINGS FILE!!!")
save_json()
MASTER_KEY = data["option"]["masterpassword"]
ignore = ["option"]
for server in data:
if server in ignore:
continue
host = server
print("")
print("")
print("")
print("--- {0} --".format(host))
for type in data[server]["types"]:
print("")
user = ""
authtype, password = ("", "")
if not "auth" in type:
sys.exit("Server {0} has no authentication".format(server))
if not "destination" in type:
sys.exit("Server {0} has no destination directory".format(server))
if not os.path.isdir(type["destination"]):
sys.exit("Destination {0} for Server {1} not found".format(type["destination"], server))
if not "user" in type["auth"] or type["auth"]["user"] == "":
sys.exit("Server {0} has no user".format(server))
else:
user = type["auth"]["user"]
if not "password" in type["auth"] or type["auth"]["password"] == "":
if not "key" in type["auth"] or type["auth"]["key"] == "":
sys.exit("Server {0} has no password or key".format(server))
else:
authtype, password = ("key", type["auth"]["key"])
else:
if type["auth"]["password"].endswith(".==="):
authtype, password = ("password", decrypt_val((str(type["auth"]["password"])[:-2]).encode(), MASTER_KEY).decode("utf-8"))
else:
authtype, password = ("password", type["auth"]["password"])
encrypted = encrypt_val(type["auth"]["password"], MASTER_KEY).decode("utf-8")
print("Encrypted {0}")
type["auth"]["password"] = "{0}.===".format(encrypted)
save_json()
print("{0} {1}@{2} using {3} destination is {4}".format(type["type"], user, host, authtype, type["destination"]))
if type["type"] == "sftp":
if not "backup" in type or type["backup"] == "":
sys.exit("Server {0} has backup paths".format(server))
rsync_base = ["rsync", "-zavx", "--ignore-errors", "--delete", "--delete-excluded"]
bpaths = []
expaths = []
bpaths.extend(type["backup"])
if "exclude" in type:
for exclude in type["exclude"]:
rsync_base.extend(["--exclude", exclude])
for bpath in bpaths:
bpath = bpath.strip()
full_path = bpath.strip()
rsync_cmd = rsync_base[:]
if authtype == "key":
rsync_cmd.append("-e")
rsync_cmd.append("'ssh -i {0} -p22'".format(password))
bpath = user + "@" + host + ":" + bpath
rsync_cmd.append(bpath)
rsync_cmd.append(type["destination"] + os.sep + full_path.replace("/", "_").replace("\\", "_"))
print("Running Rsync for {0}".format(bpath))
if not windows:
os.system(" ".join(rsync_cmd))
else:
print(" ".join(rsync_cmd))
elif type["type"] == "mysql":
if not "database" in type or type["database"] == "":
sys.exit("Server {0} has database info".format(server))
tstamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
skip = ["information_schema", "performance_schema"]
for db in type["database"]:
if db in skip:
continue
if db == "all":
db = "--all-databases"
dbbackup_name = "{0}_{1}.{2}".format(tstamp, ("all" if db == "--all-databases" else db), "sql")
dbbackup_path = type["destination"] + os.sep + dbbackup_name
dump_cmd = "mysqldump -u " + user
if host != None:
dump_cmd += " -h " + "'" + host + "'"
if authtype == "password" and password != "":
dump_cmd += " -p" + password
dump_cmd += " -e --opt -c " + db + " | gzip > " + dbbackup_path + ".gz"
print("Dump db, %s to %s." % (db, dbbackup_path))
if not windows:
os.system(dump_cmd)
else:
print(dump_cmd)