Ejemplo n.º 1
0
def parseNestedEntry(key,
                     value,
                     default=[],
                     keySplitPattern='.',
                     valueSplitPattern=':'):
    if keySplitPattern == '':
        keyList = [key]
    else:
        keyList = key.split(keySplitPattern)
    if valueSplitPattern == '':
        valueList = [value]
    else:
        valueList = value.split(valueSplitPattern)
    addList = list(default)
    rv = {}
    subtractMode = False
    if '+' == keyList[-1][-1]:
        keyList[-1] = keyList[-1][:-1].strip()
    elif '-' == keyList[-1][-1]:
        keyList[-1] = keyList[-1][:-1].strip()
        subtractMode = True
    else:
        rv['delList'] = list(keyList)
    addList[:len(keyList)] = list(keyList)
    for i, e in enumerate(valueList):
        try:
            addList[-i] = e
        except IndexError:
            log.warn('Too many arguments in parameter!')
    if subtractMode is True:
        rv['delListWithContent'] = addList
    else:
        rv['addList'] = addList
    return rv
Ejemplo n.º 2
0
def formatSRVentry(name, srvDict):
    if type(srvDict) is list:
        return [formatSRVentry(name, e) for e in srvDict]
    srv = srvDict
    for k in ['service', 'proto', 'prio', 'weight', 'port', 'server']:
        if k not in srv:
            log.warn('Missing member \"{}\" in SRV entry!'.format(k))
            return {}
    return {
        'name': '_{x[service]}._{x[proto]}.{name}'.format(x=srv,
                                                          name=str(name)),
        'type': 'SRV',
        'prio': srv['prio'],
        'content': '{x[weight]} {x[port]} {x[server]}'.format(x=srv)
    }
Ejemplo n.º 3
0
def interpreteConfig(cr, sh):
    domainconfigOrig = cr.getRawConfigOf('domain', True)
    domainconfig = applyDefault(
        domainconfigOrig
    )  # must be here because following section depends on default values
    for domain, content in domainconfig.items():
        for f in [
                'A', 'AAAA', 'DKIM', 'TLSA', 'MX', 'SRV', 'CAA', 'DMARC',
                'SOA', 'SPF', 'Handler', 'Cert'
        ]:
            domainconfig[domain].update(
                (globals()['interprete{}'.format(f)](content)))
        certSections = set(cr.getRawConfigOf('cert').keys())
        certEntry = set({})
        certDoesNotExist = set({})
        if 'cert' in domainconfig[domain]:
            certEntry = set(domainconfig[domain]['cert'])
            if 'auto' in certEntry:
                certEntry = certEntry - 'auto' + certSections
            certDoesNotExist = certEntry - certSections
            for missing in certDoesNotExist:
                log.warn(
                    "Section cert:{} referenced in domain:{} does not exist!".
                    format(missing, domain))
            domainconfig[domain]['cert'] = list(
                set(domainconfig[domain]['cert']) - certDoesNotExist)
        addDKIMcont = set(
            [e['content'] for e in domainconfig[domain]['dkimAggrAdd']])
        dkimSections = set(cr.getRawConfigOf('dkim').keys())
        dkimDoesNotExist = addDKIMcont - dkimSections
        for missing in dkimDoesNotExist:
            log.warn("Section dkim:{} referenced in domain:{} does not exist!".
                     format(missing, domain))
        for e in domainconfig[domain]['dkimAggrAdd']:
            if e['content'] not in dkimDoesNotExist:
                del e
        if 'requires' not in domainconfig[domain]:
            domainconfig[domain]['requires'] = {}
        domainconfig[domain]['requires'][
            'dkim'] = addDKIMcont - dkimDoesNotExist
        domainconfig[domain]['requires']['cert'] = certEntry - certDoesNotExist

    log.debug(domainconfig)
    cr.updateConfig({'domain': domainconfig})
    return domainconfig
Ejemplo n.º 4
0
 def addCAA(self, name, caaDict):
     try:
         self.addList({'name': str(name), 'type': 'CAA'}, genCAA(caaDict))
     except KeyError as e:
         log.warn('Not adding CAA record!')
Ejemplo n.º 5
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-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