Permissions error running EXPLAIN on MySQL VIEW - mysql

I have a view defined in a MySQL 5.0 database as:
CREATE OR REPLACE ALGORITHM=MERGE
DEFINER=db1_user#'%' SQL SECURITY DEFINER
VIEW db2.data_view AS SELECT * FROM db1.data_table;
This is done to give users of db2 access to this single table in db1, and works for SELECT queries:
[db2_user#db2]> select name from data_view limit 1;
+----------------+
| name |
+----------------+
| slartibartfast |
+----------------+
1 row in set (0.00 sec)
However, when I try and explain the same query, I get:
[db2_user#db2]> explain select name from data_view limit 1;
ERROR 1345 (HY000): EXPLAIN/SHOW can not be issued; lacking privileges for
underlying table
I granted the db2 user the SHOW VIEW privilege for the view, but I get the same error for EXPLAIN.
GRANT SHOW VIEW ON `db2`.`data_view` TO 'db2_user'#'%';
What is required to allow users with access to the view to run EXPLAIN on it?

You are trying to explain the query which is different than show create view. Explaining a query is same as selecting it (talking from privilege point of view), hence a select privilege shall be enough for it
GRANT select, SHOW VIEW ON `db2`.`data_view` TO 'db2_user'#'%';
explain select name from data_view limit 1;

Note that the behavior here appears to have changed between MySQL 5.0 and 5.5, as described in MySQL bug 64198.

I ran into a failure to run an EXPLAIN on a query and found the reason in the MySQL 5.7 documentation:
"The SELECT privilege is needed for tables or views used with EXPLAIN, including any underlying tables in view definitions. "
The needing SELECT permission on the underlying tables of the views was the problem for me. We wall our data off from our lower level analysts by exposing views that they have SELECT rights for but giving the analysts no rights to the underlying tables. This works well for us but makes it impossible for our analysts to use EXPLAIN to optimize their queries. Maybe some of you are running into the same problem.

Related

Is it possible to grant only metadata privileges in MySQL

TLDR;
Target:
Is it possible to grant privileges to a certain "audit" user to access to MySQL metadata only (schema,table,column at least) without access to exact data in tables?
Version
MySQL 8+
Try:
Before this issues,
I've been already tried or known:
review MySQL official docs on privileges (notice me if I missed the answer in it)
search keywords on SOF: mysql, privilege, metadata, etc.
find solutions with my DBA friends
grant show databases to users, but it could get the schema lists only
all grants to infomatica_schema was in vain, as known to all
SELECT ON *.* is another answer, but my leader dont wanna data leak through it
Background:
My company ordered devops to collect MySQL metadata for some issues of audits or security monitoring or else (I don't know the details of whole story). Unnecessary data leak would not be expected to my leader.
BTW, I dont know the specific method where they, audit depts maybe, are going to collect metadata. All I've been required to do is to create a granted user for them.
I think I found a workaround for this, but it's kind of a hack, not a true solution.
https://dev.mysql.com/doc/refman/8.0/en/show-tables.html says:
If you have no privileges for a base table or view, it does not show up in the output from SHOW TABLES or mysqlshow db_name.
That is, you can't use SHOW TABLES, or see the tables in queries against INFORMATION_SCHEMA (because SHOW TABLES is really just a query against those system views).
But the language of "no privileges" got me thinking. Is there a privilege that the user could have, but which does not allow reading or writing data?
https://dev.mysql.com/doc/refman/8.0/en/grant.html says:
The permissible priv_type values at the table level are ALTER, CREATE VIEW, CREATE, DELETE, DROP, GRANT OPTION, INDEX, INSERT, REFERENCES, SELECT, SHOW VIEW, TRIGGER, and UPDATE.
How about SHOW VIEW? This would only allow viewing metadata, not querying a table or a view.
So I tried it:
mysql> create user 'auditor'#'%';
mysql> grant show view on test.* to 'auditor'#'%';
Then I logged in as that user, and tried it:
mysql> show grants;
+----------------------------------------------+
| Grants for auditor#% |
+----------------------------------------------+
| GRANT USAGE ON *.* TO `auditor`#`%` |
| GRANT SHOW VIEW ON `test`.* TO `auditor`#`%` |
+----------------------------------------------+
mysql> use test
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| Accounts |
| Bugs |
| BugsProducts |
| BugStatus |
...
I could also view columns, etc.
To be clear, those are concrete tables, not views. But since my auditor user has more than no privileges on the tables (even an irrelevant privilege), it qualifies for purposes of letting them view metadata about the tables.
In MySQL 8.0.20, they added the SHOW ROUTINES privilege. Prior to that, you needed SELECT privilege to view the body of stored procedure or functions. But you didn't mention auditors viewing routines in your question.

How to set table level privileges in MySQL

I am trying to revoke select privilege from a particular table from a MySQL DB.
Database level restriction is working but table level is not.
When I write "show grants"
This is what I get :
| GRANT USAGE ON *.* TO 'rachit'#'localhost' IDENTIFIED BY PASSWORD '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19' |
| GRANT ALL PRIVILEGES ON `test123`.* TO 'rachit'#'localhost' |
| GRANT INSERT, UPDATE, DELETE ON `test123`.`names123` TO 'rachit'#'localhost'
As you can see above I want to
revoke select privilege from rachit user on 'names123' table of 'test123' database, but SELECT is working.
I have attached a screenshot below for better understanding.
https://ibb.co/GRtjXX7
If you GRANT ALL ON test123.* TO 'rachit'#'localhost' you cannot remove one table by running REVOKE ALL ON test123.* TO 'rachit'#'localhost'.
some DBMS systems specifically DENY option for specifically denying access to specific table but this is not the case for mysql.
you may consider to write script and give access to each table one by one
Discussion:
If it wasn't specifically GRANTed, it can't be REVOKEd. This is an unfortunate side effect of the not-so-user-friendly Grant/Revoke syntax and implementation.
You can use a SELECT against information_schema.TABLES to automate the discovery of all the other tables. And have the SELECT build the desired GRANTs.
Possible workaround:
Another approach to your particular problem is to move that one table to a different database. Then GRANT different permissions to that db.

Possible to have multiple users as DEFINER for MySQL Stored Procedure?

I'm struggling a little with MySQL stored procedures and getting a bit frustrated. I have a set of SPs created by Bob. As he is the DEFINER, only he can see the CREATE statement for them, amend them etc.
Mary can see Bob's stored procedures in the schema in MySQL Workbench, but can't see what they do - when she clicks on the SP and selects "Send to SQL Editor -> CREATE statement" nothing happens, because she's not the definer.
Coming from a MS SQL background this is a little bizarre to me. Is there any way I can set up a group (e.g. "DB_DEVS") and make this group the definer of the Stored Procs so Bob and Mary can see each other's code?
DEFINER always refers to the user who created the stored procedure. This can only be 1 user.
If Mary wants to see Bobs procedure, she could call:
SHOW CREATE PROCEDURE proc_name
To see the code of the procedure. She could also call the following to see the code:
SELECT ROUTINE_DEFINITION FROM information_schema.ROUTINES WHERE SPECIFIC_NAME='proc_name'
Heres how to enable Mary to access the view of the procedure via MySQL-Workbench:
By default, Mary is not able to send the create statement to the SQL-Editor. But this is just a privilege thing. Mary just needs a basic SELECT privilege in the mysql.proc table. To do this, run the following SQL-Statement (via Command line or directly in the Workbench):
GRANT SELECT ON mysql.proc TO 'mary'#'%'
This command enables Mary to access the Create-Statement from all hosts. If you want to limit it to a specific host you would do something like:
GRANT SELECT ON mysql.proc TO 'mary'#'192.168.2.1'
If Mary has the SELECT privilege she should be able to see the procedure after doing Send to SQL Editor -> CREATE statement
NOTE: In order to run the GRANT-Command you need to be logged in as user who has the privilege to grant privileges (e.g. root-user)
+++++++++++++++++++++++++EDIT+++++++++++++++++++++++++
There is a "quick and dirty" way to achieve this for a large number of users without writing for each user a new command to grant the privilege:
(make sure to do this with a user who has the privilege to insert rows via the Workbench)
Open a new SQL-Tab in your Workbench
Type SELECT * FROM mysql.tables_priv; and run it
Above the result-grid there should be the a small button which allows you to import data from a csv-File.
Create a CSV-File which looks like this:
%,mysql,jane,proc,root#localhost,"2016-02-19 22:51:47",Select,
%,mysql,max,proc,root#localhost,"2016-02-19 22:51:47",Select,
%,mysql,steve,proc,root#localhost,"2016-02-19 22:51:47",Select,
%,mysql,greg,proc,root#localhost,"2016-02-19 22:51:47",Select,
%,mysql,jamie,proc,root#localhost,"2016-02-19 22:51:47",Select,
...further users
jane, max, steve,... would be your users. Leave the other columns the way they are.
Import your csv-File
Run FLUSH PRIVILEGES in an SQL-Window (reloades privileges from priv-tables)
Finished! All your users can now access Stored Procedures

mysql replicate a view won't work

I am trying to replicate a specific view on mysql slave while ignoring the base table.
I have created a view that select * from a specific table on a specific DB.
In the slave my.cnf I have restricted the replication to the following:
replicate-do-db=DBNAME
replicate-ignore-table=TABLENAME
When I start the replication on the slave, I get an sql error :
Last_SQL_Error: Error 'TABLENAME 'DBNAME.TABLENAME' doesn't exist' on query. Default database: 'DBNAME'. Query: 'CREATE ALGORITHM=UNDEFINED DEFINER=`root`#`localhost` SQL SECURITY DEFINER VIEW `TABLENAMEVIEW` AS SELECT * FROM TABLENAME'
I am using mysql 5.5.1 and as per the following http://dev.mysql.com/doc/refman/5.5/en/replication-features-views.html a view can be replicated even if the table is ignored.
Any idea how I can solve this ?
Thanks,
Without the base table, the VIEW won't work. You can ignore the base table in replication so that new data doesn't come in but that table must exist for the VIEW to function.
VIEWs in MySQL are nothing more than simple aliases for SELECT statements. They are not materialized, no data is stored within, and thus execute their underlying SELECT each time you SELECT from the VIEW.

Mysql use of views across databases

I am using myISam tables ONLY for this, and have two accounts/databases named cpm155 and cpm179.
I have a group of tables in cpm155 which I have deleted (made a backup first), and then run the following queries for each one:
CREATE OR REPLACE VIEW cpm155.financial_items AS SELECT * FROM cpm179.financial_items;
CREATE OR REPLACE VIEW cpm155.financial_headers AS SELECT * FROM cpm179.financial_headers;
/* etc */
then I ran this query:
GRANT ALL PRIVILEGES ON cpm179.* TO cpm155#localhost;
GRANT ALL PRIVILEGES ON cpm155.* TO cpm179#localhost;
so you would think that there would be no permissions problems.
I have two questions:
1. should update, insert and delete operations work normally in both databases since the view->table is a one-to-one correspondence?
2. are there any other gotchas that I am missing here?
Thank you! Sam