Merge branch 'master' into feature/travis-python38
This commit is contained in:
commit
6d367099be
|
@ -362,6 +362,9 @@ Whenever a pending ACME certificate fails to be issued, Lemur will send a notifi
|
||||||
and security team (as specified by the ``LEMUR_SECURITY_TEAM_EMAIL`` configuration parameter). This email is not sent if
|
and security team (as specified by the ``LEMUR_SECURITY_TEAM_EMAIL`` configuration parameter). This email is not sent if
|
||||||
the pending certificate had notifications disabled.
|
the pending certificate had notifications disabled.
|
||||||
|
|
||||||
|
Lemur will attempt 3x times to resolve a pending certificate.
|
||||||
|
This can at times result into 3 duplicate certificates, if all certificate attempts get resolved.
|
||||||
|
|
||||||
**Certificate rotation**
|
**Certificate rotation**
|
||||||
|
|
||||||
Whenever a cert is rotated, Lemur will send a notification via email to the certificate owner. This notification is
|
Whenever a cert is rotated, Lemur will send a notification via email to the certificate owner. This notification is
|
||||||
|
@ -820,6 +823,20 @@ ACME Plugin
|
||||||
Enables delegated DNS domain validation using CNAMES. When enabled, Lemur will attempt to follow CNAME records to authoritative DNS servers when creating DNS-01 challenges.
|
Enables delegated DNS domain validation using CNAMES. When enabled, Lemur will attempt to follow CNAME records to authoritative DNS servers when creating DNS-01 challenges.
|
||||||
|
|
||||||
|
|
||||||
|
The following configration properties are optional for the ACME plugin to use. They allow reusing an existing ACME
|
||||||
|
account. See :ref:`Using a pre-existing ACME account <AcmeAccountReuse>` for more details.
|
||||||
|
|
||||||
|
|
||||||
|
.. data:: ACME_PRIVATE_KEY
|
||||||
|
:noindex:
|
||||||
|
|
||||||
|
This is the private key, the account was registered with (in JWK format)
|
||||||
|
|
||||||
|
.. data:: ACME_REGR
|
||||||
|
:noindex:
|
||||||
|
|
||||||
|
This is the registration for the ACME account, the most important part is the uri attribute (in JSON)
|
||||||
|
|
||||||
Active Directory Certificate Services Plugin
|
Active Directory Certificate Services Plugin
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
@ -1336,23 +1353,6 @@ The following configuration properties are required to use the PowerDNS ACME Plu
|
||||||
|
|
||||||
File/Dir path to CA Bundle: Verifies the TLS certificate was issued by a Certificate Authority in the provided CA bundle.
|
File/Dir path to CA Bundle: Verifies the TLS certificate was issued by a Certificate Authority in the provided CA bundle.
|
||||||
|
|
||||||
ACME Plugin
|
|
||||||
~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The following configration properties are optional for the ACME plugin to use. They allow reusing an existing ACME
|
|
||||||
account. See :ref:`Using a pre-existing ACME account <AcmeAccountReuse>` for more details.
|
|
||||||
|
|
||||||
|
|
||||||
.. data:: ACME_PRIVATE_KEY
|
|
||||||
:noindex:
|
|
||||||
|
|
||||||
This is the private key, the account was registered with (in JWK format)
|
|
||||||
|
|
||||||
.. data:: ACME_REGR
|
|
||||||
:noindex:
|
|
||||||
|
|
||||||
This is the registration for the ACME account, the most important part is the uri attribute (in JSON)
|
|
||||||
|
|
||||||
.. _CommandLineInterface:
|
.. _CommandLineInterface:
|
||||||
|
|
||||||
Command Line Interface
|
Command Line Interface
|
||||||
|
|
|
@ -261,10 +261,10 @@ def rotate(endpoint_name, new_certificate_name, old_certificate_name, message, c
|
||||||
|
|
||||||
log_data["endpoint"] = endpoint.dnsname
|
log_data["endpoint"] = endpoint.dnsname
|
||||||
log_data["certificate"] = endpoint.certificate.replaced[0].name
|
log_data["certificate"] = endpoint.certificate.replaced[0].name
|
||||||
request_rotation(endpoint, endpoint.certificate.replaced[0], message, commit)
|
|
||||||
print(
|
print(
|
||||||
f"[+] Rotating {endpoint.name} to {endpoint.certificate.replaced[0].name}"
|
f"[+] Rotating {endpoint.name} to {endpoint.certificate.replaced[0].name}"
|
||||||
)
|
)
|
||||||
|
request_rotation(endpoint, endpoint.certificate.replaced[0], message, commit)
|
||||||
current_app.logger.info(log_data)
|
current_app.logger.info(log_data)
|
||||||
|
|
||||||
status = SUCCESS_METRIC_STATUS
|
status = SUCCESS_METRIC_STATUS
|
||||||
|
@ -427,7 +427,7 @@ def rotate_region(endpoint_name, new_certificate_name, old_certificate_name, mes
|
||||||
1,
|
1,
|
||||||
metric_tags={
|
metric_tags={
|
||||||
"status": FAILURE_METRIC_STATUS,
|
"status": FAILURE_METRIC_STATUS,
|
||||||
"new_certificate_name": str(endpoint.certificate.replaced[0].name),
|
"new_certificate_name": str(log_data["certificate"]),
|
||||||
"endpoint_name": str(endpoint.dnsname),
|
"endpoint_name": str(endpoint.dnsname),
|
||||||
"message": str(message),
|
"message": str(message),
|
||||||
"region": str(region),
|
"region": str(region),
|
||||||
|
|
|
@ -388,6 +388,7 @@ def create(**kwargs):
|
||||||
cert = Certificate(**kwargs)
|
cert = Certificate(**kwargs)
|
||||||
kwargs["creator"].certificates.append(cert)
|
kwargs["creator"].certificates.append(cert)
|
||||||
else:
|
else:
|
||||||
|
# ACME path
|
||||||
cert = PendingCertificate(**kwargs)
|
cert = PendingCertificate(**kwargs)
|
||||||
kwargs["creator"].pending_certificates.append(cert)
|
kwargs["creator"].pending_certificates.append(cert)
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ from flask import current_app
|
||||||
from lemur.authorities.service import get as get_authority
|
from lemur.authorities.service import get as get_authority
|
||||||
from lemur.certificates import cli as cli_certificate
|
from lemur.certificates import cli as cli_certificate
|
||||||
from lemur.common.redis import RedisHandler
|
from lemur.common.redis import RedisHandler
|
||||||
|
from lemur.constants import ACME_ADDITIONAL_ATTEMPTS
|
||||||
from lemur.destinations import service as destinations_service
|
from lemur.destinations import service as destinations_service
|
||||||
from lemur.dns_providers import cli as cli_dns_providers
|
from lemur.dns_providers import cli as cli_dns_providers
|
||||||
from lemur.endpoints import cli as cli_endpoints
|
from lemur.endpoints import cli as cli_endpoints
|
||||||
|
@ -273,7 +274,8 @@ def fetch_acme_cert(id):
|
||||||
real_cert = cert.get("cert")
|
real_cert = cert.get("cert")
|
||||||
# It's necessary to reload the pending cert due to detached instance: http://sqlalche.me/e/bhk3
|
# It's necessary to reload the pending cert due to detached instance: http://sqlalche.me/e/bhk3
|
||||||
pending_cert = pending_certificate_service.get(cert.get("pending_cert").id)
|
pending_cert = pending_certificate_service.get(cert.get("pending_cert").id)
|
||||||
if not pending_cert:
|
if not pending_cert or pending_cert.resolved:
|
||||||
|
# pending_cert is cleared or it was resolved by another process
|
||||||
log_data[
|
log_data[
|
||||||
"message"
|
"message"
|
||||||
] = "Pending certificate doesn't exist anymore. Was it resolved by another process?"
|
] = "Pending certificate doesn't exist anymore. Was it resolved by another process?"
|
||||||
|
@ -301,7 +303,7 @@ def fetch_acme_cert(id):
|
||||||
error_log["last_error"] = cert.get("last_error")
|
error_log["last_error"] = cert.get("last_error")
|
||||||
error_log["cn"] = pending_cert.cn
|
error_log["cn"] = pending_cert.cn
|
||||||
|
|
||||||
if pending_cert.number_attempts > 4:
|
if pending_cert.number_attempts > ACME_ADDITIONAL_ATTEMPTS:
|
||||||
error_log["message"] = "Deleting pending certificate"
|
error_log["message"] = "Deleting pending certificate"
|
||||||
send_pending_failure_notification(
|
send_pending_failure_notification(
|
||||||
pending_cert, notify_owner=pending_cert.notify
|
pending_cert, notify_owner=pending_cert.notify
|
||||||
|
|
|
@ -12,6 +12,9 @@ NONSTANDARD_NAMING_TEMPLATE = "{issuer}-{not_before}-{not_after}"
|
||||||
SUCCESS_METRIC_STATUS = "success"
|
SUCCESS_METRIC_STATUS = "success"
|
||||||
FAILURE_METRIC_STATUS = "failure"
|
FAILURE_METRIC_STATUS = "failure"
|
||||||
|
|
||||||
|
# when ACME attempts to resolve a certificate try in total 3 times
|
||||||
|
ACME_ADDITIONAL_ATTEMPTS = 2
|
||||||
|
|
||||||
CERTIFICATE_KEY_TYPES = [
|
CERTIFICATE_KEY_TYPES = [
|
||||||
"RSA2048",
|
"RSA2048",
|
||||||
"RSA4096",
|
"RSA4096",
|
||||||
|
|
|
@ -12,10 +12,12 @@ from flask import current_app
|
||||||
from flask_script import Manager
|
from flask_script import Manager
|
||||||
|
|
||||||
from lemur.authorities.service import get as get_authority
|
from lemur.authorities.service import get as get_authority
|
||||||
|
from lemur.constants import ACME_ADDITIONAL_ATTEMPTS
|
||||||
from lemur.notifications.messaging import send_pending_failure_notification
|
from lemur.notifications.messaging import send_pending_failure_notification
|
||||||
from lemur.pending_certificates import service as pending_certificate_service
|
from lemur.pending_certificates import service as pending_certificate_service
|
||||||
from lemur.plugins.base import plugins
|
from lemur.plugins.base import plugins
|
||||||
|
|
||||||
|
|
||||||
manager = Manager(usage="Handles pending certificate related tasks.")
|
manager = Manager(usage="Handles pending certificate related tasks.")
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,7 +109,7 @@ def fetch_all_acme():
|
||||||
error_log["last_error"] = cert.get("last_error")
|
error_log["last_error"] = cert.get("last_error")
|
||||||
error_log["cn"] = pending_cert.cn
|
error_log["cn"] = pending_cert.cn
|
||||||
|
|
||||||
if pending_cert.number_attempts > 4:
|
if pending_cert.number_attempts > ACME_ADDITIONAL_ATTEMPTS:
|
||||||
error_log["message"] = "Marking pending certificate as resolved"
|
error_log["message"] = "Marking pending certificate as resolved"
|
||||||
send_pending_failure_notification(
|
send_pending_failure_notification(
|
||||||
pending_cert, notify_owner=pending_cert.notify
|
pending_cert, notify_owner=pending_cert.notify
|
||||||
|
|
|
@ -48,7 +48,7 @@ nodeenv==1.5.0
|
||||||
# pre-commit
|
# pre-commit
|
||||||
pkginfo==1.5.0.1
|
pkginfo==1.5.0.1
|
||||||
# via twine
|
# via twine
|
||||||
pre-commit==2.9.3
|
pre-commit==2.10.0
|
||||||
# via -r requirements-dev.in
|
# via -r requirements-dev.in
|
||||||
pycodestyle==2.6.0
|
pycodestyle==2.6.0
|
||||||
# via flake8
|
# via flake8
|
||||||
|
|
|
@ -4,32 +4,63 @@
|
||||||
#
|
#
|
||||||
# pip-compile --no-index --output-file=requirements-docs.txt requirements-docs.in
|
# pip-compile --no-index --output-file=requirements-docs.txt requirements-docs.in
|
||||||
#
|
#
|
||||||
alabaster==0.7.12 # via sphinx
|
alabaster==0.7.12
|
||||||
babel==2.8.0 # via sphinx
|
# via sphinx
|
||||||
certifi==2020.12.5 # via requests
|
babel==2.8.0
|
||||||
chardet==3.0.4 # via requests
|
# via sphinx
|
||||||
docutils==0.15.2 # via sphinx
|
certifi==2020.12.5
|
||||||
idna==2.9 # via requests
|
# via requests
|
||||||
imagesize==1.2.0 # via sphinx
|
chardet==3.0.4
|
||||||
jinja2==2.11.2 # via sphinx
|
# via requests
|
||||||
markupsafe==1.1.1 # via jinja2
|
docutils==0.15.2
|
||||||
packaging==20.3 # via sphinx
|
# via sphinx
|
||||||
pygments==2.6.1 # via sphinx
|
idna==2.9
|
||||||
pyparsing==2.4.7 # via packaging
|
# via requests
|
||||||
pytz==2019.3 # via babel
|
imagesize==1.2.0
|
||||||
requests==2.25.1 # via sphinx
|
# via sphinx
|
||||||
six==1.15.0 # via packaging, sphinxcontrib-httpdomain
|
jinja2==2.11.3
|
||||||
snowballstemmer==2.0.0 # via sphinx
|
# via sphinx
|
||||||
sphinx-rtd-theme==0.5.1 # via -r requirements-docs.in
|
markupsafe==1.1.1
|
||||||
sphinx==3.4.3 # via -r requirements-docs.in, sphinx-rtd-theme, sphinxcontrib-httpdomain
|
# via jinja2
|
||||||
sphinxcontrib-applehelp==1.0.2 # via sphinx
|
packaging==20.3
|
||||||
sphinxcontrib-devhelp==1.0.2 # via sphinx
|
# via sphinx
|
||||||
sphinxcontrib-htmlhelp==1.0.3 # via sphinx
|
pygments==2.6.1
|
||||||
sphinxcontrib-httpdomain==1.7.0 # via -r requirements-docs.in
|
# via sphinx
|
||||||
sphinxcontrib-jsmath==1.0.1 # via sphinx
|
pyparsing==2.4.7
|
||||||
sphinxcontrib-qthelp==1.0.3 # via sphinx
|
# via packaging
|
||||||
sphinxcontrib-serializinghtml==1.1.4 # via sphinx
|
pytz==2019.3
|
||||||
urllib3==1.25.8 # via requests
|
# via babel
|
||||||
|
requests==2.25.1
|
||||||
|
# via sphinx
|
||||||
|
six==1.15.0
|
||||||
|
# via
|
||||||
|
# packaging
|
||||||
|
# sphinxcontrib-httpdomain
|
||||||
|
snowballstemmer==2.0.0
|
||||||
|
# via sphinx
|
||||||
|
sphinx-rtd-theme==0.5.1
|
||||||
|
# via -r requirements-docs.in
|
||||||
|
sphinx==3.4.3
|
||||||
|
# via
|
||||||
|
# -r requirements-docs.in
|
||||||
|
# sphinx-rtd-theme
|
||||||
|
# sphinxcontrib-httpdomain
|
||||||
|
sphinxcontrib-applehelp==1.0.2
|
||||||
|
# via sphinx
|
||||||
|
sphinxcontrib-devhelp==1.0.2
|
||||||
|
# via sphinx
|
||||||
|
sphinxcontrib-htmlhelp==1.0.3
|
||||||
|
# via sphinx
|
||||||
|
sphinxcontrib-httpdomain==1.7.0
|
||||||
|
# via -r requirements-docs.in
|
||||||
|
sphinxcontrib-jsmath==1.0.1
|
||||||
|
# via sphinx
|
||||||
|
sphinxcontrib-qthelp==1.0.3
|
||||||
|
# via sphinx
|
||||||
|
sphinxcontrib-serializinghtml==1.1.4
|
||||||
|
# via sphinx
|
||||||
|
urllib3==1.25.8
|
||||||
|
# via requests
|
||||||
|
|
||||||
# The following packages are considered to be unsafe in a requirements file:
|
# The following packages are considered to be unsafe in a requirements file:
|
||||||
# setuptools
|
# setuptools
|
||||||
|
|
|
@ -18,13 +18,13 @@ bandit==1.7.0
|
||||||
# via -r requirements-tests.in
|
# via -r requirements-tests.in
|
||||||
black==20.8b1
|
black==20.8b1
|
||||||
# via -r requirements-tests.in
|
# via -r requirements-tests.in
|
||||||
boto3==1.16.60
|
boto3==1.16.63
|
||||||
# via
|
# via
|
||||||
# aws-sam-translator
|
# aws-sam-translator
|
||||||
# moto
|
# moto
|
||||||
boto==2.49.0
|
boto==2.49.0
|
||||||
# via moto
|
# via moto
|
||||||
botocore==1.19.60
|
botocore==1.19.63
|
||||||
# via
|
# via
|
||||||
# aws-xray-sdk
|
# aws-xray-sdk
|
||||||
# boto3
|
# boto3
|
||||||
|
@ -42,7 +42,7 @@ click==7.1.2
|
||||||
# via
|
# via
|
||||||
# black
|
# black
|
||||||
# flask
|
# flask
|
||||||
coverage==5.3.1
|
coverage==5.4
|
||||||
# via -r requirements-tests.in
|
# via -r requirements-tests.in
|
||||||
cryptography==3.3.1
|
cryptography==3.3.1
|
||||||
# via
|
# via
|
||||||
|
@ -86,7 +86,7 @@ iniconfig==1.0.1
|
||||||
# via pytest
|
# via pytest
|
||||||
itsdangerous==1.1.0
|
itsdangerous==1.1.0
|
||||||
# via flask
|
# via flask
|
||||||
jinja2==2.11.2
|
jinja2==2.11.3
|
||||||
# via
|
# via
|
||||||
# flask
|
# flask
|
||||||
# moto
|
# moto
|
||||||
|
@ -148,7 +148,7 @@ pytest-flask==1.1.0
|
||||||
# via -r requirements-tests.in
|
# via -r requirements-tests.in
|
||||||
pytest-mock==3.5.1
|
pytest-mock==3.5.1
|
||||||
# via -r requirements-tests.in
|
# via -r requirements-tests.in
|
||||||
pytest==6.2.1
|
pytest==6.2.2
|
||||||
# via
|
# via
|
||||||
# -r requirements-tests.in
|
# -r requirements-tests.in
|
||||||
# pytest-flask
|
# pytest-flask
|
||||||
|
|
|
@ -31,9 +31,9 @@ blinker==1.4
|
||||||
# flask-mail
|
# flask-mail
|
||||||
# flask-principal
|
# flask-principal
|
||||||
# raven
|
# raven
|
||||||
boto3==1.16.60
|
boto3==1.16.63
|
||||||
# via -r requirements.in
|
# via -r requirements.in
|
||||||
botocore==1.19.60
|
botocore==1.19.63
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# boto3
|
# boto3
|
||||||
|
@ -117,7 +117,7 @@ itsdangerous==1.1.0
|
||||||
# via flask
|
# via flask
|
||||||
javaobj-py3==0.4.0.1
|
javaobj-py3==0.4.0.1
|
||||||
# via pyjks
|
# via pyjks
|
||||||
jinja2==2.11.2
|
jinja2==2.11.3
|
||||||
# via
|
# via
|
||||||
# -r requirements.in
|
# -r requirements.in
|
||||||
# flask
|
# flask
|
||||||
|
|
Loading…
Reference in New Issue