[SERVER-8527] $external database is created as a database and prevented sharding Created: 12/Feb/13  Updated: 11/Jul/16  Resolved: 14/Feb/13

Status: Closed
Project: Core Server
Component/s: Security, Sharding
Affects Version/s: 2.4.0-rc0
Fix Version/s: 2.4.0-rc1

Type: Bug Priority: Major - P3
Reporter: Mark porter Assignee: Andy Schwerin
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

MongoDB2.4.0-rc0


Issue Links:
Depends
Backwards Compatibility: Fully Compatible
Operating System: ALL
Steps To Reproduce:

See above

Participants:

 Description   

The $external useSource was somehow created as a database, which doesn't seem to be quite logical. It should be an external artifact I'd have thought.

I discovered this during testing of adding a sharded cluster infrastructure consisting of two already-Kerborised replica sets.

1. Step : added realm4 replica set as a shard

mongos> sh.addShard( "realm4/kserver1a.realm4.10gen.me:27017" )
{ "shardAdded" : "realm4", "ok" : 1 }

2. Step : added realm5 set as a shard, however, this is rejected due to the existence of the $external database on both realms. This is logical but it means some reconfiguration if making two Kerberos-enabled replica sets part of a sharded cluster.

mongos> sh.addShard( "realm5/kserver1a.realm5.10gen.me:27017" )
{
	"ok" : 0,
	"errmsg" : "can't add shard realm5/kserver1a.realm5.10gen.me:27017 because a local database '$external' exists in another realm4:realm4/kserver1a.realm4.10gen.me:27017,kserver1b.realm4.10gen.me:27017,kserver1c.realm4.10gen.me:27017"
}

So as expected, I can drop the $external database below -

realm5:PRIMARY> db.dropDatabase()
{ "dropped" : "$external", "ok" : 1 }
realm5:PRIMARY> 
realm5:PRIMARY> 
realm5:PRIMARY> 
realm5:PRIMARY> show dbs
$SERVER	(empty)
admin	0.0625GB
db1	0.0625GB
fred	(empty)
local	1.07763671875GB

After removing the $external database, I can now add realm5 as the second shard -

mongos> sh.addShard( "realm5/kserver1a.realm5.10gen.me:27017" )
{ "shardAdded" : "realm5", "ok" : 1 }

mongos> sh.status()
--- Sharding Status --- 
  sharding version: {
	"_id" : 1,
	"version" : 3,
	"minCompatibleVersion" : 3,
	"currentVersion" : 4,
	"clusterId" : ObjectId("511a58f8bc0ae36e0fab6574")
}
  shards:
	{  "_id" : "realm4",  "host" : "realm4/kserver1a.realm4.10gen.me:27017,kserver1b.realm4.10gen.me:27017,kserver1c.realm4.10gen.me:27017" }
	{  "_id" : "realm5",  "host" : "realm5/kserver1a.realm5.10gen.me:27017,kserver1b.realm5.10gen.me:27017,kserver1c.realm5.10gen.me:27017" }
  databases:
	{  "_id" : "admin",  "partitioned" : false,  "primary" : "config" }
	{  "_id" : "fred",  "partitioned" : false,  "primary" : "realm4" }
	{  "_id" : "$external",  "partitioned" : false,  "primary" : "realm4" }
	{  "_id" : "db1",  "partitioned" : false,  "primary" : "realm5" }

Out of curiousity what is the $SERVER database? I never created it.



 Comments   
Comment by auto [ 14/Feb/13 ]

Author:

{u'date': u'2013-02-14T17:14:09Z', u'name': u'Andy Schwerin', u'email': u'schwerin@10gen.com'}

Message: SERVER-8527 Do not try to read the non-existent "$external" database during privilege acquisition.

It is the attempt to acquire privileges stored in "$external.system.users" that is causing the
the DatabaseHolder to construct a Database object for the non-existent "$external" database during
normal operation. This change aleviates that on the acquire privileges code path, without fixing
the more general problem of creating database objects for illegal database names. That problem
is far stickier, and this limited solution ameliorates the "can't add shards" symptom.
Branch: master
https://github.com/mongodb/mongo/commit/ca8305a028f9601f8d6b73aa7be998b014dc9f1c

Comment by Andy Schwerin [ 13/Feb/13 ]

It seems that what is happening is that a transient, in-memory Database object is created and added to the DatabaseHolder singleton via DatabaseHolder::getOrCreateDatabase() whenever a context object is created. Unfortunately, DH::gOCDB doesn't check to see if a database name is valid. That is only done, AFAICT, on the write path when deciding whether or not to create actual database files. This means that any read operation on a non-existent database, including authentication, will create one of these objects, which shows up in "listDatabases" and interferes with replicaset establishment. Restarting the affected node removes the bad entry, but I'm not certain yet what the right fix is to prevent this from manifesting.

Comment by Andy Schwerin [ 12/Feb/13 ]

Marking 2.4.0-rc1 for triage. Note that there is a workaround, albeit painful, of manually removing the "$external" database (which has no associated files, AFAICT). It's not even a real database – it's just getting into some system catalog somehow.

Generated at Thu Feb 08 03:17:41 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.