def _csr_check(self, csr): """ check CSR against definied whitelists """ self.logger.debug('CAhandler._csr_check()') if self.allowed_domainlist: result = False # get sans and build a list _san_list = csr_san_get(self.logger, csr) check_list = [] san_list = [] if _san_list: for san in _san_list: try: # SAN list must be modified/filtered) (_san_type, san_value) = san.lower().split(':') san_list.append(san_value) except Exception: # force check to fail as something went wrong during parsing check_list.append(False) self.logger.debug( 'CAhandler._csr_check(): san_list parsing failed at entry: {0}' .format(san)) # get common name and attach it to san_list cn_ = csr_cn_get(self.logger, csr) if cn_: cn_ = cn_.lower() if cn_ not in san_list: # append cn to san_list self.logger.debug( 'Ahandler._csr_check(): append cn to san_list') san_list.append(cn_) # go over the san list and check each entry for san in san_list: check_list.append( self._list_check(san, self.allowed_domainlist)) if check_list: # cover a cornercase with empty checklist (no san, no cn) if False in check_list: result = False else: result = True else: result = True self.logger.debug( 'CAhandler._csr_check() ended with: {0}'.format(result)) return result
def _csr_id_lookup(self, csr_cn, csr_san_list): """ lookup CSR based on CN """ self.logger.debug('CAhandler._csr_id_lookup()') uts_n = uts_now() # get unused requests from NCLM request_list = self._unusedrequests_get() req_id = None # check every CSR for req in request_list: req_cn = None # check the import date and consider only csr which are less then 5min old csr_uts = date_to_uts_utc(req['addedAt'][:25], '%Y-%m-%dT%H:%M:%S.%f') if uts_n - csr_uts < 300: if 'subjectName' in req: # split the subject and filter CN subject_list = req['subjectName'].split(',') for field in subject_list: field = field.strip() if field.startswith('CN='): req_cn = field.lower().replace('cn=', '') break # compare csr cn with request cn if csr_cn: if req_cn == csr_cn.lower() and 'requestID' in req: req_id = req['requestID'] break elif not req_cn: # special certbot scenario (no CN in CSR). No better idea how to handle this, take first request try: req_all = requests.get(self.api_host + '/requests', headers=self.headers, verify=self.ca_bundle, proxies=self.proxy).json() except BaseException as err_: self.logger.error( 'CAhandler._csr_id_lookup() returned error: {0}'. format(str(err_))) req_all = [] for _req in reversed(req_all): if 'pkcs10' in _req: req_san_list = csr_san_get(self.logger, _req['pkcs10']) if sorted(csr_san_list) == sorted( req_san_list) and 'requestID' in _req: req_id = _req['requestID'] break self.logger.debug( 'CAhandler._csr_id_lookup() ended with: {0}'.format(req_id)) return req_id
def _requestname_get(self, csr): """ enroll certificate """ self.logger.debug('CAhandler._request_name_get()') # try to get cn for a name in database request_name = csr_cn_get(self.logger, csr) if not request_name: san_list = csr_san_get(self.logger, csr) try: (_identifiier, request_name,) = san_list[0].split(':') except BaseException: pass self.logger.debug('CAhandler._request_name_get() ended with: {0}'.format(request_name)) return request_name
def _csr_san_get(self, csr): """ get subAltNames from CSR and format them as needed """ self.logger.debug('CAhandler._csr_san_get()') san_list = csr_san_get(self.logger, csr) o_list = [] for san in san_list: try: (_type, value) = san.lower().split(':') if value: o_list.append(value) except BaseException: pass if o_list: sans = '"{0}"'.format(', '.join(o_list)) else: sans = None self.logger.debug('CAhandler._csr_san_get() ended with: {0}'.format(sans)) return sans
def enroll(self, csr): """ enroll certificate from NCLM """ self.logger.debug('CAhandler.enroll()') cert_bundle = None error = None cert_raw = None # recode csr csr = b64_url_recode(self.logger, csr) if not self.error: if self.tsg_info_dic['id']: ca_id = self._ca_id_lookup() if ca_id and self.template_info_dic[ 'name'] and not self.template_info_dic['id']: self._template_id_lookup() # get common name of CSR csr_cn = csr_cn_get(self.logger, csr) csr_san_list = csr_san_get(self.logger, csr) # import csr to NCLM self._request_import(csr) # lookup csr id csr_id = self._csr_id_lookup(csr_cn, csr_san_list) if ca_id and csr_id and self.tsg_info_dic['id']: data_dic = { "targetSystemGroupID": self.tsg_info_dic['id'], "caID": ca_id, "requestID": csr_id } # add template if correctly configured if 'id' in self.template_info_dic and self.template_info_dic[ 'id']: data_dic['templateID'] = self.template_info_dic['id'] self._api_post( self.api_host + '/targetsystemgroups/' + str(self.tsg_info_dic['id']) + '/enroll/ca/' + str(ca_id), data_dic) # wait for certificate enrollment to get finished time.sleep(self.wait_interval) cert_id = self._cert_id_lookup(csr_cn, csr_san_list) if cert_id: (error, cert_bundle, cert_raw) = self._cert_bundle_build(cert_id) else: error = 'certifcate id lookup failed for: {0}, {1}'.format( csr_cn, csr_san_list) self.logger.error( 'CAhandler.eroll(): certifcate id lookup failed for: {0}, {1}' .format(csr_cn, csr_san_list)) else: error = 'enrollment aborted. ca_id: {0}, csr_id: {1}, tsg_id: {2}'.format( ca_id, csr_id, self.tsg_info_dic['id']) self.logger.error( 'CAhandler.eroll(): enrollment aborted. ca_id: {0}, csr_id: {1}, tsg_id: {2}' .format(ca_id, csr_id, self.tsg_info_dic['id'])) else: error = 'CAhandler.eroll(): ID lookup for targetSystemGroup "{0}" failed.'.format( self.tsg_info_dic['name']) else: self.logger.error(self.error) self.logger.debug('CAhandler.enroll() ended') return (error, cert_bundle, cert_raw, None)
def post_hook(self, certificate_name, order_name, csr, error): """ run after *attempting* to obtain/renew certificates """ self.logger.debug('Hook.post_hook()') san_list = csr_san_get(self.logger, csr) self._file_append('{0}/post_hook.txt'.format(self.save_path), json.dumps(san_list) + '\n')
def pre_hook(self, certificate_name, order_name, csr): """ run before obtaining any certificates """ self.logger.debug('Hook.pre_hook()') san_list = csr_san_get(self.logger, csr) self._file_append('{0}/pre_hook.txt'.format(self.save_path), json.dumps(san_list) + '\n')
def _csr_check(self, certificate_name, csr): """ compare csr extensions against order """ self.logger.debug('Certificate._csr_check()') # fetch certificate dictionary from DB certificate_dic = self._info(certificate_name) self.logger.debug( 'Certificate._info() ended with:{0}'.format(certificate_dic)) # empty list of statuses identifier_status = [] if 'order' in certificate_dic: # get identifiers for order try: identifier_dic = self.dbstore.order_lookup( 'name', certificate_dic['order'], ['identifiers']) except BaseException as err_: self.logger.critical( 'acme2certifier database error in Certificate._csr_check(): {0}' .format(err_)) identifier_dic = {} if identifier_dic and 'identifiers' in identifier_dic: # load identifiers try: identifiers = json.loads( identifier_dic['identifiers'].lower()) except BaseException: identifiers = [] # do we need to check for tnauth tnauthlist_identifer_in = self._tnauth_identifier_check( identifiers) if self.tnauthlist_support and tnauthlist_identifer_in: # get list of certextensions in base64 format try: tnauthlist = csr_extensions_get(self.logger, csr) identifier_status = self._identifer_tnauth_list( identifier_dic, tnauthlist) except BaseException as err_: identifier_status = [] self.logger.warning( 'Certificate._csr_check() error while parsing csr.\nerror: {0}' .format(err_)) else: # get sans and compare identifiers against san try: san_list = csr_san_get(self.logger, csr) identifier_status = self._identifer_status_list( identifiers, san_list) except BaseException as err_: identifier_status = [] self.logger.warning( 'Certificate._csr_check() error while checking csr.\nerror: {0}' .format(err_)) csr_check_result = False if identifier_status and False not in identifier_status: csr_check_result = True self.logger.debug( 'Certificate._csr_check() ended with {0}'.format(csr_check_result)) return csr_check_result