removed merge conflicts

This commit is contained in:
sirferl 2020-09-14 08:58:31 +02:00
commit 1bdfaa9739
16 changed files with 251 additions and 69 deletions

View File

@ -172,15 +172,16 @@ Specifying the `SQLALCHEMY_MAX_OVERFLOW` to 0 will enforce limit to not create c
PUBLIC_CA_MAX_VALIDITY_DAYS = 365 PUBLIC_CA_MAX_VALIDITY_DAYS = 365
.. data:: DEFAULT_MAX_VALIDITY_DAYS .. data:: DEFAULT_VALIDITY_DAYS
:noindex: :noindex:
Use this config to override the default limit of 1095 days (3 years) of validity. Any CA which is not listed in Use this config to override the default validity of 365 days for certificates offered through Lemur UI. Any CA which
PUBLIC_CA_AUTHORITY_NAMES will be using this validity to display date range on UI. Below example overrides the is not listed in PUBLIC_CA_AUTHORITY_NAMES will be using this value as default validity to be displayed on UI. Please
default validity of 1095 days and sets it to 365 days. note that this config is used for cert issuance only through Lemur UI. Below example overrides the default validity
of 365 days and sets it to 1095 days (3 years).
:: ::
DEFAULT_MAX_VALIDITY_DAYS = 365 DEFAULT_VALIDITY_DAYS = 1095
.. data:: DEBUG_DUMP .. data:: DEBUG_DUMP

View File

@ -112,6 +112,7 @@ class RootAuthorityCertificateOutputSchema(LemurOutputSchema):
not_after = fields.DateTime() not_after = fields.DateTime()
not_before = fields.DateTime() not_before = fields.DateTime()
max_issuance_days = fields.Integer() max_issuance_days = fields.Integer()
default_validity_days = fields.Integer()
owner = fields.Email() owner = fields.Email()
status = fields.Boolean() status = fields.Boolean()
user = fields.Nested(UserNestedOutputSchema) user = fields.Nested(UserNestedOutputSchema)
@ -137,7 +138,7 @@ class AuthorityNestedOutputSchema(LemurOutputSchema):
owner = fields.Email() owner = fields.Email()
plugin = fields.Nested(PluginOutputSchema) plugin = fields.Nested(PluginOutputSchema)
active = fields.Boolean() active = fields.Boolean()
authority_certificate = fields.Nested(RootAuthorityCertificateOutputSchema, only=["max_issuance_days"]) authority_certificate = fields.Nested(RootAuthorityCertificateOutputSchema, only=["max_issuance_days", "default_validity_days"])
authority_update_schema = AuthorityUpdateSchema() authority_update_schema = AuthorityUpdateSchema()

View File

