Query to retrieve list of privileges in different database - mysql

Is there a query (not a stored procedure or a command) which can be executed to retrieve list of privileges for objects (Tables, Views, Stored Procedures, Functions & Triggers) and users for a particular database (require following columns -- Schema name, Object type, Object name, Permission)?
MySQL --
Tried this but require a consolidate query -- SHOW GRANTS FOR 'root'#'localhost';
Oracle --
Tried this SELECT * FROM DBA_TAB_PRIVS but it provides for tables and views only
MariaDB --
SQL --

As of Oracle (I don't know other databases; by the way, I believe you wrongly used the sql tag. It is the language, while the database you're probably talking about is named the MS SQL Server), remember that you can ask the Dictionary. For example:
SQL> select * From dictionary where lower(comments) like '%grant%';
TABLE_NAME COMMENTS
-------------------- -------------------------------------------------------
<snip>
USER_ROLE_PRIVS Roles granted to current user
USER_SYS_PRIVS System privileges granted to current user
USER_TAB_PRIVS Grants on objects for which the user is the owner, gran
tor or grantee
USER_TAB_PRIVS_MADE All grants on objects owned by the user
USER_TAB_PRIVS_RECD Grants on objects for which the user is the grantee
<snip>
20 rows selected.
SQL>
Saying that DBA_TAB_PRIVS (which displays info for the whole database; I'm running this from an ordinary user, not a DBA) shows only tables and views, well - you are wrong. It displays procedures as well. How do I know?
This is my procedure and I'll grant execute privilege to mike:
SQL> select object_name, object_type from user_procedures where object_name = 'P_TEST';
OBJECT_NAME OBJECT_TYPE
--------------- -------------------
P_TEST PROCEDURE
SQL> grant execute on p_test to mike;
Grant succeeded.
What do I see?
SQL> select grantee, owner, table_name, privilege
2 from user_tab_privs
3 where table_name = 'P_TEST';
GRANTEE OWNER TABLE_NAME PRIVILEGE
---------- ---------- -------------------- ----------
MIKE SCOTT P_TEST EXECUTE
SQL>
Here it is. So yes, you were wrong.

Related

mysql> SHOWing GRANTS for all users

Currently I perform a manual two-step procedure to get the grants information for all the users.
Step 1:
SELECT user, host FROM mysql.user;
Step 2:
SHOW GRANTS FOR '«user»'#'«host»'; -- Repeated for all user-host pairs.
Is there a single command to give me this information?
You should be able to retrieve privileges for all users from information_schema:
select grantee, group_concat(privilege_type) from information_schema.user_privileges group by grantee

Create Tables belonging to different problems with same name in oracle

I have been involved in mysql programming a bit. There we can create separate databases under the same user for different projects.e.g.(college database, hospital database) How can we achieve that in oracle sql? And I want a command line solution.I.e. sqlplus.
The problem appearing in sqlplus is that once two tables of different databases appear having the same name, error is delivered. What to do to have a different environment for each project under the same user alone?
It might be bit confusing to start with Oracle RDBMS when you got used to MySQL world.
A user in MySQL doesn't own DB objects: tables/views/etc, all DB objects belong to database. In Oracle all objects belong to schemes (synonym for user, showing that this user owns DB objects).
I want to show you different approaches in MySQL and in Oracle for the same tasks:
set current database (MySQL)/ set current schema (Oracle)
MySQL:
use db_name;
Oracle:
alter session set current_schema = schema_name;
Create fully qualified table:
MySQL:
create table db_name.table_name ...
Oracle:
create table schema_name.table_name ...
Select from another's DB/schema table
MySQL:
select * from database_name.table_name where ...
Oracle:
select * from user_owning_table.table_name where ...
So you basically want to create another Oracle schema (let's call it "hospital") for your new project:
create user hospital identified by "<password>";
create table hospital.employee( ... );
create table college.employee ( ... );
grant select, insert, update, delete on hospital.employee to human_user;
grant select, insert, update, delete on college.employee to human_user;
sqlplus human_user#your_tnsnames_alias
SQL> insert into hospital.employee(...) values(...);
SQL> insert into college.employee(...) values(...);

Allow MySQL users access to select on all views, but not tables

How do I allow users to have select access to Views only, and not any of the underlying tables?
I know how to grand permissions one at a time using a
grant select on database.viewName to 'User'
but I am trying to make either a user or a profile that have access to all views without running the grants 1 by 1 whenever a new view is created.
In Sequel Pro, under Users>Global Privileges and Schema Privileges I added "Show View" but this is not working.
This answer was verified using MySQL 8.0.23.
Make sure that your views are set to run using the credentials of the DEFINER, that way the invoking user doesn't require any TABLE privileges; not doing this will result in an error. For more details on the {DEFINER|INVOKER} parameter see here.
Create your user, allocating no privileges at all.
As root or another user with sufficient privileges, execute the following command:
GRANT SELECT ON <database>.<view_name> TO '<user>'#'<host>';
So if my database were cars and the view were called service_history, and I had a user john.doe that needed to access this from any host, I would execute the following:
GRANT SELECT ON cars.service_history TO 'john.doe'#'%';
Note how '%' was used to indicate any host is acceptable, you can replace this with an IP address, maybe a hostname (but I have not tested that).
I don't believe this is possible.
Mysql GRANT commands take the form GRANT permission ON object_type
The object_type clause, if present, should be specified as TABLE, FUNCTION, or PROCEDURE when the following object is a table, a stored function, or a stored procedure.
https://dev.mysql.com/doc/refman/5.7/en/grant.html
I don't believe there's any facility for granting permissions solely on a view.
Keep in mind that, in mysql, a view is just a query which is executed whenever you SELECT from it. It has no data storage or indexes of its own. As such, I expect you have to have access to the underlying tables in order for the view to be usable.
I will show it, might take a few edits to do it. Because I have to attach console output at the bottom.
Schema
create table users
( userId int auto_increment primary key,
userName varchar(100) not null
-- etc
);
insert users(userName) values ('Joe'),('Gertrude');
-- drop table secretdata;
create table SecretData
( id int auto_increment primary key,
userId int not null,
theKey varchar(100) not null,
theValue varchar(1000) not null,
key(userId),
CONSTRAINT fk_sd_users FOREIGN KEY (userId) REFERENCES users(userId)
);
insert secretdata(userId,theKey,theValue) values
(1,'FB Password','8*&Fjj_anchovieS'),
(1,'Proper response','I love the meal, just like I like it'),
(2,'thing7','goat');
The view
CREATE VIEW userSecrets AS
select u.userId,u.userName,s.theKey,s.theValue
from users u
join SecretData s
on s.userId=u.userId;
select * from userSecrets where userId=2; -- works here at the moment
Note my db name is so_gibberish.
The following is what you are asking about for grant rights to view:
GRANT SELECT ON so_gibberish.userSecrets TO 'john'#'host';
↑ ↑ users so provisioned can then rifle off queries against the view. ↑ ↑
however,
CREATE USER 'plebian2'#'localhost' IDENTIFIED BY 'mypass';
GRANT SELECT ON so_gibberish.userSecrets TO 'plebian2'#'localhost';
That user does have rights to use the view, but does not have access to the underlying tables directly.
Console output:
OS Prompt>mysql -u plebian2 -p
Enter password: ******
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 938
Server version: 5.6.24-log MySQL Community Server (GPL)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| so_gibberish |
+--------------------+
2 rows in set (0.00 sec)
mysql> use so_gibberish;
Database changed
mysql> show tables;
+------------------------+
| Tables_in_so_gibberish |
+------------------------+
| usersecrets |
+------------------------+
1 row in set (0.00 sec)
mysql> select * from users;
ERROR 1142 (42000): SELECT command denied to user 'plebian2'#'localhost' for table 'users'
mysql> select * from usersecrets;
+--------+----------+-----------------+--------------------------------------+
| userId | userName | theKey | theValue |
+--------+----------+-----------------+--------------------------------------+
| 1 | Joe | FB Password | 8*&Fjj_anchovieS |
| 1 | Joe | Proper response | I love the meal, just like I like it |
| 2 | Gertrude | thing7 | goat |
+--------+----------+-----------------+--------------------------------------+
3 rows in set (0.00 sec)
Lastly, I hope, see Manual Page entitled Access Control for Stored Programs and Views to see how the Definer permissions factor into the end-state effective rights. In particular, when the definer has less privileges than the user account using the view (a rather weird condition, but there it is).
Roles
In response to your comment under the Answer.
I was basically dissatisfied with the lack of roles embedded in mysql coming from the Microsoft world where they existed. Meaning, there are made-up roles, users are attached to roles, and grants are performed at the role level (in the MSFT world). There, in MSSQL, at the bottom of each create whatever block (stored proc etc), would be my block that did grants at the role level.
So coming into mysql, I had to create that role to user mapping. Good news, I only had to do it once. And the end of the chunk (if exist drop / create) that I run, it makes calls that directly manipulate the INFORMATION_SCHEMA.user_privileges and the like. But at a very high level, just like with MSFT, with the end result being what I wanted. That is, permissions granted.
That is a whole can of worms. But without it, good luck.
The commands like grant and some other commands can be performed on your own under the hood. There is little sacred about them. Yet they are there to protect novice programmers. And those that foresake those Warning Signs saying be careful are often left thinking,
"How do I get my data back. I know it's in there somewhere. Maybe I
shouldn't have done that under the hood thing I just did"
But definitely something to tinker with, especially in a throwaway db (one you don't care about). Even better, do it on a mysql instance you don't care about. Because we are talking about system wide implications at a higher level than at the db level.
I got this working by using user() as the filter on the tables and setting SQL SECURITY DEFINER, using separate schemas for views and source tables.
Example code
CREATE
ALGORITHM = UNDEFINED
DEFINER = `xxxxxx`#`%`
SQL SECURITY DEFINER
VIEW `XX`.`assets` AS
SELECT
`a`.`ID` AS `ID`,
`a`.`serial_no` AS `serial_no`,
`a`.`sys_id` AS `sys_id`,
`a`.`status` AS `status`,
`a`.`unit_name` AS `unit_name`,
`a`.`ip` AS `ip`,
`a`.`tzOffset` AS `tzOffset`
FROM
((`YY`.`Cust_Link_Table` `l`
JOIN `YY`.`systems` `s` ON ((`l`.`cust_id` = `s`.`cust_id`)))
JOIN `YY`.`assets` `a` ON ((`s`.`sys_id` = `a`.`sys_id`)))
WHERE
(`l`.`db_user` = CONVERT( LEFT(USER(), (LOCATE('#', USER()) - 1)) USING UTF8MB4))

Privilege for CREATE AGGREGATE FUNCTION

Why am I unable to create this aggregate function?
As far as I can tell, I've granted the appropriate privileges (CREATE ROUTINE and ALTER ROUTINE) both on *.* and on my database (peacock):
mysql> SELECT User, Host, Create_priv, Create_routine_priv, Alter_routine_priv FROM mysql.user WHERE user='glpy';
+------+-----------+-------------+---------------------+--------------------+
| User | Host | Create_priv | Create_routine_priv | Alter_routine_priv |
+------+-----------+-------------+---------------------+--------------------+
| glpy | localhost | Y | Y | Y |
+------+-----------+-------------+---------------------+--------------------+
mysql> SELECT User, Host, db, Create_priv, Create_routine_priv, Alter_routine_priv FROM mysql.db WHERE user='glpy';
+------+-----------+---------+-------------+---------------------+--------------------+
| User | Host | db | Create_priv | Create_routine_priv | Alter_routine_priv |
+------+-----------+---------+-------------+---------------------+--------------------+
| glpy | localhost | peacock | N | Y | Y |
+------+-----------+---------+-------------+---------------------+--------------------+
However, when I try to create the function, I get Access denied ... to database 'mysql':
mysql> use peacock;
mysql> CREATE AGGREGATE FUNCTION coverage RETURNS INT SONAME 'my-library.so';
ERROR 1044 (42000): Access denied for user 'glpy'#'localhost' to database 'mysql'
In particular:
Why is access required to the mysql table to create the aggregate function?
Given that I have granted the privileges on *.*, why is access denied?
I also tried granting the privileges on mysql, but access was still denied.
CREATE [AGGREGATE] FUNCTION function_name
RETURNS {STRING|INTEGER|REAL|DECIMAL}
SONAME shared_library_name;
This is the declaration for a User Defined Function, which appears to be what you are trying to install. This is not declaring a Stored Function. CREATE FUNCTION has two different uses in MySQL. This is one of them.
For this to work:
you do not need the CREATE ROUTINE privilege
it does not matter what database you're in, because User-Defined Functions, unlike stored functions, are global in scope. They extend MySQL functionality in a way that is analogous to its built-in aggregate functions, like AVG() and SUM() and MIN() and MAX().
you cannot specify a database as part of the function declaration
the following is the requirement that you are missing:
13.7.3.1. CREATE FUNCTION Syntax for User-Defined Functions
To create a function, you must have the INSERT privilege for the mysql database. This is necessary because CREATE FUNCTION adds a row to the mysql.func system table that records the function's name, type, and shared library name.
— http://dev.mysql.com/doc/refman/5.6/en/create-function-udf.html
If you don't have this privilege, the function will have to be installed by someone who holds this privilege, or it will need to be granted to you. You can't grant it to yourself.
From the manual:
CREATE PROCEDURE and CREATE FUNCTION require the CREATE ROUTINE privilege.
Make sure the privilege is on the database that you are trying to use. When you run CREATE AGGREGATE FUNCTION coverage RETURNS INT SONAME 'my-library.so';, you are trying to create the function in the mysql database (that is, the system database that is actually named mysql), so you need the CREATE ROUTINE privilege on that database. If you are trying to create it in some other database, run a USE my_database command or modify your syntax:
CREATE AGGREGATE FUNCTION my_database.coverage RETURNS INTEGER SONAME 'my-library.so';
If you are in a shared environment (pretty much anything other than a VPS or dedicated server), you probably don't have access to do anything to the mysql database and never will. So, create the function in your own database.
Edit: INT should be INTEGER.

MySQL: find all users with a given permission for a db

Looking for a query to find all users who have a given permission (EG execute) for a given database.
Rationale: cleaning up ancient stored procedures and want to know who might be using them.
I can imagine a plug-n-chug SP where I loop through all the values returned from "show grants for xxx" but I'm hoping there is a better way.
select * from mysql.user where `Execute_priv` = 'Y'
Replace Execute_priv with the column name of the other priviledges you're after
For privileges on a DB by DB basis, try querying the mysql.db table:
select * from mysql.db where `Db` = 'databasename' and `Execute_priv` = 'Y'