+
+def generate_key(name):
+ print("Generating new private key '{}'".format(name))
+ with subprocess.Popen(["openssl", "genrsa", str(int(config['DEFAULT']['key-length']))], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as f:
+ (stdout, stderr) = f.communicate()
+ if f.returncode:
+ sys.stderr.write(stderr)
+ raise Exception("Error while generating private key")
+ # now we have a key, save it
+ make_backup(keyfile(name))
+ with open(keyfile(name), 'wb') as f:
+ f.write(stdout)
+
+def check_staging():
+ '''Returns 0 if nothing was done, 1 if a stage key is present but has to be kept, 2 is a stage key was unstaged.'''
+ live = config['files']['live']
+ staging = config['files'].get('staging')
+ if staging is None or not os.path.exists(keyfile(staging)):
+ return 0
+
+ staging_time = datetime.timedelta(hours = int(config['timing']['staging-hours']))
+ key_age = datetime.datetime.now() - key_mtime(staging)
+ if key_age < staging_time:
+ return 1
+ print("Unstaging '{}' to '{}'".format(staging, live))
+ # unstage the key!
+ make_backup(keyfile(live))
+ os.rename(src = keyfile(staging), dst = keyfile(live))
+ make_backup(certfile(live))
+ os.rename(src = certfile(staging), dst = certfile(live))
+ try:
+ os.rename(src = certfile(staging, 'dh'), dst = certfile(live, 'dh'))
+ except FileNotFoundError:
+ pass
+ return 2
+
+def auto_renewal():
+ '''Returns 0 if nothing was done, 1 if only certs were changed, 2 if certs and keys were changed.'''
+ live = config['files']['live']
+ staging = config['files'].get('staging')
+
+ max_key_age = datetime.timedelta(days = int(config['timing']['max-key-age-days']))
+ renew_cert_time = datetime.timedelta(days = int(config['timing']['renew-cert-before-expiry-days']))
+
+ # determine what to do
+ now = datetime.datetime.now()
+ key_age = now - key_mtime(live)
+ cert_validity = cert_expiry(live) - now
+ need_new_key = key_age >= max_key_age
+ need_new_cert = cert_validity <= renew_cert_time
+ if need_new_cert and key_age + renew_cert_time >= max_key_age:
+ # We are about to request a new certificate, and within <renew_cert_time>, we need a new key: Get the new key now
+ need_new_key = True
+
+ # Do it
+ if need_new_key:
+ new_key_name = (live if staging is None else staging)
+ generate_key(new_key_name)
+ request_cert(new_key_name)
+ return 2
+ elif need_new_cert:
+ request_cert(live)
+ return 1
+ else:
+ return 0