def trigger(self, payload): """ process trigger message and return certificate """ self.logger.debug('CAhandler.trigger()') error = None cert_bundle = None cert_raw = None if payload: # decode payload cert = b64_decode(self.logger, payload) try: # cert is a base64 encoded pem object cert_raw = b64_encode(self.logger, cert_pem2der(cert)) except BaseException: # cert is a binary der encoded object cert_raw = b64_encode(self.logger, cert) # lookup REST-PATH of issuing CA ca_dic = self._ca_get_properties('name', self.ca_name) if 'href' in ca_dic: # get serial from pem file serial = cert_serial_get(self.logger, cert_raw) if serial: # get certificate information via rest by search for ca+ serial cert_list = self._cert_get_properties( serial, ca_dic['href']) # the first entry is the cert we are looking for if 'certificates' in cert_list and len( cert_list['certificates'][0]) > 0: cert_dic = cert_list['certificates'][0] cert_bundle = self._pem_cert_chain_generate(cert_dic) else: error = 'no certifcates found in rest query' else: error = 'serial number lookup via rest failed' else: error = 'CA could not be found' else: error = 'No payload given' self.logger.debug( 'CAhandler.trigger() ended with error: {0}'.format(error)) return (error, cert_bundle, cert_raw)
def _validate_alpn_challenge(self, challenge_name, fqdn, token, jwk_thumbprint): """ validate dns challenge """ self.logger.debug( 'Challenge._validate_alpn_challenge({0}:{1}:{2})'.format( challenge_name, fqdn, token)) # resolve name (response, invalid) = fqdn_resolve(fqdn, self.dns_server_list) self.logger.debug('fqdn_resolve() ended with: {0}/{1}'.format( response, invalid)) # we are expecting a certifiate extension which is the sha256 hexdigest of token in a byte structure # which is base64 encoded '0420' has been taken from acme_srv.sh sources sha256_digest = sha256_hash_hex( self.logger, '{0}.{1}'.format(token, jwk_thumbprint)) extension_value = b64_encode( self.logger, bytearray.fromhex('0420{0}'.format(sha256_digest))) self.logger.debug('computed value: {0}'.format(extension_value)) if not invalid: # check if we need to set a proxy if self.proxy_server_list: proxy_server = proxy_check(self.logger, fqdn, self.proxy_server_list) else: proxy_server = None cert = servercert_get(self.logger, fqdn, 443, proxy_server) if cert: san_list = cert_san_get(self.logger, cert, recode=False) fqdn_in_san = fqdn_in_san_check(self.logger, san_list, fqdn) if fqdn_in_san: extension_list = cert_extensions_get(self.logger, cert, recode=False) if extension_value in extension_list: self.logger.debug('alpn validation successful') result = True else: self.logger.debug('alpn validation not successful') result = False else: self.logger.debug('fqdn check against san failed') result = False else: self.logger.debug('no cert returned...') result = False else: result = False self.logger.debug( 'Challenge._validate_alpn_challenge() ended with: {0}/{1}'.format( result, invalid)) return (result, invalid)
def enroll(self, csr): """ enroll certificate """ # pylint: disable=R0914 self.logger.debug('CAhandler.enroll()') cert_bundle = None cert_raw = None error = self._config_check() if not error: request_name = self._requestname_get(csr) if request_name: # import CSR to database _csr_info = self._csr_import(csr, request_name) # prepare the CSR to be signed csr = build_pem_file(self.logger, None, b64_url_recode(self.logger, csr), None, True) # load ca cert and key (ca_key, ca_cert, ca_id) = self._ca_load() if ca_key and ca_cert and ca_id: # load request req = crypto.load_certificate_request(crypto.FILETYPE_PEM, csr) # copy cn of request subject = req.get_subject() # rewrite CN if required if not subject.CN: self.logger.info('rewrite CN to {0}'.format(request_name)) subject.CN = request_name # create certificate object cert = crypto.X509() cert.set_pubkey(req.get_pubkey()) cert.set_version(2) cert.set_serial_number(uuid.uuid4().int & (1<<63)-1) cert.set_issuer(ca_cert.get_subject()) # load template if configured if self.template_name: (dn_dic, template_dic) = self._template_load() else: dn_dic = {} template_dic = {} # set cert_validity if 'validity' in template_dic: self.logger.info('take validity from template: {0}'.format(template_dic['validity'])) # take validity from template cert_validity = template_dic['validity'] else: cert_validity = self.cert_validity_days cert.gmtime_adj_notBefore(0) cert.gmtime_adj_notAfter(cert_validity * 86400) # get extension list from CSR csr_extensions_list = req.get_extensions() extension_list = self._extension_list_generate(template_dic, cert, ca_cert, csr_extensions_list) # add extensions (copy from CSR and take the ones we constructed) # cert.add_extensions(csr_extensions_list) cert.add_extensions(extension_list) if dn_dic: self.logger.info('modify subject with template data') subject = self._subject_modify(subject, dn_dic) cert.set_subject(subject) # sign csr cert.sign(ca_key, 'sha256') serial = cert.get_serial_number() # get hsshes issuer_hash = ca_cert.subject_name_hash() & 0x7fffffff name_hash = cert.subject_name_hash() & 0x7fffffff # store certificate self._store_cert(ca_id, request_name, '{:X}'.format(serial), convert_byte_to_string(b64_encode(self.logger, crypto.dump_certificate(crypto.FILETYPE_ASN1, cert))), name_hash, issuer_hash) cert_bundle = self._pemcertchain_generate(convert_byte_to_string(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)), convert_byte_to_string(crypto.dump_certificate(crypto.FILETYPE_PEM, ca_cert))) cert_raw = convert_byte_to_string(b64_encode(self.logger, crypto.dump_certificate(crypto.FILETYPE_ASN1, cert))) else: error = 'ca lookup failed' else: error = 'request_name lookup failed' self.logger.debug('Certificate.enroll() ended') return(error, cert_bundle, cert_raw, None)