This repository has been archived by the owner on Jan 30, 2024. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10144 from alphagov/move-check_puppetdb_ssh_host_…
…keys_check Import `check_puppetdb_ssh_host_keys` from `alphagov/nagios-plugins`
- Loading branch information
Showing
3 changed files
with
146 additions
and
1 deletion.
There are no files selected for viewing
2 changes: 1 addition & 1 deletion
2
modules/monitoring/files/etc/nagios3/conf.d/check_puppetdb_ssh_host_keys.cfg
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
define command { | ||
command_name check_puppetdb_ssh_host_keys | ||
command_line /usr/local/bin/check_puppetdb_ssh_host_keys | ||
command_line /usr/lib/nagios/plugins/check_puppetdb_ssh_host_keys | ||
} |
141 changes: 141 additions & 0 deletions
141
modules/monitoring/files/usr/lib/nagios/plugins/check_puppetdb_ssh_host_keys
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
#!/usr/bin/env python2 | ||
import json | ||
import base64 | ||
import hashlib | ||
import string | ||
import urllib | ||
import urllib2 | ||
|
||
from optparse import OptionParser | ||
|
||
class CheckException(Exception): | ||
def __init__(self, message, severity): | ||
Exception.__init__(self, message) | ||
self.severity = severity | ||
|
||
|
||
def nagios_message(message, exitcode): | ||
"""Format a Nagios message and exit""" | ||
print message | ||
sys.exit(exitcode) | ||
|
||
|
||
def nagios_ok(message): | ||
"""Nagios OK message""" | ||
raise CheckException("OK: %s" % message, 0) | ||
|
||
def nagios_critical(message): | ||
"""Nagios CRITICAL message""" | ||
raise CheckException("CRITICAL: %s" % message, 2) | ||
|
||
|
||
def nagios_unknown(message): | ||
"""Nagios UNKNOWN message""" | ||
raise CheckException("UNKNOWN: %s" % message, 3) | ||
|
||
|
||
FACTS = ('sshdsakey', 'sshecdsakey', 'sshrsakey') | ||
|
||
|
||
parser = OptionParser(description='Find duplicate SSH host keys in PuppetDB') | ||
parser.add_option( | ||
'-H', '--host', | ||
dest='puppetdb_host', type='str', default='puppetdb.cluster', | ||
help='PuppetDB hostname' | ||
) | ||
parser.add_option( | ||
'-s', '--ssl', | ||
dest='puppetdb_ssl', action='store_true', | ||
help='PuppetDB use SSL/TLS' | ||
) | ||
parser.add_option( | ||
'-V', '--api-version', | ||
dest='puppetdb_version', type='int', default=2, | ||
help='PuppetDB API version' | ||
) | ||
|
||
|
||
def check(url): | ||
"""Perform duplicate SSH host key checks""" | ||
facts = query_puppetdb(url) | ||
if count_hosts(facts) <= 1: | ||
nagios_unknown('Need at least two nodes in PuppetDB') | ||
|
||
dupes = find_dupes(facts) | ||
if len(dupes) == 0: | ||
nagios_ok('No duplicate SSH host keys found') | ||
|
||
msg = ['Found hosts with duplicate SSH host keys'] | ||
for key, hosts in dupes.items(): | ||
msg.append('') | ||
msg.append(fingerprint(key)) | ||
for host in hosts: | ||
msg.append('- {0}'.format(host)) | ||
|
||
nagios_critical("\n".join(msg)) | ||
|
||
|
||
def query_puppetdb(base_url): | ||
"""Query a list of certain facts from PuppetDB""" | ||
query = '["or", {0}]'.format(', '.join([ | ||
'["=", "name", "{0}"]'.format(fact) | ||
for fact in FACTS | ||
])) | ||
query_string = urllib.urlencode({'query': query}) | ||
url = '{0}/facts?{1}'.format( | ||
base_url, | ||
query_string, | ||
) | ||
|
||
res = urllib2.urlopen(url) | ||
return json.load(res) | ||
|
||
|
||
def count_hosts(facts): | ||
"""Count the number of unique hosts""" | ||
hosts = set([fact['certname'] for fact in facts]) | ||
return len(hosts) | ||
|
||
|
||
def find_dupes(facts): | ||
"""Find hosts with duplicate SSH host keys from PuppetDB output""" | ||
hosts_by_key = {} | ||
for fact in facts: | ||
hosts_by_key.setdefault( | ||
fact['value'], | ||
set(), | ||
).add(fact['certname']) | ||
|
||
return { | ||
k: v | ||
for k, v in hosts_by_key.items() | ||
if len(v) > 1 | ||
} | ||
|
||
|
||
def fingerprint(key): | ||
"""Convert an SSH RSA/DSA public key to a fingerprint string""" | ||
key = base64.b64decode(key.encode('ascii')) | ||
fp_plain = hashlib.md5(key).hexdigest() | ||
return ':'.join(a+b for a,b in zip(fp_plain[::2], fp_plain[1::2])) | ||
|
||
|
||
def main(): | ||
try: | ||
opts, args = parser.parse_args() | ||
url = '{0}://{1}/v{2}'.format( | ||
'https' if opts.puppetdb_ssl else 'http', | ||
opts.puppetdb_host, | ||
opts.puppetdb_version, | ||
) | ||
check(url) | ||
|
||
except CheckException as e: | ||
nagios_message(e.message, e.severity) | ||
except Exception as e: | ||
# Catching all other exceptions | ||
nagios_message("Exception: %s" % e, 3) | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters