Ejemplo n.º 1
0
    def check_certificate_status(self, order_id, order_meta, plugin_meta,
                                 barbican_meta_dto):
        """Check the status of a certificate request.

        :param order_id: ID of the order associated with this request
        :param order_meta: order_metadata associated with this order
        :param plugin_meta: data populated by previous calls for this order,
            in particular the request_id
        :param barbican_meta_dto: additional data needed to process order.
        :return: cm.ResultDTO
        """
        request_id = self._get_request_id(order_id, plugin_meta, "checking")

        request = self._get_request(request_id)
        if not request:
            raise cm.CertificateGeneralException(
                u._("No request found for request_id {request_id} for "
                    "order {order_id}").format(request_id=request_id,
                                               order_id=order_id))

        request_status = request.request_status

        if request_status == pki.cert.CertRequestStatus.REJECTED:
            return cm.ResultDTO(cm.CertificateStatus.CLIENT_DATA_ISSUE_SEEN,
                                status_message=request.error_message)
        elif request_status == pki.cert.CertRequestStatus.CANCELED:
            return cm.ResultDTO(cm.CertificateStatus.REQUEST_CANCELED)
        elif request_status == pki.cert.CertRequestStatus.PENDING:
            return cm.ResultDTO(cm.CertificateStatus.WAITING_FOR_CA)
        elif request_status == pki.cert.CertRequestStatus.COMPLETE:
            # get the cert
            cert_id = request.cert_id
            if not cert_id:
                raise cm.CertificateGeneralException(
                    u._("Request {request_id} reports status_complete, but no "
                        "cert_id has been returned").format(
                            request_id=request_id))

            cert = self._get_cert(cert_id)
            if not cert:
                raise cm.CertificateGeneralException(
                    u._("Certificate not found for cert_id: {cert_id}").format(
                        cert_id=cert_id))
            return cm.ResultDTO(cm.CertificateStatus.CERTIFICATE_GENERATED,
                                certificate=cert.encoded,
                                intermediates=cert.pkcs7_cert_chain)
        else:
            raise cm.CertificateGeneralException(
                u._("Invalid request_status returned by CA"))
Ejemplo n.º 2
0
    def create_ca(self, ca_create_dto):
        # get the parent CA from the ca list, return error if not on list
        parent_ca_id = ca_create_dto.parent_ca_id
        if not parent_ca_id:
            raise cert_manager.CertificateGeneralException(
                "No parent id passed to snake oil plugin on create_ca")

        parent_ca = self.cas.get(parent_ca_id)
        if not parent_ca:
            raise cert_manager.CertificateGeneralException(
                "Invalid parent id passed to snake oil plugin:" + parent_ca_id)

        # create a new ca, passing in key and issuer from the parent
        new_ca_id = str(uuid.uuid4())
        new_cert_path = os.path.join(self.subca_directory, new_ca_id + ".cert")
        new_key_path = os.path.join(self.subca_directory, new_ca_id + ".key")
        new_chain_path = os.path.join(self.subca_directory,
                                      new_ca_id + ".chain")
        new_pkcs7_path = os.path.join(self.subca_directory, new_ca_id + ".p7b")
        parent_chain_path = parent_ca.chain_path

        new_ca = SnakeoilCA(cert_path=new_cert_path,
                            key_path=new_key_path,
                            chain_path=new_chain_path,
                            pkcs7_path=new_pkcs7_path,
                            name=ca_create_dto.name,
                            subject_dn=ca_create_dto.subject_dn,
                            signing_dn=parent_ca.subject_dn,
                            signing_key=parent_ca.key,
                            parent_chain_path=parent_chain_path)

        self.cas[new_ca_id] = new_ca

        expiration = (datetime.datetime.utcnow() + datetime.timedelta(
            days=cert_manager.CA_INFO_DEFAULT_EXPIRATION_DAYS))

        return {
            cert_manager.INFO_NAME:
            new_ca.name,
            cert_manager.INFO_CA_SIGNING_CERT:
            crypto.dump_certificate(crypto.FILETYPE_PEM, new_ca.cert),
            cert_manager.INFO_EXPIRATION:
            expiration.isoformat(),
            cert_manager.INFO_INTERMEDIATES:
            new_ca.pkcs7,
            cert_manager.PLUGIN_CA_ID:
            new_ca_id
        }
