mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2024-11-22 02:17:26 +00:00
migrate the SSL certificates path for non-primary certs to a new layout using a new migration script
This commit is contained in:
parent
06ba25151f
commit
c8856f107d
@ -88,7 +88,7 @@ def add_mail_user(email, pw, env):
|
|||||||
if not os.path.exists(user_mail_dir):
|
if not os.path.exists(user_mail_dir):
|
||||||
os.makedirs(user_mail_dir)
|
os.makedirs(user_mail_dir)
|
||||||
os.chown(user_mail_dir, maildirstat.st_uid, maildirstat.st_gid)
|
os.chown(user_mail_dir, maildirstat.st_uid, maildirstat.st_gid)
|
||||||
shutil.copyfile(env["CONF_DIR"] + "/dovecot_sieve.txt", user_mail_dir + "/.dovecot.sieve")
|
shutil.copyfile(utils.CONF_DIR + "/dovecot_sieve.txt", user_mail_dir + "/.dovecot.sieve")
|
||||||
os.chown(user_mail_dir + "/.dovecot.sieve", maildirstat.st_uid, maildirstat.st_gid)
|
os.chown(user_mail_dir + "/.dovecot.sieve", maildirstat.st_uid, maildirstat.st_gid)
|
||||||
|
|
||||||
# Update DNS in case any new domains are added.
|
# Update DNS in case any new domains are added.
|
||||||
|
@ -1,16 +1,23 @@
|
|||||||
|
import os.path
|
||||||
|
|
||||||
|
CONF_DIR = os.path.join(os.path.dirname(__file__), "../conf")
|
||||||
|
|
||||||
def load_environment():
|
def load_environment():
|
||||||
# Load settings from /etc/mailinabox.conf.
|
# Load settings from /etc/mailinabox.conf.
|
||||||
import os.path
|
return load_env_vars_from_file("/etc/mailinabox.conf")
|
||||||
env = load_env_vars_from_file("/etc/mailinabox.conf")
|
|
||||||
env["CONF_DIR"] = os.path.join(os.path.dirname(__file__), "../conf")
|
|
||||||
return env
|
|
||||||
|
|
||||||
def load_env_vars_from_file(fn):
|
def load_env_vars_from_file(fn):
|
||||||
# Load settings from a KEY=VALUE file.
|
# Load settings from a KEY=VALUE file.
|
||||||
env = { }
|
import collections
|
||||||
|
env = collections.OrderedDict()
|
||||||
for line in open(fn): env.setdefault(*line.strip().split("=", 1))
|
for line in open(fn): env.setdefault(*line.strip().split("=", 1))
|
||||||
return env
|
return env
|
||||||
|
|
||||||
|
def save_environment(env):
|
||||||
|
with open("/etc/mailinabox.conf", "w") as f:
|
||||||
|
for k, v in env.items():
|
||||||
|
f.write("%s=%s\n" % (k, v))
|
||||||
|
|
||||||
def safe_domain_name(name):
|
def safe_domain_name(name):
|
||||||
# Sanitize a domain name so it is safe to use as a file name on disk.
|
# Sanitize a domain name so it is safe to use as a file name on disk.
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
@ -75,7 +75,7 @@ def get_domain_ssl_files(domain, env):
|
|||||||
# Don't allow the user to override the key for PRIMARY_HOSTNAME because
|
# Don't allow the user to override the key for PRIMARY_HOSTNAME because
|
||||||
# that's what's in the main file.
|
# that's what's in the main file.
|
||||||
ssl_key = os.path.join(env["STORAGE_ROOT"], 'ssl/ssl_private_key.pem')
|
ssl_key = os.path.join(env["STORAGE_ROOT"], 'ssl/ssl_private_key.pem')
|
||||||
alt_key = os.path.join(env["STORAGE_ROOT"], 'ssl/domains/%s_private_key.pem' % safe_domain_name(domain))
|
alt_key = os.path.join(env["STORAGE_ROOT"], 'ssl/%s/private_key.pem' % safe_domain_name(domain))
|
||||||
if domain != env['PRIMARY_HOSTNAME'] and os.path.exists(alt_key):
|
if domain != env['PRIMARY_HOSTNAME'] and os.path.exists(alt_key):
|
||||||
ssl_key = alt_key
|
ssl_key = alt_key
|
||||||
|
|
||||||
@ -85,14 +85,14 @@ def get_domain_ssl_files(domain, env):
|
|||||||
if domain == env['PRIMARY_HOSTNAME']:
|
if domain == env['PRIMARY_HOSTNAME']:
|
||||||
ssl_certificate = os.path.join(env["STORAGE_ROOT"], 'ssl/ssl_certificate.pem')
|
ssl_certificate = os.path.join(env["STORAGE_ROOT"], 'ssl/ssl_certificate.pem')
|
||||||
else:
|
else:
|
||||||
ssl_certificate = os.path.join(env["STORAGE_ROOT"], 'ssl/domains/%s_certifiate.pem' % safe_domain_name(domain))
|
ssl_certificate = os.path.join(env["STORAGE_ROOT"], 'ssl/%s/ssl_certificate.pem' % safe_domain_name(domain))
|
||||||
|
|
||||||
# Where would the CSR go? As with the SSL cert itself, the CSR must be
|
# Where would the CSR go? As with the SSL cert itself, the CSR must be
|
||||||
# different for each domain name.
|
# different for each domain name.
|
||||||
if domain == env['PRIMARY_HOSTNAME']:
|
if domain == env['PRIMARY_HOSTNAME']:
|
||||||
csr_path = os.path.join(env["STORAGE_ROOT"], 'ssl/ssl_cert_sign_req.csr')
|
csr_path = os.path.join(env["STORAGE_ROOT"], 'ssl/ssl_cert_sign_req.csr')
|
||||||
else:
|
else:
|
||||||
csr_path = os.path.join(env["STORAGE_ROOT"], 'ssl/domains/%s_cert_sign_req.csr' % safe_domain_name(domain))
|
csr_path = os.path.join(env["STORAGE_ROOT"], 'ssl/%s/certificate_signing_request.csr' % safe_domain_name(domain))
|
||||||
|
|
||||||
return ssl_key, ssl_certificate, csr_path
|
return ssl_key, ssl_certificate, csr_path
|
||||||
|
|
||||||
|
77
setup/migrate.py
Executable file
77
setup/migrate.py
Executable file
@ -0,0 +1,77 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
# Migrates any file structures, database schemas, etc. between versions of Mail-in-a-Box.
|
||||||
|
|
||||||
|
# We have to be careful here that any dependencies are already installed in the previous
|
||||||
|
# version since this script runs before all other aspects of the setup script.
|
||||||
|
|
||||||
|
import sys, os, os.path, glob, re, shutil
|
||||||
|
|
||||||
|
sys.path.insert(0, 'management')
|
||||||
|
from utils import load_environment, save_environment, safe_domain_name
|
||||||
|
|
||||||
|
def migration_1(env):
|
||||||
|
# Re-arrange where we store SSL certificates. There was a typo also.
|
||||||
|
|
||||||
|
def move_file(fn, domain_name_escaped, filename):
|
||||||
|
# Moves an SSL-related file into the right place.
|
||||||
|
fn1 = os.path.join( env["STORAGE_ROOT"], 'ssl', domain_name_escaped, file_type)
|
||||||
|
os.makedirs(os.path.dirname(fn1), exist_ok=True)
|
||||||
|
shutil.move(fn, fn1)
|
||||||
|
|
||||||
|
# Migrate the 'domains' directory.
|
||||||
|
for sslfn in glob.glob(os.path.join( env["STORAGE_ROOT"], 'ssl/domains/*' )):
|
||||||
|
fn = os.path.basename(sslfn)
|
||||||
|
m = re.match("(.*)_(certifiate.pem|cert_sign_req.csr|private_key.pem)$", fn)
|
||||||
|
if m:
|
||||||
|
# get the new name for the file
|
||||||
|
domain_name, file_type = m.groups()
|
||||||
|
if file_type == "certifiate.pem": file_type = "ssl_certificate.pem" # typo
|
||||||
|
if file_type == "cert_sign_req.csr": file_type = "certificate_signing_request.csr" # nicer
|
||||||
|
move_file(sslfn, domain_name, file_type)
|
||||||
|
|
||||||
|
# Move the old domains directory if it is now empty.
|
||||||
|
try:
|
||||||
|
os.rmdir(os.path.join( env["STORAGE_ROOT"], 'ssl/domains'))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if not os.access("/etc/mailinabox.conf", os.W_OK, effective_ids=True):
|
||||||
|
print("This script must be run as root.", file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
env = load_environment()
|
||||||
|
|
||||||
|
ourver = int(env.get("MIGRATIONID", "0"))
|
||||||
|
|
||||||
|
while True:
|
||||||
|
next_ver = (ourver + 1)
|
||||||
|
migration_func = globals().get("migration_%d" % next_ver)
|
||||||
|
|
||||||
|
if not migration_func:
|
||||||
|
# No more migrations to run.
|
||||||
|
break
|
||||||
|
|
||||||
|
print("Running migration to Mail-in-a-Box #%d..." % next_ver)
|
||||||
|
|
||||||
|
try:
|
||||||
|
migration_func(env)
|
||||||
|
except Exception as e:
|
||||||
|
print()
|
||||||
|
print("Error running the migration script:")
|
||||||
|
print()
|
||||||
|
print(e)
|
||||||
|
print()
|
||||||
|
print("Your system may be in an inconsistent state now. We're terribly sorry. A re-install from a backup might be the best way to continue.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
ourver = next_ver
|
||||||
|
|
||||||
|
# Write out our current version now. Do this sooner rather than later
|
||||||
|
# in case of any problems.
|
||||||
|
env["MIGRATIONID"] = ourver
|
||||||
|
save_environment(env)
|
||||||
|
|
||||||
|
# iterate and try next version...
|
||||||
|
|
@ -28,6 +28,11 @@ fi
|
|||||||
|
|
||||||
# Recall the last settings used if we're running this a second time.
|
# Recall the last settings used if we're running this a second time.
|
||||||
if [ -f /etc/mailinabox.conf ]; then
|
if [ -f /etc/mailinabox.conf ]; then
|
||||||
|
# Run any system migrations before proceeding. Since this is a second run,
|
||||||
|
# we assume we have Python already installed.
|
||||||
|
setup/migrate.py
|
||||||
|
|
||||||
|
# Okay now load the old .conf file to get existing configuration options.
|
||||||
cat /etc/mailinabox.conf | sed s/^/DEFAULT_/ > /tmp/mailinabox.prev.conf
|
cat /etc/mailinabox.conf | sed s/^/DEFAULT_/ > /tmp/mailinabox.prev.conf
|
||||||
source /tmp/mailinabox.prev.conf
|
source /tmp/mailinabox.prev.conf
|
||||||
fi
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user