Esempio n. 1
0
def processConfig(configReader,
                  module,
                  postOp=None,
                  preOp=readHandlerDefault,
                  defaultConfig={}):
    configOrig = configReader.getRawConfigOf(str(module))
    # apply general config defaults and the default section
    config = applyDefault(
        configOrig, defaultConfig
    )  # must be here because following section depends on default values
    log.debug(config)
    for secName, content in config.items():
        if preOp is not None:
            preOp({
                'content': dict(content),
                'module': str(module),
                'config': config,
                'secname': str(secName)
            })
        config[secName].update(configOrig[secName])
        if postOp is not None:
            postOp({
                'content': dict(content),
                'module': str(module),
                'config': config,
                'secname': str(secName)
            })
    log.debug(config)
    configReader.updateConfig({str(module): config})
    return config
Esempio n. 2
0
def prepare(config, state):
    subState = state.getSubstate('cert')
    for certSecName, certConfig in config['cert'].items():
        if 'DEFAULT' == certSecName:
            continue
        if 'handler' not in certConfig:
            continue
        certState = subState.getSubstate(certSecName)
        if certState.isDone():
            continue
        domains = [
            k for k, v in config['domain'].items()
            if 'cert' in v and certSecName in v['cert']
        ]
        log.info('Create certificate for section \"{}\"'.format(certSecName))
        log.info('  -> {}'.format(', '.join(domains)))
        log.debug(certConfig)
        domainAccessTable = createDomainAccessTable(config, domains)
        handlerNames = certConfig['handler'].split('/')
        handler = __import__('cryptdomainmgr.modules.cert.handler' +
                             str(handlerNames[0]),
                             fromlist=('cryptdomainmgr', 'modules', 'cert'))
        statedir = getStateDir(config, 'cert', certSecName)
        handler.prepare(certConfig, certState, statedir, domains,
                        domainAccessTable)
Esempio n. 3
0
def readHandlerDefault(args):
    if not 'keybasename' in args['content']:
        args['content']['keybasename'] = str(args['secname'])
    if 'handler' in args['content']:
        log.debug('handler in content')
        handlerNames = args['content']['handler'].split('/')
        handler = __import__('cryptdomainmgr.modules.{}.handler{}'.format(str(args['module']), handlerNames[0]), fromlist=('cryptdomainmgr', 'modules', str(args['module'])))
        args['config'][args['secname']].update(handler.defaultConfig)
Esempio n. 4
0
def parseCAA(caaRR):
    caaStr = caaRR['content']
    log.debug(caaStr)
    caa = {}
    caa['flag'], caa['tag'], caa['url'] = caaStr.split(' ')
    caa['url'] = caa['url'][1:-1]
    caa = {str(k): str(v) for k, v in caa.items()}
    log.debug(caa)
    return caa
Esempio n. 5
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']:
            domainconfig[domain].update((globals()['interprete{}'.format(f)](content)))
    log.debug(domainconfig)
    cr.updateConfig({'domain': domainconfig})
    return domainconfig
Esempio n. 6
0
def encDNSemail(x):
    xSpl = x.split('@')
    log.debug(xSpl)
    if 1 == len(xSpl):
        return x
    elif 1 < len(xSpl):
        return xSpl[0].replace('.', '\\.') + '.' + xSpl[1] + '.'
    else:
        raise (TypeError('No valid email address'))
Esempio n. 7
0
def getIPv6(aaaa='auto'):
    if 'auto' != aaaa:
        return aaaa
    try:
        ipv6Str = curlGet('ipv6.icanhazip.com')
        log.debug(ipv6Str)
    except Exception as e:
        return None
    return sanIPv6(ipv6Str)
Esempio n. 8
0
 def qry(self, filterDict):
     if type(filterDict) is list:
         self.__rv = [self.qry(e) for e in filterDict]
         return self.__rv
     log.debug(filterDict)
     createKeyDomainIfNotExists(filterDict)
     self.__rv = self.handler.info(filterDict)
     log.debug(self.__rv)
     return self.__rv
Esempio n. 9
0
def makeIP6(aaaa):
    if aaaa is None:
        aaaa = 'auto'
    if type(aaaa) is not list:
        aaaa = [aaaa]
    log.debug(aaaa)
    aaaa = [getIPv6(e) for e in aaaa]
    aaaa = [e for e in aaaa if e is not None]
    log.debug(aaaa)
    return aaaa
Esempio n. 10
0
 def interprete(self, sh):
     self.sections = getSections(self.cp)
     log.info('Interpreting config sections')
     for secName in self.sections:
         log.info('  - {}'.format(secName))
         handler = __import__('cryptdomainmgr.modules.' + str(secName) +
                              '.confighandler',
                              fromlist=('cryptdomainmgr', 'modules'))
         handler.interpreteConfig(self, sh)
     log.debug(self.config)
Esempio n. 11
0
def resolveAuto(config, serviceConfig, depends):
    if 'auto' in serviceConfig:
        log.debug("This will never be called!")
        if depends not in config:
            return []
        dependKeys = config[depends]
        serviceConfig.extend(dependKeys)
        serviceConfig = [
            e for e in serviceConfig if e != 'auto' if e != 'DEFAULT'
        ]
    return serviceConfig