@ -9,9 +9,10 @@ from datetime import timedelta
import arrow import arrow
from cryptography import x509 from cryptography import x509
from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives.asymmetric import rsa, ec
from flask import current_app from flask import current_app
from idna.core import InvalidCodepoint from idna.core import InvalidCodepoint
from lemur.common.utils import get_key_type_from_ec_curve
from sqlalchemy import ( from sqlalchemy import (
event, event,
Integer, Integer,
@ -302,6 +303,8 @@ class Certificate(db.Model):
return "RSA{key_size}".format( return "RSA{key_size}".format(
key_size=self.parsed_cert.public_key().key_size key_size=self.parsed_cert.public_key().key_size
) )
elif isinstance(self.parsed_cert.public_key(), ec.EllipticCurvePublicKey):
return get_key_type_from_ec_curve(self.parsed_cert.public_key().curve.name)
@property @property
def validity_remaining(self): def validity_remaining(self):
@ -317,7 +320,13 @@ class Certificate(db.Model):
if self.name.lower() in [ca.lower() for ca in public_CA]: if self.name.lower() in [ca.lower() for ca in public_CA]:
return current_app.config.get("PUBLIC_CA_MAX_VALIDITY_DAYS", 397) return current_app.config.get("PUBLIC_CA_MAX_VALIDITY_DAYS", 397)
return current_app.config.get("DEFAULT_MAX_VALIDITY_DAYS", 1095) # 3 years default @property
def default_validity_days(self):
public_CA = current_app.config.get("PUBLIC_CA_AUTHORITY_NAMES", [])
if self.name.lower() in [ca.lower() for ca in public_CA]:
return current_app.config.get("PUBLIC_CA_MAX_VALIDITY_DAYS", 397)
return current_app.config.get("DEFAULT_VALIDITY_DAYS", 365) # 1 year default
@property @property
def subject(self): def subject(self):

View File

@ -148,6 +148,13 @@ class CertificateInputSchema(CertificateCreationSchema):
data["extensions"]["subAltNames"]["names"] = [] data["extensions"]["subAltNames"]["names"] = []
data["extensions"]["subAltNames"]["names"] = csr_sans data["extensions"]["subAltNames"]["names"] = csr_sans
common_name = cert_utils.get_cn_from_csr(data["csr"])
if common_name:
data["common_name"] = common_name
key_type = cert_utils.get_key_type_from_csr(data["csr"])
if key_type:
data["key_type"] = key_type
return missing.convert_validity_years(data) return missing.convert_validity_years(data)

View File

@ -12,6 +12,8 @@ Utils to parse certificate data.
from cryptography import x509 from cryptography import x509
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends import default_backend
from marshmallow.exceptions import ValidationError from marshmallow.exceptions import ValidationError
from cryptography.hazmat.primitives.asymmetric import rsa, ec
from lemur.common.utils import get_key_type_from_ec_curve
def get_sans_from_csr(data): def get_sans_from_csr(data):
@ -39,3 +41,45 @@ def get_sans_from_csr(data):
pass pass
return sub_alt_names return sub_alt_names
def get_cn_from_csr(data):
"""
Fetches common name (CN) from CSR.
Works with any kind of SubjectAlternativeName
:param data: PEM-encoded string with CSR
:return: the common name
"""
try:
request = x509.load_pem_x509_csr(data.encode("utf-8"), default_backend())
except Exception:
raise ValidationError("CSR presented is not valid.")
common_name = request.subject.get_attributes_for_oid(x509.NameOID.COMMON_NAME)
return common_name[0].value
def get_key_type_from_csr(data):
"""
Fetches key_type from CSR.
Works with any kind of SubjectAlternativeName
:param data: PEM-encoded string with CSR
:return: key_type
"""
try:
request = x509.load_pem_x509_csr(data.encode("utf-8"), default_backend())
except Exception:
raise ValidationError("CSR presented is not valid.")
try:
if isinstance(request.public_key(), rsa.RSAPublicKey):
return "RSA{key_size}".format(
key_size=request.public_key().key_size
)
elif isinstance(request.public_key(), ec.EllipticCurvePublicKey):
return get_key_type_from_ec_curve(request.public_key().curve.name)
else:
raise Exception("Unsupported key type")
except NotImplemented:
raise NotImplemented()

View File

@ -114,6 +114,39 @@ def get_authority_key(body):
return authority_key.hex() return authority_key.hex()
def get_key_type_from_ec_curve(curve_name):
"""
Give an EC curve name, return the matching key_type.
:param: curve_name
:return: key_type
"""
_CURVE_TYPES = {
ec.SECP192R1().name: "ECCPRIME192V1",
ec.SECP256R1().name: "ECCPRIME256V1",
ec.SECP224R1().name: "ECCSECP224R1",
ec.SECP384R1().name: "ECCSECP384R1",
ec.SECP521R1().name: "ECCSECP521R1",
ec.SECP256K1().name: "ECCSECP256K1",
ec.SECT163K1().name: "ECCSECT163K1",
ec.SECT233K1().name: "ECCSECT233K1",
ec.SECT283K1().name: "ECCSECT283K1",
ec.SECT409K1().name: "ECCSECT409K1",
ec.SECT571K1().name: "ECCSECT571K1",
ec.SECT163R2().name: "ECCSECT163R2",
ec.SECT233R1().name: "ECCSECT233R1",
ec.SECT283R1().name: "ECCSECT283R1",
ec.SECT409R1().name: "ECCSECT409R1",
ec.SECT571R1().name: "ECCSECT571R2",
}
if curve_name in _CURVE_TYPES.keys():
return _CURVE_TYPES[curve_name]
else:
return None
def generate_private_key(key_type): def generate_private_key(key_type):
""" """
Generates a new private key based on key_type. Generates a new private key based on key_type.
@ -128,11 +161,11 @@ def generate_private_key(key_type):
""" """
_CURVE_TYPES = { _CURVE_TYPES = {
"ECCPRIME192V1": ec.SECP192R1(), "ECCPRIME192V1": ec.SECP192R1(), # duplicate
"ECCPRIME256V1": ec.SECP256R1(), "ECCPRIME256V1": ec.SECP256R1(), # duplicate
"ECCSECP192R1": ec.SECP192R1(), "ECCSECP192R1": ec.SECP192R1(), # duplicate
"ECCSECP224R1": ec.SECP224R1(), "ECCSECP224R1": ec.SECP224R1(),
"ECCSECP256R1": ec.SECP256R1(), "ECCSECP256R1": ec.SECP256R1(), # duplicate
"ECCSECP384R1": ec.SECP384R1(), "ECCSECP384R1": ec.SECP384R1(),
"ECCSECP521R1": ec.SECP521R1(), "ECCSECP521R1": ec.SECP521R1(),
"ECCSECP256K1": ec.SECP256K1(), "ECCSECP256K1": ec.SECP256K1(),

View File

@ -18,8 +18,9 @@ import json
import arrow import arrow
import pem import pem
import requests import requests
import sys
from cryptography import x509 from cryptography import x509
from flask import current_app from flask import current_app, g
from lemur.common.utils import validate_conf from lemur.common.utils import validate_conf
from lemur.extensions import metrics from lemur.extensions import metrics
from lemur.plugins import lemur_digicert as digicert from lemur.plugins import lemur_digicert as digicert
@ -129,6 +130,9 @@ def map_fields(options, csr):
data["validity_years"] = determine_validity_years(options.get("validity_years")) data["validity_years"] = determine_validity_years(options.get("validity_years"))
elif options.get("validity_end"): elif options.get("validity_end"):
data["custom_expiration_date"] = determine_end_date(options.get("validity_end")).format("YYYY-MM-DD") data["custom_expiration_date"] = determine_end_date(options.get("validity_end")).format("YYYY-MM-DD")
# check if validity got truncated. If resultant validity is not equal to requested validity, it just got truncated
if data["custom_expiration_date"] != options.get("validity_end").format("YYYY-MM-DD"):
log_validity_truncation(options, f"{__name__}.{sys._getframe().f_code.co_name}")
else: else:
data["validity_years"] = determine_validity_years(0) data["validity_years"] = determine_validity_years(0)
@ -154,6 +158,9 @@ def map_cis_fields(options, csr):
validity_end = determine_end_date(arrow.utcnow().shift(years=options["validity_years"])) validity_end = determine_end_date(arrow.utcnow().shift(years=options["validity_years"]))
elif options.get("validity_end"): elif options.get("validity_end"):
validity_end = determine_end_date(options.get("validity_end")) validity_end = determine_end_date(options.get("validity_end"))
# check if validity got truncated. If resultant validity is not equal to requested validity, it just got truncated
if validity_end != options.get("validity_end"):
log_validity_truncation(options, f"{__name__}.{sys._getframe().f_code.co_name}")
else: else:
validity_end = determine_end_date(False) validity_end = determine_end_date(False)
@ -179,6 +186,18 @@ def map_cis_fields(options, csr):
return data return data
def log_validity_truncation(options, function):
log_data = {
"cn": options["common_name"],
"creator": g.user.username
}
metrics.send("digicert_validity_truncated", "counter", 1, metric_tags=log_data)
log_data["function"] = function
log_data["message"] = "Digicert Plugin truncated the validity of certificate"
current_app.logger.info(log_data)
def handle_response(response): def handle_response(response):
""" """
Handle the DigiCert API response and any errors it might have experienced. Handle the DigiCert API response and any errors it might have experienced.

View File

@ -3,4 +3,3 @@ try:
VERSION = __import__("pkg_resources").get_distribution(__name__).version VERSION = __import__("pkg_resources").get_distribution(__name__).version
except Exception as e: except Exception as e:
VERSION = "unknown" VERSION = "unknown"

View File

@ -3,10 +3,8 @@ import arrow
import requests import requests
import json import json
from lemur.plugins import lemur_entrust as ENTRUST from lemur.plugins import lemur_entrust as ENTRUST
from OpenSSL import crypto
from flask import current_app from flask import current_app
from lemur.extensions import metrics, sentry from lemur.extensions import metrics
def log_status_code(r, *args, **kwargs): def log_status_code(r, *args, **kwargs):
@ -20,6 +18,7 @@ def log_status_code(r, *args, **kwargs):
""" """
metrics.send("ENTRUST_status_code_{}".format(r.status_code), "counter", 1) metrics.send("ENTRUST_status_code_{}".format(r.status_code), "counter", 1)
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
@ -50,6 +49,7 @@ def process_options(options):
} }
return data return data
class EntrustIssuerPlugin(IssuerPlugin): class EntrustIssuerPlugin(IssuerPlugin):
title = "ENTRUST" title = "ENTRUST"
slug = "entrust-issuer" slug = "entrust-issuer"
@ -93,7 +93,6 @@ class EntrustIssuerPlugin(IssuerPlugin):
"Entrust-Request Data (id: {1}) : {0}".format(data, current_req) "Entrust-Request Data (id: {1}) : {0}".format(data, current_req)
) )
try: try:
response = self.session.post(url, json=data, timeout=(15, 40)) response = self.session.post(url, json=data, timeout=(15, 40))
except requests.exceptions.Timeout: except requests.exceptions.Timeout:
@ -134,7 +133,6 @@ class EntrustIssuerPlugin(IssuerPlugin):
current_app.logger.info("Creating Auth: {0} {1}".format(options, entrust_issuing)) current_app.logger.info("Creating Auth: {0} {1}".format(options, entrust_issuing))
return entrust_root, "", [role] return entrust_root, "", [role]
def revoke_certificate(self, certificate, comments): def revoke_certificate(self, certificate, comments):
raise NotImplementedError("Not implemented\n", self, certificate, comments) raise NotImplementedError("Not implemented\n", self, certificate, comments)
@ -166,7 +164,7 @@ class EntrustSourcePlugin(SourcePlugin):
def get_certificates(self, options, **kwargs): def get_certificates(self, options, **kwargs):
# Not needed for ENTRUST # Not needed for ENTRUST
raise NotImplementedError("Not implemented\n", self, options, **kwargs) raise NotImplementedError("Not implemented\n", self, options, **kwargs)
def get_endpoints(self, options, **kwargs): def get_endpoints(self, options, **kwargs):
# There are no endpoints in ENTRUST # There are no endpoints in ENTRUST
raise NotImplementedError("Not implemented\n", self, options, **kwargs) raise NotImplementedError("Not implemented\n", self, options, **kwargs)

