When monitoring MongoDB 3.x instances from Nagios XI using the built-in check_mongodb.py plugin (originally written for MongoDB 2.x and older versions of pymongo), two issues commonly surface:
- An uncaught Python
AttributeError: 'ConnectionFailure' object has no attribute 'strip'masking the underlying connection or authentication failure. - Authentication failure (
AuthenticationFailed: MONGODB-CR credentials missing in the user document) caused by MongoDB 3.0+ switching its default password hash mechanism fromMONGODB-CRtoSCRAM-SHA-1.
This post walks through diagnosing and resolving both issues.
Issue 1: AttributeError: 'ConnectionFailure' object has no attribute 'strip'
Symptom
Running check_mongodb.py from /usr/local/nagios/libexec crashes with a Python traceback instead of returning a clean Nagios status message:
[ahmed@localhost libexec]$ ./check_mongodb.py -H 192.168.94.137 -P 27017 -u admin -p REPLACE_PASSWORD
Traceback (most recent call last):
File "./check_mongodb.py", line 1372, in <module>
sys.exit(main(sys.argv[1:]))
File "./check_mongodb.py", line 196, in main
err, con = mongo_connect(host, port, ssl, user, passwd, replicaset)
File "./check_mongodb.py", line 294, in mongo_connect
return exit_with_general_critical(e), None
File "./check_mongodb.py", line 310, in exit_with_general_critical
if e.strip() == "not master":
AttributeError: 'ConnectionFailure' object has no attribute 'strip'
Root Cause & Fix
In exit_with_general_critical(e), the plugin assumes e is a str and calls e.strip(). When pymongo raises a ConnectionFailure or OperationFailure exception instance directly, calling .strip() on the exception object raises AttributeError.
Open /usr/local/nagios/libexec/check_mongodb.py around line 310 and convert e (or remove .strip()) before comparing:
# Before (line 310):
else:
if e.strip() == "not master":
print "UNKNOWN - Could not get data from server:", e
return 3
# After:
else:
if str(e).strip() == "not master":
print "UNKNOWN - Could not get data from server:", e
return 3
With that fix in place, check_mongodb.py prints the actual MongoDB error message:
[ahmed@localhost libexec]$ ./check_mongodb_2.py -H 192.168.94.138 -P 27017 -u admin -p REPLACE_PASSWORD -A databases -W 5 -C 10
CRITICAL - General MongoDB Error: command SON([('authenticate', 1), ('user', u'admin'), ('nonce', u'37a502d665186449'), ('key', u'd8c683f98a5e720c28a8007018ed7414')]) failed: auth failed
Issue 2: AuthenticationFailed: MONGODB-CR credentials missing in the user document
Symptom
When check_mongodb.py attempts to authenticate against MongoDB 3.x, the plugin returns failed: auth failed, and /var/log/mongodb/mongod.log on the MongoDB server logs:
2016-09-14T19:11:32.892-0700 I NETWORK [initandlisten] connection accepted from 192.168.94.130:48657 #115 (2 connections now open)
2016-09-14T19:11:32.894-0700 I ACCESS [conn115] authenticate db: admin { authenticate: 1, user: "admin", nonce: "xxx", key: "xxx" }
2016-09-14T19:11:32.894-0700 I ACCESS [conn115] Failed to authenticate admin@admin with mechanism MONGODB-CR: AuthenticationFailed: MONGODB-CR credentials missing in the user document
2016-09-14T19:11:32.895-0700 I NETWORK [conn115] end connection 192.168.94.130:48657 (1 connection now open)
Root Cause
- MongoDB 2.6 and earlier used the
MONGODB-CRchallenge-response authentication mechanism (authSchemaversion3). - MongoDB 3.0+ switched to
SCRAM-SHA-1(authSchemaversion5) and stopped generatingMONGODB-CRcredentials on newly created user documents. - If the Nagios XI server has an older
pymongopackage installed (pymongo < 2.8),pymongoonly knows how to authenticate viaMONGODB-CR, which fails against MongoDB 3.0+ user accounts.
Option A (Recommended for Production): Upgrade pymongo on the Nagios Server
Upgrading pymongo to 2.8+ (or 3.x+) on the Nagios XI host enables SCRAM-SHA-1 support in the Python driver without weakening MongoDB’s authentication schema:
sudo pip install --upgrade pymongo
Option B (Legacy Test Workaround): Downgrade authSchema to Version 3 (MONGODB-CR)
In an isolated test lab where the Nagios client’s pymongo library cannot be updated, you can switch MongoDB 3.2’s admin.system.version (authSchema) from 5 to 3 and recreate the monitoring user so MONGODB-CR credentials are stored (do not run db.system.users.remove({}) on a production database):
use admin
var schema = db.system.version.findOne({ "_id" : "authSchema" })
schema.currentVersion = 3
db.system.version.save(schema)
After updating currentVersion to 3, drop and recreate the monitoring user so MongoDB generates MONGODB-CR credentials for that account. (Note: MONGODB-CR was removed entirely in MongoDB 4.0+.)