Ejemplo n.º 3
0
    def _process_auto_enrollment_results(self, enrollment_results, plugin_meta,
                                         barbican_meta_dto):
        """Process results received from Dogtag CA for auto-enrollment

        This processes data from enroll_cert, which submits, approves and
        gets the cert issued and returns as a list of CertEnrollment objects.

        :param enrollment_results: list of CertEnrollmentResult objects
        :param plugin_meta: metadata dict for storing plugin specific data
        :param barbican_meta_dto: object containing extra data to help process
               the request
        :return: cm.ResultDTO
        """

        # Although it is possible to create multiple certs in an invocation
        # of enroll_cert, Barbican cannot handle this case.  Assume
        # only once cert and request generated for now.
        enrollment_result = enrollment_results[0]
        request = enrollment_result.request
        if not request:
            raise cm.CertificateGeneralException(
                u._("No request returned in enrollment_results"))

        # store the request_id in the plugin metadata
        plugin_meta[self.REQUEST_ID] = request.request_id

        cert = enrollment_result.cert

        return self._create_dto(request.request_status, request.request_id,
                                request.error_message, cert)
Ejemplo n.º 4
0
    def issue_certificate_request(self, order_id, order_meta, plugin_meta,
                                  barbican_meta_dto):
        if barbican_meta_dto.generated_csr is not None:
            encoded_csr = barbican_meta_dto.generated_csr
        else:
            try:
                encoded_csr = base64.b64decode(order_meta['request_data'])
            except KeyError:
                return cert_manager.ResultDTO(
                    cert_manager.CertificateStatus.CLIENT_DATA_ISSUE_SEEN,
                    status_message=u._("No request_data specified"))
        csr = crypto.load_certificate_request(crypto.FILETYPE_PEM, encoded_csr)

        ca_id = barbican_meta_dto.plugin_ca_id
        if ca_id:
            ca = self.cas.get(ca_id)
            if ca is None:
                raise cert_manager.CertificateGeneralException(
                    "Invalid ca_id passed into snake oil plugin:" + ca_id)
        else:
            ca = self.ca

        cert_mgr = CertManager(ca)
        cert = cert_mgr.make_certificate(csr)
        cert_enc = crypto.dump_certificate(crypto.FILETYPE_PEM, cert)

        return cert_manager.ResultDTO(
            cert_manager.CertificateStatus.CERTIFICATE_GENERATED,
            certificate=base64.b64encode(cert_enc),
            intermediates=base64.b64encode(ca.pkcs7))
