aboutsummaryrefslogtreecommitdiff
path: root/freeipa-cert-alert.py
blob: f451196554e5ab25b21d2319448e16946d85925d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#!/usr/bin/env python3
# File: alert.py
# Location: https://gitlab.com/bgstack15/freeipa-cert-alert
# Author: bgstack15
# Startdate: 2021-10-27 14:00
# SPDX-License-Identifier: GPL-3.0
# Title: Script that Alerts For Expiring Certs
# Purpose: Send me alerts for certs that are about to expire
# History:
#    2022-12-18 added PASTDAYS option
#    2024-05-03 add remove replaced certs option
# Usage:
#    Set env: FREEIPA_SERVER FREEIPA_USERNAME FREEIPA_PASSWORD DAYS PASTDAYS FREEIPA_HIDE_REPLACED_CERTS
# References:
#    https://python-freeipa.readthedocs.io/en/latest/
#    https://stackoverflow.com/questions/72899/how-do-i-sort-a-list-of-dictionaries-by-a-value-of-the-dictionary/73050#73050
#    https://stackoverflow.com/questions/6871016/adding-days-to-a-date-in-python/6871482#6871482
#    https://stackoverflow.com/questions/24027863/convert-a-utc-time-to-epoch
#    https://stackoverflow.com/questions/9989334/create-nice-column-output-in-python/9996049#9996049
# Improve:
# Dependencies:
#    Somehow this is not a requisite component of freeipa! Those are named python3-ipa*
#    fedora-req: python3-freeipa

import python_freeipa, json, datetime, os, sys, re
import dateutil.parser as dparser

# Functions
def show_list(inlist):
   col1max = 0
   col2max = 0
   col3max = 0
   for i in inlist:
      col1max = max(len(i['valid_not_before']),col1max)
      col2max = max(len(i['valid_not_after']),col2max)
      col3max = max(len(i['subject']),col3max)
   col1max = col1max+2
   col2max = col2max+2
   if len(inlist) > 0:
      a = "Not valid before"
      b = "Not valid after"
      c = "Subject"
      print(f"{a:<{col1max}} {b:<{col2max}} {c:<{col3max}}")
   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):
   """
   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.
   """
   #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"])))
      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

client = python_freeipa.ClientMeta(os.getenv("FREEIPA_SERVER"))
client.login(os.getenv("FREEIPA_USERNAME"),os.getenv("FREEIPA_PASSWORD"))

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 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)
bgstack15