예제 #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
예제 #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()
예제 #3
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:
            rv = check_output(('cp', '-rfLT', str(src), str(dest)))
        except CalledProcessError as e:
            log.error(e.output)
            raise (e)
예제 #4
0
def copyDKIM(dkimConfig, dkimState):
    src = dkimState.result['keyfile']
    dest = os.path.join(dkimConfig['keylocation'], dkimConfig['keyname'])
    log.info('  {} -> {}'.format(src, dest))
    try:
        rv = check_output(('cp', '-rfLT', str(src), str(dest)))
        rv = check_output(('chown', '_rspamd:_rspamd', str(dest)))
    except CalledProcessError as e:
        log.error(e.output)
        raise (e)
예제 #5
0
def copyConf(dkimConfig, dkimState):
    src = dkimState.result['signingconftemporaryfile']
    dest = dkimConfig['signingconfdestinationfile']
    log.info('  {} -> {}'.format(src, dest))
    try:
        rv = check_output(('cp', '-rfLT', str(src), str(dest)))
        rv = check_output(('chown', '_rspamd:_rspamd', str(dest)))
    except CalledProcessError as e:
        log.error(e.output)
        raise (e)
예제 #6
0
def rollover(serviceConfig, serviceState, state):
    serviceState.setOpStateWaiting()
    if not isReady(serviceConfig, state, 'dkim'):
        return
    serviceState.setOpStateRunning()
    log.info('  -> Rspamd reload')
    try:
        rv = check_output(('sudo', 'systemctl', 'reload', 'rspamd')) # this is now working with newer version of rspamd
    except CalledProcessError as e:
        log.error(e.output)
        raise(e)
    serviceState.setOpStateDone()
예제 #7
0
def rollover(serviceConfig, serviceState, state):
    serviceState.setOpStateWaiting()
    if not isReady(serviceConfig, state, ['cert', 'dhparam']):
        return
    serviceState.setOpStateRunning()
    log.info('  -> Postfix reload')
    try:
        rv = check_output(('systemctl', 'start', 'postfix'))
        rv = check_output(('systemctl', 'reload', 'postfix'))
    except CalledProcessError as e:
        log.error(e.output)
        raise (e)
    serviceState.setOpStateDone()
예제 #8
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)}
예제 #9
0
def copyDH(dhparamConfig, dhparamState):
    if 'tmpfile' not in dhparamState.result:
        return 
    src = os.path.realpath(dhparamState.result['tmpfile'])
    dest = os.path.realpath(dhparamConfig['filename'])
    try:
        os.makedirs(os.path.dirname(dest))
    except:
        pass
    log.info('  {} -> {}'.format(src, dest))
    try:
        rv = check_output(('cp', '-rfLT', str(src), str(dest)))
    except CalledProcessError as e:
        log.error(e.output)
        raise(e)
예제 #10
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)}
예제 #11
0
def delOldCert(certConfig, certState):
    preserve = ['fullchainfile', 'certfile', 'keyfile', 'chainfile']
    preserveFiles = set([certState.result[e] for e in preserve])
    preserveFiles.update(set([os.path.realpath(e) for e in preserveFiles]))
    dirs = set([os.path.dirname(e) for e in preserveFiles])
    dirs = [e for e in dirs if os.path.isdir(e)]
    allFiles = set([os.path.join(d, f) for d in dirs for f in os.listdir(d)])
    allFiles = set([e for e in allFiles if os.path.isfile(e)])
    removeFiles = allFiles - preserveFiles
    for e in removeFiles:
        log.info('  rm {}'.format(e))
        try:
            rv = check_output(('rm', str(e)))
        except CalledProcessError as e:
            log.error(e.output)
            raise (e)
예제 #12
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)
예제 #13
0
def rollover(serviceConfig, serviceState, state):
    serviceState.setOpStateWaiting()
    if not isReady(serviceConfig, state, 'dkim'):
        return
    serviceState.setOpStateRunning()
    log.info('  -> Rspamd reload')
    try:
        rv = check_output(('systemctl', 'start', 'rspamd'))
        #rv = check_output(('systemctl', 'reload', 'rspamd')) # this is not working with rspamd
        #rv = check_output(('rspamadm', 'control', 'reload'))
        # only restart works - bug in rspamd
        rv = check_output(('systemctl', 'restart', 'rspamd'))
    except CalledProcessError as e:
        log.error(e.output)
        raise (e)
    serviceState.setOpStateDone()
