def test_4(self): """ Test CSR with badly formatted base64-encoded data """ csr = self.read_file("test4.csr") with pytest.raises(ValueError): pkcs10.load_certificate_request(csr)
def test_3(self): """ Test CSR with base64-encoded bogus data """ csr = self.read_file("test3.csr") with pytest.raises(ValueError): pkcs10.load_certificate_request(csr)
def test_4(self): """ Test CSR with badly formatted base64-encoded data """ csr = self.read_file("test4.csr") try: pkcs10.load_certificate_request(csr) except (TypeError, binascii.Error) as typeerr: assert(str(typeerr) == 'Incorrect padding')
def test_4(self): """ Test CSR with badly formatted base64-encoded data """ csr = self.read_file("test4.csr") try: pkcs10.load_certificate_request(csr) except (TypeError, binascii.Error) as typeerr: assert (str(typeerr) == 'Incorrect padding')
def test_3(self): """ Test CSR with base64-encoded bogus data """ csr = self.read_file("test3.csr") try: pkcs10.load_certificate_request(csr) except NSPRError as nsprerr: # (SEC_ERROR_BAD_DER) security library: improperly formatted DER-encoded message. assert (nsprerr.errno == -8183)
def test_3(self): """ Test CSR with base64-encoded bogus data """ csr = self.read_file("test3.csr") try: pkcs10.load_certificate_request(csr) except NSPRError as nsprerr: # (SEC_ERROR_BAD_DER) security library: improperly formatted DER-encoded message. assert(nsprerr. errno== -8183)
def validate_csr(ugettext, csr): """ Ensure the CSR is base64-encoded and can be decoded by our PKCS#10 parser. """ if api.env.context == 'cli': # If we are passed in a pointer to a valid file on the client side # escape and let the load_files() handle things if csr and os.path.exists(csr): return try: pkcs10.load_certificate_request(csr) except (TypeError, ValueError) as e: raise errors.CertificateOperationError( error=_('Failure decoding Certificate Signing Request: %s') % e)
def test_2(self): """ Test CSR with subject alt name and a list of CRL distribution points """ csr = self.read_file("test2.csr") request = pkcs10.load_certificate_request(csr) subject = request.subject cn = subject.get_attributes_for_oid( cryptography.x509.NameOID.COMMON_NAME)[-1].value assert (cn == 'test.example.com') st = subject.get_attributes_for_oid( cryptography.x509.NameOID.STATE_OR_PROVINCE_NAME)[-1].value assert (st == 'California') c = subject.get_attributes_for_oid( cryptography.x509.NameOID.COUNTRY_NAME)[-1].value assert (c == 'US') san = request.extensions.get_extension_for_oid( cryptography.x509.ExtensionOID.SUBJECT_ALTERNATIVE_NAME).value dns = san.get_values_for_type(cryptography.x509.DNSName) assert dns[0] == 'testlow.example.com' crldps = request.extensions.get_extension_for_oid( cryptography.x509.ExtensionOID.CRL_DISTRIBUTION_POINTS).value gns = [] for crldp in crldps: gns.extend(crldp.full_name) uris = [ u'http://ca.example.com/my.crl', u'http://other.example.com/my.crl', ] for uri in uris: assert cryptography.x509.UniformResourceIdentifier(uri) in gns
def test_2(self): """ Test CSR with subject alt name and a list of CRL distribution points """ csr = self.read_file("test2.csr") request = pkcs10.load_certificate_request(csr) subject = request.subject cn = subject.get_attributes_for_oid( cryptography.x509.NameOID.COMMON_NAME)[-1].value assert(cn == 'test.example.com') st = subject.get_attributes_for_oid( cryptography.x509.NameOID.STATE_OR_PROVINCE_NAME)[-1].value assert(st == 'California') c = subject.get_attributes_for_oid( cryptography.x509.NameOID.COUNTRY_NAME)[-1].value assert(c == 'US') san = request.extensions.get_extension_for_oid( cryptography.x509.ExtensionOID.SUBJECT_ALTERNATIVE_NAME).value dns = san.get_values_for_type(cryptography.x509.DNSName) assert dns[0] == 'testlow.example.com' crldps = request.extensions.get_extension_for_oid( cryptography.x509.ExtensionOID.CRL_DISTRIBUTION_POINTS).value gns = [] for crldp in crldps: gns.extend(crldp.full_name) uris = [ u'http://ca.example.com/my.crl', u'http://other.example.com/my.crl', ] for uri in uris: assert cryptography.x509.UniformResourceIdentifier(uri) in gns
def validate_csr(ugettext, csr): """ Ensure the CSR is base64-encoded and can be decoded by our PKCS#10 parser. """ if api.env.context == 'cli': # If we are passed in a pointer to a valid file on the client side # escape and let the load_files() handle things if csr and os.path.exists(csr): return try: pkcs10.load_certificate_request(csr) except (TypeError, binascii.Error) as e: raise errors.Base64DecodeError(reason=str(e)) except Exception as e: raise errors.CertificateOperationError(error=_('Failure decoding Certificate Signing Request: %s') % e)
def get_csr_hostname(csr): """ Return the value of CN in the subject of the request or None """ try: request = pkcs10.load_certificate_request(csr) subject = pkcs10.get_subject(request) return subject.common_name except NSPRError, nsprerr: raise errors.CertificateOperationError(error=_('Failure decoding Certificate Signing Request:'))
def get_csr_hostname(csr): """ Return the value of CN in the subject of the request or None """ try: request = pkcs10.load_certificate_request(csr) subject = pkcs10.get_subject(request) return subject.common_name except NSPRError, nsprerr: raise errors.CertificateOperationError( error=_('Failure decoding Certificate Signing Request:'))
def get_subjectaltname(csr): """ Return the first value of the subject alt name, if any """ try: request = pkcs10.load_certificate_request(csr) for extension in request.extensions: if extension.oid_tag == nss.SEC_OID_X509_SUBJECT_ALT_NAME: return nss.x509_alt_name(extension.value)[0] return None except NSPRError, nsprerr: raise errors.CertificateOperationError(error=_('Failure decoding Certificate Signing Request'))
def test_0(self): """ Test simple CSR with no attributes """ csr = self.read_file("test0.csr") request = pkcs10.load_certificate_request(csr) subject = pkcs10.get_subject(request) assert (subject.common_name == 'test.example.com') assert (subject.state_name == 'California') assert (subject.country_name == 'US')
def test_0(self): """ Test simple CSR with no attributes """ csr = self.read_file("test0.csr") request = pkcs10.load_certificate_request(csr) subject = pkcs10.get_subject(request) assert(subject.common_name == 'test.example.com') assert(subject.state_name == 'California') assert(subject.country_name == 'US')
def get_subjectaltname(csr): """ Return the first value of the subject alt name, if any """ try: request = pkcs10.load_certificate_request(csr) for extension in request.extensions: if extension.oid_tag == nss.SEC_OID_X509_SUBJECT_ALT_NAME: return nss.x509_alt_name(extension.value)[0] return None except NSPRError, nsprerr: raise errors.CertificateOperationError( error=_('Failure decoding Certificate Signing Request'))
def validate_csr(ugettext, csr): """ Ensure the CSR is base64-encoded and can be decoded by our PKCS#10 parser. """ if api.env.context == 'cli': # If we are passed in a pointer to a valid file on the client side # escape and let the load_files() handle things if csr and os.path.exists(csr): return try: request = pkcs10.load_certificate_request(csr) except TypeError, e: raise errors.Base64DecodeError(reason=str(e))
def test_1(self): """ Test CSR with subject alt name """ csr = self.read_file("test1.csr") request = pkcs10.load_certificate_request(csr) subject = request.subject assert(subject.common_name == 'test.example.com') assert(subject.state_name == 'California') assert(subject.country_name == 'US') for extension in request.extensions: if extension.oid_tag == nss.SEC_OID_X509_SUBJECT_ALT_NAME: assert nss.x509_alt_name(extension.value)[0] == 'testlow.example.com'
def test_0(self): """ Test simple CSR with no attributes """ csr = pkcs10.load_certificate_request(self.read_file("test0.csr")) subject = csr.subject cn = subject.get_attributes_for_oid( cryptography.x509.NameOID.COMMON_NAME)[-1].value assert (cn == 'test.example.com') st = subject.get_attributes_for_oid( cryptography.x509.NameOID.STATE_OR_PROVINCE_NAME)[-1].value assert (st == 'California') c = subject.get_attributes_for_oid( cryptography.x509.NameOID.COUNTRY_NAME)[-1].value assert (c == 'US')
def test_0(self): """ Test simple CSR with no attributes """ csr = pkcs10.load_certificate_request(self.read_file("test0.csr")) subject = csr.subject cn = subject.get_attributes_for_oid( cryptography.x509.NameOID.COMMON_NAME)[-1].value assert(cn == 'test.example.com') st = subject.get_attributes_for_oid( cryptography.x509.NameOID.STATE_OR_PROVINCE_NAME)[-1].value assert(st == 'California') c = subject.get_attributes_for_oid( cryptography.x509.NameOID.COUNTRY_NAME)[-1].value assert(c == 'US')
def request_certificate(self, csr, request_type='pkcs10'): """ :param csr: The certificate signing request. :param request_type: The request type (defaults to ``'pkcs10'``). Submit certificate signing request. The command returns a dict with these possible key/value pairs. Some key/value pairs may be absent. +---------------+---------------+---------------+ |result name |result type |comments | +===============+===============+===============+ |serial_number |unicode [1]_ | | +---------------+---------------+---------------+ |certificate |unicode [2]_ | | +---------------+---------------+---------------+ |request_id |unicode | | +---------------+---------------+---------------+ |subject |unicode | | +---------------+---------------+---------------+ .. [1] Passed through XMLRPC as decimal string. Can convert to optimal integer type (int or long) via int(serial_number) .. [2] Base64 encoded """ try: config = api.Command['config_show']()['result'] subject_base = EditableDN(config.get('ipacertificatesubjectbase')[0]) hostname = get_csr_hostname(csr) subject_base.insert(0, RDN(('CN', hostname))) request = pkcs10.load_certificate_request(csr) # python-nss normalizes the request subject request_subject = DN(str(pkcs10.get_subject(request))) if subject_base != request_subject: raise errors.CertificateOperationError(error=_('Request subject "%(request_subject)s" does not match the form "%(subject_base)s"') % \ {'request_subject' : request_subject, 'subject_base' : subject_base}) except errors.CertificateOperationError, e: raise e
def test_2(self): """ Test CSR with subject alt name and a list of CRL distribution points """ csr = self.read_file("test2.csr") request = pkcs10.load_certificate_request(csr) subject = request.subject assert(subject.common_name == 'test.example.com') assert(subject.state_name == 'California') assert(subject.country_name == 'US') for extension in request.extensions: if extension.oid_tag == nss.SEC_OID_X509_SUBJECT_ALT_NAME: assert nss.x509_alt_name(extension.value)[0] == 'testlow.example.com' if extension.oid_tag == nss.SEC_OID_X509_CRL_DIST_POINTS: pts = nss.CRLDistributionPts(extension.value) urls = pts[0].get_general_names() assert('http://ca.example.com/my.crl' in urls) assert('http://other.example.com/my.crl' in urls)
def test_1(self): """ Test CSR with subject alt name """ csr = self.read_file("test1.csr") request = pkcs10.load_certificate_request(csr) subject = request.subject cn = subject.get_attributes_for_oid( cryptography.x509.NameOID.COMMON_NAME)[-1].value assert(cn == 'test.example.com') st = subject.get_attributes_for_oid( cryptography.x509.NameOID.STATE_OR_PROVINCE_NAME)[-1].value assert(st == 'California') c = subject.get_attributes_for_oid( cryptography.x509.NameOID.COUNTRY_NAME)[-1].value assert(c == 'US') san = request.extensions.get_extension_for_oid( cryptography.x509.ExtensionOID.SUBJECT_ALTERNATIVE_NAME).value dns = san.get_values_for_type(cryptography.x509.DNSName) assert dns[0] == 'testlow.example.com'
def test_1(self): """ Test CSR with subject alt name """ csr = self.read_file("test1.csr") request = pkcs10.load_certificate_request(csr) subject = request.subject cn = subject.get_attributes_for_oid( cryptography.x509.NameOID.COMMON_NAME)[-1].value assert (cn == 'test.example.com') st = subject.get_attributes_for_oid( cryptography.x509.NameOID.STATE_OR_PROVINCE_NAME)[-1].value assert (st == 'California') c = subject.get_attributes_for_oid( cryptography.x509.NameOID.COUNTRY_NAME)[-1].value assert (c == 'US') san = request.extensions.get_extension_for_oid( cryptography.x509.ExtensionOID.SUBJECT_ALTERNATIVE_NAME).value dns = san.get_values_for_type(cryptography.x509.DNSName) assert dns[0] == 'testlow.example.com'
def execute(self, csr, all=False, raw=False, **kw): ca_enabled_check() ldap = self.api.Backend.ldap2 add = kw.get('add') request_type = kw.get('request_type') profile_id = kw.get('profile_id', self.Backend.ra.DEFAULT_PROFILE) # Check that requested authority exists (done before CA ACL # enforcement so that user gets better error message if # referencing nonexistant CA) and look up authority ID. # ca = kw['cacn'] ca_obj = api.Command.ca_show(ca)['result'] ca_id = ca_obj['ipacaid'][0] """ Access control is partially handled by the ACI titled 'Hosts can modify service userCertificate'. This is for the case where a machine binds using a host/ prinicpal. It can only do the request if the target hostname is in the managedBy attribute which is managed using the add/del member commands. Binding with a user principal one needs to be in the request_certs taskgroup (directly or indirectly via role membership). """ principal = kw.get('principal') principal_string = unicode(principal) if principal.is_user: principal_type = USER elif principal.is_host: principal_type = HOST else: principal_type = SERVICE bind_principal = kerberos.Principal(getattr(context, 'principal')) bind_principal_string = unicode(bind_principal) if bind_principal.is_user: bind_principal_type = USER elif bind_principal.is_host: bind_principal_type = HOST else: bind_principal_type = SERVICE if (bind_principal_string != principal_string and bind_principal_type != HOST): # Can the bound principal request certs for another principal? self.check_access() try: self.check_access("request certificate ignore caacl") bypass_caacl = True except errors.ACIError: bypass_caacl = False if not bypass_caacl: caacl_check(principal_type, principal, ca, profile_id) try: csr_obj = pkcs10.load_certificate_request(csr) except ValueError as e: raise errors.CertificateOperationError( error=_("Failure decoding Certificate Signing Request: %s") % e) try: ext_san = csr_obj.extensions.get_extension_for_oid( cryptography.x509.oid.ExtensionOID.SUBJECT_ALTERNATIVE_NAME) except cryptography.x509.extensions.ExtensionNotFound: ext_san = None # self-service and host principals may bypass SAN permission check if (bind_principal_string != principal_string and bind_principal_type != HOST): if ext_san is not None: self.check_access('request certificate with subjectaltname') dn = None principal_obj = None # See if the service exists and punt if it doesn't and we aren't # going to add it try: if principal_type == SERVICE: principal_obj = api.Command['service_show'](principal_string, all=True) elif principal_type == HOST: principal_obj = api.Command['host_show'](principal.hostname, all=True) elif principal_type == USER: principal_obj = api.Command['user_show'](principal.username, all=True) except errors.NotFound as e: if add: if principal_type == SERVICE: principal_obj = api.Command['service_add']( principal_string, force=True) else: princtype_str = PRINCIPAL_TYPE_STRING_MAP[principal_type] raise errors.OperationNotSupportedForPrincipalType( operation=_("'add' option"), principal_type=princtype_str) else: raise errors.NotFound( reason=_("The principal for this request doesn't exist.")) principal_obj = principal_obj['result'] dn = principal_obj['dn'] # Ensure that the DN in the CSR matches the principal # # We only look at the "most specific" CN value cns = csr_obj.subject.get_attributes_for_oid( cryptography.x509.oid.NameOID.COMMON_NAME) if len(cns) == 0: raise errors.ValidationError( name='csr', error=_("No Common Name was found in subject of request.")) cn = cns[-1].value # "most specific" is end of list if principal_type in (SERVICE, HOST): if cn.lower() != principal.hostname.lower(): raise errors.ACIError(info=_( "hostname in subject of request '%(cn)s' " "does not match principal hostname '%(hostname)s'") % dict(cn=cn, hostname=principal.hostname)) elif principal_type == USER: # check user name if cn != principal.username: raise errors.ValidationError( name='csr', error=_("DN commonName does not match user's login")) # check email address # # fail if any email addr from DN does not appear in ldap entry email_addrs = csr_obj.subject.get_attributes_for_oid( cryptography.x509.oid.NameOID.EMAIL_ADDRESS) if len(set(email_addrs) - set(principal_obj.get('mail', []))) > 0: raise errors.ValidationError( name='csr', error=_("DN emailAddress does not match " "any of user's email addresses")) # We got this far so the principal entry exists, can we write it? if not ldap.can_write(dn, "usercertificate"): raise errors.ACIError( info=_("Insufficient 'write' privilege " "to the 'userCertificate' attribute of entry '%s'.") % dn) # Validate the subject alt name, if any generalnames = [] if ext_san is not None: generalnames = x509.process_othernames(ext_san.value) for gn in generalnames: if isinstance(gn, cryptography.x509.general_name.DNSName): name = gn.value alt_principal = None alt_principal_obj = None try: if principal_type == HOST: alt_principal = kerberos.Principal((u'host', name), principal.realm) alt_principal_obj = api.Command['host_show'](name, all=True) elif principal_type == SERVICE: alt_principal = kerberos.Principal( (principal.service_name, name), principal.realm) alt_principal_obj = api.Command['service_show']( alt_principal, all=True) elif principal_type == USER: raise errors.ValidationError( name='csr', error=_("subject alt name type %s is forbidden " "for user principals") % "DNSName") except errors.NotFound: # We don't want to issue any certificates referencing # machines we don't know about. Nothing is stored in this # host record related to this certificate. raise errors.NotFound(reason=_( 'The service principal for ' 'subject alt name %s in certificate request does not ' 'exist') % name) if alt_principal_obj is not None: altdn = alt_principal_obj['result']['dn'] if not ldap.can_write(altdn, "usercertificate"): raise errors.ACIError(info=_( "Insufficient privilege to create a certificate " "with subject alt name '%s'.") % name) if alt_principal is not None and not bypass_caacl: caacl_check(principal_type, alt_principal, ca, profile_id) elif isinstance(gn, (x509.KRB5PrincipalName, x509.UPN)): if gn.name != principal_string: raise errors.ACIError( info=_("Principal '%s' in subject alt name does not " "match requested principal") % gn.name) elif isinstance(gn, cryptography.x509.general_name.RFC822Name): if principal_type == USER: if gn.value not in principal_obj.get('mail', []): raise errors.ValidationError( name='csr', error=_("RFC822Name does not match " "any of user's email addresses")) else: raise errors.ValidationError( name='csr', error=_("subject alt name type %s is forbidden " "for non-user principals") % "RFC822Name") else: raise errors.ACIError( info=_("Subject alt name type %s is forbidden") % type(gn).__name__) # Request the certificate try: # re-serialise to PEM, in case the user-supplied data has # extraneous material that will cause Dogtag to freak out csr_pem = csr_obj.public_bytes(serialization.Encoding.PEM) result = self.Backend.ra.request_certificate( csr_pem, profile_id, ca_id, request_type=request_type) except errors.HTTPRequestError as e: if e.status == 409: # pylint: disable=no-member raise errors.CertificateOperationError( error=_("CA '%s' is disabled") % ca) else: raise e if not raw: self.obj._parse(result, all) result['request_id'] = int(result['request_id']) result['cacn'] = ca_obj['cn'][0] # Success? Then add it to the principal's entry # (unless the profile tells us not to) profile = api.Command['certprofile_show'](profile_id) store = profile['result']['ipacertprofilestoreissued'][0] == 'TRUE' if store and 'certificate' in result: cert = str(result.get('certificate')) kwargs = dict(addattr=u'usercertificate={}'.format(cert)) if principal_type == SERVICE: api.Command['service_mod'](principal_string, **kwargs) elif principal_type == HOST: api.Command['host_mod'](principal.hostname, **kwargs) elif principal_type == USER: api.Command['user_mod'](principal.username, **kwargs) return dict( result=result, value=pkey_to_value(int(result['request_id']), kw), )
class cert_request(VirtualCommand): __doc__ = _('Submit a certificate signing request.') takes_args = (File( 'csr', validate_csr, label=_('CSR'), cli_name='csr_file', normalizer=normalize_csr, ), ) operation = "request certificate" takes_options = ( Str( 'principal', label=_('Principal'), doc= _('Service principal for this certificate (e.g. HTTP/test.example.com)' ), ), Str( 'request_type', default=u'pkcs10', autofill=True, ), Flag('add', doc=_("automatically add the principal if it doesn't exist"), default=False, autofill=True), ) has_output_params = ( Str( 'certificate', label=_('Certificate'), ), Str( 'subject', label=_('Subject'), ), Str( 'issuer', label=_('Issuer'), ), Str( 'valid_not_before', label=_('Not Before'), ), Str( 'valid_not_after', label=_('Not After'), ), Str( 'md5_fingerprint', label=_('Fingerprint (MD5)'), ), Str( 'sha1_fingerprint', label=_('Fingerprint (SHA1)'), ), Str( 'serial_number', label=_('Serial number'), ), Str( 'serial_number_hex', label=_('Serial number (hex)'), ), ) has_output = (Output( 'result', type=dict, doc=_('Dictionary mapping variable name to value'), ), ) def execute(self, csr, **kw): ldap = self.api.Backend.ldap2 principal = kw.get('principal') add = kw.get('add') del kw['principal'] del kw['add'] service = None """ Access control is partially handled by the ACI titled 'Hosts can modify service userCertificate'. This is for the case where a machine binds using a host/ prinicpal. It can only do the request if the target hostname is in the managedBy attribute which is managed using the add/del member commands. Binding with a user principal one needs to be in the request_certs taskgroup (directly or indirectly via role membership). """ bind_principal = getattr(context, 'principal') # Can this user request certs? if not bind_principal.startswith('host/'): self.check_access() # FIXME: add support for subject alt name # Ensure that the hostname in the CSR matches the principal subject_host = get_csr_hostname(csr) (servicename, hostname, realm) = split_principal(principal) if subject_host.lower() != hostname.lower(): raise errors.ACIError( info=_("hostname in subject of request '%(subject_host)s' " "does not match principal hostname '%(hostname)s'") % dict(subject_host=subject_host, hostname=hostname)) dn = None service = None # See if the service exists and punt if it doesn't and we aren't # going to add it try: if not principal.startswith('host/'): service = api.Command['service_show'](principal, all=True, raw=True)['result'] dn = service['dn'] else: hostname = get_host_from_principal(principal) service = api.Command['host_show'](hostname, all=True, raw=True)['result'] dn = service['dn'] except errors.NotFound, e: if not add: raise errors.NotFound(reason=_("The service principal for " "this request doesn't exist.")) try: service = api.Command['service_add'](principal, **{ 'force': True })['result'] dn = service['dn'] except errors.ACIError: raise errors.ACIError( info=_('You need to be a member of ' 'the serviceadmin role to add services')) # We got this far so the service entry exists, can we write it? if not ldap.can_write(dn, "usercertificate"): raise errors.ACIError( info=_("Insufficient 'write' privilege " "to the 'userCertificate' attribute of entry '%s'.") % dn) # Validate the subject alt name, if any request = pkcs10.load_certificate_request(csr) subjectaltname = pkcs10.get_subjectaltname(request) if subjectaltname is not None: for name in subjectaltname: name = unicode(name) try: hostentry = api.Command['host_show'](name, all=True, raw=True)['result'] hostdn = hostentry['dn'] except errors.NotFound: # We don't want to issue any certificates referencing # machines we don't know about. Nothing is stored in this # host record related to this certificate. raise errors.NotFound(reason=_( 'no host record for ' 'subject alt name %s in certificate request') % name) authprincipal = getattr(context, 'principal') if authprincipal.startswith("host/"): if not hostdn in service.get('managedby', []): raise errors.ACIError(info=_( "Insufficient privilege to create a certificate " "with subject alt name '%s'.") % name) if 'usercertificate' in service: serial = x509.get_serial_number(service['usercertificate'][0], datatype=x509.DER) # revoke the certificate and remove it from the service # entry before proceeding. First we retrieve the certificate to # see if it is already revoked, if not then we revoke it. try: result = api.Command['cert_show'](unicode(serial))['result'] if 'revocation_reason' not in result: try: api.Command['cert_revoke'](unicode(serial), revocation_reason=4) except errors.NotImplementedError: # some CA's might not implement revoke pass except errors.NotImplementedError: # some CA's might not implement get pass if not principal.startswith('host/'): api.Command['service_mod'](principal, usercertificate=None) else: hostname = get_host_from_principal(principal) api.Command['host_mod'](hostname, usercertificate=None) # Request the certificate result = self.Backend.ra.request_certificate(csr, **kw) cert = x509.load_certificate(result['certificate']) result['issuer'] = unicode(cert.issuer) result['valid_not_before'] = unicode(cert.valid_not_before_str) result['valid_not_after'] = unicode(cert.valid_not_after_str) result['md5_fingerprint'] = unicode( nss.data_to_hex(nss.md5_digest(cert.der_data), 64)[0]) result['sha1_fingerprint'] = unicode( nss.data_to_hex(nss.sha1_digest(cert.der_data), 64)[0]) # Success? Then add it to the service entry. if 'certificate' in result: if not principal.startswith('host/'): skw = {"usercertificate": str(result.get('certificate'))} api.Command['service_mod'](principal, **skw) else: hostname = get_host_from_principal(principal) skw = {"usercertificate": str(result.get('certificate'))} api.Command['host_mod'](hostname, **skw) return dict(result=result)