mongodbpymongo

mongod db.killAllSessions() reports that it works, but doesn't kill the sessions


I'm very new to MongoDB and I'm trying to get the killAllSessions or one of its variants to work, in mongosh and/or using pymongo. I have a simple, standalone instance of mongod running in a Docker container. Here's my config:

# mongod.conf

# for documentation of all options, see:
#   http://docs.mongodb.org/manual/reference/configuration-options/

# Where and how to store data.
storage:
  dbPath: /var/lib/mongodb
#  engine:
#  wiredTiger:

# where to write logging data.
systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log

# network interfaces
net:
  port: 27017
  bindIp: 127.0.0.1

# how the process runs
processManagement:
  timeZoneInfo: /usr/share/zoneinfo

security:
    authorization: enabled

#operationProfiling:

#replication:

#sharding:

## Enterprise-Only Options:

#auditLog:

I've setup the users as follows:

evertz@70412a8161ac:~/src$ mongosh mongodb://127.0.0.1:27017/?directConnection=true
Current Mongosh Log ID: 67ee6bbf756361ebb06b140a
Connecting to:      mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.4.2
Using MongoDB:      8.0.6
Using Mongosh:      2.4.2

For mongosh info see: https://www.mongodb.com/docs/mongodb-shell/


To help improve our products, anonymous usage data is collected and sent to MongoDB periodically (https://www.mongodb.com/legal/privacy-policy).
You can opt-out by running the disableTelemetry() command.

test> use admin
switched to db admin
admin> db.auth('nmosregadmin')
Enter password
**********{ ok: 1 }
admin> show users
[
  {
    _id: 'admin.nmosregadmin',
    userId: UUID('143dcc60-32bb-434a-9bfa-a789a3713be4'),
    user: 'nmosregadmin',
    db: 'admin',
    roles: [
      { role: 'userAdminAnyDatabase', db: 'admin' },
      { role: 'hostManager', db: 'admin' },
      { role: 'clusterMonitor', db: 'admin' },
      { role: 'readWriteAnyDatabase', db: 'admin' }
    ],
    mechanisms: [ 'SCRAM-SHA-1', 'SCRAM-SHA-256' ]
  },
  {
    _id: 'admin.nmosreguser',
    userId: UUID('1c1bf9c5-cc26-47a8-9e7b-73f423b522d5'),
    user: 'nmosreguser',
    db: 'admin',
    roles: [
      { role: 'readWrite', db: 'nmosreg_version' },
      { role: 'readWrite', db: 'nmosreg' }
    ],
    mechanisms: [ 'SCRAM-SHA-1', 'SCRAM-SHA-256' ]
  }
]
admin> show dbs
admin   100.00 KiB
config   12.00 KiB
local    40.00 KiB

I connect with a Python 3 venv as my regular user (i.e. nmosreguser):

evertz@70412a8161ac:~/src$ venv/bin/python
Python 3.12.3 (main, Feb  4 2025, 14:48:35) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pymongo
>>> client = pymongo.MongoClient('127.0.0.1', 27017, username='nmosreguser', password=<redacted>, authSource='admin')
>>> nmosreg_db = client.nmosreg
>>> col1 = nmosreg_db.create_collection('test-collection1')

mongosh shows that this works:

admin> show dbs
admin    100.00 KiB
config    60.00 KiB
local     40.00 KiB
nmosreg    8.00 KiB
admin> show collections
system.users
system.version
admin> use nmosreg
switched to db nmosreg
nmosreg> show collections
test-collection1

I connect with a 2nd separate Python venv as my admin user (i.e nmosregadmin) and list the sessions and revoke the readWrite role from the regular user:

evertz@70412a8161ac:~/src$ venv/bin/python
Python 3.12.3 (main, Feb  4 2025, 14:48:35) [GCC 13.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import pymongo
>>> admin_client = pymongo.MongoClient('127.0.0.1', 27017, username='nmosregadmin', password=<redacted>, authSource='admin')
>>> admin_db = admin_client.admin
>>> sessions_cursor = admin_client.config.system.sessions.aggregate([{"$listSessions": {"allUsers": True }}])
>>> sessions_list = sessions_cursor.to_list()
>>> import pprint
>>> pprint.pprint(sessions_list)
[{'_id': {'id': Binary(b'S:X2\xb3\xbaO\xba\xb14W\xe4\xe2\xcc%\x9c', 4),
          'uid': b'\xd0f\xc2_5\x03\xf6s$\xe7|\xc4\xdd4F\xa5\xa8#\x0e\x9d'
                 b"\xca\x7f#z\x05^\t\xc2\x14'<\x92"},
  'lastUse': datetime.datetime(2025, 4, 3, 11, 11, 21, 653000),
  'user': {'name': 'nmosregadmin@admin'}},
 {'_id': {'id': Binary(b'\x08\xc6\x88BN\x8cLv\x94\xcd-\xfd\xdd\xb9.\x0b', 4),
          'uid': b'\xd0f\xc2_5\x03\xf6s$\xe7|\xc4\xdd4F\xa5\xa8#\x0e\x9d'
                 b"\xca\x7f#z\x05^\t\xc2\x14'<\x92"},
  'lastUse': datetime.datetime(2025, 4, 3, 11, 26, 21, 653000),
  'user': {'name': 'nmosregadmin@admin'}},
 {'_id': {'id': Binary(b'\xba\xdd\x91\xd2\x04\x89A-\xa8\x18~\x1f\x97Y\xd6Y', 4),
          'uid': b'\xc8B\x14\x8fd\xed\xea:\x9f\xffa\xe6\xaf\xb9^\x8a\xf2*\xf1y'
                 b"'\x95v\xc6\x9c\x84\xc9\xb7\xe7\x89\xb1^"},
  'lastUse': datetime.datetime(2025, 4, 3, 11, 26, 21, 653000),
  'user': {'name': 'nmosreguser@admin'}}]
>>> admin_db.command('revokeRolesFromUser', 'nmosreguser', roles=[{"role": "readWrite", "db": "nmosreg"}])
{'ok': 1.0}

I confirm that the regular user can't create another collection:

>>> col2 = nmosreg_db.create_collection('test-collection2')
Traceback (most recent call last):
[...]
pymongo.errors.OperationFailure: not authorized on nmosreg to execute command { listCollections: 1, cursor: {}, nameOnly: true, filter: { name: "test-collection2" }, lsid: { id: UUID("badd91d2-0489-412d-a818-7e1f9759d659") }, $db: "nmosreg" }, full error: {'ok': 0.0, 'errmsg': 'not authorized on nmosreg to execute command { listCollections: 1, cursor: {}, nameOnly: true, filter: { name: "test-collection2" }, lsid: { id: UUID("badd91d2-0489-412d-a818-7e1f9759d659") }, $db: "nmosreg" }', 'code': 13, 'codeName': 'Unauthorized'}

I call db.killAllSessions() from my admin authenticated mongosh terminal:

nmosreg> db.runCommand( { killAllSessions: [{ user: "nmosreguser", db: "nmosreg" }]})
{ ok: 1 }

I go back and check the sessions in the Python admin venv terminal to see if the nmosreguser session has been killed, but it isn't:

>>> sessions_after_kill_cursor = admin_client.config.system.sessions.aggregate([{"$listSessions": {"allUsers": True }}])
>>> sessions_after_kill = sessions_after_kill_cursor.to_list()
>>> pprint.pprint(sessions_after_kill)
[{'_id': {'id': Binary(b'\x08\xc6\x88BN\x8cLv\x94\xcd-\xfd\xdd\xb9.\x0b', 4),
          'uid': b'\xd0f\xc2_5\x03\xf6s$\xe7|\xc4\xdd4F\xa5\xa8#\x0e\x9d'
                 b"\xca\x7f#z\x05^\t\xc2\x14'<\x92"},
  'lastUse': datetime.datetime(2025, 4, 3, 11, 31, 21, 653000),
  'user': {'name': 'nmosregadmin@admin'}},
 {'_id': {'id': Binary(b'\xba\xdd\x91\xd2\x04\x89A-\xa8\x18~\x1f\x97Y\xd6Y', 4),
          'uid': b'\xc8B\x14\x8fd\xed\xea:\x9f\xffa\xe6\xaf\xb9^\x8a\xf2*\xf1y'
                 b"'\x95v\xc6\x9c\x84\xc9\xb7\xe7\x89\xb1^"},
  'lastUse': datetime.datetime(2025, 4, 3, 11, 41, 21, 653000),
  'user': {'name': 'nmosreguser@admin'}},
 {'_id': {'id': Binary(b'Vek\x9a,hA\x12\xa7\x1f\xd6\x06\x17U\xef\x83', 4),
          'uid': b'\xd0f\xc2_5\x03\xf6s$\xe7|\xc4\xdd4F\xa5\xa8#\x0e\x9d'
                 b"\xca\x7f#z\x05^\t\xc2\x14'<\x92"},
  'lastUse': datetime.datetime(2025, 4, 3, 11, 36, 21, 653000),
  'user': {'name': 'nmosregadmin@admin'}}]

So, why is the session not terminated? What am I doing wrong?

Apr 3, 2025 Update:

I did a test suggested by @aneroid as follows. Here's a simple client that I will run (i.e. test_client_session.py):

import pymongo
import datetime
import pprint
import time

client = pymongo.MongoClient('127.0.0.1', 27017, username='nmosreguser', password=<redacted>, authSource='admin')
nmosreg_db = client.get_database('nmosreg')
col1 = nmosreg_db.create_collection('test-collection1')
post = {
    "author": "Mike",
    "text": "My first blog post!",
    "tags": ["mongodb", "python", "pymongo"],
    "date": datetime.datetime.now(tz=datetime.timezone.utc),
}

post_id = col1.insert_one(post).inserted_id
print("Sleeping now for 60 seconds")
time.sleep(60)
pprint.pprint(col1.find_one({"author": "Mike"}))

Once the sleep was in effect, I ran the following on the admin-authenticated mongosh terminal:

admin> show users
[
  {
    _id: 'admin.nmosregadmin',
    userId: UUID('e3619ad4-190b-4e06-9223-9fd5a8f11f14'),
    user: 'nmosregadmin',
    db: 'admin',
    roles: [ { role: 'root', db: 'admin' } ],
    mechanisms: [ 'SCRAM-SHA-1', 'SCRAM-SHA-256' ]
  },
  {
    _id: 'admin.nmosreguser',
    userId: UUID('7a0eb9d3-5c96-413a-bd8a-fbb55a9fad1c'),
    user: 'nmosreguser',
    db: 'admin',
    roles: [
      { role: 'readWrite', db: 'nmosreg_version' },
      { role: 'readWrite', db: 'nmosreg' }
    ],
    mechanisms: [ 'SCRAM-SHA-1', 'SCRAM-SHA-256' ]
  }
]
admin> db.runCommand( { killAllSessions: [{ user: "nmosreguser", db: "admin" }]})
{ ok: 1 }

The output from the test script suggests that the killAllSessions() command didn't succeed:

evertz@70412a8161ac:~/src$ venv/bin/python test_client_session.py
Sleeping now for 60 seconds
{'_id': ObjectId('67eece189e22db13b21b496d'),
 'author': 'Mike',
 'date': datetime.datetime(2025, 4, 3, 18, 6, 16, 716000),
 'tags': ['mongodb', 'python', 'pymongo'],
 'text': 'My first blog post!'}

From another venv session that is authenticated with my admin user, I looked at the local sessions before and after:

>>> sessions_cursor = admin_db.aggregate([{"$listLocalSessions": {"allUsers": True }}])
>>> sessions_list = sessions_cursor.to_list()
[Did kill command in mongosh ...]
>>> sessions_cursor_after = admin_db.aggregate([{"$listLocalSessions": {"allUsers": True }}])
>>> sessions_list_after = sessions_cursor_after.to_list()
>>> pprint.pprint(sessions_list)
[{'_id': {'id': Binary(b')\xac\x08E\xa9\xfeJ}\x87\x03\xd9M\xad\xadO\xa8', 4),
          'uid': b'\xd0f\xc2_5\x03\xf6s$\xe7|\xc4\xdd4F\xa5\xa8#\x0e\x9d'
                 b"\xca\x7f#z\x05^\t\xc2\x14'<\x92"},
  'lastUse': datetime.datetime(2025, 4, 3, 18, 4, 42, 915000),
  'user': 'nmosregadmin@admin'},
 {'_id': {'id': Binary(b'6e\xb0\xc0\xc25IR\xa2\xd1\x8bX\xa9c$C', 4),
          'uid': b'\xd0f\xc2_5\x03\xf6s$\xe7|\xc4\xdd4F\xa5\xa8#\x0e\x9d'
                 b"\xca\x7f#z\x05^\t\xc2\x14'<\x92"},
  'lastUse': datetime.datetime(2025, 4, 3, 18, 6, 23, 271000),
  'user': 'nmosregadmin@admin'},
 {'_id': {'id': Binary(b'\x07Z\xb3l\x0c\xf4K\xfd\xb6*\\"\xd6Z\x06H', 4),
          'uid': b'\xc8B\x14\x8fd\xed\xea:\x9f\xffa\xe6\xaf\xb9^\x8a\xf2*\xf1y'
                 b"'\x95v\xc6\x9c\x84\xc9\xb7\xe7\x89\xb1^"},
  'lastUse': datetime.datetime(2025, 4, 3, 18, 6, 16, 716000),
  'user': 'nmosreguser@admin'}]
>>> pprint.pprint(sessions_list_after)
[{'_id': {'id': Binary(b')\xac\x08E\xa9\xfeJ}\x87\x03\xd9M\xad\xadO\xa8', 4),
          'uid': b'\xd0f\xc2_5\x03\xf6s$\xe7|\xc4\xdd4F\xa5\xa8#\x0e\x9d'
                 b"\xca\x7f#z\x05^\t\xc2\x14'<\x92"},
  'lastUse': datetime.datetime(2025, 4, 3, 18, 4, 42, 915000),
  'user': 'nmosregadmin@admin'},
 {'_id': {'id': Binary(b'6e\xb0\xc0\xc25IR\xa2\xd1\x8bX\xa9c$C', 4),
          'uid': b'\xd0f\xc2_5\x03\xf6s$\xe7|\xc4\xdd4F\xa5\xa8#\x0e\x9d'
                 b"\xca\x7f#z\x05^\t\xc2\x14'<\x92"},
  'lastUse': datetime.datetime(2025, 4, 3, 18, 6, 45, 144000),
  'user': 'nmosregadmin@admin'},
 {'_id': {'id': Binary(b'\x07Z\xb3l\x0c\xf4K\xfd\xb6*\\"\xd6Z\x06H', 4),
          'uid': b'\xc8B\x14\x8fd\xed\xea:\x9f\xffa\xe6\xaf\xb9^\x8a\xf2*\xf1y'
                 b"'\x95v\xc6\x9c\x84\xc9\xb7\xe7\x89\xb1^"},
  'lastUse': datetime.datetime(2025, 4, 3, 18, 6, 16, 716000),
  'user': 'nmosreguser@admin'}]

The mongod log also states that the killAllSessions() completed "successfully":

{"t":{"$date":"2025-04-03T18:06:33.267+00:00"},"s":"I",  "c":"COMMAND",  "id":558701,  "ctx":"conn13","msg":"Success: kill session","attr":{"user":[{"user":"nmosregadmin","db":"admin"}],"session":{"remote":"127.0.0.1:34754","local":"127.0.0.1:27017
"},"metadata":{"application":{"name":"mongosh 2.4.2"},"driver":{"name":"nodejs|mongosh","version":"6.14.2|2.4.2"},"platform":"Node.js v20.18.3, LE","os":{"name":"linux","architecture":"x64","version":"3.10.0-327.22.2.el7.x86_64","type":"Linux"},"en
v":{"container":{"runtime":"docker"}}},"command":{"killAllSessions":[{"user":"nmosreguser","db":"admin"}],"lsid":{"id":{"$uuid":"79a0a71c-f28d-4de4-aac8-08b8826decf7"}},"$db":"admin"}}}

Solution

  • After much experimentation and such, I think I've solved my comprehension problem. Essentially, I've been bringing a PostgreSQL (PG) mentality to this situation and that has prevented me from seeing the bigger picture here.

    Here's what I've learned:

    Thanks to everyone who helped me.