ptrcnull
c1e0b04122
> Note the order of arguments (self, target) is the reverse of os.link's. fuck off
93 lines
3 KiB
Python
93 lines
3 KiB
Python
import argparse
|
|
import logging
|
|
import os.path
|
|
import shutil
|
|
import subprocess
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
from .config import read_config
|
|
|
|
logging.basicConfig(level=logging.INFO, format='[%(levelname)s] %(name)s: %(message)s')
|
|
log = logging.getLogger('nyacme')
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(
|
|
prog='nyacme',
|
|
description='fun uacme wrapper'
|
|
)
|
|
parser.add_argument('-c', '--config', default='/etc/nyacme.toml')
|
|
parser.add_argument('-o', '--output', default='/etc/ssl/uacme')
|
|
args = parser.parse_args()
|
|
|
|
config = read_config(args.config)
|
|
output_dir = Path(args.output)
|
|
|
|
acquired = False
|
|
|
|
for domain in config.certificates:
|
|
# arguments passed to uacme
|
|
uacme_domains = [domain]
|
|
if domain.startswith('*.'):
|
|
uacme_domains = [ domain[2:], domain ]
|
|
domain = domain[2:]
|
|
|
|
cert_path = output_dir / domain / 'cert.pem'
|
|
if cert_path.is_file():
|
|
cmd = [ 'openssl', 'x509', '-enddate', '-noout', '-in', cert_path ]
|
|
out = subprocess.run(cmd, stdout=subprocess.PIPE, check=True).stdout.decode('utf-8').strip()
|
|
date = datetime.strptime(out, 'notAfter=%b %d %H:%M:%S %Y %Z')
|
|
# if more than 1 month, skip
|
|
delta = date - datetime.now()
|
|
if delta.days > 30:
|
|
log.info(f'cert for {domain} expires in more than a month ({delta.days} days), skipping')
|
|
continue
|
|
|
|
log.info(f'getting cert for {domain}')
|
|
env = os.environ.copy()
|
|
env['NYACME_CONFIG'] = args.config
|
|
|
|
hook_path = shutil.which('nyacme-hook')
|
|
if not hook_path:
|
|
log.warning('setting hook path to hook launcher from git repo')
|
|
hook_path = os.path.join(os.path.dirname(__file__), '..', 'hook_launcher.py')
|
|
|
|
res = subprocess.run([
|
|
'uacme', '-v',
|
|
'--hook', hook_path,
|
|
'--confdir', args.output,
|
|
'-b', '384',
|
|
'--type', 'EC',
|
|
# '--force',
|
|
'issue'
|
|
] + uacme_domains, env=env)
|
|
|
|
if res.returncode == 0:
|
|
acquired = True
|
|
private_key = output_dir / 'private' / domain / 'key.pem'
|
|
domain_key = output_dir / domain / 'cert.pem.key'
|
|
domain_pem = output_dir / domain / 'cert.pem'
|
|
|
|
domain_key.unlink(missing_ok=True)
|
|
domain_key.hardlink_to(private_key)
|
|
# TODO: add user/group to config
|
|
shutil.chown(domain_key, 'acme', 'acme')
|
|
domain_key.chmod(0o440)
|
|
|
|
all_pem = output_dir / 'all' / f'{domain}.pem'
|
|
all_key = output_dir / 'all' / f'{domain}.pem.key'
|
|
|
|
all_pem.unlink(missing_ok=True)
|
|
all_pem.hardlink_to(domain_pem)
|
|
all_key.unlink(missing_ok=True)
|
|
all_key.hardlink_to(domain_key)
|
|
|
|
if acquired:
|
|
for cmd in config.post_acquire:
|
|
subprocess.run(cmd, shell=True, check=True)
|
|
|
|
if __name__ == '__main__':
|
|
main()
|
|
|