mashingan / anonimongo

Another Nim pure Mongo DB driver
MIT License
43 stars 5 forks source link

Authentication #16

Closed samsamros closed 3 years ago

samsamros commented 3 years ago

I have been trying to use authentication as suggested in the ReadMe file. I had initially tried performing the MongoURI method, and got the same problem, too. So, I decided to try with the basic example:

import anonimongo import strformat

const username="OOO" password = "OOOOO"
var mongo = newMongo() if not waitfor mongo.connect: quit "Cannot connect to localhost:27017" if not waitfor mongo.authenticate[:SHA256Digest](username, password): quit "Cannot login to localhost:27017" close mongo

And I got the following error:

/home/localhost/PROJECT/MONGO_ATTEMPT.nim(12, 26) template/generic instantiation of authenticate from here /home/localhost/.nimble/pkgs/anonimongo-0.5.0/anonimongo/core/types.nim(509, 62) template/generic instantiation of bulkAuthenticate from here /home/localhost/.nimble/pkgs/anonimongo-0.5.0/anonimongo/core/types.nim(497, 23) template/generic instantiation of authenticate from here /home/localhost/.nimble/pkgs/anonimongo-0.5.0/anonimongo/core/pool.nim(102, 16) Error: type mismatch: got <TableRef[system.int, pool.Connection]> but expected one of: iterator pairs(a: cstring): tuple[key: int, val: char] first type mismatch at position: 1 required type for a: cstring but expression 'p.connections' is of type: TableRef[system.int, pool.Connection] iterator pairs(a: string): tuple[key: int, val: char] first type mismatch at position: 1 required type for a: string but expression 'p.connections' is of type: TableRef[system.int, pool.Connection] iterator pairs(b: BsonDocument): (string, BsonBase) first type mismatch at position: 1 required type for b: BsonDocument but expression 'p.connections' is of type: TableRef[system.int, pool.Connection] iterator pairs(cur: Cursor): (int, BsonDocument) first type mismatch at position: 1 required type for cur: Cursor but expression 'p.connections' is of type: TableRef[system.int, pool.Connection] iterator pairs[IX, T](a: array[IX, T]): tuple[key: IX, val: T] first type mismatch at position: 1 required type for a: array[IX, T] but expression 'p.connections' is of type: TableRef[system.int, pool.Connection] iterator pairs[T](a: openArray[T]): tuple[key: int, val: T] first type mismatch at position: 1 required type for a: openArray[T] but expression 'p.connections' is of type: TableRef[system.int, pool.Connection] iterator pairs[T](a: seq[T]): tuple[key: int, val: T] first type mismatch at position: 1 required type for a: seq[T] but expression 'p.connections' is of type: TableRef[system.int, pool.Connection]

expression: pairs(p.connections)


I checked my same database using pymongo and connected no problem... Maybe I'm compiling the wrong way, maybe it's an issue. I can't seem to find any answers on my code. Both Uri and this method are not working. I've changed methods from 1 to 256, still not working. There's no ssl enabled, only access control via users.

I've also tried:

var mongo = newMongo(parseUri "mongodb://username:password@localhost:27017/TEMP") if not waitfor mongo.connect: quit "Cannot connect to localhost:27017"

if not waitFor mongo.authenticate[:SHA1Digest](): #and have also tried 256 quit "Cannot login to localhost:27017" close mongo


I've looked at: https://github.com/mashingan/anonimongo/issues/5 and tried adding nimSHA2 and sha1. When I comment out the mongo.authenticate part it runs smoothly. However, when I try to query or do something related to the collection I get:

Exception message: command count requires authentication Exception type: [MongoError]

Authentication is fine with other platforms... works fine in mongosh and in pymongo in python.

mashingan commented 3 years ago

I think I forgot putting the example that you have to import tables module like:

import tables

Please try or adjust example below whether it solves your problem or not. More likely it's because indeed the lack importing of tables module. The possible fix whether:

The SHA1 and SHA256 have already exported from anonimongo so user doesn't have to import sha1 or nimsha2 anymore.

I will patch later after deciding which fix is preferable.


This is the example I used to connect to Mongo Atlas:

import sugar
import tables
import anonimongo

var mongo = newMongo(
  MongoUri "mongodb+srv://myuser:mypassword@my-account-mongo-atlas.domain.com/sample_restaurants?ssl=true&retryWrites=true&w=majority&compressor=snappy,zlib",
  poolconn = 2,
  dnsserver = "192.168.18.1")
# this dnsserver only for my specific case because my ISP blocking
# connecting the dns server to 1.1.1.1 (cloudflare) or 8.8.8.8 (google)
# just delete the dnsserver part if you have no problem with your ISP blocking dns server.

#mongo.slaveOk

if not waitfor mongo.connect:
  quit "Cannot connect to mongo atlas"
else:
  echo "mongo connected"

