lihaibh / ditto

NPM library that helps managing MongoDB snapshots easily and efficiently
https://www.npmjs.com/package/mongodb-snapshot
MIT License
50 stars 6 forks source link

not authorized on admin to execute command #26

Open aligzl opened 3 years ago

aligzl commented 3 years ago

Hello i get fallowing error:

version 1.3.0 Mongodb Version: 4.4.5

could not write collection data into: type: Local FileSystem Connector, path: ./backup.tar due to error: VError: pack collection: dbname failed: not authorized on admin to execute command { serverStatus: 1, lsid: { id: UUID("e648e902-2be1-444c-a57c-e1ebda99242d") }, $db: "admin" }

async function dumpMongo2Localfile() {
    const mongo_connector = new MongoDBDuplexConnector({
        connection: {
            uri: `connection string`,
            dbname: 'db name',
        },
    });

    const localfile_connector = new LocalFileSystemDuplexConnector({
        connection: {
            path: './backup.tar',
        },
    });

    const transferer = new MongoTransferer({
        source: mongo_connector,
        targets: [localfile_connector],
    });

    for await (const { total, write } of transferer) {
        console.log(`remaining bytes to write: ${total - write}`);
    }
}
lihaibh commented 3 years ago

are you using an administrator username to run the backup? it happens because we access to admin db to get status about the database version

aligzl commented 3 years ago

are you using an administrator username to run the backup? it happens because we access to admin db to get status about the database version

Yes, i do. anyway if i add ?authSource=admin to end of connection string it works like below; mongodb://<username>:<password>@localhost: 27017/dbname?authSource=admin

lihaibh commented 3 years ago

I see, it is abit problematic. there is a function called snapshot which as i understood prevents the same documents to be written multiple times. https://mongodb.github.io/node-mongodb-native/3.1/api/Cursor.html#snapshot

However, the problem is that the "snapshot" function is not supported in MongoDB version 4. https://github.com/lihaibh/mongodb-snapshot/issues/9

so i had to check the version of the db and in order to do so i need to access the admin database, with admin privileges. Indeed we need to figure out how to use the snapshot function without the need to access the admin database.

sopwerdna commented 2 years ago

I've encountered the exact same problem. While this is partially dependent on security settings in the MongoDB deployment, serverStatus() provides a lot of information about the DB server and therefore is somewhat more likely to be restricted. However, serverInfo() fetches a lot less information, and still provides the server version which seems to be all you need here. This should be a simple one-line change here and may prevent this problem, since my understanding is that in the typical managed MongoDB deployment, serverInfo() is much less likely to be disallowed. I did some brief testing and it seems that this is the only place the admin database is really needed, so making this change would allow use of your otherwise excellent library in managed or shared databases where security is tightened. Normally I would just make a PR myself, but it's a one-line change and I would have to get permission from my employer to do it, so I am just letting you know on this issue. Thanks!

lihaibh commented 2 years ago

@sopwerdna thank you for sharing this information, i will open a fix PR. How would i know when serverInfo does not give version number? will it throw an error? will it be just undefined?

sopwerdna commented 2 years ago

How would i know when serverInfo does not give version number? will it throw an error? will it be just undefined?

I believe it behaves essentially the same way as serverStatus() and will either return all the specified information, or fail in the same way it currently does, described above by the original submitter.

Confusingly, the error described here (which is identical to the one I encountered) appears to come from the local file connector class, even though it originates in the MongoDBDuplexConnector class and propagates through. I think catching errors thrown when calling adminDb.serverStatus() or serverInfo() inside the Mongo connector class would be another wise improvement either way.

lihaibh commented 2 years ago

if we dont provide on the url the authSource=admin will we be able to still access the admin database? the reason why you receive the error from local file connector is because the source stream of mongodb is bounded to the output stream of local file connector. This means that when the local file connector tries to write the first chunk of data it lazingly activates the mongodb connector, that fails so the write fails.

sopwerdna commented 2 years ago

Setting the authSource shouldn't affect the ability to access admin database, as long as the credentials are correct for the database you are actually trying to connect to. Regardless, serverInfo() should work, and has a better chance of working than serverStatus() since we are gathering much less information and is less likely to be forbidden.

The error resulting from lazy-loading of the mongodb connector makes sense, that is what I suspected was happening. I do think it might be helpful for the error message thrown by the local file connector might be clearer if it mentioned whether it came from attempting to initialize the source, or something internal to the local file connection.

sopwerdna commented 2 years ago

I am curious if you're planning to make this change in the next release (maybe 1.4.2) in order to bring wider compatibility, especially for managed/shared MongoDB instances where security is a bit more locked down. Thank you!