I am trying to create a query that will show the users, their roles, and their privileges in MySQL 8.0.
Users are stored in mysql.user table.
Roles are also stored in mysql.user table but in order to identify them we filter the query like this: SELECT * FROM mysql.user WHERE host = '%'AND LENGTH(AUTHENTICATION_STRING) = 0 \G. By default roles are applied globally ('%') and they have no password
so the length would be 0 (We use strong password policy so there are
no users with no password).
The privileges, can be seen by the commands: SHOW GRANTS FOR 'username'#'hostname'; and by SELECT * FROM mysql.columns_priv, SELECT * FROM mysql.procs_priv, SELECT * FROM mysql.tables_priv tables.
I don't thing that I am missing other tables with information about the privileges, I just need to join all the data together. Has anyone tried something similar like this ? Is there a simpler way?
I am currently studying MySQL, I haven't professional experience so any help would be appreciated!
Related
In PostgreSQL, for instance, the query SELECT * FROM pg_user return the usesysid column in which you can see the users IDs. So I can get the oldest/newest user from this table through this ID.
How can I do the same in Mysql and Maria DB?
I am surprised that there is no field that shows the creation date of each user in any driver.
Listing the users should be as simple as:
select * from mysql.user
Column user give you the user id. Combined with host, this is the unique identifier of each account.
Documentation for MariaDB.
Documentation for MySQL.
Please note, however, that MySQL / MariaDB do not track the date when users are created. A solution is to add a custom column to the users table that defaults to the current date:
ALTER TABLE mysql.users ADD date_created TIMESTAMP DEFAULT CURRENT_TIMESTAMP;
Starting with MariaDB 10.4.1 the source for users and privileges is mysql.global_privs see MariaDB Docu.
Users, that are authorized by password have a property password_last_changed.
That's not the creation date you are looking for but can be a hint for the age of users entries, i.e.:
| localhost | phpmyadmin | {"access":0,"version_id":100515,"plugin":"mysql_native_password","authentication_string":"xxxx","password_last_changed":1660639196} |
I have lot of users in mysql db. How do I filter users based on a certain permission?
Like I need to find all users that have CREATE or ALTER permissions.
Mysql stores use privileges in the schema named mysql.
If you want to select users who have those privileges at global or database level,
the query you are looking for is:
SELECT user, host FROM mysql.user WHERE Alter_priv = 1 OR Create_priv = 1
UNION
SELECT user, host FROM mysql.db WHERE Alter_priv = 1 OR Create_priv = 1;
MySQL store all the privileges in mysql schema and there are various tables based on what kind of privileges you would want to look for. Below are tables in which different privileges are stored.
tables_priv
columnss_priv
procs_priv
You can have a look at what privileges you can find in each of these tables over here
What is the easiest way to list all table-level and column-level privileges for a MySQL database? I need to know what level of customized access has been granted for a specific database and which users have fine-tuned access to certain tables and/or columns.
To list table level privileges, you can query the INFORMATION_SCHEMA.TABLE_PRIVILEGES table.
The TABLE_PRIVILEGES table has these columns:
GRANTEE : the name of the account to which the privilege is granted, in 'user_name'#'host_name' format.
[...]
TABLE_NAME : the name of the table.
PRIVILEGE_TYPE : The privilege granted. The value can be any privilege that can be granted at the table level; [...] . Each row lists a single privilege, so there is one row per table privilege held by the grantee.
To list column level privileges, have a look at the INFORMATION_SCHEMA.COLUMN_PRIVILEGES table.
All table/column level privileges for a specific database:
SELECT * FROM `INFORMATION_SCHEMA`.`TABLE_PRIVILEGES` WHERE TABLE_SCHEMA = 'my_database';
SELECT * FROM `INFORMATION_SCHEMA`.`COLUMN_PRIVILEGES` WHERE TABLE_SCHEMA = 'my_database';
Using pt-show-grants from percona toolkit.
The user has INSERT and DELETE permissions but not SELECT permission. The user can write records but not read. When trying to "DELETE from my_table WHERE id=5" you get "#1143 select not allowed...". Is there a way to solve this?
Privileges
You need the DELETE privilege on a table to delete rows
from it. You need only the SELECT privilege for any columns that are
only read, such as those named in the WHERE clause.
source
Conclusion : If you use a where in the Delete you need the Select privilege too.
This question was originally using MySQL 5.1.44, but is applicable to MySQL 8.0+ too.
Let's say I have a table with records inserted by different users of my application. How can I give a specific user access to only see his/her records in that table? I've thought about creating a VIEW with his/her records, but I don't know how to create a MySQL user that can only see that VIEW.
So, is it possible to create a MySQL user that only has access to a single VIEW? Can this user also be made so they read-only access to that VIEW?
Thanks!
PS: What I call users in my example are really subsidiary offices that want to access their records with their own applications.
GRANT SELECT ON database1.view1 TO 'someuser'#'somehost';
Besides
GRANT SELECT ON <database_name>.<view_name>
TO <user>#<host>
it's better to also do
GRANT SHOW VIEW
ON <database_name>.<view_name> TO <user>#<host>
so that a lot of SQL UI tool can get the view definition and work appropriately for the view.
I believe the original question is actually asking how to limit the rows to those owned by a given user. (The idea of creating one view per user, and then granting just that, seems like a workaround.)
You can do this by inserting the user() reference into the data table, and then filtering on that.
Using MySQL 5.6. Create a view that limits SELECT to just records owned by the current user:
-- check the current user
select user();
create table t1 (myId int, mydata varchar(200), myName varchar(200));
insert t1 select 1, 'my data yes', user();
insert t1 select 2, 'my data yes2', user();
insert t1 select 3, 'my data no', 'joe';
select * from t1;
create or replace view v1 AS
select * from t1 where myName = user();
select * from v1;
GRANT SELECT ON <database name>.<view name>
TO <user>#<host> IDENTIFIED BY '<password>'
Source: MySQL Documentation
If you want to make the view read only which I suspect you do. Then you should create the view with the ALGORITHM = TEMPTABLE clause.
This will make the view read only virtue of it having to create a temp table.
Another way to achieve read only and this is depends on your data is to stick an aggregate function. For example if you have a view which is based on a table and shows all columns then you can stick a distinct onto the select.