From 28db1c3d411f62ceb3909b9e9292cec638fd5ae0 Mon Sep 17 00:00:00 2001 From: "B. Stack" Date: Fri, 21 Jun 2024 15:28:31 -0400 Subject: refactor to be more modular, and improve find-replacement logic --- freeipa-cert-alert.py | 93 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 27 deletions(-) diff --git a/freeipa-cert-alert.py b/freeipa-cert-alert.py index f451196..bf229e8 100755 --- a/freeipa-cert-alert.py +++ b/freeipa-cert-alert.py @@ -44,50 +44,89 @@ def show_list(inlist): for i in inlist: print(f"{i['valid_not_before']:<{col1max}} {i['valid_not_after']:<{col2max}} {i['subject']:<{col3max}}") -def hide_replaced_certs(certlist,future,client): +def hide_replaced_certs(certlist,client): """ Remove from certlist any certs that have been replaced already. This is defined as a cert whose subject name exists as a cert with a further-out validto date. Args: certlist: the list of objects from python_freeipa.cert_find() - future: YYYY-mm-dd of the end date of the search that generated certlist. client: the python_freeipa client object Returns: list: certlist with any superseded certificates removed. """ + # future: YYYY-mm-dd of the end date of the search that generated certlist. #print(f"Got certlist {certlist}") newlist = [] for i in certlist: - b = client.cert_find(o_validnotafter_from = future,subject = re.sub(",O=.*$","",re.sub("^CN=","",i["subject"]))) + # need to calculate expiration time of this cert, so we can look for a newer cert than it. var future is irrelevant here because it's only what generated this list. + this_future = dparser.parse(i["valid_not_after"]).strftime("%F") + b = client.cert_find(o_validnotafter_from = this_future,subject = re.sub(",O=.*$","",re.sub("^CN=","",i["subject"]))) if not ("count" in b and b["count"] > 0): newlist.append(i) return newlist -# Main -DAYS = os.getenv("DAYS",default=60) -try: - DAYS = int(DAYS) -except: - DAYS = 60 -PASTDAYS = os.getenv("PASTDAYS",default=0) -try: - PASTDAYS = int(PASTDAYS) -except: - PASTDAYS = 60 +def get_client(server, username, password): + """ + Returns the freeipa client object. + + Example: + client = get_client(os.getenv("FREEIPA_SERVER"),os.getenv("FREEIPA_USERNAME"),os.getenv("FREEIPA_PASSWORD")) + """ + client = python_freeipa.ClientMeta(server) + client.login(username,password) + return client + +def get_expiring_certs(client, days, pastdays): + days = abs(int(days)) + pastdays = abs(int(pastdays)) + today = str(datetime.date.today() + datetime.timedelta(days=-pastdays)) + future = str(datetime.date.today() + datetime.timedelta(days=days)) + results = client.cert_find(o_validnotafter_from=today,o_validnotafter_to=future) + certs = results['result'] + return certs + +def alert_certs(client, days, pastdays, _hide_replaced_certs = "false"): + """ + Given the client object, and number of days ahead, and pastdays (from today), find the certs that are expiring in this range. If you pass a truthy-like object to _hide_replaced_certs, then it will check if a newer cert matches the CN, and remove this cert from the list if it finds any newer ones. + Example: + alert_certs(client, DAYS, PASTDAYS, os.getenv("FREEIPA_HIDE_REPLACED_CERTS","false")) + """ + days = abs(int(days)) + pastdays = abs(int(pastdays)) + + if type(_hide_replaced_certs) == str and _hide_replaced_certs.lower() in ["false","f","0",""]: + _hide_replaced_certs = False + elif _hide_replaced_certs in [False,0]: + _hide_replaced_certs = False + else: + try: + _hide_replaced_certs = bool(_hide_replaced_certs) + except: + _hide_replaced_certs = False -client = python_freeipa.ClientMeta(os.getenv("FREEIPA_SERVER")) -client.login(os.getenv("FREEIPA_USERNAME"),os.getenv("FREEIPA_PASSWORD")) + certs = get_expiring_certs(client, days, pastdays) -today = str(datetime.date.today() + datetime.timedelta(days=-PASTDAYS)) -future = str(datetime.date.today() + datetime.timedelta(days=DAYS)) -results = client.cert_find(o_validnotafter_from=today,o_validnotafter_to=future) -certs = results['result'] + if _hide_replaced_certs: + certs = hide_replaced_certs(certs,client) + # Sort + certs = sorted(certs,key=lambda d: int(dparser.parse(d['valid_not_after']).strftime('%s'))) + if len(certs) > 0: + today = str(datetime.date.today() + datetime.timedelta(days=-pastdays)) + print(f"Certificates expiring within {days+pastdays} days from {today}") + show_list(certs) -if os.getenv("FREEIPA_HIDE_REPLACED_CERTS",""): - certs = hide_replaced_certs(certs,future,client) -# Sort -certs = sorted(certs,key=lambda d: int(dparser.parse(d['valid_not_after']).strftime('%s'))) -if len(certs) > 0: - print(f"Certificates expiring within {DAYS+PASTDAYS} days from {today}") -show_list(certs) +if "__main__" == __name__: + # Main + DAYS = os.getenv("DAYS",default=60) + try: + DAYS = int(DAYS) + except: + DAYS = 60 + PASTDAYS = os.getenv("PASTDAYS",default=0) + try: + PASTDAYS = int(PASTDAYS) + except: + PASTDAYS = 60 + client = get_client(os.getenv("FREEIPA_SERVER"),os.getenv("FREEIPA_USERNAME"),os.getenv("FREEIPA_PASSWORD")) + alert_certs(client, DAYS, PASTDAYS, os.getenv("FREEIPA_HIDE_REPLACED_CERTS","false")) -- cgit