Skip to content

Instantly share code, notes, and snippets.

@boileaum
Last active April 22, 2018 11:38
Show Gist options
  • Save boileaum/1e4f9ea6a3d427f0bde81d33befa832d to your computer and use it in GitHub Desktop.
Save boileaum/1e4f9ea6a3d427f0bde81d33befa832d to your computer and use it in GitHub Desktop.
A python3 script to get available security updates and "reboot required" from Ubuntu/Redhat minions using Saltstack. Send report by email if asked (typically to work as a cron).
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Report security updates and reboot required using saltstack
"""
import argparse
from collections import OrderedDict
from email.mime.text import MIMEText
import smtplib
import socket
import subprocess
import yaml
def main(email):
cmd_ubuntu = (r"salt -G 'os:Ubuntu' cmd.run "
r"'echo - \"$(/usr/lib/update-notifier/apt-check --human-readable|"
r'grep -v "^0 updates" | grep -i security)\" ; '
r'echo - \"'
r"$(/usr/lib/update-notifier/update-motd-reboot-required)\"'")
cmd_redhat = (r"salt -G 'os:RedHat' cmd.run "
r"'echo - \"$(yum check-update --security |"
r'grep "needed for security, out of")\" ; '
r'echo - \"'
r"$(/root/bin/needs-restarting.py -r |"
r'grep "Reboot is required")\"\'')
output = subprocess.check_output(cmd_ubuntu, shell=True)
output += subprocess.check_output(cmd_redhat, shell=True)
unordered_report = yaml.load(output)
# sort hosts by their name
report = OrderedDict(sorted(unordered_report.items(), key=lambda t: t[0]))
body = ""
for host in report:
# Report only if there is something to report
if report[host][0] or report[host][1]:
body += "{}:\n".format(host)
if report[host][0]: # Report security updates
body += " {}\n".format(report[host][0])
if report[host][1]: # Report if reboot is required
body += " {}\n".format(report[host][1])
if email and body:
html = """\
<html>
<font face="Courier New, Courier, monospace">
<body>
<p><pre>{}</pre>
</p>
</body>
</font>
</html>
""".format(body)
msg = MIMEText(html, 'html')
msg['Subject'] = "[saltmaster] Minions report"
msg['From'] = "root@{}".format(socket.getfqdn())
msg['To'] = email
smtp = smtplib.SMTP("localhost")
smtp.send_message(msg)
smtp.quit()
else:
print(body)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Report minions state: update/restart required?")
parser.add_argument('--email', nargs=1, required=False, metavar="email",
help="Send output to email address")
args = parser.parse_args()
email = args.email[0] if args.email else ''
main(email)
@boileaum
Copy link
Author

A typical cron.sls file to run this script on the salt-master:

minion-report-cron:
  cron.present:
    - user: root
    - name: /srv/scripts/minions-report.py --email admin@our.organization
    - special: '@weekly'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment