Пример #1
0
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"})
Пример #2
0
    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"))