Esempio n. 12
0
 def deleteRv(self, deleteRv, preserveRv=[]):
     deleteIds = set(flatten(extractIds(deleteRv)))
     preserveIds = set(flatten(extractIds(preserveRv)))
     deleteOnlyIds = deleteIds - preserveIds
     log.debug('deleteRecords {}'.format(deleteOnlyIds))
     for e in deleteOnlyIds:
         rr = self.qry({'recordId': e})
         infoRecord(rr[0], 'delete')
     self.__rv = [self.delById(e) for e in deleteOnlyIds]
     log.debug(self.__rv)
     return self.__rv
Esempio n. 13
0
def cleanup(config, state):
    subState = state.getSubstate('service')
    for serviceSecName, serviceConfig in config['service'].items():
        if 'DEFAULT' == serviceSecName:
            continue
        serviceState = subState.getSubstate(serviceSecName)
        if serviceState.isDone():
            continue
        log.info('Cleanup service for section \"{}\"'.format(serviceSecName))
        log.debug(serviceConfig)
        handler = __import__('cryptdomainmgr.modules.service.handler'+str(serviceSecName), fromlist=('cryptdomainmgr', 'modules','service'))
        handler.cleanup(serviceConfig, serviceState, state) 
Esempio n. 14
0
 def addTLSAfromCert(self,
                     name,
                     certFilenames,
                     tlsaTypes=[[3, 0, 1], [3, 0, 2], [3, 1, 1], [3, 1, 2],
                                [2, 0, 1], [2, 0, 2], [2, 1, 1], [2, 1,
                                                                  2]]):
     if 'auto' == str(tlsaTypes):
         tlsaTypes = [[3, 0, 1], [3, 0, 2], [3, 1, 1], [3, 1, 2], [2, 0, 1],
                      [2, 0, 2], [2, 1, 1], [2, 1, 2]]
     log.debug('name = %s' % name)
     log.debug('certFilenames = %s' % certFilenames)
     self.addTLSA(name, tlsaRecordsFromCertFile(certFilenames, tlsaTypes))
Esempio n. 15
0
 def delete(self, deleteDict, preserveDict=[], wild=False):
     if wild is True:
         deleteRv = self.qryWild(deleteDict)
         preserveRv = self.qryWild(preserveDict)
     elif callable(wild):
         deleteRv = self.qryWild(deleteDict, wild)
         preserveRv = self.qryWild(preserveDict, wild)
     else:
         deleteRv = self.qry(deleteDict)
         preserveRv = self.qry(preserveDict)
     log.debug(deleteRv)
     return self.deleteRv(deleteRv, preserveRv)
Esempio n. 16
0
 def setDMARC(self, name, dmarcDict):
     log.debug(dmarcDict)
     if {} == dmarcDict:
         self.delDMARC(name)
         return
     dmarc = {'v': 'DMARC1', 'p': 'none'}
     dmarc.update(dmarcDict)
     dmarc = {k: v for k, v in dmarc.items() if '' != v}
     dmarcStr = formatDMARC(dmarc)
     self.update({
         'name': '_dmarc.' + str(name),
         'type': 'TXT'
     }, {'content': dmarcStr})
Esempio n. 17
0
 def update(self, baseRecord, updateDict):
     matchRv = self.qry(baseRecord)
     matchIds = set(flatten(extractIds(matchRv)))
     if len(matchRv) > 0:
         baseRecord = matchRv[0]
     baseRecord.update(updateDict)
     if len(matchIds) > 0:
         log.debug('updateRecord {}'.format(baseRecord))
         infoRecord(baseRecord, 'update')
         self.__rv = self.handler.update(baseRecord)
         log.debug(self.__rv)
     else:
         self.__rv = self.add(baseRecord)
     return self.__rv
Esempio n. 18
0
def prepare(config, state):
    subState = state.getSubstate('domain')
    for domainSecName, domainConfig in config['domain'].items():
        if 'DEFAULT' == domainSecName:
            continue
        if 'handler' not in domainConfig:
            continue
        domainState = subState.getSubstate(domainSecName)
        if domainState.isDone():
            continue
        log.info('Create resource records for section \"{}\"'.format(domainSecName))
        log.debug(domainConfig)
        handlerNames = domainConfig['handler'].split('/')
        handler = __import__('cryptdomainmgr.modules.domain.handler'+str(handlerNames[0]), fromlist=('cryptdomainmgr', 'modules','domain'))
        handler.prepare(domainConfig, domainState, domainSecName, state) 
Esempio n. 19
0
def rollover(config, state):
    subState = state.getSubstate('service')
    for serviceSecName, serviceConfig in config['service'].items():
        if 'DEFAULT' == serviceSecName:
            continue
        if 'handler' not in serviceConfig:
            continue
        serviceState = subState.getSubstate(serviceSecName)
        if serviceState.isDone():
            continue
        log.info('Rollover service for section \"{}\"'.format(serviceSecName))
        log.debug(serviceConfig)
        handlerNames = serviceConfig['handler'].split('/')
        handler = __import__('cryptdomainmgr.modules.service.handler'+str(handlerNames[0]), fromlist=('cryptdomainmgr', 'modules','service'))
        handler.rollover(serviceConfig, serviceState, state)