if not waitfor mongo.authenticate[:SHA1Digest]:
  quit "cannot authenticate to mongo atlas"
else:
  echo "mongo authenticated"

var coll = mongo["sample_restaurants"]["restaurants"]
let restaurantsCount = waitfor coll.count()
dump restaurantsCount
echo getCurrentExceptionMsg()

close mongo

Run with nim r -d:ssl connect_atlas.nim (with Nim v1.4.2)

samsamros commented 3 years ago

Oh! That's fantastic!!! The tables module helped wonders.... I get the following errors, however. When running the code you suggested I get:

Error: unhandled exception: Dns cannot resolve the my-account-mongo-atlas.domain.com, check your internet connection [MongoError].

I've tried different dnsservers to no avail...

But, I incorporated the tables to my code. It worked, but I still can't authenticate... I use the same URI as in pymongo and mongosh, but here I get:

"Authentication failed." "Authentication failed." "Authentication failed." "Authentication failed." ...... Some connection failed to authenticate. Failed Connection on localhost:27018 cannot authenticate ..... .....

Exception message: command distinct requires authentication Exception type: [MongoError]

At least the previous issue is solved... Thank you so much, it was just the module. Any ideas on this new issue? The port is 27018 for this database in particular and it's local. For some reason the same URI works fine in pymongo and mongosh. I guess it's entirely a differnt issue now.

var mongo1 = newMongo(MongoUri "mongodb://username:password@localhost:27018/database) doAssert waitFor mongo1.connect if not waitFor mongo1.authenticate[:SHA1Digest]: echo("Error")

mashingan commented 3 years ago

That my-account-mongo-atlas.domain.com is dummy link, change to your own url host mongodb server ;)

Your last example should work too, and also, don't forget to import tables too ;)

samsamros commented 3 years ago

Jeez, I didn't even see it was a dummy link... I'm sorry... I've been at it all day... D:

The Authentication error results from my own code, though. The import tables lines is already in my code and solved the previous issue. But, with that last line of code I get authentication error.

"Authentication failed."
"Authentication failed."
"Authentication failed."
"Authentication failed."
......
Some connection failed to authenticate. Failed
Connection on localhost:27018 cannot authenticate
.....
.....

Exception message: command distinct requires authentication
Exception type: [MongoError]

I must be missing something obvious, I'm sure. I even copy-pasted the URI from pymongo directly to my nim code... I still can't get it to authenticate. Thank you for your patiance and work... anonimongo has helped so much.

mashingan commented 3 years ago

Hmm, I'm not sure because as long the config is correct, it should have no problem. As I'm able to authenticate to Mongo Atlas, I think the problem is just a slight mistake which hard to identify at glance.
Advised to look again later, if the problem persists, please provide information the system you're testing so I'll try to reproduce and look at it.

samsamros commented 3 years ago

Got it to work with some tweaks. I'm using Parrot OS, a debian distro. Using pymongo and the same URI has no problems. I tried this after restarting mongo on the host machine, restarting my working station and taking a break from the code. I can't see any problem with the URI: I've copied and pasted it directly from pymongo.

However, when I authenticate using this mongo's root user it loads no problem at all...

New update.... If I create a user within the database iteslf, pymongo recognizes it without any hassle. But anonimongo does not, for some strange reason. Now, when I created the same user using: use admin db.createUser({user:"something", pwd:"password", roles:[{role:"read", db:"database"}]}) it works fantastic....

One user is: admin.something (which works perfectly) <-- this one works ...and the other: database.something. <-- this one doesn't

This is strange... Authentication works absolutely fine with pymongo using database.something, but doesn't work in anonimongo. thank you @mashingan. Is this the normal behavior?

mashingan commented 3 years ago

I've checked your case, yes it's indeed a bug in the authentication implementation.

By default it's always pointing to admin database. Normally when connecting with MongoURI argument whether we can get the database target from the path or from the query authSource=our-target-db.

A quick temporary fix is by adding e.g. client.db = "our-target-db" before authenticating.

With your config, the complete example becomes:


import tables, sugar
import anonimongo

proc main =
    var mongo = newMongo(
        MongoUri "mongodb://something:password@localhost:27017/database"
        poolconn = 1)
    defer: mongo.close

    dump mongo.db # this will print empty string

    if not waitfor mongo.connect:
        echo "cannot connect"
        return

    mongo.db = "database" # this is the quick fix without waiting the new patch version
    if not waitfor mongo.authenticate[:SHA1Digest]:
        echo "cannot authenticate"
        return
    var coll = mongo["database"]["somecoll"]
    for doc in waitfor coll.findAll():
        dump doc

main()

Please test the example above whether it's working as intended or not for your case.
You can keep the issues open even after the above example/fix is working because this needs the commit for new patch version, so this will be closed with referring the patch commit.

samsamros commented 3 years ago

Fix worked perfectly. Thank you so very much! I'll be on the lookout for a new fix... but this worked flawlessly.