MySQL Database: Querying All Users with Access Privileges (Complete Guide for Developers)


2 views

html

Understanding MySQL User Access Control

As a database administrator or developer, knowing exactly which users have access to your MySQL databases is crucial for security and maintenance. Here's a comprehensive approach to retrieve this information.

The first place to look is the mysql.user table, which stores all user accounts and their global privileges:

SELECT User, Host FROM mysql.user;

To see which users have access to specific databases, query the mysql.db table:

SELECT User, Host, Db FROM mysql.db 
WHERE Db = 'your_database_name';

For a complete view of privileges granted to users on particular databases:

SELECT * FROM mysql.db 
WHERE Db = 'your_database_name'\G

MySQL 5.7.6+ introduced the SHOW GRANTS command which displays effective privileges:

SHOW GRANTS FOR 'username'@'host';

Here's a complete script to audit database access:

SELECT 
    u.User, 
    u.Host, 
    d.Db,
    d.Select_priv, 
    d.Insert_priv,
    d.Update_priv,
    d.Delete_priv,
    d.Create_priv,
    d.Alter_priv,
    d.Index_priv,
    d.Drop_priv
FROM 
    mysql.user u
LEFT JOIN 
    mysql.db d ON u.User = d.User AND u.Host = d.Host
WHERE 
    d.Db = 'your_database_name'
    OR (u.Select_priv = 'Y' AND u.Host = '%');

Remember that wildcard hosts ('%') and anonymous users (empty username) can affect your security posture. Always review these carefully.

For MySQL 8.0+, consider using the new roles-based privilege system and check the mysql.role_edges table for additional complexity in role assignments.



Understanding MySQL User Privileges

When administering MySQL databases, one of the fundamental security tasks is auditing which users have access to specific databases. MySQL stores privilege information in several system tables within the mysql database.

The key tables involved in storing access permissions are:

  • mysql.user - Global privileges
  • mysql.db - Database-level privileges
  • mysql.tables_priv - Table-level privileges
  • mysql.columns_priv - Column-level privileges

To find all users with access to a specific database (let's say 'inventory_db'), use:

SELECT DISTINCT User, Host 
FROM mysql.db 
WHERE Db = 'inventory_db'
UNION
SELECT User, Host 
FROM mysql.user 
WHERE Select_priv = 'Y' 
   OR Insert_priv = 'Y'
   OR Update_priv = 'Y'
   OR Delete_priv = 'Y'
   OR Create_priv = 'Y'
   OR Drop_priv = 'Y'
   OR Grant_priv = 'Y'
   OR References_priv = 'Y'
   OR Index_priv = 'Y'
   OR Alter_priv = 'Y';

For a more granular view of user permissions on a database:

SELECT 
    u.User, 
    u.Host, 
    db.Db,
    db.Select_priv,
    db.Insert_priv,
    db.Update_priv,
    db.Delete_priv,
    db.Create_priv,
    db.Drop_priv,
    db.Grant_priv,
    db.References_priv,
    db.Index_priv,
    db.Alter_priv,
    db.Create_tmp_table_priv,
    db.Lock_tables_priv,
    db.Create_view_priv,
    db.Show_view_priv,
    db.Create_routine_priv,
    db.Alter_routine_priv,
    db.Execute_priv,
    db.Event_priv,
    db.Trigger_priv
FROM 
    mysql.user u
LEFT JOIN 
    mysql.db db ON u.User = db.User AND u.Host = db.Host
WHERE 
    db.Db = 'inventory_db' OR 
    (u.Select_priv = 'Y' OR u.Insert_priv = 'Y' OR u.Update_priv = 'Y' OR u.Delete_priv = 'Y');

To see the effective privileges for a specific user (considering all privilege levels):

SHOW GRANTS FOR 'username'@'host';

Example output might look like:

GRANT USAGE ON *.* TO 'app_user'@'%' 
GRANT SELECT, INSERT, UPDATE ON inventory_db.* TO 'app_user'@'%'
GRANT EXECUTE ON PROCEDURE inventory_db.update_stock TO 'app_user'@'%'

For regular security audits, you might want to create a stored procedure:

DELIMITER //
CREATE PROCEDURE audit_database_access(IN db_name VARCHAR(64))
BEGIN
    SELECT 
        u.User, 
        u.Host,
        IFNULL(GROUP_CONCAT(DISTINCT priv.PRIVILEGE_TYPE), 'Global Privileges') AS Privileges
    FROM 
        mysql.user u
    LEFT JOIN 
        information_schema.USER_PRIVILEGES priv ON 
            CONCAT('\'', u.User, '\'@\'', u.Host, '\'') = priv.GRANTEE
    LEFT JOIN 
        mysql.db db ON u.User = db.User AND u.Host = db.Host
    WHERE 
        db.Db = db_name OR
        (priv.PRIVILEGE_TYPE IS NOT NULL AND priv.IS_GRANTABLE = 'YES')
    GROUP BY 
        u.User, u.Host;
END //
DELIMITER ;

-- Usage:
CALL audit_database_access('inventory_db');
  • Always review privileges after MySQL upgrades
  • Monitor for anonymous users (empty username)
  • Check for wildcard hosts (%)
  • Regularly review application-specific accounts