Esempio n. 20
0
def prepare(config, state):
    subState = state.getSubstate('dhparam')
    for dhparamSecName, dhparamConfig in config['dhparam'].items():
        if 'DEFAULT' == dhparamSecName:
            continue
        if 'handler' not in dhparamConfig:
            continue
        dhparamState = subState.getSubstate(dhparamSecName)
        if dhparamState.isDone():
            continue
        log.info('Create dhparams for section \"{}\"'.format(dhparamSecName))
        log.debug(dhparamConfig)
        handlerNames = dhparamConfig['handler'].split('/')
        handler = __import__('cryptdomainmgr.modules.dhparam.handler'+str(handlerNames[0]), fromlist=('cryptdomainmgr', 'modules','dhparam'))
        statedir = getStateDir(config, 'dhparam', dhparamSecName)
        handler.prepare(dhparamConfig, dhparamState, statedir, dhparamSecName) 
Esempio n. 21
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
Esempio n. 22
0
 def login(self, domain):
     if 'user' in self.__loggedInCredentials and 'pass' in self.__loggedInCredentials:
         if self.getUser(domain) == self.__loggedInCredentials[
                 'user'] and self.getPasswd(
                     domain) == self.__loggedInCredentials['pass']:
             return
     self.connect()
     loggedInCredentials = {
         'lang': 'en',
         'user': self.getUser(domain),
         'pass': self.getPasswd(domain)
     }
     log.debug(loggedInCredentials)
     self.__rv = self.__conn.login(loggedInCredentials['user'],
                                   loggedInCredentials['pass'])
     log.debug(self.__rv)
     if 1000 != self.__rv['code']:
         return
     self.__loggedInCredentials = dict(loggedInCredentials)
     self.__openedDomain = str(domain)
     self.__isLoggedIn = True
Esempio n. 23
0
def parseTLSAentry(record):
    key = record['name']
    keyList = key.split('.')
    log.debug(keyList)
    val = record['content']
    valList = val.split(' ')
    tlsa = {
        'name': '.'.join(keyList[2:]),
        'port': keyList[0],
        'proto': keyList[1],
        'usage': valList[0],
        'selector': valList[1],
        'matchingtype': valList[2],
        'tlsa': valList[3]
    }
    #tlsa = {'port': keyList[0], 'proto': keyList[1], 'usage': valList[0], 'selector': valList[1], 'matchingtype': valList[2], 'tlsa': valList[3]}
    if '_' == tlsa['port'][0]:
        tlsa['port'] = tlsa['port'][1:]
    if '_' == tlsa['proto'][0]:
        tlsa['proto'] = tlsa['proto'][1:]
    tlsa['tlsa'] = tlsa['tlsa'].replace('\n', '')
    return tlsa
Esempio n. 24
0
 def add(self, updateDict):
     if type(updateDict) is list:
         self.__rv = [self.add(e) for e in updateDict]
         return self.__rv
     if 'ttl' not in updateDict:
         updateDict['ttl'] = self.defaultTTL
     try:
         log.debug('createRecord {}'.format(updateDict))
         if 'id' not in updateDict:
             self.__rv = self.handler.create(updateDict)
             infoRecord(updateDict, 'add (new)')
             log.debug(self.__rv)
     except Exception as e:
         if 1 < len(e.args):
             self.__rv = e.args[1]
         else:
             self.__rv = e.args
         if 2302 == self.__rv['code']:
             infoRecord(updateDict, 'add (exists)')
         log.debug(self.__rv)
     return self.__rv
Esempio n. 25
0
def interpreteConfig(cr, sh):
    defaultServiceConfig = {'cert': 'auto', 'dkim': 'auto', 'dhparam': 'auto'}
    serviceConfig = cr.getRawConfigOf('service')
    log.debug(serviceConfig)
    # apply general config defaults and the default section
    serviceConfig = applyDefault(
        serviceConfig, defaultServiceConfig
    )  # must be here because following section depends on default values
    log.debug(serviceConfig)

    for serviceSecName, content in serviceConfig.items():
        content = dict(content)
        for depends in ['cert', 'dkim', 'dhparam']:
            if depends in content:
                serviceConfig[serviceSecName][depends] = resolveAuto(
                    cr, [
                        e for e in content[depends].replace(' ', '').split(',')
                        if len(e) > 0
                    ], depends)
    log.debug(serviceConfig)
    cr.updateConfig({'service': serviceConfig})
    return serviceConfig
Esempio n. 26
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
Esempio n. 27
0
 def addSRV(self, name, srvDict):
     log.debug(srvDict)
     srvDictList = defaultDictList({'prio': 10, 'weight': 0}, srvDict)
     srvRRdictList = formatSRVentry(name, srvDictList)
     self.addDictList({}, srvRRdictList)
Esempio n. 28
0
def extractIds(rv):
    if type(rv) is list:
        return [extractIds(e) for e in rv]
    log.debug(rv)
    return rv['id']
Esempio n. 29
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