Example #1
0
 def delete(self, req, tenant_id, instance_id, id):
     LOG.info("Delete instance '%(id)s'\n"
              "req : '%(req)s'\n\n",
              {"id": instance_id, "req": req})
     context = req.environ[wsgi.CONTEXT_KEY]
     self.authorize_target_action(context, 'user:delete', instance_id)
     id = correct_id_with_req(id, req)
     username, host = unquote_user_host(id)
     user = None
     context.notification = notification.DBaaSUserDelete(context,
                                                         request=req)
     with StartNotification(context, instance_id=instance_id,
                            username=username):
         try:
             user = guest_models.MySQLUser(name=username,
                                           host=host)
             found_user = models.User.load(context, instance_id, username,
                                           host)
             if not found_user:
                 user = None
         except (ValueError, AttributeError) as e:
             raise exception.BadRequest(_("User delete error: %(e)s")
                                        % {'e': e})
         if not user:
             raise exception.UserNotFound(uuid=id)
         models.User.delete(context, instance_id, user.serialize())
     return wsgi.Result(None, 202)
Example #2
0
    def _create_replication_user(self):
        replication_user = None
        replication_password = utils.generate_random_password(16)

        mysql_user = None  # cache the model as we just want name validation

        retry_count = 0

        while replication_user is None:
            try:
                name = 'slave_' + str(uuid.uuid4())[:8]
                if mysql_user:
                    mysql_user.name = name
                else:
                    mysql_user = models.MySQLUser(
                        name=name, password=replication_password
                    )
                    mysql_user.check_create()
                MySqlAdmin().create_user([mysql_user.serialize()])
                LOG.debug("Trying to create replication user " +
                          mysql_user.name)
                replication_user = {
                    'name': mysql_user.name,
                    'password': replication_password
                }
            except Exception:
                retry_count += 1
                if retry_count > 5:
                    LOG.error("Replication user retry count exceeded")
                    raise

        return replication_user
Example #3
0
 def _get_user(self, username, hostname):
     """Return a single user matching the criteria."""
     user = None
     try:
         # Could possibly throw a ValueError here.
         user = models.MySQLUser(name=username)
         user.check_reserved()
     except ValueError as ve:
         LOG.exception(_("Error Getting user information"))
         err_msg = encodeutils.exception_to_unicode(ve)
         raise exception.BadRequest(
             _("Username %(user)s is not valid"
               ": %(reason)s") % {
                   'user': username,
                   'reason': err_msg
               })
     with self.local_sql_client(self.mysql_app.get_engine()) as client:
         q = sql_query.Query()
         q.columns = ['User', 'Host']
         q.tables = ['mysql.user']
         q.where = [
             "Host != 'localhost'",
             "User = '******'" % username,
             "Host = '%s'" % hostname
         ]
         q.order = ['User', 'Host']
         t = text(str(q))
         result = client.execute(t).fetchall()
         LOG.debug("Getting user information %s.", result)
         if len(result) != 1:
             return None
         found_user = result[0]
         user.host = found_user['Host']
         self._associate_dbs(user)
         return user
Example #4
0
    def update_attributes(cls, context, instance_id, username, hostname,
                          user_attrs):
        load_and_verify(context, instance_id)
        client = create_guest_client(context, instance_id)

        user_changed = user_attrs.get('name')
        host_changed = user_attrs.get('host')

        user = user_changed or username
        host = host_changed or hostname

        validate = guest_models.MySQLUser(name=user, host=host)
        validate.check_reserved()

        userhost = "%s@%s" % (user, host)
        if user_changed or host_changed:
            existing_users, _nadda = Users.load_with_client(
                client,
                limit=1,
                marker=userhost,
                include_marker=True)
            if (len(existing_users) > 0 and
                    existing_users[0].name == user and
                    existing_users[0].host == host):
                raise exception.UserAlreadyExists(name=user,
                                                  host=host)
        client.update_attributes(username, hostname, user_attrs)
Example #5
0
 def load(cls, context, instance_id, username, hostname, root_user=False):
     load_and_verify(context, instance_id)
     validate = guest_models.MySQLUser(name=username, host=hostname)
     if root_user:
         validate.make_root()
     validate.check_reserved()
     client = create_guest_client(context, instance_id)
     found_user = client.get_user(username=username, hostname=hostname)
     if not found_user:
         return None
     database_names = [{
         'name': db['_name']
     } for db in found_user['_databases']]
     return cls(found_user['_name'], found_user['_host'],
                found_user['_password'], database_names)
