parent
f13a3505f3
commit
bc94353850
|
@ -233,34 +233,46 @@ class Certificate(db.Model):
|
||||||
return_extensions = {}
|
return_extensions = {}
|
||||||
cert = lemur.common.utils.parse_certificate(self.body)
|
cert = lemur.common.utils.parse_certificate(self.body)
|
||||||
for extension in cert.extensions:
|
for extension in cert.extensions:
|
||||||
if isinstance(extension, x509.BasicConstraints):
|
value = extension.value
|
||||||
return_extensions['basic_constraints'] = extension
|
if isinstance(value, x509.BasicConstraints):
|
||||||
elif isinstance(extension, x509.SubjectAlternativeName):
|
return_extensions['basic_constraints'] = extension.value
|
||||||
return_extensions['sub_alt_names'] = extension
|
|
||||||
elif isinstance(extension, x509.ExtendedKeyUsage):
|
elif isinstance(value, x509.SubjectAlternativeName):
|
||||||
return_extensions['extended_key_usage'] = extension
|
return_extensions['sub_alt_names'] = {'names': extension.value}
|
||||||
elif isinstance(extension, x509.KeyUsage):
|
|
||||||
return_extensions['key_usage'] = extension
|
elif isinstance(value, x509.ExtendedKeyUsage):
|
||||||
elif isinstance(extension, x509.SubjectKeyIdentifier):
|
return_extensions['extended_key_usage'] = extension.value
|
||||||
|
|
||||||
|
elif isinstance(value, x509.KeyUsage):
|
||||||
|
return_extensions['key_usage'] = extension.value
|
||||||
|
|
||||||
|
elif isinstance(value, x509.SubjectKeyIdentifier):
|
||||||
return_extensions['subject_key_identifier'] = {'include_ski': True}
|
return_extensions['subject_key_identifier'] = {'include_ski': True}
|
||||||
elif isinstance(extension, x509.AuthorityInformationAccess):
|
|
||||||
|
elif isinstance(value, x509.AuthorityInformationAccess):
|
||||||
return_extensions['certificate_info_access'] = {'include_aia': True}
|
return_extensions['certificate_info_access'] = {'include_aia': True}
|
||||||
elif isinstance(extension, x509.AuthorityKeyIdentifier):
|
|
||||||
|
elif isinstance(value, x509.AuthorityKeyIdentifier):
|
||||||
aki = {
|
aki = {
|
||||||
'use_key_identifier': False,
|
'use_key_identifier': False,
|
||||||
'use_authority_cert': False
|
'use_authority_cert': False
|
||||||
}
|
}
|
||||||
if extension.key_identifier:
|
|
||||||
|
if value.key_identifier:
|
||||||
aki['use_key_identifier'] = True
|
aki['use_key_identifier'] = True
|
||||||
if extension.authority_cert_issuer:
|
|
||||||
|
if value.authority_cert_issuer:
|
||||||
aki['use_authority_cert'] = True
|
aki['use_authority_cert'] = True
|
||||||
|
|
||||||
return_extensions['authority_key_identifier'] = aki
|
return_extensions['authority_key_identifier'] = aki
|
||||||
elif isinstance(extension, x509.CRLDistributionPoints):
|
|
||||||
# FIXME: Don't support CRLDistributionPoints yet https://github.com/Netflix/lemur/issues/662
|
# TODO: Don't support CRLDistributionPoints yet https://github.com/Netflix/lemur/issues/662
|
||||||
pass
|
elif isinstance(value, x509.CRLDistributionPoints):
|
||||||
|
current_app.logger.warning('CRLDistributionPoints not yet supported for clone operation.')
|
||||||
|
|
||||||
|
# TODO: Not supporting custom OIDs yet. https://github.com/Netflix/lemur/issues/665
|
||||||
else:
|
else:
|
||||||
# FIXME: Not supporting custom OIDs yet. https://github.com/Netflix/lemur/issues/665
|
current_app.logger.warning('Custom OIDs not yet supported for clone operation.')
|
||||||
pass
|
|
||||||
|
|
||||||
return return_extensions
|
return return_extensions
|
||||||
|
|
||||||
|
|
|
@ -330,10 +330,8 @@ def create_csr(**csr_config):
|
||||||
|
|
||||||
:param csr_config:
|
:param csr_config:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
private_key = generate_private_key(csr_config.get('key_type'))
|
private_key = generate_private_key(csr_config.get('key_type'))
|
||||||
|
|
||||||
# TODO When we figure out a better way to validate these options they should be parsed as str
|
|
||||||
builder = x509.CertificateSigningRequestBuilder()
|
builder = x509.CertificateSigningRequestBuilder()
|
||||||
builder = builder.subject_name(x509.Name([
|
builder = builder.subject_name(x509.Name([
|
||||||
x509.NameAttribute(x509.OID_COMMON_NAME, csr_config['common_name']),
|
x509.NameAttribute(x509.OID_COMMON_NAME, csr_config['common_name']),
|
||||||
|
@ -349,12 +347,17 @@ def create_csr(**csr_config):
|
||||||
critical_extensions = ['basic_constraints', 'sub_alt_names', 'key_usage']
|
critical_extensions = ['basic_constraints', 'sub_alt_names', 'key_usage']
|
||||||
noncritical_extensions = ['extended_key_usage']
|
noncritical_extensions = ['extended_key_usage']
|
||||||
for k, v in extensions.items():
|
for k, v in extensions.items():
|
||||||
if k in critical_extensions and v:
|
if v:
|
||||||
current_app.logger.debug("Add CExt: {0} {1}".format(k, v))
|
if k in critical_extensions:
|
||||||
builder = builder.add_extension(v, critical=True)
|
current_app.logger.debug('Adding Critical Extension: {0} {1}'.format(k, v))
|
||||||
if k in noncritical_extensions and v:
|
if k == 'sub_alt_names':
|
||||||
current_app.logger.debug("Add Ext: {0} {1}".format(k, v))
|
builder = builder.add_extension(v['names'], critical=True)
|
||||||
builder = builder.add_extension(v, critical=False)
|
else:
|
||||||
|
builder = builder.add_extension(v, critical=True)
|
||||||
|
|
||||||
|
if k in noncritical_extensions:
|
||||||
|
current_app.logger.debug('Adding Extension: {0} {1}'.format(k, v))
|
||||||
|
builder = builder.add_extension(v, critical=False)
|
||||||
|
|
||||||
ski = extensions.get('subject_key_identifier', {})
|
ski = extensions.get('subject_key_identifier', {})
|
||||||
if ski.get('include_ski', False):
|
if ski.get('include_ski', False):
|
||||||
|
|
|
@ -131,23 +131,24 @@ class KeyUsageExtension(Field):
|
||||||
'encipher_only': False,
|
'encipher_only': False,
|
||||||
'decipher_only': False
|
'decipher_only': False
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v in value.items():
|
for k, v in value.items():
|
||||||
if k == 'useDigitalSignature':
|
if k == 'useDigitalSignature':
|
||||||
keyusages['digital_signature'] = v
|
keyusages['digital_signature'] = v
|
||||||
if k == 'useNonRepudiation':
|
elif k == 'useNonRepudiation':
|
||||||
keyusages['content_commitment'] = v
|
keyusages['content_commitment'] = v
|
||||||
if k == 'useKeyEncipherment':
|
elif k == 'useKeyEncipherment':
|
||||||
keyusages['key_encipherment'] = v
|
keyusages['key_encipherment'] = v
|
||||||
if k == 'useDataEncipherment':
|
elif k == 'useDataEncipherment':
|
||||||
keyusages['data_encipherment'] = v
|
keyusages['data_encipherment'] = v
|
||||||
if k == 'useKeyCertSign':
|
elif k == 'useKeyCertSign':
|
||||||
keyusages['key_cert_sign'] = v
|
keyusages['key_cert_sign'] = v
|
||||||
if k == 'useCrlSign':
|
elif k == 'useCrlSign':
|
||||||
keyusages['crl_sign'] = v
|
keyusages['crl_sign'] = v
|
||||||
if k == 'useEncipherOnly' and v:
|
elif k == 'useEncipherOnly' and v:
|
||||||
keyusages['encipher_only'] = True
|
keyusages['encipher_only'] = True
|
||||||
keyusages['key_agreement'] = True
|
keyusages['key_agreement'] = True
|
||||||
if k == 'useDecipherOnly' and v:
|
elif k == 'useDecipherOnly' and v:
|
||||||
keyusages['decipher_only'] = True
|
keyusages['decipher_only'] = True
|
||||||
keyusages['key_agreement'] = True
|
keyusages['key_agreement'] = True
|
||||||
|
|
||||||
|
@ -182,23 +183,23 @@ class ExtendedKeyUsageExtension(Field):
|
||||||
usage_list = {}
|
usage_list = {}
|
||||||
for usage in usages:
|
for usage in usages:
|
||||||
if usage.dotted_string == x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH:
|
if usage.dotted_string == x509.oid.ExtendedKeyUsageOID.CLIENT_AUTH:
|
||||||
usage_list["useClientAuthentication"] = True
|
usage_list['useClientAuthentication'] = True
|
||||||
if usage.dotted_string == x509.oid.ExtendedKeyUsageOID.SERVER_AUTH:
|
if usage.dotted_string == x509.oid.ExtendedKeyUsageOID.SERVER_AUTH:
|
||||||
usage_list["useServerAuthentication"] = True
|
usage_list['useServerAuthentication'] = True
|
||||||
if usage.dotted_string == x509.oid.ExtendedKeyUsageOID.CODE_SIGNING:
|
if usage.dotted_string == x509.oid.ExtendedKeyUsageOID.CODE_SIGNING:
|
||||||
usage_list["useCodeSigning"] = True
|
usage_list['useCodeSigning'] = True
|
||||||
if usage.dotted_string == x509.oid.ExtendedKeyUsageOID.EMAIL_PROTECTION:
|
if usage.dotted_string == x509.oid.ExtendedKeyUsageOID.EMAIL_PROTECTION:
|
||||||
usage_list["useEmailProtection"] = True
|
usage_list['useEmailProtection'] = True
|
||||||
if usage.dotted_string == x509.oid.ExtendedKeyUsageOID.TIME_STAMPING:
|
if usage.dotted_string == x509.oid.ExtendedKeyUsageOID.TIME_STAMPING:
|
||||||
usage_list["useTimestamping"] = True
|
usage_list['useTimestamping'] = True
|
||||||
if usage.dotted_string == x509.oid.ExtendedKeyUsageOID.OCSP_SIGNING:
|
if usage.dotted_string == x509.oid.ExtendedKeyUsageOID.OCSP_SIGNING:
|
||||||
usage_list["useOCSPSigning"] = True
|
usage_list['useOCSPSigning'] = True
|
||||||
if usage.dotted_string == "1.3.6.1.5.5.7.3.14":
|
if usage.dotted_string == '1.3.6.1.5.5.7.3.14':
|
||||||
usage_list["useEapOverLAN"] = True
|
usage_list['useEapOverLAN'] = True
|
||||||
if usage.dotted_string == "1.3.6.1.5.5.7.3.13":
|
if usage.dotted_string == '1.3.6.1.5.5.7.3.13':
|
||||||
usage_list["useEapOverPPP"] = True
|
usage_list['useEapOverPPP'] = True
|
||||||
if usage.dotted_string == "1.3.6.1.4.1.311.20.2.2":
|
if usage.dotted_string == '1.3.6.1.4.1.311.20.2.2':
|
||||||
usage_list["useSmartCardLogon"] = True
|
usage_list['useSmartCardLogon'] = True
|
||||||
|
|
||||||
return usage_list
|
return usage_list
|
||||||
|
|
||||||
|
@ -238,7 +239,7 @@ class BasicConstraintsExtension(Field):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _serialize(self, value, attr, obj):
|
def _serialize(self, value, attr, obj):
|
||||||
return {'ca': value.ca(), 'path_length': value.path_length()}
|
return {'ca': value.ca, 'path_length': value.path_length}
|
||||||
|
|
||||||
def _deserialize(self, value, attr, data):
|
def _deserialize(self, value, attr, data):
|
||||||
ca = value.get('ca', False)
|
ca = value.get('ca', False)
|
||||||
|
@ -261,16 +262,15 @@ class SubjectAlternativeNameExtension(Field):
|
||||||
:param kwargs: The same keyword arguments that :class:`Field` receives.
|
:param kwargs: The same keyword arguments that :class:`Field` receives.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _serialize(self, value, attr, obj):
|
def _serialize(self, value, attr, obj):
|
||||||
general_names = []
|
general_names = []
|
||||||
|
name_type = None
|
||||||
for name in value._general_names:
|
for name in value._general_names:
|
||||||
value = name.value()
|
value = name.value
|
||||||
if isinstance(name, x509.DNSName):
|
if isinstance(name, x509.DNSName):
|
||||||
name_type = 'DNSName'
|
name_type = 'DNSName'
|
||||||
if isinstance(name, x509.IPAddress):
|
if isinstance(name, x509.IPAddress):
|
||||||
name_type = 'IPAddress'
|
name_type = 'IPAddress'
|
||||||
value = str(value)
|
|
||||||
if isinstance(name, x509.UniformResourceIdentifier):
|
if isinstance(name, x509.UniformResourceIdentifier):
|
||||||
name_type = 'uniformResourceIdentifier'
|
name_type = 'uniformResourceIdentifier'
|
||||||
if isinstance(name, x509.DirectoryName):
|
if isinstance(name, x509.DirectoryName):
|
||||||
|
@ -286,7 +286,7 @@ class SubjectAlternativeNameExtension(Field):
|
||||||
|
|
||||||
def _deserialize(self, value, attr, data):
|
def _deserialize(self, value, attr, data):
|
||||||
general_names = []
|
general_names = []
|
||||||
for name in value.get('names', []):
|
for name in value:
|
||||||
if name['nameType'] == 'DNSName':
|
if name['nameType'] == 'DNSName':
|
||||||
general_names.append(x509.DNSName(name['value']))
|
general_names.append(x509.DNSName(name['value']))
|
||||||
if name['nameType'] == 'IPAddress':
|
if name['nameType'] == 'IPAddress':
|
||||||
|
@ -296,7 +296,7 @@ class SubjectAlternativeNameExtension(Field):
|
||||||
if name['nameType'] == 'uniformResourceIdentifier':
|
if name['nameType'] == 'uniformResourceIdentifier':
|
||||||
general_names.append(x509.UniformResourceIdentifier(name['value']))
|
general_names.append(x509.UniformResourceIdentifier(name['value']))
|
||||||
if name['nameType'] == 'directoryName':
|
if name['nameType'] == 'directoryName':
|
||||||
# FIXME: Need to parse a string in name['value'] like:
|
# TODO: Need to parse a string in name['value'] like:
|
||||||
# 'CN=Common Name, O=Org Name, OU=OrgUnit Name, C=US, ST=ST, L=City/emailAddress=person@example.com'
|
# 'CN=Common Name, O=Org Name, OU=OrgUnit Name, C=US, ST=ST, L=City/emailAddress=person@example.com'
|
||||||
# or
|
# or
|
||||||
# 'CN=Common Name/O=Org Name/OU=OrgUnit Name/C=US/ST=NH/L=City/emailAddress=person@example.com'
|
# 'CN=Common Name/O=Org Name/OU=OrgUnit Name/C=US/ST=NH/L=City/emailAddress=person@example.com'
|
||||||
|
@ -327,7 +327,4 @@ class SubjectAlternativeNameExtension(Field):
|
||||||
# The Python Cryptography library doesn't support EDIPartyName types (yet?)
|
# The Python Cryptography library doesn't support EDIPartyName types (yet?)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if general_names:
|
return x509.SubjectAlternativeName(general_names)
|
||||||
return x509.SubjectAlternativeName(general_names)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
|
@ -22,13 +22,14 @@ from retrying import retry
|
||||||
|
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
|
||||||
|
from cryptography import x509
|
||||||
|
|
||||||
from lemur.extensions import metrics
|
from lemur.extensions import metrics
|
||||||
|
from lemur.common.utils import validate_conf
|
||||||
from lemur.plugins.bases import IssuerPlugin, SourcePlugin
|
from lemur.plugins.bases import IssuerPlugin, SourcePlugin
|
||||||
|
|
||||||
from lemur.plugins import lemur_digicert as digicert
|
from lemur.plugins import lemur_digicert as digicert
|
||||||
|
|
||||||
from lemur.common.utils import validate_conf
|
|
||||||
|
|
||||||
|
|
||||||
def log_status_code(r, *args, **kwargs):
|
def log_status_code(r, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -106,7 +107,8 @@ def get_additional_names(options):
|
||||||
# add SANs if present
|
# add SANs if present
|
||||||
if options.get('extensions'):
|
if options.get('extensions'):
|
||||||
for san in options['extensions']['sub_alt_names']['names']:
|
for san in options['extensions']['sub_alt_names']['names']:
|
||||||
names.append(san['value'])
|
if isinstance(san, x509.DNSName):
|
||||||
|
names.append(san.value)
|
||||||
return names
|
return names
|
||||||
|
|
||||||
|
|
||||||
|
@ -119,19 +121,14 @@ def map_fields(options, csr):
|
||||||
"""
|
"""
|
||||||
options = get_issuance(options)
|
options = get_issuance(options)
|
||||||
|
|
||||||
data = {
|
data = dict(certificate={
|
||||||
"certificate":
|
"common_name": options['common_name'],
|
||||||
{
|
"csr": csr,
|
||||||
"common_name": options['common_name'],
|
"signature_hash":
|
||||||
"csr": csr,
|
signature_hash(options.get('signing_algorithm')),
|
||||||
"signature_hash":
|
}, organization={
|
||||||
signature_hash(options.get('signing_algorithm')),
|
"id": current_app.config.get("DIGICERT_ORG_ID")
|
||||||
},
|
})
|
||||||
"organization":
|
|
||||||
{
|
|
||||||
"id": current_app.config.get("DIGICERT_ORG_ID")
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
data['certificate']['dns_names'] = get_additional_names(options)
|
data['certificate']['dns_names'] = get_additional_names(options)
|
||||||
data['custom_expiration_date'] = options['validity_end'].format('YYYY-MM-DD')
|
data['custom_expiration_date'] = options['validity_end'].format('YYYY-MM-DD')
|
||||||
|
|
|
@ -4,6 +4,8 @@ from freezegun import freeze_time
|
||||||
|
|
||||||
from lemur.tests.vectors import CSR_STR
|
from lemur.tests.vectors import CSR_STR
|
||||||
|
|
||||||
|
from cryptography import x509
|
||||||
|
|
||||||
|
|
||||||
def test_map_fields(app):
|
def test_map_fields(app):
|
||||||
from lemur.plugins.lemur_digicert.plugin import map_fields
|
from lemur.plugins.lemur_digicert.plugin import map_fields
|
||||||
|
@ -16,7 +18,7 @@ def test_map_fields(app):
|
||||||
'description': 'test certificate',
|
'description': 'test certificate',
|
||||||
'extensions': {
|
'extensions': {
|
||||||
'sub_alt_names': {
|
'sub_alt_names': {
|
||||||
'names': [{'name_type': 'DNSName', 'value': x} for x in names]
|
'names': [x509.DNSName(x) for x in names]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'validity_end': arrow.get(2017, 5, 7),
|
'validity_end': arrow.get(2017, 5, 7),
|
||||||
|
@ -48,7 +50,7 @@ def test_map_cis_fields(app):
|
||||||
'description': 'test certificate',
|
'description': 'test certificate',
|
||||||
'extensions': {
|
'extensions': {
|
||||||
'sub_alt_names': {
|
'sub_alt_names': {
|
||||||
'names': [{'name_type': 'DNSName', 'value': x} for x in names]
|
'names': [x509.DNSName(x) for x in names]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'organization': 'Example, Inc.',
|
'organization': 'Example, Inc.',
|
||||||
|
|
|
@ -13,6 +13,7 @@ import xmltodict
|
||||||
|
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
|
||||||
|
from cryptography import x509
|
||||||
from lemur.extensions import metrics
|
from lemur.extensions import metrics
|
||||||
|
|
||||||
from lemur.plugins import lemur_verisign as verisign
|
from lemur.plugins import lemur_verisign as verisign
|
||||||
|
@ -76,6 +77,22 @@ def log_status_code(r, *args, **kwargs):
|
||||||
metrics.send('symantec_status_code_{}'.format(r.status_code), 'counter', 1)
|
metrics.send('symantec_status_code_{}'.format(r.status_code), 'counter', 1)
|
||||||
|
|
||||||
|
|
||||||
|
def get_additional_names(options):
|
||||||
|
"""
|
||||||
|
Return a list of strings to be added to a SAN certificates.
|
||||||
|
|
||||||
|
:param options:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
names = []
|
||||||
|
# add SANs if present
|
||||||
|
if options.get('extensions'):
|
||||||
|
for san in options['extensions']['sub_alt_names']:
|
||||||
|
if isinstance(san, x509.DNSName):
|
||||||
|
names.append(san.value)
|
||||||
|
return names
|
||||||
|
|
||||||
|
|
||||||
def process_options(options):
|
def process_options(options):
|
||||||
"""
|
"""
|
||||||
Processes and maps the incoming issuer options to fields/options that
|
Processes and maps the incoming issuer options to fields/options that
|
||||||
|
@ -94,9 +111,7 @@ def process_options(options):
|
||||||
'email': current_app.config.get("VERISIGN_EMAIL")
|
'email': current_app.config.get("VERISIGN_EMAIL")
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.get('extensions'):
|
data['subject_alt_names'] = ",".join(get_additional_names(options))
|
||||||
if options['extensions'].get('sub_alt_names'):
|
|
||||||
data['subject_alt_names'] = ",".join(x['value'] for x in options['extensions']['sub_alt_names']['names'])
|
|
||||||
|
|
||||||
if options.get('validity_end'):
|
if options.get('validity_end'):
|
||||||
period = get_default_issuance(options)
|
period = get_default_issuance(options)
|
||||||
|
|
|
@ -195,12 +195,16 @@ class CustomOIDSchema(BaseExtensionSchema):
|
||||||
is_critical = fields.Boolean()
|
is_critical = fields.Boolean()
|
||||||
|
|
||||||
|
|
||||||
|
class NamesSchema(BaseExtensionSchema):
|
||||||
|
names = SubjectAlternativeNameExtension()
|
||||||
|
|
||||||
|
|
||||||
class ExtensionSchema(BaseExtensionSchema):
|
class ExtensionSchema(BaseExtensionSchema):
|
||||||
basic_constraints = BasicConstraintsExtension()
|
basic_constraints = BasicConstraintsExtension()
|
||||||
key_usage = KeyUsageExtension()
|
key_usage = KeyUsageExtension()
|
||||||
extended_key_usage = ExtendedKeyUsageExtension()
|
extended_key_usage = ExtendedKeyUsageExtension()
|
||||||
subject_key_identifier = fields.Nested(SubjectKeyIdentifierSchema)
|
subject_key_identifier = fields.Nested(SubjectKeyIdentifierSchema)
|
||||||
sub_alt_names = SubjectAlternativeNameExtension()
|
sub_alt_names = fields.Nested(NamesSchema)
|
||||||
authority_key_identifier = fields.Nested(AuthorityKeyIdentifierSchema)
|
authority_key_identifier = fields.Nested(AuthorityKeyIdentifierSchema)
|
||||||
certificate_info_access = fields.Nested(CertificateInfoAccessSchema)
|
certificate_info_access = fields.Nested(CertificateInfoAccessSchema)
|
||||||
# FIXME: Convert custom OIDs to a custom field in fields.py like other Extensions
|
# FIXME: Convert custom OIDs to a custom field in fields.py like other Extensions
|
||||||
|
|
|
@ -26,40 +26,6 @@
|
||||||
class="help-block">Enter a valid certificate signing request.</p>
|
class="help-block">Enter a valid certificate signing request.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
|
||||||
<label class="control-label col-sm-2">
|
|
||||||
Subject Alternate Names
|
|
||||||
</label>
|
|
||||||
<div class="col-sm-3">
|
|
||||||
<select class="form-control" ng-model="certificate.subAltType"
|
|
||||||
ng-options="item for item in ['DNSName', 'IPAddress', 'IPNetwork', 'uniformResourceIdentifier', 'directoryName','rfc822Name', 'registeredID']"></select>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<div class="input-group">
|
|
||||||
<input tooltip-trigger="focus" tooltip-placement="top"
|
|
||||||
uib-tooltip="String or Base64-encoded DER ASN.1 structure for the value" class="form-control"
|
|
||||||
name="value" ng-model="certificate.subAltValue" placeholder="Value" class="form-control" required/>
|
|
||||||
<span class="input-group-btn">
|
|
||||||
<button ng-click="certificate.attachSubAltName()" class="btn btn-info">Add</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="col-sm-10 col-sm-offset-2">
|
|
||||||
<table class="table">
|
|
||||||
<tr ng-repeat="alt in certificate.extensions.subAltNames.names track by $index">
|
|
||||||
<td>{{ alt.nameType }}</td>
|
|
||||||
<td>{{ alt.value }}</td>
|
|
||||||
<td>
|
|
||||||
<button type="button" ng-click="certificate.removeSubAltName($index)"
|
|
||||||
class="btn btn-danger btn-sm pull-right">Remove
|
|
||||||
</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="control-label col-sm-2">
|
<label class="control-label col-sm-2">
|
||||||
Key Type
|
Key Type
|
||||||
|
|
|
@ -40,6 +40,40 @@
|
||||||
enter a common name and it must be less than 64 characters</p>
|
enter a common name and it must be less than 64 characters</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="control-label col-sm-2">
|
||||||
|
Subject Alternate Names
|
||||||
|
</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<select class="form-control" ng-model="certificate.subAltType"
|
||||||
|
ng-options="item for item in ['DNSName', 'IPAddress', 'IPNetwork', 'uniformResourceIdentifier', 'directoryName','rfc822Name', 'registeredID']"></select>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<div class="input-group">
|
||||||
|
<input tooltip-trigger="focus" tooltip-placement="top"
|
||||||
|
uib-tooltip="String or Base64-encoded DER ASN.1 structure for the value" class="form-control"
|
||||||
|
name="value" ng-model="certificate.subAltValue" placeholder="Value" class="form-control" required/>
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button ng-click="certificate.attachSubAltName()" class="btn btn-info">Add</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-10 col-sm-offset-2">
|
||||||
|
<table class="table">
|
||||||
|
<tr ng-repeat="alt in certificate.extensions.subAltNames.names track by $index">
|
||||||
|
<td>{{ alt.nameType }}</td>
|
||||||
|
<td>{{ alt.value }}</td>
|
||||||
|
<td>
|
||||||
|
<button type="button" ng-click="certificate.removeSubAltName($index)"
|
||||||
|
class="btn btn-danger btn-sm pull-right">Remove
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group"
|
<div class="form-group"
|
||||||
ng-class="{'has-error': trackingForm.description.$invalid, 'has-success': !trackingForm.$invalid&&trackingForm.description.$dirty}">
|
ng-class="{'has-error': trackingForm.description.$invalid, 'has-success': !trackingForm.$invalid&&trackingForm.description.$dirty}">
|
||||||
<label class="control-label col-sm-2">
|
<label class="control-label col-sm-2">
|
||||||
|
|
|
@ -310,7 +310,7 @@ def test_create_csr():
|
||||||
assert csr
|
assert csr
|
||||||
assert private_key
|
assert private_key
|
||||||
|
|
||||||
extensions = {'sub_alt_names': x509.SubjectAlternativeName([x509.DNSName('AnotherCommonName')])}
|
extensions = {'sub_alt_names': {'names': x509.SubjectAlternativeName([x509.DNSName('AnotherCommonName')])}}
|
||||||
csr, private_key = create_csr(owner='joe@example.com', common_name='ACommonName', organization='test', organizational_unit='Meters', country='US',
|
csr, private_key = create_csr(owner='joe@example.com', common_name='ACommonName', organization='test', organizational_unit='Meters', country='US',
|
||||||
state='CA', location='Here', extensions=extensions, key_type='RSA2048')
|
state='CA', location='Here', extensions=extensions, key_type='RSA2048')
|
||||||
assert csr
|
assert csr
|
||||||
|
|
Loading…
Reference in New Issue