I'm running some tests and I'm trying to see if I can create a user with access to only 1 or 2 tables in my db. Does anyone know how this is done? My code below fails:
GRANT SELECT ON testdb.fruits, testdb.sports TO joe#localhost IDENTIFIED BY 'pass';
The error says I have an error in my syntax.
Run them as two individual GRANT statements:
GRANT SELECT ON testdb.fruits TO joe#localhost IDENTIFIED BY 'pass';
GRANT SELECT ON testdb.sports TO joe#localhost IDENTIFIED BY 'pass';
The MySQL GRANT syntax only permits one object in the priv_level position:, though it may use a * as a wildcard:
GRANT
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type] priv_level
TO user_specification [, user_specification] ...
[REQUIRE {NONE | ssl_option [[AND] ssl_option] ...}]
[WITH with_option ...]
object_type:
TABLE
| FUNCTION
| PROCEDURE
priv_level:
*
| *.*
| db_name.*
| db_name.tbl_name
| tbl_name
| db_name.routine_name
The part below does not appear to work on MySQL 5.5. How to "subtract" privileges in MySQL addresses why.
To grant SELECT on all tables then selectively revoke, you could do:
GRANT SELECT ON testdb.* TO joe#localhost IDENTIFIED BY 'pass';
REVOKE ALL PRIVILEGES ON testdb.tblname FROM joe#localhost;
This seems to be an odd method though, and I think I would individually GRANT rather than individually REVOKE.
You can use the mysql.tables_priv table directly:
INSERT INTO mysql.tables_priv (`Host`, `Db`, `User`, `Table_name`, `Grantor`, `Table_priv`)
VALUES
('%', DATABASE(), 'someuser', 'mytable1', CURRENT_USER, 'Select,Insert,Update,Delete'),
('%', DATABASE(), 'someuser', 'mytable2', CURRENT_USER, 'Select,Insert,Update,Delete')
After a manual update to these tables, you will need to explicitly run FLUSH PRIVILEGES query to tell MySQL to update its permissions cache (not required when using GRANT)
Related
how do I grant a new user the privilege to create a new database in MySQL
Specifically:
the database does not exist yet
I have successfuly created a new DB user account (that is not admin)
I want that non-admin user to create a new database
I do NOT want the 'admin' user to create the database and then grant privs to the database to the new user
as 'admin', I want to grant the new user the privilege to create a new database
I do not want to grant the new user any additional privileges on existing databases
This is not covered anywhere in the documentation that I can find.
Monday 2022-04-04
Update:
I created user 'scott' and then logged in as MySQL user 'admin' When I run this command
Note: The 'test' database does not yet exist
mysql>GRANT CREATE ON test.* to 'scott'#'localhost';
I get an error
==> ERROR 1410 (42000): You are not allowed to create a user with GRANT
Why do I get this error? I am not attempting to create a user, but rather grant a user access to a non-existent database (as is the approach with MySQL to grant a user privileges to create a database).
If up update the SQL statement to:
mysql>GRANT CREATE ON test.* to scott;
It runs OK
Query OK, 0 rows affected (0.07 sec)
And so now I login as user 'scott and run this statement:
mysql>create database rum;
==> ERROR 1049 (42000): Unknown database 'test'
Why do I get this error?
At this point, I am still not able to create a database as a non-admin user.
Example: grant "scott" the privilege to create the test3 database, which does not exist yet:
mysql> select user();
+----------------+
| user() |
+----------------+
| root#localhost |
+----------------+
mysql> grant create on test3.* to 'scott'#'localhost';
Query OK, 0 rows affected (0.01 sec)
Now try as scott to create the database:
mysql> select user();
+-----------------+
| user() |
+-----------------+
| scott#localhost |
+-----------------+
mysql> show grants;
+---------------------------------------------------------+
| Grants for scott#localhost |
+---------------------------------------------------------+
| GRANT USAGE ON *.* TO `scott`#`localhost` |
| GRANT ALL PRIVILEGES ON `test`.* TO `scott`#`localhost` |
| GRANT CREATE ON `test3`.* TO `scott`#`localhost` |
+---------------------------------------------------------+
mysql> create database test3;
Query OK, 1 row affected (0.00 sec)
mysql> use test3;
Database changed
MySQL has one privilege called CREATE which is for creating both databases and tables. See https://dev.mysql.com/doc/refman/8.0/en/privileges-provided.html#priv_create
You can either grant the user privilege to create a database of a specific name, or else grant them the privilege to create a database of any name, but that means they can also create other tables, either in the new database or in other existing databases. Sorry, there may not be a solution for you to allow them to create any new database without specifying the name when you grant the privilege, but then only have privilege in that database.
You are not allowed to create a user with GRANT
You did not create the user scott. Older versions of MySQL allows GRANT to implicitly create a user if one does not exist, but that has been disabled on more recent versions because folks realized it is a security weakness.
To be clear, the user "scott" is just an example I used. Don't literally use the name "scott" if that's not the user to whom you want to grant privileges.
The other errors you got seem to be that you granted the user privileges on a database named test.* but then you tried to create a database with a different name. The example I showed only grants the privilege to create the specific named database, not a database named rum or any other database.
I understand you want to grant privilege to create a database of any name. The syntax for that would be GRANT CREATE ON *.* TO... but that would grant the user privileges on all the other existing databases too.
There is no combination of syntax to grant privileges on any database name wildcard that means any database, provided that it is not yet created.
I have a user with all privileges for a specific DB in MySQL 8:
GRANT ALL PRIVILEGES ON `mydatabase`.* TO `foo`#`localhost`
I can check the grants with SHOW GRANTS FOR 'foo'#'localhost'; and I get:
+-------------------------------------------------------------+
| Grants for foo#localhost |
+-------------------------------------------------------------+
| GRANT USAGE ON *.* TO `foo`#`localhost` |
| GRANT ALL PRIVILEGES ON `mydatabase`.* TO `foo`#`localhost` |
+-------------------------------------------------------------+
Now I need to remove the DELETE grant on a specific table, so I've tried with:
REVOKE DELETE ON `mydatabase`.`mytable` FROM 'foo'#'localhost';
but I get the following error:
ERROR 1147 (42000): There is no such grant defined for user 'foo' on host 'localhost' on table 'mytable'
How can I remove the delete grant? I have to add all grants one by one (which ones are they?) and then remove the delete grant?
GRANT adds according row into privileges table.
REVOKE deletes the row with specified privilege from this table, not add another row with removing the privilege. So you can revoke only those privilege which is present in a table. Precisely.
You may:
Add separate privileges list with all privileges included into ALL PRIVILEGES except DELETE privilege on the database level
Add DELETE privilege on all tables except mytable
Remove ALL PRIVILEGES privilege
This is too complex. But correct.
Alternatively you may simplify the solution, do not use privileges system (of course this is not good practice), and forbid the deletion on the programming level using according trigger:
CREATE TRIGGER forbid_delete_for_user
BEFORE DELETE
ON mytable
FOR EACH ROW
BEGIN
IF LOCATE(USER(), 'foo#localhost,bar#localhost') THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Deletion from 'mytable' not allowed for current user.';
END IF;
END
But you must remember that cascaded foreign key actions do not activate triggers. So the user can find the way for to delete the rows from this table nevertheless.
If I grant SELECT to user I don't have a problem but if I grant SELECT to role and then grant role to user SELECT query doesn't work even though SHOW GRANTS for 'user' using 'role' shows that user has privilege to select
--as root
create role 'seller';
grant select on pharmacy.sells to 'seller';
create user 'seller1'#'localhost' identified by '1';
grant 'seller' to 'seller1'#'localhost'
--now as seller1
select * from pharmacy.sells
--Error Code: 1142. SELECT command denied to user 'seller1'#'localhost' for table 'sells'
show grants for 'seller1'#'localhost' using 'seller'
--GRANT USAGE ON *.* TO `seller1`#`localhost`
--GRANT SELECT ON `pharmacy`.`sells` TO `seller1`#`localhost`
--GRANT `seller`#`%` TO `seller1`#`localhost`
--as root
grant select on pharmacy.sells to 'seller1'#'localhost'
--as seller 1
select * from pharmacy.sells
--it works
--show grants shows the same thing
This is the user privileges:
GRANT USAGE ON *.* TO 'LMMXT'#'localhost' IDENTIFIED BY PASSWORD '*...'
GRANT ALL PRIVILEGES ON `LMMXT`.`*` TO 'LMMXT'#'localhost'
I can LOGIN with the user, USE Database, but always when I want CREATE TABLE:
# mysql -u LMMXT -p -h localhost
mysql> use LMMXT
Database changed
mysql> create table test;
ERROR 1142 (42000): CREATE command denied to user 'LMMXT'#'localhost' for table 'test'
And:
mysql> SELECT USER(),CURRENT_USER();
+---------------------+---------------------+
| USER() | CURRENT_USER() |
+---------------------+---------------------+
| LMMXT#localhost | LMMXT#localhost |
+---------------------+---------------------+
1 row in set (0.00 sec)
So, also I've tried with:
mysql> FLUSH PRIVILEGES;
User is set for host access from 'localhost' and '%'
I've seen other solutions on StackOverflow, but none works.
Thanks in advance
Try changing your grant statement to
GRANT ALL PRIVILEGES ON LMMXT.* TO 'LMMXT'#'localhost'
I'm not sure if the ` characters around the statement are causing a problem
To allow someuser to do SELECTs on mydb, I can execute the following statement:
GRANT SELECT ON mydb.* TO 'someuser'#'somehost';
Suppose that I want allow SELECTs on only two tables: event and event_detail.
I guess I can do the following:
GRANT SELECT ON mydb.event TO 'someuser'#'somehost';
GRANT SELECT ON mydb.event_detail TO 'someuser'#'somehost';
Would the following also work? (Supposing no other tables are matched)
GRANT SELECT ON mydb.event* TO 'someuser'#'somehost';
No - wildcards can only be used for entire table or database names.
You'll have to either type the grant statement for every table explicitly, or write a script or program to do it for you.
Based on the GRANT syntax:
GRANT
... priv_level ...
priv_level:
*
| *.*
| db_name.*
| db_name.tbl_name
| tbl_name
| db_name.routine_name
So I guess you can't. You can, anyway, use the INFORMATION_SCHEMA to find those tables with the name prefix you desire, and then iterate through them.