I am using the latest driver (2.5) for C#, trying to copy a database from one mongod instance to another. As I understand it, the process to copy from the QA mongod to the Dev mongod is:
- Instantiate an instance of the MongoClient for the dev instance
- Get an instance of the 'admin' database
- Generate a nonce from the admin database of the dev MongoClient
- For this, I specify 'fromhost' as one of the qa mongod replica instances
- Calculate the md5 hash of the key
- Issue the appropriate 'copydb' command
I understand that authentication for the copydb command, since fromhost was specified, will be in the 'fromdb' defined in the command. I have had our DBA give the same credentials dbOwner permissions for the fromdb specified, but I'm still unable to connect. Since I'm doing my work through the C# driver, as I understand it, copydb command is available, but not copydatabase which seems to simplify the authentication process.
Is anyone able to see a problem with the following code? All I can manage to get is an error stating: MongoCommandException: Command copydb failed: unable to login { ok: 0.0, errmsg: "auth failed", code: 18 }. I'm able to manually connect to all the endpoints via Robo 3T and view collections. Our DBA has verified that i'm set to dbOwner in all the appropriate places (admin DB, source/target DBs).
public static void CopyDatabase()
{
string mongoDBUsername = "someDbOwner";
string mongoDBPassword = "superSecretPassword";
var devClientSettings = new MongoClientSettings()
{
Credential = MongoCredential.CreateCredential("admin", mongoDBUsername, mongoDBPassword),
ConnectionMode = ConnectionMode.ReplicaSet,
Servers = new List<MongoServerAddress>() { new MongoServerAddress("dev01", 27017), new MongoServerAddress("dev02", 27017), new MongoServerAddress("dev03", 27017) }
};
var devClient = new MongoClient(devClientSettings);
var devAdminDb = devClient.GetDatabase("admin");
var nonceCommand = @"{ copydbgetnonce : 1, fromhost: 'qa01:27017' }";
var nonceValueDev = devAdminDb.RunCommand<BsonDocument>(nonceCommand).ToString();
string hashedSecret = CalculateMD5Hash(nonceValueDev + mongoDBUsername + CalculateMD5Hash(mongoDBUsername + ":mongo:" + mongoDBPassword));
string commandString = @"{ copydb: 1, fromhost: 'qa01:27017', fromdb: 'qa01-db01', todb: 'qa01-db01', username:'" + mongoDBUsername + "', nonce: '" + nonceValueDev + "', key: '" + hashedSecret + "', slaveOk: 'true'}";
devAdminDb.RunCommandAsync<BsonDocument>(commandString).Wait();
}
public static string CalculateMD5Hash(string input)
{
using (MD5 md5 = MD5.Create())
{
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hash = md5.ComputeHash(inputBytes);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
sb.Append(hash[i].ToString("X2"));
}
return sb.ToString();
}
}