def prepare(dhparamConfig, dhparamState, statedir, dhparamSecName): if 'openssl' != dhparamConfig['handler'].split('/')[0]: return keysize = 2048 if 'keysize' in dhparamConfig: keysize = dhparamConfig['keysize'] path = os.path.realpath(os.path.join(statedir, 'dhparams', dhparamSecName)) makeDir(os.path.dirname(path)) dhparamState.setOpStateRunning() try: rv = check_output( ('openssl', 'dhparam', '-out', str(path), str(int(keysize)))) log.info(rv) except CalledProcessError as e: log.error(e.output) time.sleep(1) raise (e) resDict = {} resDict['tmpfile'] = path if 'running' == dhparamState.opstate: dhparamState.registerResult(resDict) dhparamState.setOpStateDone() return rv
def rollover(serviceConfig, serviceState, state): serviceState.setOpStateWaiting() if not isReady(serviceConfig, state, ['dhparam', 'cert']): return serviceState.setOpStateRunning() certNames = serviceConfig['cert'] if 'auto' == serviceConfig['dirext'] or 'auto' == serviceConfig['dirint']: client = docker.DockerClient(base_url=serviceConfig['dockersock']) containers = [c for c in client.containers.list() if c.attrs['Name'][1:] == serviceConfig['container']] if len(containers) == 0: log.error("container does not exist") container = containers[0] log.info("Updating traefik container: {}".format(container.attrs['Name'])) destinations = [e.replace(' ','').split('=')[1] for e in container.attrs['Args'] if e.replace(' ','').split('=')[0] == '--providers.file.directory'] if len(destinations) == 0: log.error("traefik container misses providers.file.directory argument") destination = destinations[0] traefikProvidersFileDirectory = dch.dockerPathMap('/'+serviceConfig['container'], destination)[0] #traefikProvidersFileDirectory = mount['Source'] if 'auto' == serviceConfig['dirext'] else serviceConfig['dirext'] #'./configuration' traefikConfigFilename = os.path.join(traefikProvidersFileDirectory,'files/configuration.toml') traefikCertDir = os.path.join(traefikProvidersFileDirectory,'certs') traefikProvidersFileDirectoryMount = os.path.normpath(destination) if 'auto' == serviceConfig['dirint'] else serviceConfig['dirint'] # '/configuration' traefikConfigFilenameMount = os.path.join(traefikProvidersFileDirectoryMount,'files/configuration.toml') traefikCertDirMount = os.path.join(traefikProvidersFileDirectoryMount,'certs') log.info(" -> Volume: {}:{}".format(traefikProvidersFileDirectory, traefikProvidersFileDirectoryMount)) tcfc = '' for certName in certNames: certState = state.getSubstate('cert').getSubstate(certName).result certPath = os.path.join(traefikCertDir,certName,'cert.pem') keyPath = os.path.join(traefikCertDir,certName,'key.pem') certPathMount = os.path.join(traefikCertDirMount,certName,'cert.pem') keyPathMount = os.path.join(traefikCertDirMount,certName,'key.pem') makeDir(os.path.dirname(certPath)) copyfile(certState['fullchainfile'], certPath) log.info(' {} -> {}'.format(certState['fullchainfile'], certPath)) copyfile(certState['keyfile'], keyPath) log.info(' {} -> {}'.format(certState['keyfile'], keyPath)) tcfc += '[[tls.certificates]]\n certFile = "{}"\n keyFile = "{}"\n\n'.format(certPathMount, keyPathMount) makeDir(os.path.dirname(traefikConfigFilename)) with open(traefikConfigFilename,'w') as f: f.write(tcfc) # traefik reloads config and certs only if a random file is written in # traefik's config root directory specified by: # --providers.file.directory = <config root directory> with open(os.path.join(traefikProvidersFileDirectory,'reloadtrigger'), 'w') as f: f.write('') log.info(' -> Traefik reload') serviceState.setOpStateDone()
def createDKIM(keysize, destination): makeDir(os.path.dirname(str(destination))) try: keyTxt = str( check_output( ('rspamadm', 'dkim_keygen', '-b', str(int(keysize)), '-s', str('dkimkey'), '-k', str(destination)))) except CalledProcessError as e: log.error(e.output) raise (e) v = keyTxt.split('v=')[1].split(';')[0] k = keyTxt.split('k=')[1].split(';')[0] p = keyTxt.split('p=')[1].split('\"')[0] return {'v': v, 'k': k, 'p': p, 'keyfile': str(destination)}
def copyCert(certConfig, certState): src = os.path.dirname(certState.result['fullchainfile']) for name in certState.result['san']: dest = os.path.join(certConfig['destination'], name) log.info(' {} -> {}'.format(src, dest)) try: makeDir(str(dest)) for k in ['fullchainfile', 'chainfile', 'certfile', 'keyfile']: lnksrc = certState.result[k] lnkdst = os.path.join(os.path.dirname(lnksrc), os.readlink(lnksrc)) shutil.copy2(lnkdst, os.path.join(dest, os.path.basename(lnksrc))) except CalledProcessError as e: log.error(e.output) raise (e)
def createConf(signingConfTemplateFile, signingConfDestFile, keyFile, keySelector): f = open(os.path.expanduser(signingConfTemplateFile), 'r') templateContent = f.read() f.close() template = Template(templateContent) confDestContent = str( template.render(keyselector=keySelector, keyfile=keyFile)) makeDir(os.path.dirname(str(signingConfDestFile))) f = open(os.path.expanduser(signingConfDestFile), 'w') f.write(confDestContent) f.close() return { 'signingconftemporaryfile': signingConfDestFile, 'keyname': keySelector }
def createDKIM(keysize, destination): makeDir(os.path.dirname(str(destination))) try: keyTxt = str( check_output( ('sudo', 'rspamadm', 'dkim_keygen', '-b', str(int(keysize)), '-s', str('dkimkey'), '-k', str(destination)))) except CalledProcessError as e: log.error(e.output) raise (e) v = keyTxt.split('v=')[1].split(';')[0] k = keyTxt.split('k=')[1].split(';')[0] pL = keyTxt.split('p=')[1].split('\"') p = "".join([e for e in pL if ")" not in e and "\n" not in e]) p = p.replace("\\n", "").replace("\\t", "") return {'v': v, 'k': k, 'p': p, 'keyfile': str(destination)}
def prepare(certConfig, certState, statedir, domainList, domainAccessTable): if 'dehydrated' != certConfig['handler'].split('/')[0]: return if 0 == len(domainList): return email = certConfig['email'] keysize = 4096 if 'keysize' in certConfig: keysize = certConfig['keysize'] if 'extraflags' in certConfig: extraFlags = certConfig['extraflags'] extraFlags = [e if '-' == e[0] else '--' + e for e in extraFlags] if '--staging' in extraFlags: ca = "https://acme-staging.api.letsencrypt.org/directory" extraFlags.remove('--staging') if 'staging' in extraFlags: extraFlags.remove('staging') elif 'ca' in certConfig: ca = certConfig['ca'] else: ca = "https://acme-v02.api.letsencrypt.org/directory" makeDir(os.path.realpath(statedir)) confFilename = os.path.normpath(os.path.join(statedir, 'dehydrated.conf')) confFile = open(confFilename, 'w') confFile.write('CA={}\n'.format(str(ca))) confFile.write('CONTACT_EMAIL={}\n'.format(str(email))) confFile.write('KEYSIZE={}\n'.format(int(keysize))) confFile.write('CERTDIR={}\n'.format(os.path.join(statedir, 'certs'))) confFile.write('\n') confFile.close() here = os.path.dirname(os.path.realpath(__file__)) args = [ os.path.join(here, 'dehydrated/dehydrated'), '-f', confFilename, '--accept-terms', '-c', '-t', 'dns-01', '-k', os.path.join(here, 'hook.sh') ] log.debug(extraFlags) args.extend(extraFlags) for d in domainList: args.extend(['-d', str(d)]) log.debug(args) certState.setOpStateRunning() for i in range(10): try: rv = check_output(args, env=dict(os.environ, DOMAINACCESSTABLE=domainAccessTable)) log.info(rv) break except CalledProcessError as e: log.error(e.output) time.sleep(1) if 9 == i: raise (e) res = [] rv = rv.splitlines() for s, e in enumerate(rv): if '---- DEPLOYMENTRESULT ----' == e[:len('---- DEPLOYMENTRESULT ----' )]: break for i, e in enumerate(rv[s + 1:]): if '---- END DEPLOYMENTRESULT ----' == e[:len( '---- END DEPLOYMENTRESULT ----')]: break res.append(e) resDict = {e.split('=')[0].lower(): e.split('=')[1] for e in res} resDict['san'] = list(domainList) if 'running' == certState.opstate: certState.registerResult(resDict) certState.setOpStateDone() return rv
def prepare(certConfig, certState, statedir, domainList, domainAccessTable): if 'dehydrated' != certConfig['handler'].split('/')[0]: return if 0 == len(domainList): return email = certConfig['email'] keysize = 4096 if 'keysize' in certConfig: keysize = certConfig['keysize'] if 'extraflags' in certConfig: extraFlags = certConfig['extraflags'] extraFlags = [e if '-' == e[0] else '--' + e for e in extraFlags] if '--staging' in extraFlags: ca = "https://acme-staging-v02.api.letsencrypt.org/directory" extraFlags.remove('--staging') if 'staging' in extraFlags: extraFlags.remove('staging') elif 'ca' in certConfig: ca = certConfig['ca'] else: ca = "https://acme-v02.api.letsencrypt.org/directory" makeDir(os.path.realpath(statedir)) confFilename = os.path.normpath(os.path.join(statedir, 'dehydrated.conf')) confFile = open(confFilename, 'w') confFile.write('CA={}\n'.format(str(ca))) confFile.write('CONTACT_EMAIL={}\n'.format(str(email))) confFile.write('KEYSIZE={}\n'.format(int(keysize))) confFile.write('CERTDIR={}\n'.format(os.path.join(statedir, 'certs'))) confFile.write('\n') confFile.close() here = os.path.dirname(os.path.realpath(__file__)) args = [ os.path.join(here, 'dehydrated/dehydrated'), '-f', confFilename, '--accept-terms', '-c', '-t', 'dns-01', '-k', os.path.join(here, 'hook.sh') ] log.debug(extraFlags) args.extend(extraFlags) for d in domainList: args.extend(['-d', str(d)]) log.debug(args) certState.setOpStateRunning() i = 2 while True: try: log.info('Starting DNS-01 authentication') rv = runCmd(' '.join(args), stderr=STDOUT, env=dict(os.environ, DOMAINACCESSTABLE=domainAccessTable, STATEDIR=statedir, WAITSEC="{}".format(3**i))) break except CalledProcessError as e: if 'ERROR: Lock file' in e.output: lockFilename = e.output.split('ERROR: Lock file \'')[-1].split( '\' present, aborting')[0] log.warn('Lock file from imcomplete run found: {}'.format( lockFilename)) log.warn(' -> Removing') os.remove(lockFilename) elif 'Incorrect TXT record' in e.output: log.info( ' -> Invalid DNS-01 challenge, maybe due to DNS caching interval. Trying to wait longer!' ) i += 1 log.info( ' -> Will wait {} s to give challenge time to propagate DNS cache.' .format(3**i)) elif 'NXDOMAIN' in e.output: log.info( ' -> Missing DNS-01 challenge, maybe due to DNS caching interval. Trying to wait longer!' ) i += 1 log.info( ' -> Will wait {} s to give challenge time to propagate DNS cache.' .format(3**i)) else: raise (e) if 9 == i: raise (e) res = [] rv = rv.splitlines() for s, e in enumerate(rv): if '---- DEPLOYMENTRESULT ----' == e[:len('---- DEPLOYMENTRESULT ----' )]: break for i, e in enumerate(rv[s + 1:]): if '---- END DEPLOYMENTRESULT ----' == e[:len( '---- END DEPLOYMENTRESULT ----')]: break res.append(e) resDict = {e.split('=')[0].lower(): e.split('=')[1] for e in res} resDict['san'] = list(domainList) if 'running' == certState.opstate: certState.registerResult(resDict) certState.setOpStateDone() return rv