def remove_all_users(db): if Version.from_client(db.client).at_least(2, 5, 3, -1): db.command("dropAllUsersFromDatabase", 1, writeConcern={"w": client_context.w}) else: db = db.client.get_database( db.name, write_concern=WriteConcern(w=client_context.w)) db.system.users.delete_many({})
def remove_all_users(db): if Version.from_client(db.client).at_least(2, 5, 3, -1): db.command("dropAllUsersFromDatabase", 1, writeConcern={"w": client_context.w}) else: db = db.client.get_database( db.name, write_concern=WriteConcern(w=client_context.w)) db.system.users.delete_many({})
def setUp(self): super(TestCommandAndReadPreference, self).setUp() self.c = ReadPrefTester( '%s:%s' % (host, port), replicaSet=self.name, # Ignore round trip times, to test ReadPreference modes only. localThresholdMS=1000*1000) if client_context.auth_enabled: self.c.admin.authenticate(db_user, db_pwd) self.client_version = Version.from_client(self.c) self.addCleanup(self.c.drop_database, 'pymongo_test')
def setUp(self): super(TestCommandAndReadPreference, self).setUp() self.c = ReadPrefTester( '%s:%s' % (host, port), replicaSet=self.name, # Ignore round trip times, to test ReadPreference modes only. localThresholdMS=1000*1000) if client_context.auth_enabled: self.c.admin.authenticate(db_user, db_pwd) self.client_version = Version.from_client(self.c) self.addCleanup(self.c.drop_database, 'pymongo_test')
def setUpClass(cls): super(TestCommandAndReadPreference, cls).setUpClass() cls.c = ReadPrefTester( client_context.pair, # Ignore round trip times, to test ReadPreference modes only. localThresholdMS=1000*1000) cls.client_version = Version.from_client(cls.c) # mapReduce fails if the collection does not exist. coll = cls.c.pymongo_test.get_collection( 'test', write_concern=WriteConcern(w=client_context.w)) coll.insert_one({})
def setUpClass(cls): super(TestCommandAndReadPreference, cls).setUpClass() cls.c = ReadPrefTester( client_context.pair, replicaSet=cls.name, # Ignore round trip times, to test ReadPreference modes only. localThresholdMS=1000*1000) if client_context.auth_enabled: cls.c.admin.authenticate(db_user, db_pwd) cls.client_version = Version.from_client(cls.c) # mapReduce and group fail with no collection coll = cls.c.pymongo_test.get_collection( 'test', write_concern=WriteConcern(w=cls.w)) coll.insert_one({})
def setUpClass(cls): super(TestCommandAndReadPreference, cls).setUpClass() cls.c = ReadPrefTester( client_context.pair, replicaSet=cls.name, # Ignore round trip times, to test ReadPreference modes only. localThresholdMS=1000 * 1000) if client_context.auth_enabled: cls.c.admin.authenticate(db_user, db_pwd) cls.client_version = Version.from_client(cls.c) # mapReduce and group fail with no collection coll = cls.c.pymongo_test.get_collection( 'test', write_concern=WriteConcern(w=cls.w)) coll.insert_one({})
def test_mongodb_x509_auth(self): # Expects the server to be running with the server.pem, ca.pem # and crl.pem provided in mongodb and the server tests as well as # --auth # # --sslPEMKeyFile=/path/to/pymongo/test/certificates/server.pem # --sslCAFile=/path/to/pymongo/test/certificates/ca.pem # --sslCRLFile=/path/to/pymongo/test/certificates/crl.pem # --auth if not CERT_SSL: raise SkipTest("No mongod available over SSL with certs") if not Version.from_client(ssl_client).at_least(2, 5, 3, -1): raise SkipTest("MONGODB-X509 tests require MongoDB 2.5.3 or newer") if not server_started_with_auth(ssl_client): raise SkipTest('Authentication is not enabled on server') self.addCleanup(ssl_client['$external'].logout) self.addCleanup(remove_all_users, ssl_client['$external']) # Give admin all necessary privileges. ssl_client['$external'].add_user(MONGODB_X509_USERNAME, roles=[ {'role': 'readWriteAnyDatabase', 'db': 'admin'}, {'role': 'userAdminAnyDatabase', 'db': 'admin'}]) coll = ssl_client.pymongo_test.test self.assertRaises(OperationFailure, coll.count) self.assertTrue(ssl_client.admin.authenticate( MONGODB_X509_USERNAME, mechanism='MONGODB-X509')) coll.drop() uri = ('mongodb://%s@%s:%d/?authMechanism=' 'MONGODB-X509' % ( quote_plus(MONGODB_X509_USERNAME), host, port)) # SSL options aren't supported in the URI... self.assertTrue(MongoClient(uri, ssl=True, ssl_certfile=CLIENT_PEM)) # Should require a username uri = ('mongodb://%s:%d/?authMechanism=MONGODB-X509' % (host, port)) client_bad = MongoClient(uri, ssl=True, ssl_certfile=CLIENT_PEM) self.assertRaises(OperationFailure, client_bad.pymongo_test.test.delete_one, {}) # Auth should fail if username and certificate do not match uri = ('mongodb://%s@%s:%d/?authMechanism=' 'MONGODB-X509' % ( quote_plus("not the username"), host, port)) bad_client = MongoClient(uri, ssl=True, ssl_certfile=CLIENT_PEM) with self.assertRaises(OperationFailure): bad_client.pymongo_test.test.find_one() self.assertRaises(OperationFailure, ssl_client.admin.authenticate, "not the username", mechanism="MONGODB-X509") # Invalid certificate (using CA certificate as client certificate) uri = ('mongodb://%s@%s:%d/?authMechanism=' 'MONGODB-X509' % ( quote_plus(MONGODB_X509_USERNAME), host, port)) # These tests will raise SSLError (>= 3.2) or ConnectionFailure # (2.x) depending on where OpenSSL first sees the PEM file. try: connected(MongoClient(uri, ssl=True, ssl_certfile=CA_PEM, serverSelectionTimeoutMS=100)) except (ssl.SSLError, ConnectionFailure): pass else: self.fail("Invalid certificate accepted.") try: connected(MongoClient(pair, ssl=True, ssl_certfile=CA_PEM, serverSelectionTimeoutMS=100)) except (ssl.SSLError, ConnectionFailure): pass else: self.fail("Invalid certificate accepted.")
def setup_version(self): """Set self.version to the server's version.""" self.version = Version.from_client(self.sync_cx)
def __init__(self): """Create a client and grab essential information from the server.""" self.connected = False self.ismaster = {} self.w = None self.nodes = set() self.replica_set_name = None self.cmd_line = None self.version = Version(-1) # Needs to be comparable with Version self.auth_enabled = False self.test_commands_enabled = False self.is_mongos = False self.is_rs = False self.has_ipv6 = False self.ssl = False self.ssl_cert_none = False self.ssl_certfile = False self.server_is_resolvable = is_server_resolvable() self.ssl_client_options = {} self.sessions_enabled = False self.client = _connect(host, port) if HAVE_SSL and not self.client: # Is MongoDB configured for SSL? self.client = _connect(host, port, **_SSL_OPTIONS) if self.client: self.ssl = True self.ssl_client_options = _SSL_OPTIONS self.ssl_certfile = True if _SSL_OPTIONS.get('ssl_cert_reqs') == ssl.CERT_NONE: self.ssl_cert_none = True if self.client: self.connected = True try: self.cmd_line = self.client.admin.command('getCmdLineOpts') except pymongo.errors.OperationFailure as e: msg = e.details.get('errmsg', '') if e.code == 13 or 'unauthorized' in msg or 'login' in msg: # Unauthorized. self.auth_enabled = True else: raise else: self.auth_enabled = self._server_started_with_auth() if self.auth_enabled: # See if db_user already exists. if not self._check_user_provided(): self.client.admin.add_user(db_user, db_pwd, roles=['root']) self.client = _connect(host, port, username=db_user, password=db_pwd, replicaSet=self.replica_set_name, **self.ssl_client_options) # May not have this if OperationFailure was raised earlier. self.cmd_line = self.client.admin.command('getCmdLineOpts') self.ismaster = ismaster = self.client.admin.command('isMaster') self.sessions_enabled = 'logicalSessionTimeoutMinutes' in ismaster if 'setName' in ismaster: self.replica_set_name = ismaster['setName'] self.is_rs = True if self.auth_enabled: # It doesn't matter which member we use as the seed here. self.client = pymongo.MongoClient( host, port, username=db_user, password=db_pwd, replicaSet=self.replica_set_name, **self.ssl_client_options) else: self.client = pymongo.MongoClient( host, port, replicaSet=self.replica_set_name, **self.ssl_client_options) # Get the authoritative ismaster result from the primary. self.ismaster = self.client.admin.command('ismaster') nodes = [ partition_node(node.lower()) for node in self.ismaster.get('hosts', []) ] nodes.extend([ partition_node(node.lower()) for node in self.ismaster.get('passives', []) ]) nodes.extend([ partition_node(node.lower()) for node in self.ismaster.get('arbiters', []) ]) self.nodes = set(nodes) else: self.ismaster = ismaster self.nodes = set([(host, port)]) self.w = len(self.ismaster.get("hosts", [])) or 1 self.version = Version.from_client(self.client) if 'enableTestCommands=1' in self.cmd_line['argv']: self.test_commands_enabled = True elif 'parsed' in self.cmd_line: params = self.cmd_line['parsed'].get('setParameter', []) if 'enableTestCommands=1' in params: self.test_commands_enabled = True else: params = self.cmd_line['parsed'].get('setParameter', {}) if params.get('enableTestCommands') == '1': self.test_commands_enabled = True self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid') self.has_ipv6 = self._server_started_with_ipv6()
def __init__(self): """Create a client and grab essential information from the server.""" # Seed host. This may be updated further down. self.host, self.port = host, port self.connected = False self.ismaster = {} self.w = None self.nodes = set() self.replica_set_name = None self.cmd_line = None self.version = Version(-1) # Needs to be comparable with Version self.auth_enabled = False self.test_commands_enabled = False self.is_mongos = False self.is_rs = False self.has_ipv6 = False self.ssl = False self.ssl_cert_none = False self.ssl_certfile = False self.server_is_resolvable = is_server_resolvable() self.ssl_client_options = {} self.client = _connect(self.host, self.port) if HAVE_SSL and not self.client: # Is MongoDB configured for SSL? self.client = _connect(self.host, self.port, **_SSL_OPTIONS) if self.client: self.ssl = True self.ssl_client_options = _SSL_OPTIONS self.ssl_certfile = True if _SSL_OPTIONS.get('ssl_cert_reqs') == ssl.CERT_NONE: self.ssl_cert_none = True if self.client: self.connected = True self.ismaster = self.client.admin.command('ismaster') self.w = len(self.ismaster.get("hosts", [])) or 1 self.nodes = set([(self.host, self.port)]) self.replica_set_name = self.ismaster.get('setName', '') self.version = Version.from_client(self.client) if self.replica_set_name: self.is_rs = True self.client = pymongo.MongoClient( self.ismaster['primary'], replicaSet=self.replica_set_name, **self.ssl_client_options) # Force connection self.client.admin.command('ismaster') self.host, self.port = self.client.primary nodes = [partition_node(node.lower()) for node in self.ismaster.get('hosts', [])] nodes.extend([partition_node(node.lower()) for node in self.ismaster.get('passives', [])]) nodes.extend([partition_node(node.lower()) for node in self.ismaster.get('arbiters', [])]) self.nodes = set(nodes) try: self.cmd_line = self.client.admin.command('getCmdLineOpts') except pymongo.errors.OperationFailure as e: msg = e.details.get('errmsg', '') if e.code == 13 or 'unauthorized' in msg or 'login' in msg: # Unauthorized. self.auth_enabled = True else: raise else: self.auth_enabled = self._server_started_with_auth() if self.auth_enabled: # See if db_user already exists. self.user_provided = self._check_user_provided() if not self.user_provided: roles = {} if self.version.at_least(2, 5, 3, -1): roles = {'roles': ['root']} self.client.admin.add_user(db_user, db_pwd, **roles) self.client.admin.authenticate(db_user, db_pwd) # May not have this if OperationFailure was raised earlier. self.cmd_line = self.client.admin.command('getCmdLineOpts') if 'enableTestCommands=1' in self.cmd_line['argv']: self.test_commands_enabled = True elif 'parsed' in self.cmd_line: params = self.cmd_line['parsed'].get('setParameter', []) if 'enableTestCommands=1' in params: self.test_commands_enabled = True else: params = self.cmd_line['parsed'].get('setParameter', {}) if params.get('enableTestCommands') == '1': self.test_commands_enabled = True self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid') self.has_ipv6 = self._server_started_with_ipv6()
def __init__(self): """Create a client and grab essential information from the server.""" self.connected = False self.ismaster = {} self.w = None self.nodes = set() self.replica_set_name = None self.rs_client = None self.cmd_line = None self.version = Version(-1) # Needs to be comparable with Version self.auth_enabled = False self.test_commands_enabled = False self.is_mongos = False self.is_rs = False self.has_ipv6 = False try: client = pymongo.MongoClient(host, port, serverSelectionTimeoutMS=100) client.admin.command('ismaster') # Can we connect? # If so, then reset client to defaults. self.client = pymongo.MongoClient(host, port) except pymongo.errors.ConnectionFailure: self.client = self.rs_or_standalone_client = None else: self.connected = True self.ismaster = self.client.admin.command('ismaster') self.w = len(self.ismaster.get("hosts", [])) or 1 self.nodes = set([(host, port)]) self.replica_set_name = self.ismaster.get('setName', '') self.rs_client = None self.version = Version.from_client(self.client) if self.replica_set_name: self.is_rs = True self.rs_client = pymongo.MongoClient( pair, replicaSet=self.replica_set_name) nodes = [ partition_node(node.lower()) for node in self.ismaster.get('hosts', []) ] nodes.extend([ partition_node(node.lower()) for node in self.ismaster.get('passives', []) ]) nodes.extend([ partition_node(node.lower()) for node in self.ismaster.get('arbiters', []) ]) self.nodes = set(nodes) self.rs_or_standalone_client = self.rs_client or self.client try: self.cmd_line = self.client.admin.command('getCmdLineOpts') except pymongo.errors.OperationFailure as e: msg = e.details.get('errmsg', '') if e.code == 13 or 'unauthorized' in msg or 'login' in msg: # Unauthorized. self.auth_enabled = True else: raise else: self.auth_enabled = self._server_started_with_auth() if self.auth_enabled: # See if db_user already exists. self.user_provided = self._check_user_provided() if not self.user_provided: roles = {} if self.version.at_least(2, 5, 3, -1): roles = {'roles': ['root']} self.client.admin.add_user(db_user, db_pwd, **roles) self.client.admin.authenticate(db_user, db_pwd) if self.rs_client: self.rs_client.admin.authenticate(db_user, db_pwd) # May not have this if OperationFailure was raised earlier. self.cmd_line = self.client.admin.command('getCmdLineOpts') if 'enableTestCommands=1' in self.cmd_line['argv']: self.test_commands_enabled = True elif 'parsed' in self.cmd_line: params = self.cmd_line['parsed'].get('setParameter', []) if 'enableTestCommands=1' in params: self.test_commands_enabled = True self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid') self.has_ipv6 = self._server_started_with_ipv6()
def __init__(self): """Create a client and grab essential information from the server.""" self.connected = False self.ismaster = {} self.w = None self.nodes = set() self.replica_set_name = None self.rs_client = None self.cmd_line = None self.version = Version(-1) # Needs to be comparable with Version self.auth_enabled = False self.test_commands_enabled = False self.is_mongos = False self.is_rs = False self.has_ipv6 = False try: client = pymongo.MongoClient(host, port, serverSelectionTimeoutMS=100) client.admin.command('ismaster') # Can we connect? # If so, then reset client to defaults. self.client = pymongo.MongoClient(host, port) except pymongo.errors.ConnectionFailure: self.client = None else: self.connected = True self.ismaster = self.client.admin.command('ismaster') self.w = len(self.ismaster.get("hosts", [])) or 1 self.nodes = set([(host, port)]) self.replica_set_name = self.ismaster.get('setName', '') self.rs_client = None self.version = Version.from_client(self.client) if self.replica_set_name: self.is_rs = True self.rs_client = pymongo.MongoClient( pair, replicaSet=self.replica_set_name) nodes = [partition_node(node) for node in self.ismaster.get('hosts', [])] nodes.extend([partition_node(node) for node in self.ismaster.get('passives', [])]) nodes.extend([partition_node(node) for node in self.ismaster.get('arbiters', [])]) self.nodes = set(nodes) self.rs_or_standalone_client = self.rs_client or self.client try: self.cmd_line = self.client.admin.command('getCmdLineOpts') except pymongo.errors.OperationFailure as e: msg = e.details.get('errmsg', '') if e.code == 13 or 'unauthorized' in msg or 'login' in msg: # Unauthorized. self.auth_enabled = True else: raise else: self.auth_enabled = self._server_started_with_auth() if self.auth_enabled: # See if db_user already exists. self.user_provided = self._check_user_provided() if not self.user_provided: roles = {} if self.version.at_least(2, 5, 3, -1): roles = {'roles': ['root']} self.client.admin.add_user(db_user, db_pwd, **roles) self.client.admin.authenticate(db_user, db_pwd) if self.rs_client: self.rs_client.admin.authenticate(db_user, db_pwd) # May not have this if OperationFailure was raised earlier. self.cmd_line = self.client.admin.command('getCmdLineOpts') if 'enableTestCommands=1' in self.cmd_line['argv']: self.test_commands_enabled = True elif 'parsed' in self.cmd_line: params = self.cmd_line['parsed'].get('setParameter', []) if 'enableTestCommands=1' in params: self.test_commands_enabled = True self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid') self.has_ipv6 = self._server_started_with_ipv6()
def _init_client(self): self.client = self._connect(host, port) if self.client is not None: # Return early when connected to dataLake as mongohoused does not # support the getCmdLineOpts command and is tested without TLS. build_info = self.client.admin.command('buildInfo') if 'dataLake' in build_info: self.is_data_lake = True self.auth_enabled = True self.client = self._connect(host, port, username=db_user, password=db_pwd) self.connected = True return if HAVE_SSL and not self.client: # Is MongoDB configured for SSL? self.client = self._connect(host, port, **TLS_OPTIONS) if self.client: self.tls = True self.default_client_options.update(TLS_OPTIONS) self.ssl_certfile = True if self.client: self.connected = True try: self.cmd_line = self.client.admin.command('getCmdLineOpts') except pymongo.errors.OperationFailure as e: msg = e.details.get('errmsg', '') if e.code == 13 or 'unauthorized' in msg or 'login' in msg: # Unauthorized. self.auth_enabled = True else: raise else: self.auth_enabled = self._server_started_with_auth() if self.auth_enabled: # See if db_user already exists. if not self._check_user_provided(): _create_user(self.client.admin, db_user, db_pwd) self.client = self._connect(host, port, username=db_user, password=db_pwd, replicaSet=self.replica_set_name, **self.default_client_options) # May not have this if OperationFailure was raised earlier. self.cmd_line = self.client.admin.command('getCmdLineOpts') self.server_status = self.client.admin.command('serverStatus') if self.storage_engine == "mmapv1": # MMAPv1 does not support retryWrites=True. self.default_client_options['retryWrites'] = False ismaster = self.ismaster self.sessions_enabled = 'logicalSessionTimeoutMinutes' in ismaster if 'setName' in ismaster: self.replica_set_name = str(ismaster['setName']) self.is_rs = True if self.auth_enabled: # It doesn't matter which member we use as the seed here. self.client = pymongo.MongoClient( host, port, username=db_user, password=db_pwd, replicaSet=self.replica_set_name, **self.default_client_options) else: self.client = pymongo.MongoClient( host, port, replicaSet=self.replica_set_name, **self.default_client_options) # Get the authoritative ismaster result from the primary. ismaster = self.ismaster nodes = [ partition_node(node.lower()) for node in ismaster.get('hosts', []) ] nodes.extend([ partition_node(node.lower()) for node in ismaster.get('passives', []) ]) nodes.extend([ partition_node(node.lower()) for node in ismaster.get('arbiters', []) ]) self.nodes = set(nodes) else: self.nodes = set([(host, port)]) self.w = len(ismaster.get("hosts", [])) or 1 self.version = Version.from_client(self.client) self.server_parameters = self.client.admin.command( 'getParameter', '*') if 'enableTestCommands=1' in self.cmd_line['argv']: self.test_commands_enabled = True elif 'parsed' in self.cmd_line: params = self.cmd_line['parsed'].get('setParameter', []) if 'enableTestCommands=1' in params: self.test_commands_enabled = True else: params = self.cmd_line['parsed'].get('setParameter', {}) if params.get('enableTestCommands') == '1': self.test_commands_enabled = True self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid') self.has_ipv6 = self._server_started_with_ipv6() if self.is_mongos: # Check for another mongos on the next port. address = self.client.address next_address = address[0], address[1] + 1 self.mongoses.append(address) mongos_client = self._connect(*next_address, **self.default_client_options) if mongos_client: ismaster = mongos_client.admin.command('ismaster') if ismaster.get('msg') == 'isdbgrid': self.mongoses.append(next_address)
def setup_version(self): """Set self.version to the server's version.""" self.version = Version.from_client(self.sync_cx)
def test_mongodb_x509_auth(self): # Expects the server to be running with the server.pem and ca.pem # as well as --auth # # --sslPEMKeyFile=/path/to/pymongo/test/certificates/server.pem # --sslCAFile=/path/to/pymongo/test/certificates/ca.pem # --auth if not CERT_SSL: raise SkipTest("No mongod available over SSL with certs") if not Version.from_client(ssl_client).at_least(2, 5, 3, -1): raise SkipTest("MONGODB-X509 tests require MongoDB 2.5.3 or newer") if not server_started_with_auth(ssl_client): raise SkipTest('Authentication is not enabled on server') self.addCleanup(ssl_client['$external'].logout) self.addCleanup(remove_all_users, ssl_client['$external']) self.addCleanup(remove_all_users, ssl_client.admin) ssl_client.admin.add_user('admin', 'pass') ssl_client.admin.authenticate('admin', 'pass') # Give admin all necessary privileges. ssl_client['$external'].add_user(MONGODB_X509_USERNAME, roles=[{ 'role': 'readWriteAnyDatabase', 'db': 'admin' }, { 'role': 'userAdminAnyDatabase', 'db': 'admin' }]) ssl_client.admin.logout() coll = ssl_client.pymongo_test.test self.assertRaises(OperationFailure, coll.count) self.assertTrue( ssl_client.admin.authenticate(MONGODB_X509_USERNAME, mechanism='MONGODB-X509')) coll.drop() uri = ('mongodb://%s@%s:%d/?authMechanism=' 'MONGODB-X509' % (quote_plus(MONGODB_X509_USERNAME), host, port)) # SSL options aren't supported in the URI... self.assertTrue(MongoClient(uri, ssl=True, ssl_certfile=CLIENT_PEM)) # Should require a username uri = ('mongodb://%s:%d/?authMechanism=MONGODB-X509' % (host, port)) client_bad = MongoClient(uri, ssl=True, ssl_cert_reqs="CERT_NONE", ssl_certfile=CLIENT_PEM) self.assertRaises(OperationFailure, client_bad.pymongo_test.test.delete_one, {}) # Auth should fail if username and certificate do not match uri = ('mongodb://%s@%s:%d/?authMechanism=' 'MONGODB-X509' % (quote_plus("not the username"), host, port)) bad_client = MongoClient(uri, ssl=True, ssl_cert_reqs="CERT_NONE", ssl_certfile=CLIENT_PEM) with self.assertRaises(OperationFailure): bad_client.pymongo_test.test.find_one() self.assertRaises(OperationFailure, ssl_client.admin.authenticate, "not the username", mechanism="MONGODB-X509") # Invalid certificate (using CA certificate as client certificate) uri = ('mongodb://%s@%s:%d/?authMechanism=' 'MONGODB-X509' % (quote_plus(MONGODB_X509_USERNAME), host, port)) try: connected( MongoClient(uri, ssl=True, ssl_cert_reqs="CERT_NONE", ssl_certfile=CA_PEM, serverSelectionTimeoutMS=100)) except OperationFailure: pass else: self.fail("Invalid certificate accepted.")
def __init__(self): """Create a client and grab essential information from the server.""" # Seed host. This may be updated further down. self.host, self.port = host, port self.connected = False self.ismaster = {} self.w = None self.nodes = set() self.replica_set_name = None self.rs_client = None self.cmd_line = None self.version = Version(-1) # Needs to be comparable with Version self.auth_enabled = False self.test_commands_enabled = False self.is_mongos = False self.is_rs = False self.has_ipv6 = False self.ssl_cert_none = False self.ssl_certfile = False self.server_is_resolvable = is_server_resolvable() self.client = self.rs_or_standalone_client = None def connect(**kwargs): try: client = pymongo.MongoClient(self.host, self.port, serverSelectionTimeoutMS=100, **kwargs) client.admin.command('ismaster') # Can we connect? # If connected, then return client with default timeout return pymongo.MongoClient(self.host, self.port, **kwargs) except pymongo.errors.ConnectionFailure: return None self.client = connect() if HAVE_SSL and not self.client: # Is MongoDB configured for SSL? self.client = connect(ssl=True, ssl_cert_reqs=ssl.CERT_NONE) if self.client: self.ssl_cert_none = True # Can client connect with certfile? client = connect( ssl=True, ssl_cert_reqs=ssl.CERT_NONE, ssl_certfile=CLIENT_PEM, ) if client: self.ssl_certfile = True self.client = client if self.client: self.connected = True self.ismaster = self.client.admin.command('ismaster') self.w = len(self.ismaster.get("hosts", [])) or 1 self.nodes = set([(self.host, self.port)]) self.replica_set_name = self.ismaster.get('setName', '') self.rs_client = None self.version = Version.from_client(self.client) if self.replica_set_name: self.is_rs = True self.rs_client = pymongo.MongoClient( self.ismaster['primary'], replicaSet=self.replica_set_name) # Force connection self.rs_client.admin.command('ismaster') self.host, self.port = self.rs_client.primary self.client = connect() nodes = [ partition_node(node.lower()) for node in self.ismaster.get('hosts', []) ] nodes.extend([ partition_node(node.lower()) for node in self.ismaster.get('passives', []) ]) nodes.extend([ partition_node(node.lower()) for node in self.ismaster.get('arbiters', []) ]) self.nodes = set(nodes) self.rs_or_standalone_client = self.rs_client or self.client try: self.cmd_line = self.client.admin.command('getCmdLineOpts') except pymongo.errors.OperationFailure as e: msg = e.details.get('errmsg', '') if e.code == 13 or 'unauthorized' in msg or 'login' in msg: # Unauthorized. self.auth_enabled = True else: raise else: self.auth_enabled = self._server_started_with_auth() if self.auth_enabled: # See if db_user already exists. self.user_provided = self._check_user_provided() if not self.user_provided: roles = {} if self.version.at_least(2, 5, 3, -1): roles = {'roles': ['root']} self.client.admin.add_user(db_user, db_pwd, **roles) self.client.admin.authenticate(db_user, db_pwd) if self.rs_client: self.rs_client.admin.authenticate(db_user, db_pwd) # May not have this if OperationFailure was raised earlier. self.cmd_line = self.client.admin.command('getCmdLineOpts') if 'enableTestCommands=1' in self.cmd_line['argv']: self.test_commands_enabled = True elif 'parsed' in self.cmd_line: params = self.cmd_line['parsed'].get('setParameter', []) if 'enableTestCommands=1' in params: self.test_commands_enabled = True self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid') self.has_ipv6 = self._server_started_with_ipv6() # Do this after we connect so we know who the primary is. self.pair = "%s:%d" % (self.host, self.port)
def _init_client(self): self.client = self._connect(host, port) if HAVE_SSL and not self.client: # Is MongoDB configured for SSL? self.client = self._connect(host, port, **_SSL_OPTIONS) if self.client: self.ssl = True self.default_client_options.update(_SSL_OPTIONS) self.ssl_certfile = True if _SSL_OPTIONS.get('ssl_cert_reqs') == ssl.CERT_NONE: self.ssl_cert_none = True if self.client: self.connected = True try: self.cmd_line = self.client.admin.command('getCmdLineOpts') except pymongo.errors.OperationFailure as e: msg = e.details.get('errmsg', '') if e.code == 13 or 'unauthorized' in msg or 'login' in msg: # Unauthorized. self.auth_enabled = True else: raise else: self.auth_enabled = self._server_started_with_auth() if self.auth_enabled: # See if db_user already exists. if not self._check_user_provided(): _create_user(self.client.admin, db_user, db_pwd) self.client = self._connect( host, port, username=db_user, password=db_pwd, replicaSet=self.replica_set_name, **self.default_client_options) # May not have this if OperationFailure was raised earlier. self.cmd_line = self.client.admin.command('getCmdLineOpts') self.server_status = self.client.admin.command('serverStatus') self.ismaster = ismaster = self.client.admin.command('isMaster') self.sessions_enabled = 'logicalSessionTimeoutMinutes' in ismaster if 'setName' in ismaster: self.replica_set_name = str(ismaster['setName']) self.is_rs = True if self.auth_enabled: # It doesn't matter which member we use as the seed here. self.client = pymongo.MongoClient( host, port, username=db_user, password=db_pwd, replicaSet=self.replica_set_name, **self.default_client_options) else: self.client = pymongo.MongoClient( host, port, replicaSet=self.replica_set_name, **self.default_client_options) # Get the authoritative ismaster result from the primary. self.ismaster = self.client.admin.command('ismaster') nodes = [partition_node(node.lower()) for node in self.ismaster.get('hosts', [])] nodes.extend([partition_node(node.lower()) for node in self.ismaster.get('passives', [])]) nodes.extend([partition_node(node.lower()) for node in self.ismaster.get('arbiters', [])]) self.nodes = set(nodes) else: self.ismaster = ismaster self.nodes = set([(host, port)]) self.w = len(self.ismaster.get("hosts", [])) or 1 self.version = Version.from_client(self.client) if 'enableTestCommands=1' in self.cmd_line['argv']: self.test_commands_enabled = True elif 'parsed' in self.cmd_line: params = self.cmd_line['parsed'].get('setParameter', []) if 'enableTestCommands=1' in params: self.test_commands_enabled = True else: params = self.cmd_line['parsed'].get('setParameter', {}) if params.get('enableTestCommands') == '1': self.test_commands_enabled = True self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid') self.has_ipv6 = self._server_started_with_ipv6() if self.is_mongos: # Check for another mongos on the next port. address = self.client.address next_address = address[0], address[1] + 1 self.mongoses.append(address) mongos_client = self._connect(*next_address, **self.default_client_options) if mongos_client: ismaster = mongos_client.admin.command('ismaster') if ismaster.get('msg') == 'isdbgrid': self.mongoses.append(next_address)
def __init__(self): """Create a client and grab essential information from the server.""" self.connected = False self.ismaster = {} self.w = None self.nodes = set() self.replica_set_name = None self.cmd_line = None self.version = Version(-1) # Needs to be comparable with Version self.auth_enabled = False self.test_commands_enabled = False self.is_mongos = False self.is_rs = False self.has_ipv6 = False self.ssl = False self.ssl_cert_none = False self.ssl_certfile = False self.server_is_resolvable = is_server_resolvable() self.ssl_client_options = {} self.client = _connect(host, port) if HAVE_SSL and not self.client: # Is MongoDB configured for SSL? self.client = _connect(host, port, **_SSL_OPTIONS) if self.client: self.ssl = True self.ssl_client_options = _SSL_OPTIONS self.ssl_certfile = True if _SSL_OPTIONS.get('ssl_cert_reqs') == ssl.CERT_NONE: self.ssl_cert_none = True if self.client: self.connected = True ismaster = self.client.admin.command('ismaster') if 'setName' in ismaster: self.replica_set_name = ismaster['setName'] self.is_rs = True # It doesn't matter which member we use as the seed here. self.client = pymongo.MongoClient( host, port, replicaSet=self.replica_set_name, **self.ssl_client_options) # Get the authoritative ismaster result from the primary. self.ismaster = self.client.admin.command('ismaster') nodes = [partition_node(node.lower()) for node in self.ismaster.get('hosts', [])] nodes.extend([partition_node(node.lower()) for node in self.ismaster.get('passives', [])]) nodes.extend([partition_node(node.lower()) for node in self.ismaster.get('arbiters', [])]) self.nodes = set(nodes) else: self.ismaster = ismaster self.nodes = set([(host, port)]) self.w = len(self.ismaster.get("hosts", [])) or 1 self.version = Version.from_client(self.client) try: self.cmd_line = self.client.admin.command('getCmdLineOpts') except pymongo.errors.OperationFailure as e: msg = e.details.get('errmsg', '') if e.code == 13 or 'unauthorized' in msg or 'login' in msg: # Unauthorized. self.auth_enabled = True else: raise else: self.auth_enabled = self._server_started_with_auth() if self.auth_enabled: # See if db_user already exists. self.user_provided = self._check_user_provided() if not self.user_provided: roles = {} if self.version.at_least(2, 5, 3, -1): roles = {'roles': ['root']} self.client.admin.add_user(db_user, db_pwd, **roles) self.client.admin.authenticate(db_user, db_pwd) # May not have this if OperationFailure was raised earlier. self.cmd_line = self.client.admin.command('getCmdLineOpts') if 'enableTestCommands=1' in self.cmd_line['argv']: self.test_commands_enabled = True elif 'parsed' in self.cmd_line: params = self.cmd_line['parsed'].get('setParameter', []) if 'enableTestCommands=1' in params: self.test_commands_enabled = True else: params = self.cmd_line['parsed'].get('setParameter', {}) if params.get('enableTestCommands') == '1': self.test_commands_enabled = True self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid') self.has_ipv6 = self._server_started_with_ipv6()
def _all_users(db): if Version.from_client(db.client).at_least(2, 5, 3, -1): return set(u['user'] for u in db.command('usersInfo').get('users', [])) else: return set(u['user'] for u in db.system.users.find())