Beispiel #1
0
def get_roles(database: Database, db_user: str) -> List[Dict]:
    """
    Get all user's roles with find privileges if user exists
    Args:
        database: MongoDB DB instance
        db_user: DB user name to get roles for

    Returns: List of roles found

    """

    # usersInfo Command  returns object in shape:
    # {
    #   < some_other_keys >
    #   'users': [
    #                {
    #                    '_id': < auth_db >. < user >,
    #                    'db': < auth_db >,
    #                    'mechanisms': ['SCRAM-SHA-1', 'SCRAM-SHA-256'],
    #                     'roles': [{'db': 'admin', 'role': 'readWriteAnyDatabase'},
    #                               {'db': 'local', 'role': 'read'}],
    #                     'user': < user >,
    #                     'userId': < userId >
    #                 }
    #           ]
    # }
    user_info = database.command({'usersInfo': db_user})

    users = [u for u in user_info.get('users') if u.get('user') == db_user]
    if len(users) != 1:
        LOGGER.warning('Could not find any users for %s', db_user)
        return []

    return get_roles_with_find_privs(database, users[0])
Beispiel #2
0
def getChanges(collName: str, db: database.Database, since: datetime.datetime) -> object:
    logging.info(f"Checking for changes since: {since}")
    pipeline = [
        { "$changeStream": { "fullDocument": "updateLookup" } },
        { "$match": { "operationType": { "$in": ["insert", "update", "replace"] } } },
        { "$project": { "_id": 1, "fullDocument": 1, "ns": 1, "documentKey": 1 } }
    ]
    return db.command({ "aggregate": collName, "pipeline": pipeline, "startAtOperationTime": since })
Beispiel #3
0
def get_roles_with_find_privs(database: Database, user: Dict) -> List[Dict]:
    """
    Finds and returns all the user's roles that have find privileges.
    User is dictionary in the form:
     {
         '_id': <auth_db>.<user>,
         'db': <auth_db>,
         'mechanisms': ['SCRAM-SHA-1', 'SCRAM-SHA-256'],
         'roles': [{'db': 'admin', 'role': 'readWriteAnyDatabase'},
                   {'db': 'local', 'role': 'read'}],
         'user': <user>,
         'userId': <userId>
     }
    Args:
        database: MongoDB Database instance
        user: db user dictionary

    Returns: list of roles

    """
    roles = []

    for role in user.get('roles', []):
        if role.get('role') in ROLES_WITHOUT_FIND_PRIVILEGES:
            continue

        role_name = role['role']

        # roles with find privileges
        if role_name in ROLES_WITH_FIND_PRIVILEGES and role.get('db'):
            roles.append(role)

        # for custom roles, get the "sub-roles"
        else:
            role_info_list = database.command(
                {'rolesInfo': {
                    'role': role_name,
                    'db': database.name
                }})
            role_info = [
                r for r in role_info_list.get('roles', [])
                if r['role'] == role_name
            ]

            if len(role_info) != 1:
                continue

            roles.extend([
                sub_role for sub_role in role_info[0].get('roles', [])
                if sub_role.get('role') in ROLES_WITH_FIND_PRIVILEGES
                and sub_role.get('db')
            ])

    return roles
Beispiel #4
0
def getMoreChanges(collName: str, db: database.Database, result: object) -> object:
    return db.command({ "getMore": result['cursor']['id'], "collection": collName })
Beispiel #5
0
class DatabaseConnection(object):
    """Establishes a connection to the mongodb."""
    def __init__(self, database=None, host='localhost', port=27017):
        """
        Can be initialized without parameters.
        :param database: Str name of database.
        :param host: Host.
        :param port: Port.
        """

        self.timeout = 1
        self.host = str(host)
        if not isinstance(port, int):
            raise ValueError(
                'Entered port is "{}"! Must be integer type'.format(port))
        self.port = port
        self.client = MongoClient(host=self.host,
                                  port=self.port,
                                  serverSelectionTimeoutMS=self.timeout)
        try:
            if database is not None:
                if database in self.client.database_names():
                    self.database = Database(self.client, database)
                    if self.database.command("serverStatus")['ok'] == 1.0:
                        print('connecting to: mongodb://{}:{}'.format(
                            self.host, self.port))
                        print('database - "{}"'.format(self.database.name))
                    else:
                        pass

                else:
                    raise ValueError
            else:
                self.database = database

        except ServerSelectionTimeoutError as err:
            sys.exit('Error! {}'.format(err))
        except ValueError:
            print('"{}" is not in database names! Please check the name of '
                  'database!'.format(database))

    def use_db(self, database=None):
        """
        Switches between databases.
        :param database: Str name of database.
        """
        try:
            if database in self.client.database_names():
                self.database = Database(self.client, database)
                print('switched to db {}'.format(self.database.name))
            else:
                raise ValueError
        except ServerSelectionTimeoutError as err:
            sys.exit('Error! {}'.format(err))
        except ValueError:
            print('"{}" is not in database names! Please check the name of '
                  'database!'.format(database))

    def authenticate(self, user=None, password=None):
        """
        Authenticates the user in the connected database.
        :param user: The name of the user.
        :param password: The password.
        """
        if user is not None and password is not None:
            try:
                if user in [
                        user['user'] for user in (
                            self.database.command('usersInfo'))['users']
                ]:
                    try:
                        if self.database.authenticate(user, password):
                            self.auth = self.database.authenticate(
                                user, password)
                            print('1')
                        else:
                            raise OperationFailure
                    except OperationFailure:
                        print('Error: Authentication failed.')
                        print('0')
                else:
                    print('"{}" user is not in "{}" database users!'.format(
                        user, self.database.name))
            except AttributeError:
                print('At first you must connect to the database with use '
                      'method!')
        else:
            print('Please check entered user and password!')