View File

@ -107,7 +107,6 @@ angular.module('lemur')
startingDay: 1 startingDay: 1
}; };
$scope.open1 = function() { $scope.open1 = function() {
$scope.popup1.opened = true; $scope.popup1.opened = true;
}; };
@ -140,6 +139,14 @@ angular.module('lemur')
); );
$scope.create = function (certificate) { $scope.create = function (certificate) {
if(certificate.validityType === 'customDates' &&
(!certificate.validityStart || !certificate.validityEnd)) { // these are not mandatory fields in schema, thus handling validation in js
return showMissingDateError();
}
if(certificate.validityType === 'defaultDays') {
populateValidityDateAsPerDefault(certificate);
}
WizardHandler.wizard().context.loading = true; WizardHandler.wizard().context.loading = true;
CertificateService.create(certificate).then( CertificateService.create(certificate).then(
function () { function () {
@ -164,6 +171,30 @@ angular.module('lemur')
}); });
}; };
function showMissingDateError() {
let error = {};
error.message = '';
error.reasons = {};
error.reasons.validityRange = 'Valid start and end dates are needed, else select Default option';
toaster.pop({
type: 'error',
title: 'Validation Error',
body: 'lemur-bad-request',
bodyOutputType: 'directive',
directiveData: error,
timeout: 100000
});
}
function populateValidityDateAsPerDefault(certificate) {
// calculate start and end date as per default validity
let startDate = new Date(), endDate = new Date();
endDate.setDate(startDate.getDate() + certificate.authority.authorityCertificate.defaultValidityDays);
certificate.validityStart = startDate;
certificate.validityEnd = endDate;
}
$scope.templates = [ $scope.templates = [
{ {
'name': 'Client Certificate', 'name': 'Client Certificate',
@ -277,6 +308,14 @@ angular.module('lemur')
}; };
$scope.create = function (certificate) { $scope.create = function (certificate) {
if(certificate.validityType === 'customDates' &&
(!certificate.validityStart || !certificate.validityEnd)) { // these are not mandatory fields in schema, thus handling validation in js
return showMissingDateError();
}
if(certificate.validityType === 'defaultDays') {
populateValidityDateAsPerDefault(certificate);
}
WizardHandler.wizard().context.loading = true; WizardHandler.wizard().context.loading = true;
CertificateService.create(certificate).then( CertificateService.create(certificate).then(
function () { function () {
@ -301,6 +340,30 @@ angular.module('lemur')
}); });
}; };
function showMissingDateError() {
let error = {};
error.message = '';
error.reasons = {};
error.reasons.validityRange = 'Valid start and end dates are needed, else select Default option';
toaster.pop({
type: 'error',
title: 'Validation Error',
body: 'lemur-bad-request',
bodyOutputType: 'directive',
directiveData: error,
timeout: 100000
});
}
function populateValidityDateAsPerDefault(certificate) {
// calculate start and end date as per default validity
let startDate = new Date(), endDate = new Date();
endDate.setDate(startDate.getDate() + certificate.authority.authorityCertificate.defaultValidityDays);
certificate.validityStart = startDate;
certificate.validityEnd = endDate;
}
$scope.templates = [ $scope.templates = [
{ {
'name': 'Client Certificate', 'name': 'Client Certificate',

View File

@ -20,7 +20,7 @@
name="certificate signing request" name="certificate signing request"
ng-model="certificate.csr" ng-model="certificate.csr"
placeholder="PEM encoded string..." class="form-control" placeholder="PEM encoded string..." class="form-control"
ng-pattern="/^-----BEGIN CERTIFICATE REQUEST-----/"></textarea> ng-pattern="/(^-----BEGIN CERTIFICATE REQUEST-----[\S\s]*-----END CERTIFICATE REQUEST-----)|(^-----BEGIN NEW CERTIFICATE REQUEST-----[\S\s]*-----END NEW CERTIFICATE REQUEST-----)/"></textarea>
<p ng-show="trackingForm.csr.$invalid && !trackingForm.csr.$pristine" <p ng-show="trackingForm.csr.$invalid && !trackingForm.csr.$pristine"
class="help-block">Enter a valid certificate signing request.</p> class="help-block">Enter a valid certificate signing request.</p>

View File

@ -96,7 +96,7 @@
Certificate Authority Certificate Authority
</label> </label>
<div class="col-sm-10"> <div class="col-sm-10">
<ui-select class="input-md" ng-model="certificate.authority" theme="bootstrap" title="choose an authority"> <ui-select class="input-md" ng-model="certificate.authority" theme="bootstrap" title="choose an authority" ng-change="clearDates()">
<ui-select-match placeholder="select an authority...">{{$select.selected.name}}</ui-select-match> <ui-select-match placeholder="select an authority...">{{$select.selected.name}}</ui-select-match>
<ui-select-choices class="form-control" repeat="authority in authorities" <ui-select-choices class="form-control" repeat="authority in authorities"
refresh="getAuthoritiesByName($select.search)" refresh="getAuthoritiesByName($select.search)"
@ -133,22 +133,20 @@
</div> </div>
<div class="form-group" ng-hide="certificate.authority.plugin.slug == 'acme-issuer'"> <div class="form-group" ng-hide="certificate.authority.plugin.slug == 'acme-issuer'">
<label class="control-label col-sm-2" <label class="control-label col-sm-2"
uib-tooltip="If no date is selected Lemur attempts to issue a 1 year certificate"> uib-tooltip="You can select custom date range; however, we recommend continuing with default validity.">
Validity Range <span class="glyphicon glyphicon-question-sign"></span> Validity Range <span class="glyphicon glyphicon-question-sign"></span>
</label> </label>
<div class="col-sm-2"> <div class="col-sm-4">
<select ng-model="certificate.validityYears" class="form-control"> <div class="btn-group btn-group-toggle" data-toggle="buttons">
<option value="">-</option> <label class="btn btn-info" ng-model="certificate.validityType" uib-btn-radio="'defaultDays'" ng-click="clearDates()">
<option value="1">1 year</option> Default ({{certificate.authority.authorityCertificate.defaultValidityDays}} days)</label>
</select> <label class="btn btn-info" ng-model="certificate.validityType" uib-btn-radio="'customDates'" ng-change="clearDates()">Custom</label>
</div> </div>
<span style="padding-top: 15px" class="text-center col-sm-1"> </div>
<strong>or</strong> <div class="col-sm-3" ng-if="certificate.validityType==='customDates'">
</span>
<div class="col-sm-3">
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control" <input type="text" class="form-control"
uib-tooltip="yyyy/MM/dd" uib-tooltip="Start Date (yyyy/MM/dd)"
uib-datepicker-popup="yyyy/MM/dd" uib-datepicker-popup="yyyy/MM/dd"
ng-model="certificate.validityStart" ng-model="certificate.validityStart"
ng-change="certificate.setValidityEndDateRange(certificate.validityStart)" ng-change="certificate.setValidityEndDateRange(certificate.validityStart)"
@ -159,6 +157,7 @@
min-date="certificate.authority.authorityCertificate.notBefore" min-date="certificate.authority.authorityCertificate.notBefore"
alt-input-formats="altInputFormats" alt-input-formats="altInputFormats"
placeholder="Start Date" placeholder="Start Date"
readonly="true"
/> />
<span class="input-group-btn"> <span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open1()"><i <button type="button" class="btn btn-default" ng-click="open1()"><i
@ -166,10 +165,10 @@
</span> </span>
</div> </div>
</div> </div>
<div class="col-sm-3"> <div class="col-sm-3" ng-if="certificate.validityType==='customDates'">
<div class="input-group"> <div class="input-group">
<input type="text" class="form-control" <input type="text" class="form-control"
uib-tooltip="yyyy/MM/dd" uib-tooltip="End Date (yyyy/MM/dd)"
uib-datepicker-popup="yyyy/MM/dd" uib-datepicker-popup="yyyy/MM/dd"
ng-model="certificate.validityEnd" ng-model="certificate.validityEnd"
is-open="popup2.opened" is-open="popup2.opened"
@ -179,6 +178,7 @@
min-date="certificate.authority.authorityCertificate.minValidityEnd" min-date="certificate.authority.authorityCertificate.minValidityEnd"
alt-input-formats="altInputFormats" alt-input-formats="altInputFormats"
placeholder="End Date" placeholder="End Date"
readonly="true"
/> />
<span class="input-group-btn"> <span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="open2()"><i <button type="button" class="btn btn-default" ng-click="open2()"><i
@ -186,10 +186,6 @@
</span> </span>
</div> </div>
</div> </div>
<div class="col-sm-1">
<button uib-tooltip="Clear Validity" ng-click="clearDates()" class="btn btn-default"><i
class="glyphicon glyphicon-remove"></i></button>
</div>
</div> </div>
<div class="form-group" ng-show="certificate.authority.plugin.slug == 'acme-issuer'"> <div class="form-group" ng-show="certificate.authority.plugin.slug == 'acme-issuer'">
<label class="control-label col-sm-2"> <label class="control-label col-sm-2">

View File

@ -167,18 +167,20 @@ angular.module('lemur')
}, },
setValidityEndDateRange: function (value) { setValidityEndDateRange: function (value) {
// clear selected validity end date as we are about to calculate new range // clear selected validity end date as we are about to calculate new range
if(this.validityEnd) {
this.validityEnd = ''; this.validityEnd = '';
}
// Minimum end date will be same as selected start date // Minimum end date will be same as selected start date
this.authority.authorityCertificate.minValidityEnd = value; this.authority.authorityCertificate.minValidityEnd = value;
if(!this.authority.authorityCertificate || !this.authority.authorityCertificate.maxIssuanceDays) {
this.authority.authorityCertificate.maxValidityEnd = this.authority.authorityCertificate.notAfter;
} else {
// Move max end date by maxIssuanceDays // Move max end date by maxIssuanceDays
let endDate = new Date(value); let endDate = new Date(value);
endDate.setDate(endDate.getDate() + this.authority.authorityCertificate.maxIssuanceDays); endDate.setDate(endDate.getDate() + this.authority.authorityCertificate.maxIssuanceDays);
this.authority.authorityCertificate.maxValidityEnd = endDate; this.authority.authorityCertificate.maxValidityEnd = endDate;
} }
}
}); });
}); });
return LemurRestangular.all('certificates'); return LemurRestangular.all('certificates');
@ -195,7 +197,7 @@ angular.module('lemur')
CertificateService.create = function (certificate) { CertificateService.create = function (certificate) {
certificate.attachSubAltName(); certificate.attachSubAltName();
certificate.attachCustom(); certificate.attachCustom();
if (certificate.validityYears === '') { // if a user de-selects validity years we ignore it if (certificate.validityYears === '') { // if a user de-selects validity years we ignore it - might not be needed anymore
delete certificate.validityYears; delete certificate.validityYears;
} }
return CertificateApi.post(certificate); return CertificateApi.post(certificate);
@ -281,6 +283,9 @@ angular.module('lemur')
certificate.authority.authorityCertificate.minValidityEnd = defaults.authority.authorityCertificate.notBefore; certificate.authority.authorityCertificate.minValidityEnd = defaults.authority.authorityCertificate.notBefore;
certificate.authority.authorityCertificate.maxValidityEnd = defaults.authority.authorityCertificate.notAfter; certificate.authority.authorityCertificate.maxValidityEnd = defaults.authority.authorityCertificate.notAfter;
// pre-select validity type radio button to default days
certificate.validityType = 'defaultDays';
if (certificate.dnsProviderId) { if (certificate.dnsProviderId) {
certificate.dnsProvider = {id: certificate.dnsProviderId}; certificate.dnsProvider = {id: certificate.dnsProviderId};
} }

View File

@ -147,18 +147,20 @@ angular.module('lemur')
}, },
setValidityEndDateRange: function (value) { setValidityEndDateRange: function (value) {
// clear selected validity end date as we are about to calculate new range // clear selected validity end date as we are about to calculate new range
if(this.validityEnd) {
this.validityEnd = ''; this.validityEnd = '';
}
// Minimum end date will be same as selected start date // Minimum end date will be same as selected start date
this.authority.authorityCertificate.minValidityEnd = value; this.authority.authorityCertificate.minValidityEnd = value;
if(!this.authority.authorityCertificate || !this.authority.authorityCertificate.maxIssuanceDays) {
this.authority.authorityCertificate.maxValidityEnd = this.authority.authorityCertificate.notAfter;
} else {
// Move max end date by maxIssuanceDays // Move max end date by maxIssuanceDays
let endDate = new Date(value); let endDate = new Date(value);
endDate.setDate(endDate.getDate() + this.authority.authorityCertificate.maxIssuanceDays); endDate.setDate(endDate.getDate() + this.authority.authorityCertificate.maxIssuanceDays);
this.authority.authorityCertificate.maxValidityEnd = endDate; this.authority.authorityCertificate.maxValidityEnd = endDate;
} }
}
}); });
}); });
return LemurRestangular.all('pending_certificates'); return LemurRestangular.all('pending_certificates');

View File

@ -11,6 +11,12 @@ from lemur.tests.vectors import (
) )
def test_get_key_type_from_ec_curve():
from lemur.common.utils import get_key_type_from_ec_curve
assert get_key_type_from_ec_curve("secp256r1") == "ECCPRIME256V1"
def test_generate_private_key(): def test_generate_private_key():
from lemur.common.utils import generate_private_key from lemur.common.utils import generate_private_key

View File

@ -156,7 +156,6 @@ setup(
'adcs_source = lemur.plugins.lemur_adcs.plugin:ADCSSourcePlugin', 'adcs_source = lemur.plugins.lemur_adcs.plugin:ADCSSourcePlugin',
'entrust_issuer = lemur.plugins.lemur_entrust.plugin:EntrustIssuerPlugin', 'entrust_issuer = lemur.plugins.lemur_entrust.plugin:EntrustIssuerPlugin',
'entrust_source = lemur.plugins.lemur_entrust.plugin:EntrustSourcePlugin' 'entrust_source = lemur.plugins.lemur_entrust.plugin:EntrustSourcePlugin'
], ],
}, },
classifiers=[ classifiers=[