Esempio n. 1
0
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
Esempio n. 2
0
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()
Esempio n. 3
0
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)}
Esempio n. 4
0
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)
Esempio n. 5
0
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
    }
Esempio n. 6
0
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)}
Esempio n. 7
0
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