in lemur/sources/service.py [0:0]
def sync_endpoints(source):
new, updated, updated_by_hash = 0, 0, 0
current_app.logger.debug(f"Retrieving endpoints from {source.label}")
s = plugins.get(source.plugin_name)
try:
endpoints = s.get_endpoints(source.options)
except NotImplementedError:
current_app.logger.warning(
"Unable to sync endpoints for source {} plugin has not implemented 'get_endpoints'".format(
source.label
)
)
return new, updated, updated_by_hash
for endpoint in endpoints:
try:
exists = endpoint_service.get_by_dnsname_and_port(
endpoint["dnsname"], endpoint["port"]
)
except OperationalError as e:
# This is a workaround for handling sqlalchemy error "idle-in-transaction timeout", which is seen rarely
# during the sync of sources with few thousands of resources. The DB interaction may need a rewrite to
# avoid prolonged idle transactions.
if e.connection_invalidated:
# all the update, insert operations are committed individually. So this should be harmless/no-op
database.rollback()
# retry one more time
exists = endpoint_service.get_by_dnsname_and_port(
endpoint["dnsname"], endpoint["port"]
)
else:
raise e
certificate_name = endpoint.pop("certificate_name")
endpoint["certificate"] = certificate_service.get_by_name(certificate_name)
# if get cert by name failed, we attempt a search via serial number and hash comparison
# and link the endpoint certificate to Lemur certificate
if not endpoint["certificate"]:
certificate_attached_to_endpoint = None
try:
certificate_attached_to_endpoint = s.get_certificate_by_name(certificate_name, source.options)
except NotImplementedError:
current_app.logger.warning(
"Unable to describe server certificate for endpoints in source {}:"
" plugin has not implemented 'get_certificate_by_name'".format(
source.label
)
)
capture_exception()
if certificate_attached_to_endpoint:
lemur_matching_cert, updated_by_hash_tmp = find_cert(certificate_attached_to_endpoint)
updated_by_hash += updated_by_hash_tmp
if lemur_matching_cert:
endpoint["certificate"] = lemur_matching_cert[0]
if len(lemur_matching_cert) > 1:
current_app.logger.error(
"Too Many Certificates Found{}. Name: {} Endpoint: {}".format(
len(lemur_matching_cert), certificate_name, endpoint["name"]
)
)
metrics.send("endpoint.certificate.conflict",
"gauge", len(lemur_matching_cert),
metric_tags={"cert": certificate_name, "endpoint": endpoint["name"],
"acct": s.get_option("accountNumber", source.options)})
if not endpoint["certificate"]:
current_app.logger.error({
"message": "Certificate Not Found",
"certificate_name": certificate_name,
"endpoint_name": endpoint["name"],
"dns_name": endpoint.get("dnsname"),
"account": s.get_option("accountNumber", source.options),
})
metrics.send("endpoint.certificate.not.found",
"counter", 1,
metric_tags={"cert": certificate_name, "endpoint": endpoint["name"],
"acct": s.get_option("accountNumber", source.options),
"dnsname": endpoint.get("dnsname")})
continue
policy = endpoint.pop("policy")
policy_ciphers = []
for nc in policy["ciphers"]:
policy_ciphers.append(endpoint_service.get_or_create_cipher(name=nc))
policy["ciphers"] = policy_ciphers
endpoint["policy"] = endpoint_service.get_or_create_policy(**policy)
endpoint["source"] = source
if not exists:
current_app.logger.debug(
"Endpoint Created: Name: {name}".format(name=endpoint["name"])
)
endpoint_service.create(**endpoint)
new += 1
else:
current_app.logger.debug(f"Endpoint Updated: {endpoint}")
endpoint_service.update(exists.id, **endpoint)
updated += 1
return new, updated, updated_by_hash