2016-11-07 23:40:00 +01:00
|
|
|
"""
|
2016-12-14 18:29:04 +01:00
|
|
|
.. module: lemur.plugins.lemur_digicert.plugin
|
2016-11-07 23:40:00 +01:00
|
|
|
:platform: Unix
|
|
|
|
:synopsis: This module is responsible for communicating with the DigiCert '
|
|
|
|
Advanced API.
|
|
|
|
:license: Apache, see LICENSE for more details.
|
|
|
|
|
|
|
|
DigiCert CertCentral (v2 API) Documentation
|
|
|
|
https://www.digicert.com/services/v2/documentation
|
|
|
|
|
|
|
|
Original Implementation:
|
|
|
|
Chris Dorros, github.com/opendns/lemur-digicert
|
|
|
|
|
|
|
|
.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
|
|
|
|
"""
|
|
|
|
import json
|
|
|
|
|
2020-03-03 23:29:17 +01:00
|
|
|
import arrow
|
2016-11-07 23:40:00 +01:00
|
|
|
import pem
|
2020-03-03 23:29:17 +01:00
|
|
|
import requests
|
2020-09-01 03:20:32 +02:00
|
|
|
import sys
|
2017-01-28 06:05:25 +01:00
|
|
|
from cryptography import x509
|
2020-09-01 03:20:32 +02:00
|
|
|
from flask import current_app, g
|
2020-10-08 05:06:20 +02:00
|
|
|
from lemur.common.utils import validate_conf, convert_pkcs7_bytes_to_pem
|
2020-03-03 23:29:17 +01:00
|
|
|
from lemur.extensions import metrics
|
2016-11-07 23:40:00 +01:00
|
|
|
from lemur.plugins import lemur_digicert as digicert
|
2020-03-03 23:29:17 +01:00
|
|
|
from lemur.plugins.bases import IssuerPlugin, SourcePlugin
|
|
|
|
from retrying import retry
|
2016-11-07 23:40:00 +01:00
|
|
|
|
|
|
|
|
2016-12-02 22:02:59 +01:00
|
|
|
def log_status_code(r, *args, **kwargs):
|
|
|
|
"""
|
|
|
|
Is a request hook that logs all status codes to the digicert api.
|
|
|
|
|
|
|
|
:param r:
|
|
|
|
:param args:
|
|
|
|
:param kwargs:
|
|
|
|
:return:
|
|
|
|
"""
|
2019-05-16 16:57:02 +02:00
|
|
|
metrics.send("digicert_status_code_{}".format(r.status_code), "counter", 1)
|
2016-12-02 22:02:59 +01:00
|
|
|
|
|
|
|
|
2016-11-07 23:40:00 +01:00
|
|
|
def signature_hash(signing_algorithm):
|
|
|
|
"""Converts Lemur's signing algorithm into a format DigiCert understands.
|
|
|
|
|
|
|
|
:param signing_algorithm:
|
|
|
|
:return: str digicert specific algorithm string
|
|
|
|
"""
|
|
|
|
if not signing_algorithm:
|
2019-05-16 16:57:02 +02:00
|
|
|
return current_app.config.get("DIGICERT_DEFAULT_SIGNING_ALGORITHM", "sha256")
|
2016-11-07 23:40:00 +01:00
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
if signing_algorithm == "sha256WithRSA":
|
|
|
|
return "sha256"
|
2016-11-07 23:40:00 +01:00
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
elif signing_algorithm == "sha384WithRSA":
|
|
|
|
return "sha384"
|
2016-11-07 23:40:00 +01:00
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
elif signing_algorithm == "sha512WithRSA":
|
|
|
|
return "sha512"
|
2016-11-07 23:40:00 +01:00
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
raise Exception("Unsupported signing algorithm.")
|
2016-11-07 23:40:00 +01:00
|
|
|
|
|
|
|
|
2020-03-03 23:29:17 +01:00
|
|
|
def determine_validity_years(years):
|
2020-08-12 03:02:42 +02:00
|
|
|
"""
|
2020-08-12 03:53:19 +02:00
|
|
|
Considering maximum allowed certificate validity period of 397 days, this method should not return
|
|
|
|
more than 1 year of validity. Thus changing it to always return 1.
|
2020-08-12 03:02:42 +02:00
|
|
|
Lemur will change this method in future to handle validity in months (determine_validity_months)
|
|
|
|
instead of years. This will allow flexibility to handle short-lived certificates.
|
|
|
|
|
2020-03-03 23:29:17 +01:00
|
|
|
:param years:
|
2020-08-12 03:02:42 +02:00
|
|
|
:return: 1
|
2020-03-03 23:29:17 +01:00
|
|
|
"""
|
2020-08-12 03:02:42 +02:00
|
|
|
return 1
|
2020-03-03 23:29:17 +01:00
|
|
|
|
|
|
|
|
|
|
|
def determine_end_date(end_date):
|
|
|
|
"""
|
|
|
|
Determine appropriate end date
|
2016-11-07 23:40:00 +01:00
|
|
|
|
|
|
|
:param end_date:
|
2020-03-03 23:29:17 +01:00
|
|
|
:return: validity_end
|
2016-11-07 23:40:00 +01:00
|
|
|
"""
|
2020-08-11 02:30:34 +02:00
|
|
|
default_days = current_app.config.get("DIGICERT_DEFAULT_VALIDITY_DAYS", 397)
|
|
|
|
max_validity_end = arrow.utcnow().shift(days=current_app.config.get("DIGICERT_MAX_VALIDITY_DAYS", default_days))
|
2016-11-07 23:40:00 +01:00
|
|
|
|
2020-03-03 23:29:17 +01:00
|
|
|
if not end_date:
|
2020-08-11 02:30:34 +02:00
|
|
|
end_date = arrow.utcnow().shift(days=default_days)
|
2016-11-07 23:40:00 +01:00
|
|
|
|
2020-03-03 23:29:17 +01:00
|
|
|
if end_date > max_validity_end:
|
|
|
|
end_date = max_validity_end
|
|
|
|
return end_date
|
2016-11-07 23:40:00 +01:00
|
|
|
|
|
|
|
|
2016-11-28 19:50:58 +01:00
|
|
|
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
|
2019-05-16 16:57:02 +02:00
|
|
|
if options.get("extensions"):
|
|
|
|
for san in options["extensions"]["sub_alt_names"]["names"]:
|
2017-01-28 06:05:25 +01:00
|
|
|
if isinstance(san, x509.DNSName):
|
|
|
|
names.append(san.value)
|
2016-11-28 19:50:58 +01:00
|
|
|
return names
|
|
|
|
|
|
|
|
|
|
|
|
def map_fields(options, csr):
|
2016-11-07 23:40:00 +01:00
|
|
|
"""Set the incoming issuer options to DigiCert fields/options.
|
|
|
|
|
|
|
|
:param options:
|
|
|
|
:param csr:
|
|
|
|
:return: dict or valid DigiCert options
|
|
|
|
"""
|
2019-05-16 16:57:02 +02:00
|
|
|
data = dict(
|
|
|
|
certificate={
|
|
|
|
"common_name": options["common_name"],
|
|
|
|
"csr": csr,
|
|
|
|
"signature_hash": signature_hash(options.get("signing_algorithm")),
|
|
|
|
},
|
|
|
|
organization={"id": current_app.config.get("DIGICERT_ORG_ID")},
|
|
|
|
)
|
2016-11-07 23:40:00 +01:00
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
data["certificate"]["dns_names"] = get_additional_names(options)
|
2017-04-05 02:11:17 +02:00
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
if options.get("validity_years"):
|
2020-03-03 23:29:17 +01:00
|
|
|
data["validity_years"] = determine_validity_years(options.get("validity_years"))
|
|
|
|
elif options.get("validity_end"):
|
|
|
|
data["custom_expiration_date"] = determine_end_date(options.get("validity_end")).format("YYYY-MM-DD")
|
2020-09-01 03:20:32 +02:00
|
|
|
# check if validity got truncated. If resultant validity is not equal to requested validity, it just got truncated
|
2020-09-01 21:44:49 +02:00
|
|
|
if data["custom_expiration_date"] != options.get("validity_end").format("YYYY-MM-DD"):
|
2020-09-01 03:20:32 +02:00
|
|
|
log_validity_truncation(options, f"{__name__}.{sys._getframe().f_code.co_name}")
|
2017-05-10 21:05:03 +02:00
|
|
|
else:
|
2020-03-03 23:29:17 +01:00
|
|
|
data["validity_years"] = determine_validity_years(0)
|
2017-04-05 02:11:17 +02:00
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
if current_app.config.get("DIGICERT_PRIVATE", False):
|
|
|
|
if "product" in data:
|
|
|
|
data["product"]["type_hint"] = "private"
|
2017-06-14 18:20:24 +02:00
|
|
|
else:
|
2019-05-16 16:57:02 +02:00
|
|
|
data["product"] = dict(type_hint="private")
|
2017-06-14 18:20:24 +02:00
|
|
|
|
2016-11-07 23:40:00 +01:00
|
|
|
return data
|
|
|
|
|
|
|
|
|
2016-11-28 19:50:58 +01:00
|
|
|
def map_cis_fields(options, csr):
|
|
|
|
"""
|
|
|
|
MAP issuer options to DigiCert CIS fields/options.
|
|
|
|
|
|
|
|
:param options:
|
|
|
|
:param csr:
|
2020-03-03 23:29:17 +01:00
|
|
|
:return: data
|
2016-11-28 19:50:58 +01:00
|
|
|
"""
|
2020-03-03 23:29:17 +01:00
|
|
|
|
|
|
|
if options.get("validity_years"):
|
|
|
|
validity_end = determine_end_date(arrow.utcnow().shift(years=options["validity_years"]))
|
|
|
|
elif options.get("validity_end"):
|
|
|
|
validity_end = determine_end_date(options.get("validity_end"))
|
2020-09-01 03:20:32 +02:00
|
|
|
# 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}")
|
2017-05-10 21:05:03 +02:00
|
|
|
else:
|
2020-03-03 23:29:17 +01:00
|
|
|
validity_end = determine_end_date(False)
|
2017-05-10 21:05:03 +02:00
|
|
|
|
2016-11-28 19:50:58 +01:00
|
|
|
data = {
|
2019-08-07 21:05:13 +02:00
|
|
|
"profile_name": current_app.config.get("DIGICERT_CIS_PROFILE_NAMES", {}).get(options['authority'].name),
|
2019-05-16 16:57:02 +02:00
|
|
|
"common_name": options["common_name"],
|
2016-11-28 19:50:58 +01:00
|
|
|
"additional_dns_names": get_additional_names(options),
|
|
|
|
"csr": csr,
|
2019-05-16 16:57:02 +02:00
|
|
|
"signature_hash": signature_hash(options.get("signing_algorithm")),
|
2016-11-28 19:50:58 +01:00
|
|
|
"validity": {
|
2020-03-03 23:29:17 +01:00
|
|
|
"valid_to": validity_end.format("YYYY-MM-DDTHH:MM") + "Z"
|
2016-11-28 19:50:58 +01:00
|
|
|
},
|
|
|
|
"organization": {
|
2019-05-16 16:57:02 +02:00
|
|
|
"name": options["organization"],
|
|
|
|
},
|
2016-11-28 19:50:58 +01:00
|
|
|
}
|
2020-01-16 01:19:48 +01:00
|
|
|
# possibility to default to a SIGNING_ALGORITHM for a given profile
|
|
|
|
if current_app.config.get("DIGICERT_CIS_SIGNING_ALGORITHMS", {}).get(options['authority'].name):
|
2020-03-03 23:29:17 +01:00
|
|
|
data["signature_hash"] = current_app.config.get("DIGICERT_CIS_SIGNING_ALGORITHMS", {}).get(
|
|
|
|
options['authority'].name)
|
2016-11-28 19:50:58 +01:00
|
|
|
|
|
|
|
return data
|
|
|
|
|
2020-09-01 21:44:49 +02:00
|
|
|
|
2020-09-01 03:20:32 +02:00
|
|
|
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
|
2020-09-12 00:53:05 +02:00
|
|
|
log_data["message"] = "Digicert Plugin truncated the validity of certificate"
|
2020-09-01 03:20:32 +02:00
|
|
|
current_app.logger.info(log_data)
|
2016-11-28 19:50:58 +01:00
|
|
|
|
2020-09-01 21:44:49 +02:00
|
|
|
|
2016-11-07 23:40:00 +01:00
|
|
|
def handle_response(response):
|
|
|
|
"""
|
|
|
|
Handle the DigiCert API response and any errors it might have experienced.
|
|
|
|
:param response:
|
|
|
|
:return:
|
|
|
|
"""
|
2016-11-28 19:50:58 +01:00
|
|
|
if response.status_code > 399:
|
2019-05-16 16:57:02 +02:00
|
|
|
raise Exception(response.json()["errors"][0]["message"])
|
2016-11-07 23:40:00 +01:00
|
|
|
|
|
|
|
return response.json()
|
|
|
|
|
|
|
|
|
2016-11-30 19:54:53 +01:00
|
|
|
def handle_cis_response(response):
|
|
|
|
"""
|
|
|
|
Handle the DigiCert CIS API response and any errors it might have experienced.
|
|
|
|
:param response:
|
|
|
|
:return:
|
|
|
|
"""
|
|
|
|
if response.status_code > 399:
|
2019-05-15 22:36:40 +02:00
|
|
|
raise Exception(response.text)
|
2016-11-30 19:54:53 +01:00
|
|
|
|
|
|
|
return response.json()
|
|
|
|
|
|
|
|
|
2016-11-10 23:34:45 +01:00
|
|
|
@retry(stop_max_attempt_number=10, wait_fixed=10000)
|
2016-11-10 20:23:37 +01:00
|
|
|
def get_certificate_id(session, base_url, order_id):
|
|
|
|
"""Retrieve certificate order id from Digicert API."""
|
|
|
|
order_url = "{0}/services/v2/order/certificate/{1}".format(base_url, order_id)
|
|
|
|
response_data = handle_response(session.get(order_url))
|
2019-05-16 16:57:02 +02:00
|
|
|
if response_data["status"] != "issued":
|
2016-11-10 20:23:37 +01:00
|
|
|
raise Exception("Order not in issued state.")
|
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
return response_data["certificate"]["id"]
|
2016-11-10 20:23:37 +01:00
|
|
|
|
|
|
|
|
2016-11-28 19:50:58 +01:00
|
|
|
@retry(stop_max_attempt_number=10, wait_fixed=10000)
|
|
|
|
def get_cis_certificate(session, base_url, order_id):
|
2020-10-08 05:06:20 +02:00
|
|
|
"""Retrieve certificate order id from Digicert API, including the chain"""
|
|
|
|
certificate_url = "{0}/platform/cis/certificate/{1}/download".format(base_url, order_id)
|
|
|
|
session.headers.update({"Accept": "application/x-pkcs7-certificates"})
|
2016-11-28 19:50:58 +01:00
|
|
|
response = session.get(certificate_url)
|
|
|
|
|
|
|
|
if response.status_code == 404:
|
|
|
|
raise Exception("Order not in issued state.")
|
|
|
|
|
2020-10-08 05:06:20 +02:00
|
|
|
cert_chain_pem = convert_pkcs7_bytes_to_pem(response.content)
|
|
|
|
if len(cert_chain_pem) < 3:
|
|
|
|
raise Exception("Missing the certificate chain")
|
|
|
|
return cert_chain_pem
|
2016-11-28 19:50:58 +01:00
|
|
|
|
|
|
|
|
2016-11-07 23:40:00 +01:00
|
|
|
class DigiCertSourcePlugin(SourcePlugin):
|
|
|
|
"""Wrap the Digicert Certifcate API."""
|
2019-05-16 16:57:02 +02:00
|
|
|
|
|
|
|
title = "DigiCert"
|
|
|
|
slug = "digicert-source"
|
2016-11-07 23:40:00 +01:00
|
|
|
description = "Enables the use of Digicert as a source of existing certificates."
|
|
|
|
version = digicert.VERSION
|
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
author = "Kevin Glisson"
|
|
|
|
author_url = "https://github.com/netflix/lemur.git"
|
2016-11-07 23:40:00 +01:00
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
"""Initialize source with appropriate details."""
|
2016-11-28 19:50:58 +01:00
|
|
|
required_vars = [
|
2019-05-16 16:57:02 +02:00
|
|
|
"DIGICERT_API_KEY",
|
|
|
|
"DIGICERT_URL",
|
|
|
|
"DIGICERT_ORG_ID",
|
|
|
|
"DIGICERT_ROOT",
|
2016-11-28 19:50:58 +01:00
|
|
|
]
|
|
|
|
validate_conf(current_app, required_vars)
|
2016-11-07 23:40:00 +01:00
|
|
|
|
|
|
|
self.session = requests.Session()
|
|
|
|
self.session.headers.update(
|
|
|
|
{
|
2019-05-16 16:57:02 +02:00
|
|
|
"X-DC-DEVKEY": current_app.config["DIGICERT_API_KEY"],
|
|
|
|
"Content-Type": "application/json",
|
2016-11-07 23:40:00 +01:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2016-12-02 22:02:59 +01:00
|
|
|
self.session.hooks = dict(response=log_status_code)
|
|
|
|
|
2016-11-07 23:40:00 +01:00
|
|
|
super(DigiCertSourcePlugin, self).__init__(*args, **kwargs)
|
|
|
|
|
|
|
|
def get_certificates(self):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class DigiCertIssuerPlugin(IssuerPlugin):
|
|
|
|
"""Wrap the Digicert Issuer API."""
|
2019-05-16 16:57:02 +02:00
|
|
|
|
|
|
|
title = "DigiCert"
|
|
|
|
slug = "digicert-issuer"
|
2018-02-26 21:37:31 +01:00
|
|
|
description = "Enables the creation of certificates by the DigiCert REST API."
|
2016-11-07 23:40:00 +01:00
|
|
|
version = digicert.VERSION
|
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
author = "Kevin Glisson"
|
|
|
|
author_url = "https://github.com/netflix/lemur.git"
|
2016-11-07 23:40:00 +01:00
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
"""Initialize the issuer with the appropriate details."""
|
2016-11-28 19:50:58 +01:00
|
|
|
required_vars = [
|
2019-05-16 16:57:02 +02:00
|
|
|
"DIGICERT_API_KEY",
|
|
|
|
"DIGICERT_URL",
|
|
|
|
"DIGICERT_ORG_ID",
|
|
|
|
"DIGICERT_ORDER_TYPE",
|
|
|
|
"DIGICERT_ROOT",
|
2016-11-28 19:50:58 +01:00
|
|
|
]
|
|
|
|
|
|
|
|
validate_conf(current_app, required_vars)
|
2016-11-07 23:40:00 +01:00
|
|
|
|
|
|
|
self.session = requests.Session()
|
|
|
|
self.session.headers.update(
|
|
|
|
{
|
2019-05-16 16:57:02 +02:00
|
|
|
"X-DC-DEVKEY": current_app.config["DIGICERT_API_KEY"],
|
|
|
|
"Content-Type": "application/json",
|
2016-11-07 23:40:00 +01:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2016-12-02 22:02:59 +01:00
|
|
|
self.session.hooks = dict(response=log_status_code)
|
|
|
|
|
2016-11-07 23:40:00 +01:00
|
|
|
super(DigiCertIssuerPlugin, self).__init__(*args, **kwargs)
|
|
|
|
|
|
|
|
def create_certificate(self, csr, issuer_options):
|
|
|
|
"""Create a DigiCert certificate.
|
|
|
|
|
|
|
|
:param csr:
|
|
|
|
:param issuer_options:
|
|
|
|
:return: :raise Exception:
|
|
|
|
"""
|
2019-05-16 16:57:02 +02:00
|
|
|
base_url = current_app.config.get("DIGICERT_URL")
|
|
|
|
cert_type = current_app.config.get("DIGICERT_ORDER_TYPE")
|
2016-11-07 23:40:00 +01:00
|
|
|
|
|
|
|
# make certificate request
|
2019-05-16 16:57:02 +02:00
|
|
|
determinator_url = "{0}/services/v2/order/certificate/{1}".format(
|
|
|
|
base_url, cert_type
|
|
|
|
)
|
2016-11-28 19:50:58 +01:00
|
|
|
data = map_fields(issuer_options, csr)
|
2016-11-07 23:40:00 +01:00
|
|
|
response = self.session.post(determinator_url, data=json.dumps(data))
|
2016-11-30 02:15:39 +01:00
|
|
|
|
|
|
|
if response.status_code > 399:
|
2019-05-16 16:57:02 +02:00
|
|
|
raise Exception(response.json()["errors"][0]["message"])
|
2016-11-30 02:15:39 +01:00
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
order_id = response.json()["id"]
|
2016-11-07 23:40:00 +01:00
|
|
|
|
2016-11-10 20:23:37 +01:00
|
|
|
certificate_id = get_certificate_id(self.session, base_url, order_id)
|
2016-11-07 23:40:00 +01:00
|
|
|
|
2017-04-27 18:14:20 +02:00
|
|
|
# retrieve certificate
|
2019-05-16 16:57:02 +02:00
|
|
|
certificate_url = "{0}/services/v2/certificate/{1}/download/format/pem_all".format(
|
|
|
|
base_url, certificate_id
|
|
|
|
)
|
|
|
|
end_entity, intermediate, root = pem.parse(
|
|
|
|
self.session.get(certificate_url).content
|
|
|
|
)
|
|
|
|
return (
|
|
|
|
"\n".join(str(end_entity).splitlines()),
|
|
|
|
"\n".join(str(intermediate).splitlines()),
|
|
|
|
certificate_id,
|
|
|
|
)
|
2017-09-29 03:27:56 +02:00
|
|
|
|
|
|
|
def revoke_certificate(self, certificate, comments):
|
|
|
|
"""Revoke a Digicert certificate."""
|
2019-05-16 16:57:02 +02:00
|
|
|
base_url = current_app.config.get("DIGICERT_URL")
|
2017-09-29 03:27:56 +02:00
|
|
|
|
|
|
|
# make certificate revoke request
|
2019-05-16 16:57:02 +02:00
|
|
|
create_url = "{0}/services/v2/certificate/{1}/revoke".format(
|
|
|
|
base_url, certificate.external_id
|
|
|
|
)
|
|
|
|
metrics.send("digicert_revoke_certificate", "counter", 1)
|
|
|
|
response = self.session.put(create_url, data=json.dumps({"comments": comments}))
|
2017-09-29 03:27:56 +02:00
|
|
|
return handle_response(response)
|
2016-11-07 23:40:00 +01:00
|
|
|
|
2018-04-24 18:38:57 +02:00
|
|
|
def get_ordered_certificate(self, pending_cert):
|
Async Certificate Issuing using Pending Certificates (#1037)
* Add PendingCertificate model
This change creates a DB table called pending_certificates and
associated mapping relationship tables from pending certificate to
roles, rotation policy, destination, sources, etc.
The table is generated on initialization of Lemur. A pending
certificate holds most of the information of a Certificate, while it has
not be issued so that it can later backfill the information when the CA
has issued the certificate.
Change-Id: I277c16b776a71fe5edaf0fa0e76bbedc88924db0
Tickets: PBL-36499
* Create a PendingCertificate if cert is empty
IssuePlugins should return empty cert bodies if the request failed to
complete immediately (such as Digicert). This way, we can immediately
return the certificate, or if not just place into PendingCertificates
for later processing.
+ Fix relation from Certificate to Pending Certificate, as view only.
There is no real need for anything more than that since Pending cert
only needs to know the cert to replace when it is issued later.
+ Made PendingCertificate private key be empty: UI does not allow
private key on 'Create' but only on 'Import'. For Instart, we require
the private key but upstream does not necessarily need it. Thus, if
someone at Instart wants to create a CSR / key combo, they should
manually issue the cert themselves and import later. Otherwise you
should let Lemur generate that. This keeps the workflow transparent for
upstream Lemur users.
Change-Id: Ib74722a5ed5792d4b10ca702659422739c95ae26
Tickets: PBL-36343
* Fix empty private_key when create Pending Cert
On creation of a certificate with a CSR, there is no option for private
key. In this case, we actually have a dictionary with private_key as
key, but the value is None. This fixes the strip() called on NoneType.
Change-Id: I7b265564d8095bfc83d9d4cd14ae13fea3c03199
Tickets: PBL-36499
* Source sync finds and uses pending certificate
When a source syncs certificates, it will check for a pending
certificate. If that is found via external_id (given by digicert as
order_id) then it will use the found Pending Certificate's fields to
create a new certificate. Then the pending certificate is deleted.
Tickets: PBL-36343
Change-Id: I4f7959da29275ebc47a3996741f7e98d3e2d29d9
* Add Lemur static files and views for pending certs
This adds the basic static files to view pending certificates in a
table.
Tickets: PBL-36343
Change-Id: Ia4362e6664ec730d05d280c5ef5c815a6feda0d9
* Add CLI and plugin based pending fetch
This change uses the adds a new function to issuer plugins to fetch
certificates like source, but for one order. This way, we can control
which pending certificates to try and populate instead of getting all
certificates from source.
Tickets: PBL-36343
Change-Id: Ifc1747ccdc2cba09a81f298b31ddddebfee1b1d6
* Revert source using Pending Certificate
Tickets: PBL-36343
Change-Id: I05121bc951e0530d804070afdb9c9e09baa0bc51
* Fix PendingCertificate init getting authority id
Should get authority id from authority.id instead of the authority_id
key in kwargs.
Change-Id: Ie56df1a5fb0ab2729e91050f3ad1a831853e0623
Tickets: n/a
* Add fixtures and basic test for PendingCertificate
Change-Id: I4cca34105544d40dac1cc50a87bba93d8af9ab34
Tickets: PBL-36343
* Add User to create_certificate parameters
create_certificate now takes a User, which will be used to populate the
'creator' field in certificates.service.upload(). This allows the UI
populate with the current user if the owner does not exist in Lemur.
+ Fix chain being replaced with version from pending certificate, which
may be empty (depends on plugin implementation).
Change-Id: I516027b36bc643c4978b9c4890060569e03f3049
Tickets: n/a
* Fix permalink and filters to pending certs
Fixes the permalink button to get a single pending certificate
Add argument filter parsing for the pending certificate API
Fix comment on API usage
Added get_by_name for pending_certificate (currently unused, but useful
for CLI, instead of using IDs)
Change-Id: Iaa48909c45606bec65dfb193c13d6bd0e816f6db
Tickets: PBL-36910
* Update displayed fields for Pending Certificates
There are a number of unused / unpopulated fields from Certificate UI
that does apply to Pending Certificates. Those ones were removed, and
added other useful fields:
Owner, number of attempts to fetch and date created
Change-Id: I3010a715f0357ba149cf539a19fdb5974c5ce08b
Tickets: PBL-36910
* Add common name (cn) to Pending Certificate model
Fixes the UI missing the CN for Pending Certificate, as it was
originally being parsed from the generated certificate. In the case of
pending certificate, the CN from the user generates the request, which
means a pending cert can trust the original user putting in the CN
instead of having to parse the not-yet-generated certificate. There is
no real possibility to return a certificate from a pending certificate
where the CN has changed since it was initially ordered.
Change-Id: I88a4fa28116d5d8d293e58970d9777ce73fbb2ab
Tickets: PBL-36910
* Fix missing imports for service filter
+ Removed duplicate get_by_name function from old merge
Change-Id: I04ae6852533aa42988433338de74390e2868d69b
Tickets: PBL-36910
* Add private key viewing to Pending Certificates
Add private key API for Pending Certificates, with the same
authorization as Certificates (only owner, creator or owner-roles can
view private key).
Change-Id: Ie5175154a10fe0007cc0e9f35b80c0a01ed48d5b
Tickets: PBL-36910
* Add edit capability to pending certificates
Like editing certificates, we should be able to modify some parts of a
pending certificate so the resulting certificate has the right
references, owner, etc.
+ Added API to update pending certificate
+ Fix UI to use pending certificate scope instead of reusing Certificate
+ Change pending_certificate.replaces to non-passive association, so
that updates do affect it (similar to roles/notifications/etc)
Tickets: PBL-36910
Change-Id: Ibbcb166a33f0337e1b14f426472261222f790ce6
* Add common_name parsing instead using kwargs
To fix tests where common name may not be passed in, use the CSR
generated to find the official common name.
Change-Id: I09f9258fa92c2762d095798676ce210c5d7a3da4
Tickets: PBL-36343
* Add Cancel to pending certificates and plugins
This allows pending certificates to be cancelled, which will be handled
by the issuer plugin.
Change-Id: Ibd6b5627c3977e33aca7860690cfb7f677236ca9
Tickets: PBL-36910
* Add API for Cancelling Pending Certificate
Added the DELETE handler for pending_certificates, which will cancel and
delete the pending certificate from the pending certs table on
successful cancellation via Issuer Plugin.
+ Add UT for testing cancel API
Change-Id: I11b1d87872e4284f6e4f9c366a15da4ddba38bc4
Tickets: PBL-36910
* Remove Export from Pending Certificates
Pending Certificates doesn't need an export since it should just be
fetched by Lemur via plugins, and the CSR is viewable via the UI.
Change-Id: I9a3e65ea11ac5a85316f6428e7f526c3c09178ae
Tickets: PBL-36910
* Add cancel button functionality to UI
This adds the Cancel option to the dropdown of pending certificates.
+ Adds modal window for Note (may not be required for all issuers, just
Digicert)
+ Add schema for cancel input
+ Fix Digitcert plugin for non-existant orders
When an order is actually issued, then attempting to cancel will return
a 403 from Digicert. This is a case where it should only be done once
we know the pending cert has been sitting for too long.
Change-Id: I256c81ecd142dd51dcf8e38802d2c202829887b0
Tickets: PBL-36910
* Fix test_pending_cancel UT
This change creates and injects a pending cert, which will then be used
for the ID so it can be canceled by the unit test.
Change-Id: I686e7e0fafd68cdaeb26438fb8504d79de77c346
Tickets: PBL-36343
* Fix test_digicert on non-existent order
cancelling a non-existent order is fine since we're cancelling it
Change-Id: I70c0e82ba2f4b8723a7f65b113c19e6eeff7e68c
Tickets: PBL-36343
* Add migrations for PendingCertificates
Added revision for Pending Certificates table and foreign key mapping
tables.
Change-Id: Ife8202cef1e6b99db377851264639ba540b749db
Tickets: n/a
* Fix relationship copy from Pending to Certificate
When a Pending Certificate is changed to a full Certificate, the
relationship fields are not copied via vars() function, as it's not a
column but mapped via association table. This adds an explicit copy for
these relations. Which will properly copy them to the new Certificate,
and thus also update destinations.
Change-Id: I322032ce4a9e3e67773f7cf39ee4971054c92685
Tickets: PBL-36343
* Fix renaming of certificates and unit tests
The rename flag was not used to rename certificates on creation as
expected.
Fixed unit test, instead of expunging the session, just copy the
pending_certificate so we don't have a weird reference to the object
that can't be copied via vars() function.
Change-Id: I962943272ed92386ab6eab2af4ed6d074d4cffa0
Tickets: PBL-36343
* Updated developer docs for async certs
Added blurb for implementing new issuer functions.
Change-Id: I1caed6e914bcd73214eae2d241e4784e1b8a0c4c
Tickets: n/a
2018-02-22 17:13:16 +01:00
|
|
|
""" Retrieve a certificate via order id """
|
2018-04-24 18:38:57 +02:00
|
|
|
order_id = pending_cert.external_id
|
2019-05-16 16:57:02 +02:00
|
|
|
base_url = current_app.config.get("DIGICERT_URL")
|
Async Certificate Issuing using Pending Certificates (#1037)
* Add PendingCertificate model
This change creates a DB table called pending_certificates and
associated mapping relationship tables from pending certificate to
roles, rotation policy, destination, sources, etc.
The table is generated on initialization of Lemur. A pending
certificate holds most of the information of a Certificate, while it has
not be issued so that it can later backfill the information when the CA
has issued the certificate.
Change-Id: I277c16b776a71fe5edaf0fa0e76bbedc88924db0
Tickets: PBL-36499
* Create a PendingCertificate if cert is empty
IssuePlugins should return empty cert bodies if the request failed to
complete immediately (such as Digicert). This way, we can immediately
return the certificate, or if not just place into PendingCertificates
for later processing.
+ Fix relation from Certificate to Pending Certificate, as view only.
There is no real need for anything more than that since Pending cert
only needs to know the cert to replace when it is issued later.
+ Made PendingCertificate private key be empty: UI does not allow
private key on 'Create' but only on 'Import'. For Instart, we require
the private key but upstream does not necessarily need it. Thus, if
someone at Instart wants to create a CSR / key combo, they should
manually issue the cert themselves and import later. Otherwise you
should let Lemur generate that. This keeps the workflow transparent for
upstream Lemur users.
Change-Id: Ib74722a5ed5792d4b10ca702659422739c95ae26
Tickets: PBL-36343
* Fix empty private_key when create Pending Cert
On creation of a certificate with a CSR, there is no option for private
key. In this case, we actually have a dictionary with private_key as
key, but the value is None. This fixes the strip() called on NoneType.
Change-Id: I7b265564d8095bfc83d9d4cd14ae13fea3c03199
Tickets: PBL-36499
* Source sync finds and uses pending certificate
When a source syncs certificates, it will check for a pending
certificate. If that is found via external_id (given by digicert as
order_id) then it will use the found Pending Certificate's fields to
create a new certificate. Then the pending certificate is deleted.
Tickets: PBL-36343
Change-Id: I4f7959da29275ebc47a3996741f7e98d3e2d29d9
* Add Lemur static files and views for pending certs
This adds the basic static files to view pending certificates in a
table.
Tickets: PBL-36343
Change-Id: Ia4362e6664ec730d05d280c5ef5c815a6feda0d9
* Add CLI and plugin based pending fetch
This change uses the adds a new function to issuer plugins to fetch
certificates like source, but for one order. This way, we can control
which pending certificates to try and populate instead of getting all
certificates from source.
Tickets: PBL-36343
Change-Id: Ifc1747ccdc2cba09a81f298b31ddddebfee1b1d6
* Revert source using Pending Certificate
Tickets: PBL-36343
Change-Id: I05121bc951e0530d804070afdb9c9e09baa0bc51
* Fix PendingCertificate init getting authority id
Should get authority id from authority.id instead of the authority_id
key in kwargs.
Change-Id: Ie56df1a5fb0ab2729e91050f3ad1a831853e0623
Tickets: n/a
* Add fixtures and basic test for PendingCertificate
Change-Id: I4cca34105544d40dac1cc50a87bba93d8af9ab34
Tickets: PBL-36343
* Add User to create_certificate parameters
create_certificate now takes a User, which will be used to populate the
'creator' field in certificates.service.upload(). This allows the UI
populate with the current user if the owner does not exist in Lemur.
+ Fix chain being replaced with version from pending certificate, which
may be empty (depends on plugin implementation).
Change-Id: I516027b36bc643c4978b9c4890060569e03f3049
Tickets: n/a
* Fix permalink and filters to pending certs
Fixes the permalink button to get a single pending certificate
Add argument filter parsing for the pending certificate API
Fix comment on API usage
Added get_by_name for pending_certificate (currently unused, but useful
for CLI, instead of using IDs)
Change-Id: Iaa48909c45606bec65dfb193c13d6bd0e816f6db
Tickets: PBL-36910
* Update displayed fields for Pending Certificates
There are a number of unused / unpopulated fields from Certificate UI
that does apply to Pending Certificates. Those ones were removed, and
added other useful fields:
Owner, number of attempts to fetch and date created
Change-Id: I3010a715f0357ba149cf539a19fdb5974c5ce08b
Tickets: PBL-36910
* Add common name (cn) to Pending Certificate model
Fixes the UI missing the CN for Pending Certificate, as it was
originally being parsed from the generated certificate. In the case of
pending certificate, the CN from the user generates the request, which
means a pending cert can trust the original user putting in the CN
instead of having to parse the not-yet-generated certificate. There is
no real possibility to return a certificate from a pending certificate
where the CN has changed since it was initially ordered.
Change-Id: I88a4fa28116d5d8d293e58970d9777ce73fbb2ab
Tickets: PBL-36910
* Fix missing imports for service filter
+ Removed duplicate get_by_name function from old merge
Change-Id: I04ae6852533aa42988433338de74390e2868d69b
Tickets: PBL-36910
* Add private key viewing to Pending Certificates
Add private key API for Pending Certificates, with the same
authorization as Certificates (only owner, creator or owner-roles can
view private key).
Change-Id: Ie5175154a10fe0007cc0e9f35b80c0a01ed48d5b
Tickets: PBL-36910
* Add edit capability to pending certificates
Like editing certificates, we should be able to modify some parts of a
pending certificate so the resulting certificate has the right
references, owner, etc.
+ Added API to update pending certificate
+ Fix UI to use pending certificate scope instead of reusing Certificate
+ Change pending_certificate.replaces to non-passive association, so
that updates do affect it (similar to roles/notifications/etc)
Tickets: PBL-36910
Change-Id: Ibbcb166a33f0337e1b14f426472261222f790ce6
* Add common_name parsing instead using kwargs
To fix tests where common name may not be passed in, use the CSR
generated to find the official common name.
Change-Id: I09f9258fa92c2762d095798676ce210c5d7a3da4
Tickets: PBL-36343
* Add Cancel to pending certificates and plugins
This allows pending certificates to be cancelled, which will be handled
by the issuer plugin.
Change-Id: Ibd6b5627c3977e33aca7860690cfb7f677236ca9
Tickets: PBL-36910
* Add API for Cancelling Pending Certificate
Added the DELETE handler for pending_certificates, which will cancel and
delete the pending certificate from the pending certs table on
successful cancellation via Issuer Plugin.
+ Add UT for testing cancel API
Change-Id: I11b1d87872e4284f6e4f9c366a15da4ddba38bc4
Tickets: PBL-36910
* Remove Export from Pending Certificates
Pending Certificates doesn't need an export since it should just be
fetched by Lemur via plugins, and the CSR is viewable via the UI.
Change-Id: I9a3e65ea11ac5a85316f6428e7f526c3c09178ae
Tickets: PBL-36910
* Add cancel button functionality to UI
This adds the Cancel option to the dropdown of pending certificates.
+ Adds modal window for Note (may not be required for all issuers, just
Digicert)
+ Add schema for cancel input
+ Fix Digitcert plugin for non-existant orders
When an order is actually issued, then attempting to cancel will return
a 403 from Digicert. This is a case where it should only be done once
we know the pending cert has been sitting for too long.
Change-Id: I256c81ecd142dd51dcf8e38802d2c202829887b0
Tickets: PBL-36910
* Fix test_pending_cancel UT
This change creates and injects a pending cert, which will then be used
for the ID so it can be canceled by the unit test.
Change-Id: I686e7e0fafd68cdaeb26438fb8504d79de77c346
Tickets: PBL-36343
* Fix test_digicert on non-existent order
cancelling a non-existent order is fine since we're cancelling it
Change-Id: I70c0e82ba2f4b8723a7f65b113c19e6eeff7e68c
Tickets: PBL-36343
* Add migrations for PendingCertificates
Added revision for Pending Certificates table and foreign key mapping
tables.
Change-Id: Ife8202cef1e6b99db377851264639ba540b749db
Tickets: n/a
* Fix relationship copy from Pending to Certificate
When a Pending Certificate is changed to a full Certificate, the
relationship fields are not copied via vars() function, as it's not a
column but mapped via association table. This adds an explicit copy for
these relations. Which will properly copy them to the new Certificate,
and thus also update destinations.
Change-Id: I322032ce4a9e3e67773f7cf39ee4971054c92685
Tickets: PBL-36343
* Fix renaming of certificates and unit tests
The rename flag was not used to rename certificates on creation as
expected.
Fixed unit test, instead of expunging the session, just copy the
pending_certificate so we don't have a weird reference to the object
that can't be copied via vars() function.
Change-Id: I962943272ed92386ab6eab2af4ed6d074d4cffa0
Tickets: PBL-36343
* Updated developer docs for async certs
Added blurb for implementing new issuer functions.
Change-Id: I1caed6e914bcd73214eae2d241e4784e1b8a0c4c
Tickets: n/a
2018-02-22 17:13:16 +01:00
|
|
|
try:
|
|
|
|
certificate_id = get_certificate_id(self.session, base_url, order_id)
|
|
|
|
except Exception as ex:
|
|
|
|
return None
|
2019-05-16 16:57:02 +02:00
|
|
|
certificate_url = "{0}/services/v2/certificate/{1}/download/format/pem_all".format(
|
|
|
|
base_url, certificate_id
|
|
|
|
)
|
|
|
|
end_entity, intermediate, root = pem.parse(
|
|
|
|
self.session.get(certificate_url).content
|
|
|
|
)
|
|
|
|
cert = {
|
|
|
|
"body": "\n".join(str(end_entity).splitlines()),
|
|
|
|
"chain": "\n".join(str(intermediate).splitlines()),
|
|
|
|
"external_id": str(certificate_id),
|
|
|
|
}
|
Async Certificate Issuing using Pending Certificates (#1037)
* Add PendingCertificate model
This change creates a DB table called pending_certificates and
associated mapping relationship tables from pending certificate to
roles, rotation policy, destination, sources, etc.
The table is generated on initialization of Lemur. A pending
certificate holds most of the information of a Certificate, while it has
not be issued so that it can later backfill the information when the CA
has issued the certificate.
Change-Id: I277c16b776a71fe5edaf0fa0e76bbedc88924db0
Tickets: PBL-36499
* Create a PendingCertificate if cert is empty
IssuePlugins should return empty cert bodies if the request failed to
complete immediately (such as Digicert). This way, we can immediately
return the certificate, or if not just place into PendingCertificates
for later processing.
+ Fix relation from Certificate to Pending Certificate, as view only.
There is no real need for anything more than that since Pending cert
only needs to know the cert to replace when it is issued later.
+ Made PendingCertificate private key be empty: UI does not allow
private key on 'Create' but only on 'Import'. For Instart, we require
the private key but upstream does not necessarily need it. Thus, if
someone at Instart wants to create a CSR / key combo, they should
manually issue the cert themselves and import later. Otherwise you
should let Lemur generate that. This keeps the workflow transparent for
upstream Lemur users.
Change-Id: Ib74722a5ed5792d4b10ca702659422739c95ae26
Tickets: PBL-36343
* Fix empty private_key when create Pending Cert
On creation of a certificate with a CSR, there is no option for private
key. In this case, we actually have a dictionary with private_key as
key, but the value is None. This fixes the strip() called on NoneType.
Change-Id: I7b265564d8095bfc83d9d4cd14ae13fea3c03199
Tickets: PBL-36499
* Source sync finds and uses pending certificate
When a source syncs certificates, it will check for a pending
certificate. If that is found via external_id (given by digicert as
order_id) then it will use the found Pending Certificate's fields to
create a new certificate. Then the pending certificate is deleted.
Tickets: PBL-36343
Change-Id: I4f7959da29275ebc47a3996741f7e98d3e2d29d9
* Add Lemur static files and views for pending certs
This adds the basic static files to view pending certificates in a
table.
Tickets: PBL-36343
Change-Id: Ia4362e6664ec730d05d280c5ef5c815a6feda0d9
* Add CLI and plugin based pending fetch
This change uses the adds a new function to issuer plugins to fetch
certificates like source, but for one order. This way, we can control
which pending certificates to try and populate instead of getting all
certificates from source.
Tickets: PBL-36343
Change-Id: Ifc1747ccdc2cba09a81f298b31ddddebfee1b1d6
* Revert source using Pending Certificate
Tickets: PBL-36343
Change-Id: I05121bc951e0530d804070afdb9c9e09baa0bc51
* Fix PendingCertificate init getting authority id
Should get authority id from authority.id instead of the authority_id
key in kwargs.
Change-Id: Ie56df1a5fb0ab2729e91050f3ad1a831853e0623
Tickets: n/a
* Add fixtures and basic test for PendingCertificate
Change-Id: I4cca34105544d40dac1cc50a87bba93d8af9ab34
Tickets: PBL-36343
* Add User to create_certificate parameters
create_certificate now takes a User, which will be used to populate the
'creator' field in certificates.service.upload(). This allows the UI
populate with the current user if the owner does not exist in Lemur.
+ Fix chain being replaced with version from pending certificate, which
may be empty (depends on plugin implementation).
Change-Id: I516027b36bc643c4978b9c4890060569e03f3049
Tickets: n/a
* Fix permalink and filters to pending certs
Fixes the permalink button to get a single pending certificate
Add argument filter parsing for the pending certificate API
Fix comment on API usage
Added get_by_name for pending_certificate (currently unused, but useful
for CLI, instead of using IDs)
Change-Id: Iaa48909c45606bec65dfb193c13d6bd0e816f6db
Tickets: PBL-36910
* Update displayed fields for Pending Certificates
There are a number of unused / unpopulated fields from Certificate UI
that does apply to Pending Certificates. Those ones were removed, and
added other useful fields:
Owner, number of attempts to fetch and date created
Change-Id: I3010a715f0357ba149cf539a19fdb5974c5ce08b
Tickets: PBL-36910
* Add common name (cn) to Pending Certificate model
Fixes the UI missing the CN for Pending Certificate, as it was
originally being parsed from the generated certificate. In the case of
pending certificate, the CN from the user generates the request, which
means a pending cert can trust the original user putting in the CN
instead of having to parse the not-yet-generated certificate. There is
no real possibility to return a certificate from a pending certificate
where the CN has changed since it was initially ordered.
Change-Id: I88a4fa28116d5d8d293e58970d9777ce73fbb2ab
Tickets: PBL-36910
* Fix missing imports for service filter
+ Removed duplicate get_by_name function from old merge
Change-Id: I04ae6852533aa42988433338de74390e2868d69b
Tickets: PBL-36910
* Add private key viewing to Pending Certificates
Add private key API for Pending Certificates, with the same
authorization as Certificates (only owner, creator or owner-roles can
view private key).
Change-Id: Ie5175154a10fe0007cc0e9f35b80c0a01ed48d5b
Tickets: PBL-36910
* Add edit capability to pending certificates
Like editing certificates, we should be able to modify some parts of a
pending certificate so the resulting certificate has the right
references, owner, etc.
+ Added API to update pending certificate
+ Fix UI to use pending certificate scope instead of reusing Certificate
+ Change pending_certificate.replaces to non-passive association, so
that updates do affect it (similar to roles/notifications/etc)
Tickets: PBL-36910
Change-Id: Ibbcb166a33f0337e1b14f426472261222f790ce6
* Add common_name parsing instead using kwargs
To fix tests where common name may not be passed in, use the CSR
generated to find the official common name.
Change-Id: I09f9258fa92c2762d095798676ce210c5d7a3da4
Tickets: PBL-36343
* Add Cancel to pending certificates and plugins
This allows pending certificates to be cancelled, which will be handled
by the issuer plugin.
Change-Id: Ibd6b5627c3977e33aca7860690cfb7f677236ca9
Tickets: PBL-36910
* Add API for Cancelling Pending Certificate
Added the DELETE handler for pending_certificates, which will cancel and
delete the pending certificate from the pending certs table on
successful cancellation via Issuer Plugin.
+ Add UT for testing cancel API
Change-Id: I11b1d87872e4284f6e4f9c366a15da4ddba38bc4
Tickets: PBL-36910
* Remove Export from Pending Certificates
Pending Certificates doesn't need an export since it should just be
fetched by Lemur via plugins, and the CSR is viewable via the UI.
Change-Id: I9a3e65ea11ac5a85316f6428e7f526c3c09178ae
Tickets: PBL-36910
* Add cancel button functionality to UI
This adds the Cancel option to the dropdown of pending certificates.
+ Adds modal window for Note (may not be required for all issuers, just
Digicert)
+ Add schema for cancel input
+ Fix Digitcert plugin for non-existant orders
When an order is actually issued, then attempting to cancel will return
a 403 from Digicert. This is a case where it should only be done once
we know the pending cert has been sitting for too long.
Change-Id: I256c81ecd142dd51dcf8e38802d2c202829887b0
Tickets: PBL-36910
* Fix test_pending_cancel UT
This change creates and injects a pending cert, which will then be used
for the ID so it can be canceled by the unit test.
Change-Id: I686e7e0fafd68cdaeb26438fb8504d79de77c346
Tickets: PBL-36343
* Fix test_digicert on non-existent order
cancelling a non-existent order is fine since we're cancelling it
Change-Id: I70c0e82ba2f4b8723a7f65b113c19e6eeff7e68c
Tickets: PBL-36343
* Add migrations for PendingCertificates
Added revision for Pending Certificates table and foreign key mapping
tables.
Change-Id: Ife8202cef1e6b99db377851264639ba540b749db
Tickets: n/a
* Fix relationship copy from Pending to Certificate
When a Pending Certificate is changed to a full Certificate, the
relationship fields are not copied via vars() function, as it's not a
column but mapped via association table. This adds an explicit copy for
these relations. Which will properly copy them to the new Certificate,
and thus also update destinations.
Change-Id: I322032ce4a9e3e67773f7cf39ee4971054c92685
Tickets: PBL-36343
* Fix renaming of certificates and unit tests
The rename flag was not used to rename certificates on creation as
expected.
Fixed unit test, instead of expunging the session, just copy the
pending_certificate so we don't have a weird reference to the object
that can't be copied via vars() function.
Change-Id: I962943272ed92386ab6eab2af4ed6d074d4cffa0
Tickets: PBL-36343
* Updated developer docs for async certs
Added blurb for implementing new issuer functions.
Change-Id: I1caed6e914bcd73214eae2d241e4784e1b8a0c4c
Tickets: n/a
2018-02-22 17:13:16 +01:00
|
|
|
return cert
|
|
|
|
|
|
|
|
def cancel_ordered_certificate(self, pending_cert, **kwargs):
|
|
|
|
""" Set the certificate order to canceled """
|
2019-05-16 16:57:02 +02:00
|
|
|
base_url = current_app.config.get("DIGICERT_URL")
|
|
|
|
api_url = "{0}/services/v2/order/certificate/{1}/status".format(
|
|
|
|
base_url, pending_cert.external_id
|
|
|
|
)
|
|
|
|
payload = {"status": "CANCELED", "note": kwargs.get("note")}
|
Async Certificate Issuing using Pending Certificates (#1037)
* Add PendingCertificate model
This change creates a DB table called pending_certificates and
associated mapping relationship tables from pending certificate to
roles, rotation policy, destination, sources, etc.
The table is generated on initialization of Lemur. A pending
certificate holds most of the information of a Certificate, while it has
not be issued so that it can later backfill the information when the CA
has issued the certificate.
Change-Id: I277c16b776a71fe5edaf0fa0e76bbedc88924db0
Tickets: PBL-36499
* Create a PendingCertificate if cert is empty
IssuePlugins should return empty cert bodies if the request failed to
complete immediately (such as Digicert). This way, we can immediately
return the certificate, or if not just place into PendingCertificates
for later processing.
+ Fix relation from Certificate to Pending Certificate, as view only.
There is no real need for anything more than that since Pending cert
only needs to know the cert to replace when it is issued later.
+ Made PendingCertificate private key be empty: UI does not allow
private key on 'Create' but only on 'Import'. For Instart, we require
the private key but upstream does not necessarily need it. Thus, if
someone at Instart wants to create a CSR / key combo, they should
manually issue the cert themselves and import later. Otherwise you
should let Lemur generate that. This keeps the workflow transparent for
upstream Lemur users.
Change-Id: Ib74722a5ed5792d4b10ca702659422739c95ae26
Tickets: PBL-36343
* Fix empty private_key when create Pending Cert
On creation of a certificate with a CSR, there is no option for private
key. In this case, we actually have a dictionary with private_key as
key, but the value is None. This fixes the strip() called on NoneType.
Change-Id: I7b265564d8095bfc83d9d4cd14ae13fea3c03199
Tickets: PBL-36499
* Source sync finds and uses pending certificate
When a source syncs certificates, it will check for a pending
certificate. If that is found via external_id (given by digicert as
order_id) then it will use the found Pending Certificate's fields to
create a new certificate. Then the pending certificate is deleted.
Tickets: PBL-36343
Change-Id: I4f7959da29275ebc47a3996741f7e98d3e2d29d9
* Add Lemur static files and views for pending certs
This adds the basic static files to view pending certificates in a
table.
Tickets: PBL-36343
Change-Id: Ia4362e6664ec730d05d280c5ef5c815a6feda0d9
* Add CLI and plugin based pending fetch
This change uses the adds a new function to issuer plugins to fetch
certificates like source, but for one order. This way, we can control
which pending certificates to try and populate instead of getting all
certificates from source.
Tickets: PBL-36343
Change-Id: Ifc1747ccdc2cba09a81f298b31ddddebfee1b1d6
* Revert source using Pending Certificate
Tickets: PBL-36343
Change-Id: I05121bc951e0530d804070afdb9c9e09baa0bc51
* Fix PendingCertificate init getting authority id
Should get authority id from authority.id instead of the authority_id
key in kwargs.
Change-Id: Ie56df1a5fb0ab2729e91050f3ad1a831853e0623
Tickets: n/a
* Add fixtures and basic test for PendingCertificate
Change-Id: I4cca34105544d40dac1cc50a87bba93d8af9ab34
Tickets: PBL-36343
* Add User to create_certificate parameters
create_certificate now takes a User, which will be used to populate the
'creator' field in certificates.service.upload(). This allows the UI
populate with the current user if the owner does not exist in Lemur.
+ Fix chain being replaced with version from pending certificate, which
may be empty (depends on plugin implementation).
Change-Id: I516027b36bc643c4978b9c4890060569e03f3049
Tickets: n/a
* Fix permalink and filters to pending certs
Fixes the permalink button to get a single pending certificate
Add argument filter parsing for the pending certificate API
Fix comment on API usage
Added get_by_name for pending_certificate (currently unused, but useful
for CLI, instead of using IDs)
Change-Id: Iaa48909c45606bec65dfb193c13d6bd0e816f6db
Tickets: PBL-36910
* Update displayed fields for Pending Certificates
There are a number of unused / unpopulated fields from Certificate UI
that does apply to Pending Certificates. Those ones were removed, and
added other useful fields:
Owner, number of attempts to fetch and date created
Change-Id: I3010a715f0357ba149cf539a19fdb5974c5ce08b
Tickets: PBL-36910
* Add common name (cn) to Pending Certificate model
Fixes the UI missing the CN for Pending Certificate, as it was
originally being parsed from the generated certificate. In the case of
pending certificate, the CN from the user generates the request, which
means a pending cert can trust the original user putting in the CN
instead of having to parse the not-yet-generated certificate. There is
no real possibility to return a certificate from a pending certificate
where the CN has changed since it was initially ordered.
Change-Id: I88a4fa28116d5d8d293e58970d9777ce73fbb2ab
Tickets: PBL-36910
* Fix missing imports for service filter
+ Removed duplicate get_by_name function from old merge
Change-Id: I04ae6852533aa42988433338de74390e2868d69b
Tickets: PBL-36910
* Add private key viewing to Pending Certificates
Add private key API for Pending Certificates, with the same
authorization as Certificates (only owner, creator or owner-roles can
view private key).
Change-Id: Ie5175154a10fe0007cc0e9f35b80c0a01ed48d5b
Tickets: PBL-36910
* Add edit capability to pending certificates
Like editing certificates, we should be able to modify some parts of a
pending certificate so the resulting certificate has the right
references, owner, etc.
+ Added API to update pending certificate
+ Fix UI to use pending certificate scope instead of reusing Certificate
+ Change pending_certificate.replaces to non-passive association, so
that updates do affect it (similar to roles/notifications/etc)
Tickets: PBL-36910
Change-Id: Ibbcb166a33f0337e1b14f426472261222f790ce6
* Add common_name parsing instead using kwargs
To fix tests where common name may not be passed in, use the CSR
generated to find the official common name.
Change-Id: I09f9258fa92c2762d095798676ce210c5d7a3da4
Tickets: PBL-36343
* Add Cancel to pending certificates and plugins
This allows pending certificates to be cancelled, which will be handled
by the issuer plugin.
Change-Id: Ibd6b5627c3977e33aca7860690cfb7f677236ca9
Tickets: PBL-36910
* Add API for Cancelling Pending Certificate
Added the DELETE handler for pending_certificates, which will cancel and
delete the pending certificate from the pending certs table on
successful cancellation via Issuer Plugin.
+ Add UT for testing cancel API
Change-Id: I11b1d87872e4284f6e4f9c366a15da4ddba38bc4
Tickets: PBL-36910
* Remove Export from Pending Certificates
Pending Certificates doesn't need an export since it should just be
fetched by Lemur via plugins, and the CSR is viewable via the UI.
Change-Id: I9a3e65ea11ac5a85316f6428e7f526c3c09178ae
Tickets: PBL-36910
* Add cancel button functionality to UI
This adds the Cancel option to the dropdown of pending certificates.
+ Adds modal window for Note (may not be required for all issuers, just
Digicert)
+ Add schema for cancel input
+ Fix Digitcert plugin for non-existant orders
When an order is actually issued, then attempting to cancel will return
a 403 from Digicert. This is a case where it should only be done once
we know the pending cert has been sitting for too long.
Change-Id: I256c81ecd142dd51dcf8e38802d2c202829887b0
Tickets: PBL-36910
* Fix test_pending_cancel UT
This change creates and injects a pending cert, which will then be used
for the ID so it can be canceled by the unit test.
Change-Id: I686e7e0fafd68cdaeb26438fb8504d79de77c346
Tickets: PBL-36343
* Fix test_digicert on non-existent order
cancelling a non-existent order is fine since we're cancelling it
Change-Id: I70c0e82ba2f4b8723a7f65b113c19e6eeff7e68c
Tickets: PBL-36343
* Add migrations for PendingCertificates
Added revision for Pending Certificates table and foreign key mapping
tables.
Change-Id: Ife8202cef1e6b99db377851264639ba540b749db
Tickets: n/a
* Fix relationship copy from Pending to Certificate
When a Pending Certificate is changed to a full Certificate, the
relationship fields are not copied via vars() function, as it's not a
column but mapped via association table. This adds an explicit copy for
these relations. Which will properly copy them to the new Certificate,
and thus also update destinations.
Change-Id: I322032ce4a9e3e67773f7cf39ee4971054c92685
Tickets: PBL-36343
* Fix renaming of certificates and unit tests
The rename flag was not used to rename certificates on creation as
expected.
Fixed unit test, instead of expunging the session, just copy the
pending_certificate so we don't have a weird reference to the object
that can't be copied via vars() function.
Change-Id: I962943272ed92386ab6eab2af4ed6d074d4cffa0
Tickets: PBL-36343
* Updated developer docs for async certs
Added blurb for implementing new issuer functions.
Change-Id: I1caed6e914bcd73214eae2d241e4784e1b8a0c4c
Tickets: n/a
2018-02-22 17:13:16 +01:00
|
|
|
response = self.session.put(api_url, data=json.dumps(payload))
|
|
|
|
if response.status_code == 404:
|
|
|
|
# not well documented by Digicert, but either the certificate does not exist or we
|
|
|
|
# don't own that order (someone else's order id!). Either way, we can just ignore it
|
|
|
|
# and have it removed from Lemur
|
|
|
|
current_app.logger.warning(
|
2019-05-16 16:57:02 +02:00
|
|
|
"Digicert Plugin tried to cancel pending certificate {0} but it does not exist!".format(
|
|
|
|
pending_cert.name
|
|
|
|
)
|
|
|
|
)
|
Async Certificate Issuing using Pending Certificates (#1037)
* Add PendingCertificate model
This change creates a DB table called pending_certificates and
associated mapping relationship tables from pending certificate to
roles, rotation policy, destination, sources, etc.
The table is generated on initialization of Lemur. A pending
certificate holds most of the information of a Certificate, while it has
not be issued so that it can later backfill the information when the CA
has issued the certificate.
Change-Id: I277c16b776a71fe5edaf0fa0e76bbedc88924db0
Tickets: PBL-36499
* Create a PendingCertificate if cert is empty
IssuePlugins should return empty cert bodies if the request failed to
complete immediately (such as Digicert). This way, we can immediately
return the certificate, or if not just place into PendingCertificates
for later processing.
+ Fix relation from Certificate to Pending Certificate, as view only.
There is no real need for anything more than that since Pending cert
only needs to know the cert to replace when it is issued later.
+ Made PendingCertificate private key be empty: UI does not allow
private key on 'Create' but only on 'Import'. For Instart, we require
the private key but upstream does not necessarily need it. Thus, if
someone at Instart wants to create a CSR / key combo, they should
manually issue the cert themselves and import later. Otherwise you
should let Lemur generate that. This keeps the workflow transparent for
upstream Lemur users.
Change-Id: Ib74722a5ed5792d4b10ca702659422739c95ae26
Tickets: PBL-36343
* Fix empty private_key when create Pending Cert
On creation of a certificate with a CSR, there is no option for private
key. In this case, we actually have a dictionary with private_key as
key, but the value is None. This fixes the strip() called on NoneType.
Change-Id: I7b265564d8095bfc83d9d4cd14ae13fea3c03199
Tickets: PBL-36499
* Source sync finds and uses pending certificate
When a source syncs certificates, it will check for a pending
certificate. If that is found via external_id (given by digicert as
order_id) then it will use the found Pending Certificate's fields to
create a new certificate. Then the pending certificate is deleted.
Tickets: PBL-36343
Change-Id: I4f7959da29275ebc47a3996741f7e98d3e2d29d9
* Add Lemur static files and views for pending certs
This adds the basic static files to view pending certificates in a
table.
Tickets: PBL-36343
Change-Id: Ia4362e6664ec730d05d280c5ef5c815a6feda0d9
* Add CLI and plugin based pending fetch
This change uses the adds a new function to issuer plugins to fetch
certificates like source, but for one order. This way, we can control
which pending certificates to try and populate instead of getting all
certificates from source.
Tickets: PBL-36343
Change-Id: Ifc1747ccdc2cba09a81f298b31ddddebfee1b1d6
* Revert source using Pending Certificate
Tickets: PBL-36343
Change-Id: I05121bc951e0530d804070afdb9c9e09baa0bc51
* Fix PendingCertificate init getting authority id
Should get authority id from authority.id instead of the authority_id
key in kwargs.
Change-Id: Ie56df1a5fb0ab2729e91050f3ad1a831853e0623
Tickets: n/a
* Add fixtures and basic test for PendingCertificate
Change-Id: I4cca34105544d40dac1cc50a87bba93d8af9ab34
Tickets: PBL-36343
* Add User to create_certificate parameters
create_certificate now takes a User, which will be used to populate the
'creator' field in certificates.service.upload(). This allows the UI
populate with the current user if the owner does not exist in Lemur.
+ Fix chain being replaced with version from pending certificate, which
may be empty (depends on plugin implementation).
Change-Id: I516027b36bc643c4978b9c4890060569e03f3049
Tickets: n/a
* Fix permalink and filters to pending certs
Fixes the permalink button to get a single pending certificate
Add argument filter parsing for the pending certificate API
Fix comment on API usage
Added get_by_name for pending_certificate (currently unused, but useful
for CLI, instead of using IDs)
Change-Id: Iaa48909c45606bec65dfb193c13d6bd0e816f6db
Tickets: PBL-36910
* Update displayed fields for Pending Certificates
There are a number of unused / unpopulated fields from Certificate UI
that does apply to Pending Certificates. Those ones were removed, and
added other useful fields:
Owner, number of attempts to fetch and date created
Change-Id: I3010a715f0357ba149cf539a19fdb5974c5ce08b
Tickets: PBL-36910
* Add common name (cn) to Pending Certificate model
Fixes the UI missing the CN for Pending Certificate, as it was
originally being parsed from the generated certificate. In the case of
pending certificate, the CN from the user generates the request, which
means a pending cert can trust the original user putting in the CN
instead of having to parse the not-yet-generated certificate. There is
no real possibility to return a certificate from a pending certificate
where the CN has changed since it was initially ordered.
Change-Id: I88a4fa28116d5d8d293e58970d9777ce73fbb2ab
Tickets: PBL-36910
* Fix missing imports for service filter
+ Removed duplicate get_by_name function from old merge
Change-Id: I04ae6852533aa42988433338de74390e2868d69b
Tickets: PBL-36910
* Add private key viewing to Pending Certificates
Add private key API for Pending Certificates, with the same
authorization as Certificates (only owner, creator or owner-roles can
view private key).
Change-Id: Ie5175154a10fe0007cc0e9f35b80c0a01ed48d5b
Tickets: PBL-36910
* Add edit capability to pending certificates
Like editing certificates, we should be able to modify some parts of a
pending certificate so the resulting certificate has the right
references, owner, etc.
+ Added API to update pending certificate
+ Fix UI to use pending certificate scope instead of reusing Certificate
+ Change pending_certificate.replaces to non-passive association, so
that updates do affect it (similar to roles/notifications/etc)
Tickets: PBL-36910
Change-Id: Ibbcb166a33f0337e1b14f426472261222f790ce6
* Add common_name parsing instead using kwargs
To fix tests where common name may not be passed in, use the CSR
generated to find the official common name.
Change-Id: I09f9258fa92c2762d095798676ce210c5d7a3da4
Tickets: PBL-36343
* Add Cancel to pending certificates and plugins
This allows pending certificates to be cancelled, which will be handled
by the issuer plugin.
Change-Id: Ibd6b5627c3977e33aca7860690cfb7f677236ca9
Tickets: PBL-36910
* Add API for Cancelling Pending Certificate
Added the DELETE handler for pending_certificates, which will cancel and
delete the pending certificate from the pending certs table on
successful cancellation via Issuer Plugin.
+ Add UT for testing cancel API
Change-Id: I11b1d87872e4284f6e4f9c366a15da4ddba38bc4
Tickets: PBL-36910
* Remove Export from Pending Certificates
Pending Certificates doesn't need an export since it should just be
fetched by Lemur via plugins, and the CSR is viewable via the UI.
Change-Id: I9a3e65ea11ac5a85316f6428e7f526c3c09178ae
Tickets: PBL-36910
* Add cancel button functionality to UI
This adds the Cancel option to the dropdown of pending certificates.
+ Adds modal window for Note (may not be required for all issuers, just
Digicert)
+ Add schema for cancel input
+ Fix Digitcert plugin for non-existant orders
When an order is actually issued, then attempting to cancel will return
a 403 from Digicert. This is a case where it should only be done once
we know the pending cert has been sitting for too long.
Change-Id: I256c81ecd142dd51dcf8e38802d2c202829887b0
Tickets: PBL-36910
* Fix test_pending_cancel UT
This change creates and injects a pending cert, which will then be used
for the ID so it can be canceled by the unit test.
Change-Id: I686e7e0fafd68cdaeb26438fb8504d79de77c346
Tickets: PBL-36343
* Fix test_digicert on non-existent order
cancelling a non-existent order is fine since we're cancelling it
Change-Id: I70c0e82ba2f4b8723a7f65b113c19e6eeff7e68c
Tickets: PBL-36343
* Add migrations for PendingCertificates
Added revision for Pending Certificates table and foreign key mapping
tables.
Change-Id: Ife8202cef1e6b99db377851264639ba540b749db
Tickets: n/a
* Fix relationship copy from Pending to Certificate
When a Pending Certificate is changed to a full Certificate, the
relationship fields are not copied via vars() function, as it's not a
column but mapped via association table. This adds an explicit copy for
these relations. Which will properly copy them to the new Certificate,
and thus also update destinations.
Change-Id: I322032ce4a9e3e67773f7cf39ee4971054c92685
Tickets: PBL-36343
* Fix renaming of certificates and unit tests
The rename flag was not used to rename certificates on creation as
expected.
Fixed unit test, instead of expunging the session, just copy the
pending_certificate so we don't have a weird reference to the object
that can't be copied via vars() function.
Change-Id: I962943272ed92386ab6eab2af4ed6d074d4cffa0
Tickets: PBL-36343
* Updated developer docs for async certs
Added blurb for implementing new issuer functions.
Change-Id: I1caed6e914bcd73214eae2d241e4784e1b8a0c4c
Tickets: n/a
2018-02-22 17:13:16 +01:00
|
|
|
elif response.status_code != 204:
|
2019-05-16 16:57:02 +02:00
|
|
|
current_app.logger.debug(
|
|
|
|
"{0} code {1}".format(response.status_code, response.content)
|
|
|
|
)
|
|
|
|
raise Exception(
|
|
|
|
"Failed to cancel pending certificate {0}".format(pending_cert.name)
|
|
|
|
)
|
Async Certificate Issuing using Pending Certificates (#1037)
* Add PendingCertificate model
This change creates a DB table called pending_certificates and
associated mapping relationship tables from pending certificate to
roles, rotation policy, destination, sources, etc.
The table is generated on initialization of Lemur. A pending
certificate holds most of the information of a Certificate, while it has
not be issued so that it can later backfill the information when the CA
has issued the certificate.
Change-Id: I277c16b776a71fe5edaf0fa0e76bbedc88924db0
Tickets: PBL-36499
* Create a PendingCertificate if cert is empty
IssuePlugins should return empty cert bodies if the request failed to
complete immediately (such as Digicert). This way, we can immediately
return the certificate, or if not just place into PendingCertificates
for later processing.
+ Fix relation from Certificate to Pending Certificate, as view only.
There is no real need for anything more than that since Pending cert
only needs to know the cert to replace when it is issued later.
+ Made PendingCertificate private key be empty: UI does not allow
private key on 'Create' but only on 'Import'. For Instart, we require
the private key but upstream does not necessarily need it. Thus, if
someone at Instart wants to create a CSR / key combo, they should
manually issue the cert themselves and import later. Otherwise you
should let Lemur generate that. This keeps the workflow transparent for
upstream Lemur users.
Change-Id: Ib74722a5ed5792d4b10ca702659422739c95ae26
Tickets: PBL-36343
* Fix empty private_key when create Pending Cert
On creation of a certificate with a CSR, there is no option for private
key. In this case, we actually have a dictionary with private_key as
key, but the value is None. This fixes the strip() called on NoneType.
Change-Id: I7b265564d8095bfc83d9d4cd14ae13fea3c03199
Tickets: PBL-36499
* Source sync finds and uses pending certificate
When a source syncs certificates, it will check for a pending
certificate. If that is found via external_id (given by digicert as
order_id) then it will use the found Pending Certificate's fields to
create a new certificate. Then the pending certificate is deleted.
Tickets: PBL-36343
Change-Id: I4f7959da29275ebc47a3996741f7e98d3e2d29d9
* Add Lemur static files and views for pending certs
This adds the basic static files to view pending certificates in a
table.
Tickets: PBL-36343
Change-Id: Ia4362e6664ec730d05d280c5ef5c815a6feda0d9
* Add CLI and plugin based pending fetch
This change uses the adds a new function to issuer plugins to fetch
certificates like source, but for one order. This way, we can control
which pending certificates to try and populate instead of getting all
certificates from source.
Tickets: PBL-36343
Change-Id: Ifc1747ccdc2cba09a81f298b31ddddebfee1b1d6
* Revert source using Pending Certificate
Tickets: PBL-36343
Change-Id: I05121bc951e0530d804070afdb9c9e09baa0bc51
* Fix PendingCertificate init getting authority id
Should get authority id from authority.id instead of the authority_id
key in kwargs.
Change-Id: Ie56df1a5fb0ab2729e91050f3ad1a831853e0623
Tickets: n/a
* Add fixtures and basic test for PendingCertificate
Change-Id: I4cca34105544d40dac1cc50a87bba93d8af9ab34
Tickets: PBL-36343
* Add User to create_certificate parameters
create_certificate now takes a User, which will be used to populate the
'creator' field in certificates.service.upload(). This allows the UI
populate with the current user if the owner does not exist in Lemur.
+ Fix chain being replaced with version from pending certificate, which
may be empty (depends on plugin implementation).
Change-Id: I516027b36bc643c4978b9c4890060569e03f3049
Tickets: n/a
* Fix permalink and filters to pending certs
Fixes the permalink button to get a single pending certificate
Add argument filter parsing for the pending certificate API
Fix comment on API usage
Added get_by_name for pending_certificate (currently unused, but useful
for CLI, instead of using IDs)
Change-Id: Iaa48909c45606bec65dfb193c13d6bd0e816f6db
Tickets: PBL-36910
* Update displayed fields for Pending Certificates
There are a number of unused / unpopulated fields from Certificate UI
that does apply to Pending Certificates. Those ones were removed, and
added other useful fields:
Owner, number of attempts to fetch and date created
Change-Id: I3010a715f0357ba149cf539a19fdb5974c5ce08b
Tickets: PBL-36910
* Add common name (cn) to Pending Certificate model
Fixes the UI missing the CN for Pending Certificate, as it was
originally being parsed from the generated certificate. In the case of
pending certificate, the CN from the user generates the request, which
means a pending cert can trust the original user putting in the CN
instead of having to parse the not-yet-generated certificate. There is
no real possibility to return a certificate from a pending certificate
where the CN has changed since it was initially ordered.
Change-Id: I88a4fa28116d5d8d293e58970d9777ce73fbb2ab
Tickets: PBL-36910
* Fix missing imports for service filter
+ Removed duplicate get_by_name function from old merge
Change-Id: I04ae6852533aa42988433338de74390e2868d69b
Tickets: PBL-36910
* Add private key viewing to Pending Certificates
Add private key API for Pending Certificates, with the same
authorization as Certificates (only owner, creator or owner-roles can
view private key).
Change-Id: Ie5175154a10fe0007cc0e9f35b80c0a01ed48d5b
Tickets: PBL-36910
* Add edit capability to pending certificates
Like editing certificates, we should be able to modify some parts of a
pending certificate so the resulting certificate has the right
references, owner, etc.
+ Added API to update pending certificate
+ Fix UI to use pending certificate scope instead of reusing Certificate
+ Change pending_certificate.replaces to non-passive association, so
that updates do affect it (similar to roles/notifications/etc)
Tickets: PBL-36910
Change-Id: Ibbcb166a33f0337e1b14f426472261222f790ce6
* Add common_name parsing instead using kwargs
To fix tests where common name may not be passed in, use the CSR
generated to find the official common name.
Change-Id: I09f9258fa92c2762d095798676ce210c5d7a3da4
Tickets: PBL-36343
* Add Cancel to pending certificates and plugins
This allows pending certificates to be cancelled, which will be handled
by the issuer plugin.
Change-Id: Ibd6b5627c3977e33aca7860690cfb7f677236ca9
Tickets: PBL-36910
* Add API for Cancelling Pending Certificate
Added the DELETE handler for pending_certificates, which will cancel and
delete the pending certificate from the pending certs table on
successful cancellation via Issuer Plugin.
+ Add UT for testing cancel API
Change-Id: I11b1d87872e4284f6e4f9c366a15da4ddba38bc4
Tickets: PBL-36910
* Remove Export from Pending Certificates
Pending Certificates doesn't need an export since it should just be
fetched by Lemur via plugins, and the CSR is viewable via the UI.
Change-Id: I9a3e65ea11ac5a85316f6428e7f526c3c09178ae
Tickets: PBL-36910
* Add cancel button functionality to UI
This adds the Cancel option to the dropdown of pending certificates.
+ Adds modal window for Note (may not be required for all issuers, just
Digicert)
+ Add schema for cancel input
+ Fix Digitcert plugin for non-existant orders
When an order is actually issued, then attempting to cancel will return
a 403 from Digicert. This is a case where it should only be done once
we know the pending cert has been sitting for too long.
Change-Id: I256c81ecd142dd51dcf8e38802d2c202829887b0
Tickets: PBL-36910
* Fix test_pending_cancel UT
This change creates and injects a pending cert, which will then be used
for the ID so it can be canceled by the unit test.
Change-Id: I686e7e0fafd68cdaeb26438fb8504d79de77c346
Tickets: PBL-36343
* Fix test_digicert on non-existent order
cancelling a non-existent order is fine since we're cancelling it
Change-Id: I70c0e82ba2f4b8723a7f65b113c19e6eeff7e68c
Tickets: PBL-36343
* Add migrations for PendingCertificates
Added revision for Pending Certificates table and foreign key mapping
tables.
Change-Id: Ife8202cef1e6b99db377851264639ba540b749db
Tickets: n/a
* Fix relationship copy from Pending to Certificate
When a Pending Certificate is changed to a full Certificate, the
relationship fields are not copied via vars() function, as it's not a
column but mapped via association table. This adds an explicit copy for
these relations. Which will properly copy them to the new Certificate,
and thus also update destinations.
Change-Id: I322032ce4a9e3e67773f7cf39ee4971054c92685
Tickets: PBL-36343
* Fix renaming of certificates and unit tests
The rename flag was not used to rename certificates on creation as
expected.
Fixed unit test, instead of expunging the session, just copy the
pending_certificate so we don't have a weird reference to the object
that can't be copied via vars() function.
Change-Id: I962943272ed92386ab6eab2af4ed6d074d4cffa0
Tickets: PBL-36343
* Updated developer docs for async certs
Added blurb for implementing new issuer functions.
Change-Id: I1caed6e914bcd73214eae2d241e4784e1b8a0c4c
Tickets: n/a
2018-02-22 17:13:16 +01:00
|
|
|
|
2016-11-07 23:40:00 +01:00
|
|
|
@staticmethod
|
|
|
|
def create_authority(options):
|
|
|
|
"""Create an authority.
|
|
|
|
|
|
|
|
Creates an authority, this authority is then used by Lemur to
|
|
|
|
allow a user to specify which Certificate Authority they want
|
|
|
|
to sign their certificate.
|
|
|
|
|
|
|
|
:param options:
|
|
|
|
:return:
|
|
|
|
"""
|
2019-05-16 16:57:02 +02:00
|
|
|
role = {"username": "", "password": "", "name": "digicert"}
|
|
|
|
return current_app.config.get("DIGICERT_ROOT"), "", [role]
|
2016-11-28 19:50:58 +01:00
|
|
|
|
|
|
|
|
2017-10-05 01:56:01 +02:00
|
|
|
class DigiCertCISSourcePlugin(SourcePlugin):
|
|
|
|
"""Wrap the Digicert CIS Certifcate API."""
|
2019-05-16 16:57:02 +02:00
|
|
|
|
|
|
|
title = "DigiCert"
|
|
|
|
slug = "digicert-cis-source"
|
2017-10-05 01:56:01 +02:00
|
|
|
description = "Enables the use of Digicert as a source of existing certificates."
|
|
|
|
version = digicert.VERSION
|
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
author = "Kevin Glisson"
|
|
|
|
author_url = "https://github.com/netflix/lemur.git"
|
2017-10-05 01:56:01 +02:00
|
|
|
|
2017-10-06 02:27:45 +02:00
|
|
|
additional_options = []
|
|
|
|
|
2017-10-05 01:56:01 +02:00
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
"""Initialize source with appropriate details."""
|
|
|
|
required_vars = [
|
2019-05-16 16:57:02 +02:00
|
|
|
"DIGICERT_CIS_API_KEY",
|
|
|
|
"DIGICERT_CIS_URL",
|
2019-08-07 19:24:38 +02:00
|
|
|
"DIGICERT_CIS_ROOTS",
|
|
|
|
"DIGICERT_CIS_PROFILE_NAMES",
|
2017-10-05 01:56:01 +02:00
|
|
|
]
|
|
|
|
validate_conf(current_app, required_vars)
|
|
|
|
|
|
|
|
self.session = requests.Session()
|
|
|
|
self.session.headers.update(
|
|
|
|
{
|
2019-05-16 16:57:02 +02:00
|
|
|
"X-DC-DEVKEY": current_app.config["DIGICERT_CIS_API_KEY"],
|
|
|
|
"Content-Type": "application/json",
|
2017-10-05 01:56:01 +02:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
self.session.hooks = dict(response=log_status_code)
|
|
|
|
|
2017-10-12 19:37:58 +02:00
|
|
|
a = requests.adapters.HTTPAdapter(max_retries=3)
|
2019-05-16 16:57:02 +02:00
|
|
|
self.session.mount("https://", a)
|
2017-10-12 19:37:58 +02:00
|
|
|
|
2017-10-05 01:56:01 +02:00
|
|
|
super(DigiCertCISSourcePlugin, self).__init__(*args, **kwargs)
|
|
|
|
|
|
|
|
def get_certificates(self, options, **kwargs):
|
|
|
|
"""Fetch all Digicert certificates."""
|
2019-05-16 16:57:02 +02:00
|
|
|
base_url = current_app.config.get("DIGICERT_CIS_URL")
|
2017-10-05 01:56:01 +02:00
|
|
|
|
|
|
|
# make request
|
2019-05-16 16:57:02 +02:00
|
|
|
search_url = "{0}/platform/cis/certificate/search".format(base_url)
|
2017-10-05 01:56:01 +02:00
|
|
|
|
|
|
|
certs = []
|
|
|
|
page = 1
|
|
|
|
|
|
|
|
while True:
|
2019-05-16 16:57:02 +02:00
|
|
|
response = self.session.get(
|
|
|
|
search_url, params={"status": ["issued"], "page": page}
|
|
|
|
)
|
2017-10-05 01:56:01 +02:00
|
|
|
data = handle_cis_response(response)
|
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
for c in data["certificates"]:
|
|
|
|
download_url = "{0}/platform/cis/certificate/{1}".format(
|
|
|
|
base_url, c["id"]
|
|
|
|
)
|
2017-10-05 01:56:01 +02:00
|
|
|
certificate = self.session.get(download_url)
|
|
|
|
|
|
|
|
# normalize serial
|
2019-05-16 16:57:02 +02:00
|
|
|
serial = str(int(c["serial_number"], 16))
|
|
|
|
cert = {
|
|
|
|
"body": certificate.content,
|
|
|
|
"serial": serial,
|
|
|
|
"external_id": c["id"],
|
|
|
|
}
|
2017-10-05 01:56:01 +02:00
|
|
|
certs.append(cert)
|
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
if page == data["total_pages"]:
|
2017-10-05 01:56:01 +02:00
|
|
|
break
|
|
|
|
|
|
|
|
page += 1
|
|
|
|
return certs
|
|
|
|
|
|
|
|
|
2016-11-28 19:50:58 +01:00
|
|
|
class DigiCertCISIssuerPlugin(IssuerPlugin):
|
|
|
|
"""Wrap the Digicert Certificate Issuing API."""
|
2019-05-16 16:57:02 +02:00
|
|
|
|
|
|
|
title = "DigiCert CIS"
|
|
|
|
slug = "digicert-cis-issuer"
|
2016-11-28 19:50:58 +01:00
|
|
|
description = "Enables the creation of certificates by the DigiCert CIS REST API."
|
|
|
|
version = digicert.VERSION
|
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
author = "Kevin Glisson"
|
|
|
|
author_url = "https://github.com/netflix/lemur.git"
|
2016-11-28 19:50:58 +01:00
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
"""Initialize the issuer with the appropriate details."""
|
|
|
|
required_vars = [
|
2019-05-16 16:57:02 +02:00
|
|
|
"DIGICERT_CIS_API_KEY",
|
|
|
|
"DIGICERT_CIS_URL",
|
2019-08-07 19:24:38 +02:00
|
|
|
"DIGICERT_CIS_ROOTS",
|
|
|
|
"DIGICERT_CIS_PROFILE_NAMES",
|
2016-11-28 19:50:58 +01:00
|
|
|
]
|
|
|
|
|
|
|
|
validate_conf(current_app, required_vars)
|
|
|
|
|
|
|
|
self.session = requests.Session()
|
|
|
|
self.session.headers.update(
|
|
|
|
{
|
2019-05-16 16:57:02 +02:00
|
|
|
"X-DC-DEVKEY": current_app.config["DIGICERT_CIS_API_KEY"],
|
|
|
|
"Content-Type": "application/json",
|
2016-11-28 19:50:58 +01:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2016-12-02 22:02:59 +01:00
|
|
|
self.session.hooks = dict(response=log_status_code)
|
|
|
|
|
2016-11-28 19:50:58 +01:00
|
|
|
super(DigiCertCISIssuerPlugin, self).__init__(*args, **kwargs)
|
|
|
|
|
|
|
|
def create_certificate(self, csr, issuer_options):
|
|
|
|
"""Create a DigiCert certificate."""
|
2019-05-16 16:57:02 +02:00
|
|
|
base_url = current_app.config.get("DIGICERT_CIS_URL")
|
2016-11-28 19:50:58 +01:00
|
|
|
|
|
|
|
# make certificate request
|
2019-05-16 16:57:02 +02:00
|
|
|
create_url = "{0}/platform/cis/certificate".format(base_url)
|
2016-11-28 19:50:58 +01:00
|
|
|
|
|
|
|
data = map_cis_fields(issuer_options, csr)
|
|
|
|
response = self.session.post(create_url, data=json.dumps(data))
|
2016-11-30 19:54:53 +01:00
|
|
|
data = handle_cis_response(response)
|
2016-11-28 19:50:58 +01:00
|
|
|
|
|
|
|
# retrieve certificate
|
2020-10-08 05:06:20 +02:00
|
|
|
certificate_chain_pem = get_cis_certificate(self.session, base_url, data["id"])
|
2016-12-11 17:38:59 +01:00
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
self.session.headers.pop("Accept")
|
2020-10-08 05:06:20 +02:00
|
|
|
end_entity = certificate_chain_pem[0]
|
|
|
|
intermediate = certificate_chain_pem[1]
|
2018-04-11 01:54:17 +02:00
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
return (
|
|
|
|
"\n".join(str(end_entity).splitlines()),
|
2020-10-08 05:06:20 +02:00
|
|
|
"\n".join(str(intermediate).splitlines()),
|
2019-05-16 16:57:02 +02:00
|
|
|
data["id"],
|
|
|
|
)
|
2017-09-29 03:27:56 +02:00
|
|
|
|
|
|
|
def revoke_certificate(self, certificate, comments):
|
|
|
|
"""Revoke a Digicert certificate."""
|
2019-05-16 16:57:02 +02:00
|
|
|
base_url = current_app.config.get("DIGICERT_CIS_URL")
|
2017-09-29 03:27:56 +02:00
|
|
|
|
|
|
|
# make certificate revoke request
|
2019-05-16 16:57:02 +02:00
|
|
|
revoke_url = "{0}/platform/cis/certificate/{1}/revoke".format(
|
|
|
|
base_url, certificate.external_id
|
|
|
|
)
|
|
|
|
metrics.send("digicert_revoke_certificate_success", "counter", 1)
|
|
|
|
response = self.session.put(revoke_url, data=json.dumps({"comments": comments}))
|
2017-09-29 03:27:56 +02:00
|
|
|
|
|
|
|
if response.status_code != 204:
|
2019-05-16 16:57:02 +02:00
|
|
|
metrics.send("digicert_revoke_certificate_failure", "counter", 1)
|
|
|
|
raise Exception("Failed to revoke certificate.")
|
2017-09-29 03:27:56 +02:00
|
|
|
|
2019-05-16 16:57:02 +02:00
|
|
|
metrics.send("digicert_revoke_certificate_success", "counter", 1)
|
2016-11-28 19:50:58 +01:00
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def create_authority(options):
|
|
|
|
"""Create an authority.
|
|
|
|
|
|
|
|
Creates an authority, this authority is then used by Lemur to
|
|
|
|
allow a user to specify which Certificate Authority they want
|
|
|
|
to sign their certificate.
|
|
|
|
|
|
|
|
:param options:
|
|
|
|
:return:
|
|
|
|
"""
|
2019-05-16 16:57:02 +02:00
|
|
|
role = {"username": "", "password": "", "name": "digicert"}
|
2019-08-07 21:05:13 +02:00
|
|
|
return current_app.config.get("DIGICERT_CIS_ROOTS", {}).get(options['authority'].name), "", [role]
|