def delete_request(common_name): # Validate CN if not re.match(RE_HOSTNAME, common_name): raise ValueError("Invalid common name") path = os.path.join(config.REQUESTS_DIR, common_name + ".pem") request = Request(open(path)) os.unlink(path) # Publish event at CA channel push.publish("request-deleted", request.common_name) # Write empty certificate to long-polling URL requests.delete(config.PUSH_PUBLISH % request.fingerprint(), headers={"User-Agent": "Certidude API"})
def on_post(self, req, resp): """ Submit certificate signing request (CSR) in PEM format """ body = req.stream.read(req.content_length) # Normalize body, TODO: newlines if not body.endswith("\n"): body += "\n" csr = Request(body) if not csr.common_name: logger.warning(u"Rejected signing request without common name from %s", req.context.get("remote_addr")) raise falcon.HTTPBadRequest( "Bad request", "No common name specified!") machine = req.context.get("machine") if machine: if csr.common_name != machine: raise falcon.HTTPBadRequest( "Bad request", "Common name %s differs from Kerberos credential %s!" % (csr.common_name, machine)) if csr.signable: # Automatic enroll with Kerberos machine cerdentials resp.set_header("Content-Type", "application/x-x509-user-cert") resp.body = authority.sign(csr, overwrite=True).dump() return # Check if this request has been already signed and return corresponding certificte if it has been signed try: cert = authority.get_signed(csr.common_name) except EnvironmentError: pass else: if cert.pubkey == csr.pubkey: resp.status = falcon.HTTP_SEE_OTHER resp.location = os.path.join(os.path.dirname(req.relative_uri), "signed", csr.common_name) return # TODO: check for revoked certificates and return HTTP 410 Gone # Process automatic signing if the IP address is whitelisted, autosigning was requested and certificate can be automatically signed if req.get_param_as_bool("autosign") and csr.signable: for subnet in config.AUTOSIGN_SUBNETS: if req.context.get("remote_addr") in subnet: try: resp.set_header("Content-Type", "application/x-x509-user-cert") resp.body = authority.sign(csr).dump() return except EnvironmentError: # Certificate already exists, try to save the request pass break # Attempt to save the request otherwise try: csr = authority.store_request(body) except errors.RequestExists: # We should stil redirect client to long poll URL below pass except errors.DuplicateCommonNameError: # TODO: Certificate renewal logger.warning(u"Rejected signing request with overlapping common name from %s", req.context.get("remote_addr")) raise falcon.HTTPConflict( "CSR with such CN already exists", "Will not overwrite existing certificate signing request, explicitly delete CSR and try again") else: push.publish("request-submitted", csr.common_name) # Wait the certificate to be signed if waiting is requested if req.get_param("wait"): # Redirect to nginx pub/sub url = config.PUSH_LONG_POLL % csr.fingerprint() click.echo("Redirecting to: %s" % url) resp.status = falcon.HTTP_SEE_OTHER resp.set_header("Location", url.encode("ascii")) logger.debug(u"Redirecting signing request from %s to %s", req.context.get("remote_addr"), url) else: # Request was accepted, but not processed resp.status = falcon.HTTP_202 logger.info(u"Signing request from %s stored", req.context.get("remote_addr"))