예제 #14
0
def setTLSA(domainConfig,
            domainState,
            domainSecName,
            dnsup,
            state,
            add=True,
            delete=True):
    rrState = domainState.getSubstate('settlsa')
    if rrState.isDone():
        return True
    if 'cert' in domainConfig and ('tlsaAggrAdd' in domainConfig
                                   or 'tlsaAggrDel' in domainConfig):
        rrState.setOpStateWaiting()
        tlsaPres = []
        for certSec in domainConfig['cert']:
            if not isCertReady(state, certSec):
                return False
            rrState.setOpStateRunning()
            cert = getFullchain(state, certSec)
            if cert is None:
                log.info(
                    'not deploying TLSA record for {} (no certificate)'.format(
                        domainSecName))
            else:
                log.info(
                    'deploying TLSA record for {} (certificate found)'.format(
                        domainSecName))
                sanList = getCertSAN(cert)
                log.info('  -> found certificate: {} for: {}'.format(
                    cert, b', '.join(sanList)))
                if domainSecName.encode() not in sanList:
                    log.error('{} not in certificate {}'.format(
                        domainSecName, cert))
                tlsaAdd = [
                    dict(e, filename=cert) for e in domainConfig['tlsaAggrAdd']
                    if 'op' in e if 'auto' == e['op']
                ]
                tlsaPres.extend(tlsaAdd)
                if add is True:
                    dnsup.addTLSA(domainSecName, tlsaAdd)
        log.info('removing old TLSA record for {}'.format(domainSecName))
        if delete is True:
            tlsaDel = domainConfig['tlsaAggrDel']
            dnsup.delTLSA(domainSecName, tlsaDel, tlsaPres)
    rrState.setOpStateDone()
    return True
예제 #15
0
def list2rrType(rrType, entry, hasContent=True):
    if 'mx' == rrType:
        return list2MX(entry, hasContent)
    elif 'srv' == rrType:
        return list2SRV(entry, hasContent)
    elif 'ip4' == rrType:
        return list2ip(entry, hasContent)
    elif 'ip6' == rrType:
        return list2ip(entry, hasContent)
    elif 'dkim' == rrType:
        return list2dkim(entry, hasContent)
    elif 'tlsa' == rrType:
        return list2tlsa(entry, hasContent)
    elif 'caa' == rrType:
        return list2CAA(entry, hasContent)
    elif 'spf' == rrType:
        return list2SPF(entry, hasContent)
    log.error('rrType not supported')
    assert TypeError('rrType not supported')
예제 #16
0
    def callAPI(self, method, params):
        for i in range(10):
            if i > 0:
                log.info('INWX api wait {} s before retry'.format(i**3))
                time.sleep(i**3)
            rv = self.__conn.call_api(api_method=method, method_params=params)
            if 2400 == rv['code']:
                log.info('INWX api error code: {}'.format(rv['code']))
                continue
            if 2500 == rv['code']:
                log.info('INWX api error code: {}'.format(rv['code']))
                continue
            if 2502 == rv['code']:
                log.info('INWX api error code: {}'.format(rv['code']))
                continue
            return rv

        log.error('INWX api retry limit exceeded!')
        log.error('INWX api error code was: {}'.format(rv['code']))
        return rv
예제 #17
0
def serviceAction(serviceName, action):
    try:
        return check_output(('sudo', 'systemctl', action, serviceName))
    except Exception as e:
        log.error(e)
    try:
        return check_output(('systemctl', action, serviceName))
    except Exception as e:
        log.error(e)
    if 'reload' == action:
        try:
            return check_output(('killall', serviceName, '-s', 'SIGHUP'))
        except Exception as e:
            log.error(e)
    log.error("reload failed")
    raise("reload failed")
예제 #18
0
def copyDKIM(dkimConfig, dkimState):
    src = dkimState.result['keyfile']
    dest = os.path.join(dkimConfig['keylocation'], dkimConfig['keyname'])
    log.info('  {} -> {}'.format(src, dest))
    try:
        rv = check_output(('mkdir', '-p', os.path.dirname(str(dest))))
    except CalledProcessError as e:
        log.error("Failed to create directory path for {}".format(str(dest)))
    try:
        rv = check_output(('cp', '-rfLT', str(src), str(dest)))
    except CalledProcessError as e:
        log.error("Failed to copy file")
        log.error("  {} -> {}".format(str(src), str(dest)))
    try:
        rv = check_output(('chown', '_rspamd:_rspamd', str(dest)))
    except CalledProcessError as e:
        log.error("Failed to change ownership of {}".format(str(dest)))
예제 #19
0
def copyConf(dkimConfig, dkimState):
    src = dkimState.result['signingconftemporaryfile']
    dest = dkimConfig['signingconfdestinationfile']
    log.info('  {} -> {}'.format(src, dest))
    try:
        rv = check_output(('sudo', 'mkdir', '-p', os.path.dirname(str(dest))))
    except CalledProcessError as e:
        log.error("Failed to create directory path for {}".format(str(dest)))
    try:
        rv = check_output(('sudo', 'cp', '-rfLT', str(src), str(dest)))
    except CalledProcessError as e:
        log.error("Failed to copy file")
        log.error("  {} -> {}".format(str(src), str(dest)))
    try:
        rv = check_output(('sudo', 'chown', '_rspamd:_rspamd', str(dest)))
    except CalledProcessError as e:
        log.error("Failed to change ownership of {}".format(str(dest)))
예제 #20
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