Ejemplo n.º 5
0
    def _process_enrollment_results(self, enrollment_results, plugin_meta):
        """Process results received from Dogtag CA for enrollment

        :param enrollment_results: list of CertEnrollmentResult objects
        :param plugin_meta: metadata dict for storing plugin specific data
        :return: cm.ResultDTO
        """

        # Although it is possible to create multiple certs in an invocation
        # of enroll_cert, Barbican cannot handle this case.  Assume
        # only once cert and request generated for now.
        enrollment_result = enrollment_results[0]

        request = enrollment_result.request
        if not request:
            raise cm.CertificateGeneralException(
                u._("No request returned in enrollment_results"))

        # store the request_id in the plugin metadata
        plugin_meta[self.REQUEST_ID] = request.request_id

        cert = enrollment_result.cert
        if not cert:
            request_status = request.request_status
            if request_status == pki.cert.CertRequestStatus.REJECTED:
                return cm.ResultDTO(
                    cm.CertificateStatus.CLIENT_DATA_ISSUE_SEEN,
                    status_message=request.error_message)
            elif request_status == pki.cert.CertRequestStatus.CANCELED:
                return cm.ResultDTO(cm.CertificateStatus.REQUEST_CANCELED)
            elif request_status == pki.cert.CertRequestStatus.PENDING:
                return cm.ResultDTO(cm.CertificateStatus.WAITING_FOR_CA)
            elif request_status == pki.cert.CertRequestStatus.COMPLETE:
                raise cm.CertificateGeneralException(
                    u._("request_id {req_id} returns COMPLETE but no cert "
                        "returned").format(req_id=request.request_id))
            else:
                raise cm.CertificateGeneralException(
                    u._("Invalid request_status {status} for "
                        "request_id {request_id}").format(
                            status=request_status,
                            request_id=request.request_id))

        return cm.ResultDTO(cm.CertificateStatus.CERTIFICATE_GENERATED,
                            certificate=cert.encoded,
                            intermediates=cert.pkcs7_cert_chain)
Ejemplo n.º 6
0
 def _get_request_id(self, order_id, plugin_meta, operation):
     request_id = plugin_meta.get(self.REQUEST_ID, None)
     if not request_id:
         raise cm.CertificateGeneralException(
             u._("{request} not found for {operation} for "
                 "order_id {order_id}").format(request=self.REQUEST_ID,
                                               operation=operation,
                                               order_id=order_id))
     return request_id
Ejemplo n.º 7
0
 def _catch_enrollment_exception(self, *args, **kwargs):
     try:
         return ca_related_function(self, *args, **kwargs)
     except pki.BadRequestException as e:
         return cm.ResultDTO(cm.CertificateStatus.CLIENT_DATA_ISSUE_SEEN,
                             status_message=e.message)
     except pki.PKIException as e:
         raise cm.CertificateGeneralException(
             u._("Exception thrown by enroll_cert: {message}").format(
                 message=e.message))
Ejemplo n.º 8
0
    def _create_dto(self, request_status, request_id, error_message, cert):
        dto = None
        if request_status == pki.cert.CertRequestStatus.COMPLETE:
            if cert is not None:
                # Barbican is expecting base 64 encoded PEM, so we base64
                # encode below.
                #
                # Currently there is an inconsistency in what Dogtag returns
                # for certificates and intermediates.  For certs, we return
                # PEM, whereas for intermediates, we return headerless PEM.
                # This is being addressed in Dogtag ticket:
                # https://fedorahosted.org/pki/ticket/1374
                #
                # Until this is addressed, simply add the missing headers
                cert_chain = (CERT_HEADER + "\r\n" + cert.pkcs7_cert_chain +
                              CERT_FOOTER)

                dto = cm.ResultDTO(cm.CertificateStatus.CERTIFICATE_GENERATED,
                                   certificate=base64.b64encode(cert.encoded),
                                   intermediates=base64.b64encode(cert_chain))
            else:
                raise cm.CertificateGeneralException(
                    u._("request_id {req_id} returns COMPLETE but no cert "
                        "returned").format(req_id=request_id))

        elif request_status == pki.cert.CertRequestStatus.REJECTED:
            dto = cm.ResultDTO(cm.CertificateStatus.CLIENT_DATA_ISSUE_SEEN,
                               status_message=error_message)
        elif request_status == pki.cert.CertRequestStatus.CANCELED:
            dto = cm.ResultDTO(cm.CertificateStatus.REQUEST_CANCELED)
        elif request_status == pki.cert.CertRequestStatus.PENDING:
            dto = cm.ResultDTO(cm.CertificateStatus.WAITING_FOR_CA)
        else:
            raise cm.CertificateGeneralException(
                u._("Invalid request_status {status} for "
                    "request_id {request_id}").format(status=request_status,
                                                      request_id=request_id))

        return dto