0

I have MongoDB replica set with enabled authentication. I want to change replica set name. In order to do that I have to delete documents from local.system.replset collection. I have admin user with root@admin role assigned, also I have regular user with readWrite@local role. When I try to execute remove from the shell with any of the users above I get Unauthorized exception:

> db.system.replset.remove({})
WriteCommandError({
        "operationTime" : Timestamp(1582026365, 1),
        "ok" : 0,
        "errmsg" : "not authorized on local to execute command { delete: \"system.replset\", ordered: true, lsid: { id: UUID(\"43182bad-b13d-4ff4-a31b-3cdcb1dd49fa\") }, $clusterTime: { clusterTime: Timestamp(1582026355, 1), signature: { hash: BinData(0, E9FD8A23702CE215B193423CAF1C2AF3FEE83D6B), keyId: 6794747247067136002 } }, $db: \"local\" }",
        "code" : 13,
        "codeName" : "Unauthorized",
        "$clusterTime" : {
                "clusterTime" : Timestamp(1582026365, 1),
                "signature" : {
                        "hash" : BinData(0,"CyCvFtgLkpdhIrsJV67KBlVwL+U="),
                        "keyId" : NumberLong("6794747247067136002")
                }
        }
})

If I try to execute same command on replica set with no authentication enabled I can successfully remove the record. What role am I missing on order to let user to delete record from local.system.replset? Or is it not supported when authentication is enabled?

Andrii Litvinov
  • 12,402
  • 3
  • 52
  • 59

2 Answers2

1

This answer https://stackoverflow.com/a/20120639/2138959 gave me a hint that root user may not have the privileges required and indeed it only has find privilege. I still don't know why readWrite@local didn't allow to write to system.replicaset, but when I added new role with find, insert, remove, update, bypassDocumentValidation, useUUID privileges for local.system.replset resource I was able to finally remove the replica set and update the name.

Another even simpler option is to assign dbOwner@local role to the user.

Andrii Litvinov
  • 12,402
  • 3
  • 52
  • 59
  • 2
    Same problem here, local DB is not allowed to create any custom roles. But we can create roles in admin DB for local DB. – wendong Mar 06 '20 at 08:38
1

Both root and dbOwner@local do have general privileges to the database:

> db.getRole( "dbOwner", { showPrivileges: true } )
{
    "role" : "dbOwner",
    "db" : "local",
    "isBuiltin" : true,
    "roles" : [ ],
    "inheritedRoles" : [ ],
    "privileges" : [
        {
            "resource" : {
                **"db" : "local",
                "collection" : ""**
            },
(...)

But, quoting the documentation:

If only the collection field is an empty string (""), the resource is the specified database, excluding the system collections.

Therefore, in order to get write access to the system.replicaset, you need to add a role specifically for this collection:

> db.createRole( { role: "rs_admin",  privileges: [ { resource: { db: "local", collection: "system.replset" }, actions: [ "find", "insert", "remove" ] } ], roles: [] } )