Merge branch 'powerdnsplugin_02' of github.com:Netflix/lemur into powerdnsplugin_02
This commit is contained in:
commit
9d9bf9d7ba
|
@ -321,7 +321,8 @@ class Certificate(db.Model):
|
||||||
|
|
||||||
@hybrid_property
|
@hybrid_property
|
||||||
def expired(self):
|
def expired(self):
|
||||||
if self.not_after <= arrow.utcnow():
|
# can't compare offset-naive and offset-aware datetimes
|
||||||
|
if arrow.Arrow.fromdatetime(self.not_after) <= arrow.utcnow():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@expired.expression
|
@expired.expression
|
||||||
|
@ -445,6 +446,9 @@ def update_destinations(target, value, initiator):
|
||||||
"""
|
"""
|
||||||
destination_plugin = plugins.get(value.plugin_name)
|
destination_plugin = plugins.get(value.plugin_name)
|
||||||
status = FAILURE_METRIC_STATUS
|
status = FAILURE_METRIC_STATUS
|
||||||
|
|
||||||
|
if target.expired:
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
if target.private_key or not destination_plugin.requires_key:
|
if target.private_key or not destination_plugin.requires_key:
|
||||||
destination_plugin.upload(
|
destination_plugin.upload(
|
||||||
|
|
|
@ -102,12 +102,13 @@ def get_all_certs():
|
||||||
return Certificate.query.all()
|
return Certificate.query.all()
|
||||||
|
|
||||||
|
|
||||||
def get_all_pending_cleaning(source):
|
def get_all_pending_cleaning_expired(source):
|
||||||
"""
|
"""
|
||||||
Retrieves all certificates that are available for cleaning.
|
Retrieves all certificates that are available for cleaning. These are certificates which are expired and are not
|
||||||
|
attached to any endpoints.
|
||||||
|
|
||||||
:param source:
|
:param source: the source to search for certificates
|
||||||
:return:
|
:return: list of pending certificates
|
||||||
"""
|
"""
|
||||||
return (
|
return (
|
||||||
Certificate.query.filter(Certificate.sources.any(id=source.id))
|
Certificate.query.filter(Certificate.sources.any(id=source.id))
|
||||||
|
@ -117,6 +118,41 @@ def get_all_pending_cleaning(source):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_pending_cleaning_expiring_in_days(source, days_to_expire):
|
||||||
|
"""
|
||||||
|
Retrieves all certificates that are available for cleaning, not attached to endpoint,
|
||||||
|
and within X days from expiration.
|
||||||
|
|
||||||
|
:param days_to_expire: defines how many days till the certificate is expired
|
||||||
|
:param source: the source to search for certificates
|
||||||
|
:return: list of pending certificates
|
||||||
|
"""
|
||||||
|
expiration_window = arrow.now().shift(days=+days_to_expire).format("YYYY-MM-DD")
|
||||||
|
return (
|
||||||
|
Certificate.query.filter(Certificate.sources.any(id=source.id))
|
||||||
|
.filter(not_(Certificate.endpoints.any()))
|
||||||
|
.filter(Certificate.not_after < expiration_window)
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_pending_cleaning_issued_since_days(source, days_since_issuance):
|
||||||
|
"""
|
||||||
|
Retrieves all certificates that are available for cleaning: not attached to endpoint, and X days since issuance.
|
||||||
|
|
||||||
|
:param days_since_issuance: defines how many days since the certificate is issued
|
||||||
|
:param source: the source to search for certificates
|
||||||
|
:return: list of pending certificates
|
||||||
|
"""
|
||||||
|
not_in_use_window = arrow.now().shift(days=-days_since_issuance).format("YYYY-MM-DD")
|
||||||
|
return (
|
||||||
|
Certificate.query.filter(Certificate.sources.any(id=source.id))
|
||||||
|
.filter(not_(Certificate.endpoints.any()))
|
||||||
|
.filter(Certificate.date_created > not_in_use_window)
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_all_pending_reissue():
|
def get_all_pending_reissue():
|
||||||
"""
|
"""
|
||||||
Retrieves all certificates that need to be rotated.
|
Retrieves all certificates that need to be rotated.
|
||||||
|
|
|
@ -325,14 +325,17 @@ class AWSDestinationPlugin(DestinationPlugin):
|
||||||
]
|
]
|
||||||
|
|
||||||
def upload(self, name, body, private_key, cert_chain, options, **kwargs):
|
def upload(self, name, body, private_key, cert_chain, options, **kwargs):
|
||||||
iam.upload_cert(
|
try:
|
||||||
name,
|
iam.upload_cert(
|
||||||
body,
|
name,
|
||||||
private_key,
|
body,
|
||||||
self.get_option("path", options),
|
private_key,
|
||||||
cert_chain=cert_chain,
|
self.get_option("path", options),
|
||||||
account_number=self.get_option("accountNumber", options),
|
cert_chain=cert_chain,
|
||||||
)
|
account_number=self.get_option("accountNumber", options),
|
||||||
|
)
|
||||||
|
except ClientError:
|
||||||
|
sentry.captureException()
|
||||||
|
|
||||||
def deploy(self, elb_name, account, region, certificate):
|
def deploy(self, elb_name, account, region, certificate):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -54,6 +54,17 @@ def validate_sources(source_strings):
|
||||||
return sources
|
return sources
|
||||||
|
|
||||||
|
|
||||||
|
def execute_clean(plugin, certificate, source):
|
||||||
|
try:
|
||||||
|
plugin.clean(certificate, source.options)
|
||||||
|
certificate.sources.remove(source)
|
||||||
|
certificate_service.database.update(certificate)
|
||||||
|
return SUCCESS_METRIC_STATUS
|
||||||
|
except Exception as e:
|
||||||
|
current_app.logger.exception(e)
|
||||||
|
sentry.captureException()
|
||||||
|
|
||||||
|
|
||||||
@manager.option(
|
@manager.option(
|
||||||
"-s",
|
"-s",
|
||||||
"--sources",
|
"--sources",
|
||||||
|
@ -132,11 +143,9 @@ def clean(source_strings, commit):
|
||||||
s = plugins.get(source.plugin_name)
|
s = plugins.get(source.plugin_name)
|
||||||
|
|
||||||
if not hasattr(s, "clean"):
|
if not hasattr(s, "clean"):
|
||||||
print(
|
info_text = f"Cannot clean source: {source.label}, source plugin does not implement 'clean()'"
|
||||||
"Cannot clean source: {0}, source plugin does not implement 'clean()'".format(
|
current_app.logger.warning(info_text)
|
||||||
source.label
|
print(info_text)
|
||||||
)
|
|
||||||
)
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
@ -144,35 +153,147 @@ def clean(source_strings, commit):
|
||||||
print("[+] Staring to clean source: {label}!\n".format(label=source.label))
|
print("[+] Staring to clean source: {label}!\n".format(label=source.label))
|
||||||
|
|
||||||
cleaned = 0
|
cleaned = 0
|
||||||
for certificate in certificate_service.get_all_pending_cleaning(source):
|
certificates = certificate_service.get_all_pending_cleaning_expired(source)
|
||||||
|
for certificate in certificates:
|
||||||
status = FAILURE_METRIC_STATUS
|
status = FAILURE_METRIC_STATUS
|
||||||
if commit:
|
if commit:
|
||||||
try:
|
status = execute_clean(s, certificate, source)
|
||||||
s.clean(certificate, source.options)
|
|
||||||
certificate.sources.remove(source)
|
|
||||||
certificate_service.database.update(certificate)
|
|
||||||
status = SUCCESS_METRIC_STATUS
|
|
||||||
except Exception as e:
|
|
||||||
current_app.logger.exception(e)
|
|
||||||
sentry.captureException()
|
|
||||||
|
|
||||||
metrics.send(
|
metrics.send(
|
||||||
"clean",
|
"certificate_clean",
|
||||||
"counter",
|
"counter",
|
||||||
1,
|
1,
|
||||||
metric_tags={"source": source.label, "status": status},
|
metric_tags={"status": status, "source": source.label, "certificate": certificate.name},
|
||||||
)
|
)
|
||||||
|
current_app.logger.warning(f"Removed {certificate.name} from source {source.label} during cleaning")
|
||||||
current_app.logger.warning(
|
|
||||||
"Removed {0} from source {1} during cleaning".format(
|
|
||||||
certificate.name, source.label
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
cleaned += 1
|
cleaned += 1
|
||||||
|
|
||||||
print(
|
info_text = f"[+] Finished cleaning source: {source.label}. " \
|
||||||
"[+] Finished cleaning source: {label}. Removed {cleaned} certificates from source. Run Time: {time}\n".format(
|
f"Removed {cleaned} certificates from source. " \
|
||||||
label=source.label, time=(time.time() - start_time), cleaned=cleaned
|
f"Run Time: {(time.time() - start_time)}\n"
|
||||||
|
print(info_text)
|
||||||
|
current_app.logger.warning(info_text)
|
||||||
|
|
||||||
|
|
||||||
|
@manager.option(
|
||||||
|
"-s",
|
||||||
|
"--sources",
|
||||||
|
dest="source_strings",
|
||||||
|
action="append",
|
||||||
|
help="Sources to operate on.",
|
||||||
|
)
|
||||||
|
@manager.option(
|
||||||
|
"-d",
|
||||||
|
"--days",
|
||||||
|
dest="days_to_expire",
|
||||||
|
type=int,
|
||||||
|
action="store",
|
||||||
|
required=True,
|
||||||
|
help="The expiry range within days.",
|
||||||
|
)
|
||||||
|
@manager.option(
|
||||||
|
"-c",
|
||||||
|
"--commit",
|
||||||
|
dest="commit",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="Persist changes.",
|
||||||
|
)
|
||||||
|
def clean_unused_and_expiring_within_days(source_strings, days_to_expire, commit):
|
||||||
|
sources = validate_sources(source_strings)
|
||||||
|
for source in sources:
|
||||||
|
s = plugins.get(source.plugin_name)
|
||||||
|
|
||||||
|
if not hasattr(s, "clean"):
|
||||||
|
info_text = f"Cannot clean source: {source.label}, source plugin does not implement 'clean()'"
|
||||||
|
current_app.logger.warning(info_text)
|
||||||
|
print(info_text)
|
||||||
|
continue
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
|
print("[+] Staring to clean source: {label}!\n".format(label=source.label))
|
||||||
|
|
||||||
|
cleaned = 0
|
||||||
|
certificates = certificate_service.get_all_pending_cleaning_expiring_in_days(source, days_to_expire)
|
||||||
|
for certificate in certificates:
|
||||||
|
status = FAILURE_METRIC_STATUS
|
||||||
|
if commit:
|
||||||
|
status = execute_clean(s, certificate, source)
|
||||||
|
|
||||||
|
metrics.send(
|
||||||
|
"certificate_clean",
|
||||||
|
"counter",
|
||||||
|
1,
|
||||||
|
metric_tags={"status": status, "source": source.label, "certificate": certificate.name},
|
||||||
)
|
)
|
||||||
)
|
current_app.logger.warning(f"Removed {certificate.name} from source {source.label} during cleaning")
|
||||||
|
cleaned += 1
|
||||||
|
|
||||||
|
info_text = f"[+] Finished cleaning source: {source.label}. " \
|
||||||
|
f"Removed {cleaned} certificates from source. " \
|
||||||
|
f"Run Time: {(time.time() - start_time)}\n"
|
||||||
|
print(info_text)
|
||||||
|
current_app.logger.warning(info_text)
|
||||||
|
|
||||||
|
|
||||||
|
@manager.option(
|
||||||
|
"-s",
|
||||||
|
"--sources",
|
||||||
|
dest="source_strings",
|
||||||
|
action="append",
|
||||||
|
help="Sources to operate on.",
|
||||||
|
)
|
||||||
|
@manager.option(
|
||||||
|
"-d",
|
||||||
|
"--days",
|
||||||
|
dest="days_since_issuance",
|
||||||
|
type=int,
|
||||||
|
action="store",
|
||||||
|
required=True,
|
||||||
|
help="Days since issuance.",
|
||||||
|
)
|
||||||
|
@manager.option(
|
||||||
|
"-c",
|
||||||
|
"--commit",
|
||||||
|
dest="commit",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="Persist changes.",
|
||||||
|
)
|
||||||
|
def clean_unused_and_issued_since_days(source_strings, days_since_issuance, commit):
|
||||||
|
sources = validate_sources(source_strings)
|
||||||
|
for source in sources:
|
||||||
|
s = plugins.get(source.plugin_name)
|
||||||
|
|
||||||
|
if not hasattr(s, "clean"):
|
||||||
|
info_text = f"Cannot clean source: {source.label}, source plugin does not implement 'clean()'"
|
||||||
|
current_app.logger.warning(info_text)
|
||||||
|
print(info_text)
|
||||||
|
continue
|
||||||
|
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
|
print("[+] Staring to clean source: {label}!\n".format(label=source.label))
|
||||||
|
|
||||||
|
cleaned = 0
|
||||||
|
certificates = certificate_service.get_all_pending_cleaning_issued_since_days(source, days_since_issuance)
|
||||||
|
for certificate in certificates:
|
||||||
|
status = FAILURE_METRIC_STATUS
|
||||||
|
if commit:
|
||||||
|
status = execute_clean(s, certificate, source)
|
||||||
|
|
||||||
|
metrics.send(
|
||||||
|
"certificate_clean",
|
||||||
|
"counter",
|
||||||
|
1,
|
||||||
|
metric_tags={"status": status, "source": source.label, "certificate": certificate.name},
|
||||||
|
)
|
||||||
|
current_app.logger.warning(f"Removed {certificate.name} from source {source.label} during cleaning")
|
||||||
|
cleaned += 1
|
||||||
|
|
||||||
|
info_text = f"[+] Finished cleaning source: {source.label}. " \
|
||||||
|
f"Removed {cleaned} certificates from source. " \
|
||||||
|
f"Run Time: {(time.time() - start_time)}\n"
|
||||||
|
print(info_text)
|
||||||
|
current_app.logger.warning(info_text)
|
||||||
|
|
Loading…
Reference in New Issue