Example #6
0
 def update_all(self, req, body, tenant_id, instance_id):
     """Change the password of one or more users."""
     LOG.info(
         _("Updating user password for instance '%(id)s'\n"
           "req : '%(req)s'\n\n") % {
               "id": instance_id,
               "req": strutils.mask_password(req)
           })
     context = req.environ[wsgi.CONTEXT_KEY]
     self.authorize_target_action(context, 'user:update_all', instance_id)
     context.notification = notification.DBaaSUserChangePassword(
         context, request=req)
     users = body['users']
     model_users = []
     with StartNotification(context,
                            instance_id=instance_id,
                            username="******".join(
                                [user['name'] for user in users])):
         for user in users:
             try:
                 mu = guest_models.MySQLUser(name=user['name'],
                                             host=user.get('host'),
                                             password=user['password'])
                 found_user = models.User.load(context, instance_id,
                                               mu.name, mu.host)
                 if not found_user:
                     user_and_host = mu.name
                     if mu.host:
                         user_and_host += '@' + mu.host
                     raise exception.UserNotFound(uuid=user_and_host)
                 model_users.append(mu)
             except (ValueError, AttributeError) as e:
                 raise exception.BadRequest(
                     _("Error loading user: %(e)s") % {'e': e})
         try:
             models.User.change_password(context, instance_id, model_users)
         except (ValueError, AttributeError) as e:
             raise exception.BadRequest(
                 _("User password update error: "
                   "%(e)s") % {'e': e})
     return wsgi.Result(None, 202)
Example #7
0
def populate_users(users, initial_databases=None):
    """Create a serializable request containing users."""
    users_data = []
    unique_identities = set()
    for user in users:
        u = guest_models.MySQLUser(name=user.get('name', ''),
                                   host=user.get('host', '%'))
        u.check_reserved()
        user_identity = (u.name, u.host)
        if user_identity in unique_identities:
            raise exception.DatabaseInitialUserDuplicateError()
        unique_identities.add(user_identity)
        u.password = user.get('password', '')
        user_dbs = user.get('databases', '')
        # user_db_names guaranteed unique and non-empty by apischema
        user_db_names = [user_db.get('name', '') for user_db in user_dbs]
        for user_db_name in user_db_names:
            if (initial_databases is not None and user_db_name not in
                    initial_databases):
                raise exception.DatabaseForUserNotInDatabaseListError(
                    user=u.name, database=user_db_name)
            u.databases = user_db_name
        users_data.append(u.serialize())
    return users_data
Example #8
0
    def list_users(self, limit=None, marker=None, include_marker=False):
        """List users that have access to the database."""
        '''
        SELECT
            User,
            Host,
            Marker
        FROM
            (SELECT
                User,
                Host,
                CONCAT(User, '@', Host) as Marker
            FROM mysql.user
            ORDER BY 1, 2) as innerquery
        WHERE
            Marker > :marker
        ORDER BY
            Marker
        LIMIT :limit;
        '''
        LOG.debug("---Listing Users---")
        ignored_user_names = "'%s'" % "', '".join(cfg.get_ignored_users())
        LOG.debug(
            "The following user names are on ignore list and will "
            "be omitted from the listing: %s", ignored_user_names)
        users = []
        with self.local_sql_client(self.mysql_app.get_engine()) as client:
            iq = sql_query.Query()  # Inner query.
            iq.columns = ['User', 'Host', "CONCAT(User, '@', Host) as Marker"]
            iq.tables = ['mysql.user']
            iq.order = ['User', 'Host']
            innerquery = str(iq).rstrip(';')

            oq = sql_query.Query()  # Outer query.
            oq.columns = ['User', 'Host', 'Marker']
            oq.tables = ['(%s) as innerquery' % innerquery]
            oq.where = [
                "Host != 'localhost'",
                "User NOT IN (" + ignored_user_names + ")"
            ]
            oq.order = ['Marker']
            if marker:
                oq.where.append(
                    "Marker %s '%s'" %
                    (INCLUDE_MARKER_OPERATORS[include_marker], marker))
            if limit:
                oq.limit = limit + 1
            t = text(str(oq))
            result = client.execute(t)
            next_marker = None
            LOG.debug("result = %s", str(result))
            for count, row in enumerate(result):
                if limit is not None and count >= limit:
                    break
                LOG.debug("user = %s", str(row))
                mysql_user = models.MySQLUser(name=row['User'],
                                              host=row['Host'])
                mysql_user.check_reserved()
                self._associate_dbs(mysql_user)
                next_marker = row['Marker']
                users.append(mysql_user.serialize())
        if limit is not None and result.rowcount <= limit:
            next_marker = None
        LOG.debug("users = %s", str(users))

        return users, next_marker
Example #9
0
 def _empty_user(self):
     return models.MySQLUser(deserializing=True)