have a security routine that, from an array of user names, passwords and permissions
- drops a user
- creates the (same) user
- grants access to tables, procedures, etc
// $users - Array of user records
// $tables - list of tables from `show tables`
// create users as necessary, reset password
foreach( $users as $user=>$arr ) {
mysql_query( "drop user {$arr['user']}" );
mysql_query( "create user {$arr['user']} identified by '{$arr['pwd']}'" );
};
// for each user set permission
foreach( $users as $user=>$arr ) {
if( @$arr['table_grant'] ) foreach( $tables as $table )
mysql_query( "grant {$arr['table_grant']} on $table to {$arr['user']}" );
if( @$arr['tables_revoke'] ) foreach( $arr['tables_revoke'] as $table )
mysql_query( "revoke {$arr['table_grant']} on $table from {$arr['user']}" );
if( @$arr['procedures_grant'] ) foreach( $arr['procedures_grant'] as $proc
mysql_query( "grant execute on procedure $proc to {$arr['user']}" );
if( @$arr['functions_grant'] ) foreach( $arr['functions_grant'] as $func )
mysql_query( "grant execute on function $func to {$arr['user']}" );
}
If no users exist, it works fine.
If users already exist, the user is there, but without the password for all but the last user created.
mysql> select user, password from mysql.user where user like 'm%'; +------------+-------------------------------------------+ | user | password | +------------+-------------------------------------------+ | massage150 | *21A196706D99436A1C8163A98AE0687C432C37E2 | | mlogin | *DE069F0ED7E311D173CB01C3DD136D282E66048D | | mselect | | | mdml | | +------------+-------------------------------------------+ 4 rows in set (0.00 sec)
Is there some sort of sync process that needs to be run in MySQL when working with users and permission? Do I need to delete them, wait a few seconds, and recreate? Or what?
(Code works fine in postgreSQL and Oracle. Some modifications were made for MySQL’s limitations with GRANT and REVOKE, viz, GRANT was made on a table by table basis (instead of SCHEMA wide) so the subsequently issued REVOKE would work correctly.)
KLUDGE Solution
After setting GRANTs and REVOKEs for users, make one more pass through the users and SET PASSWORD. Ugly, but it works.
Still looking for better understanding of what’s going on.
Correct KLUDGE Solution
As per answer below (thanks!) MySQL has a non-ANSI command FLUSH PRIVILEGES. Issued this after DROP USER and before CREATE USER and MySQL no longer dropped user password.
Try executing a FLUSH PRIVILEGES after the CREATE USER statements. Per the docs:
Worth a shot. I’ve noticed updates to the users table does not directly take effect without running this command.