Grant INSERT without having it.
Suppose the following code snippet is executed every time a new manager is created (with different names for the database and user account each time, of course):
#Executed as root
CREATE DATABASE `Manager1Section`;
CREATE TABLE Manager1Data(`SomeData` INT);
CREATE USER 'Manager1'#'localhost' IDENTIFIED BY 'Something';
GRANT SELECT, INSERT, UPDATE, DELETE ON `Manager1Section`.`Manager1Data` TO 'Manager1'#'localhost';
GRANT CREATE, DROP ON `Manager1Section`.* TO 'Manager1'#'localhost';
GRANT CREATE USER ON *.* TO 'Manager1Section'#'localhost' WITH GRANT OPTION;
And the following code is executed every time a new intern is created (again, names substituted):
#Executed as manager
CREATE TABLE `Manager1Section`.`Intern1Data`(`Value` INT NOT NULL);
CREATE USER 'Intern1'#'localhost' IDENTIFIED BY 'Something';
GRANT SELECT, INSERT, UPDATE, DELETE ON `Manager1Section`.`Intern1Data` TO 'Intern1'#'localhost';
(Mind that this is just an example to show the hierarchical structure. I am not actually modeling a company's personnel structure.)
The manager manages a single database (Manager1Section in this example) and has a table to work with. The manager can only read and write to that table but not e.g. drop it. (Actually nevermind, I just realized that the manager can, in fact, drop the table. Not a big deal though.).
Each intern in this database also has a table to work with, and again, can only read and write to it but not drop it. Additionally, interns can only access their own tables, but not the manager's table and not other interns' tables.
And very importantly: The manager cannot read and write to interns' tables.
The above code would achieve this, but it is not valid. The last line in the second snippet fails. The manager does not have the SELECT, INSERT, UPDATE and DELETE privileges to interns' tables and therefore cannot grant those privileges to the interns. Changing the second-to-last line in the first snippet (GRANT CREATE, DROP ON `Manager1Section`.* TO 'Manager1'#'localhost';) to GRANT CREATE, DROP, SELECT, INSERT, UPDATE, DELETE ON `Manager1Section`.* TO 'Manager1'#'localhost'; makes that work but it also allows the manager to read and write to interns' tables, which I want to avoid.
How can I make the manager not able to read and write to interns' tables but still grant read and write privileges to interns?
Or alternatively: How can I avoid that problem altogether?
Only allowing users to grant privileges they already have is generally a good idea and my gut feeling tells me that my intended solution is not possible because the manager could circumvent the situation by creating a spoof intern account, executing GRANT SELECT, INSERT, UPDATE, DELETE ON `Manager1Section`.`Intern1Data` TO 'SpoofIntern'#'localhost'; (mind the mismatched user names) and then access the data through that account. But I could be missing something, so I am asking for ideas.
Related
I am building a database for students. I want the students to be able to perform any action on the database, create tables etc. I do not want them to delete the master table.
So far, I granted them almost all the permissions using this grant
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, RELOAD,
PROCESS, REFERENCES, INDEX, ALTER, SHOW DATABASES,
CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE,
REPLICATION SLAVE, REPLICATION CLIENT, CREATE VIEW, SHOW VIEW,
CREATE ROUTINE, ALTER ROUTINE, CREATE USER, EVENT, TRIGGER
ON *.*
TO 'mta_student'#'%' WITH GRANT OPTION
However, how can I keep them from interfering with master_table I have?
a data table?
You can't revoke a specific privilege that hasn't been granted specifically. In this case, you haven't granted access per table, so you can't revoke access per table.
The only way to accomplish what you describe is to locate your master_table in a separate schema:
create schema main;
rename table master_table to main.master_table;
Then grant your students privileges on other schemas, but not the main schema.
grant ... on student_schema.* to 'mta_student'#'%';
I have a table, lets call it student, in a schema called enrollment. Table student has a column called address that I don't want a certain user to update (other permissions are fine such as select, insert). All other columns in that table AND in that schema should have the update privilege.
Is this doable?
You can set privileges on database / table / column. But I really would not try to use MySQL's privilege mechanism at that level. I would instead write application code to decide who can see/change what. This is more flexible in the long run. And more graceful to the user -- instead of getting a cryptic MySQL error message about permissions, the UI would simply not show what should not be shown. For updating, the UI would not even give the user the option.
In my case, I wanted a specific application to be able to update only 1 field (my_field) in only 1 table (table_name) while being able to read the entire database.
I created a special user for that purpose:
CREATE USER 'restrictedUser'#'%' IDENTIFIED BY 'PASSWORD_HERE';
SET PASSWORD FOR 'restrictedUser'#'%' = PASSWORD('PASSWORD_HERE');
GRANT USAGE ON *.* TO 'restrictedUser'#'%';
GRANT SELECT ON DATABASE_NAME.* TO 'restrictedUser'#'%';
GRANT UPDATE (my_field) ON DATABASE_NAME.table_name TO 'restrictedUser'#'%';
Documentation for Column privilege can be found here for mariaDb and here for mysql
I recently tried this in MySQL 5.5.x:
GRANT
SELECT, INSERT, UPDATE, DELETE, TRUNCATE ON crawler.*
TO 'my_user'#'localhost' WITH GRANT OPTION;
This results in an error:
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'TRUNCATE ON crawler.*
TO 'my_user'#'localhost' WITH GRANT OPTION' at line 2
This used to work before I added TRUNCATE, so after a bit of research I find that this is not supported in MySQL.
The reason for this is that TRUNCATE is classified as a DDL operation, and so it doesn't use DELETE internally, it uses DROP. Alright, so I'd like to restrict this user to dropping tables (in the event of a security breach, at least a malicious user would have to determine the names of tables and drop them individually).
However, it turns out I would need to grant this user the DROP privilege, which allows the user to drop whole databases too. Given that there is not a grant for individual tables, is there another way to do this? I suppose I could hand this off to another process with a different user, but it feels a bit cumbersome for such a small issue.
For the time being, I'll stick with DELETE, even though it is rather slow! (On my laptop it takes ~55 sec to delete 1.6M small rows, and a fraction of a second to truncate the same). However, I am all ears if there is a faster and secure alternative.
To grant DROP privilege on a specific table in a specific database to a specific user in MySQL, you can use a GRANT statement like this. (This assumes that table fi exists in database fee, and this is the table you want to allow the user 'fo'#'%' to be able to TRUNCATE):
GRANT DROP ON TABLE fee.fi TO 'fo'#'%'
To see that the user has privilege to truncate that specific table:
SHOW GRANTS FOR 'fo'#'%' ;
And connect as user 'fo'#'%' to test:
TRUNCATE TABLE fee.fi ;
(Obviously, the user also has the privilege to DROP that same table. But that's just the way it is in MySQL.)
As an alternative, to allow the user to perform only the TRUNCATE operation on that specific table, without granting the user DROP privilege on the table...
create a stored procedure that performs a TRUNCATE fee.fi; (That will probably need to be executed dynamically since it's DDL.) The procedure will need to be created with DEFINER privileges, and created by a user that has the required privileges.
Then you can grant execute on the procedure to the user:
GRANT EXECUTE ON fee.truncate_table_fee_fi TO 'fo'#'%';
Then user 'fo'#'%' can
CALL fee.truncate_table_fee_fi
I talked to the developer of HeidiSQL about it and he told me I can query it by "show grants" command of sql, but i don't understand the result set coming from it.
show grants // I execute query here
GRANT USAGE ON . TO 'fsdb1user1'#'%' IDENTIFIED BY PASSWORD
'something'
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP,
REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES ON
fsdb1.* TO 'fsdb1user1'#'%'
mysql documentation says
SHOW GRANTS displays only the privileges granted explicitly to the
named account. Other privileges might be available to the account, but
they are not displayed. For example, if an anonymous account exists,
the named account might be able to use its privileges, but SHOW GRANTS
will not display them.
I think there might be some software somewhere trying some queries and checks grants that way.
It appears that this user is allowed to do a lot. Here is actually a good reference on all of these http://dev.mysql.com/doc/refman/5.1/en/grant.html#grant-privileges.
The user in question can run SELECT, UPDATE, and DELETE queries. They can CREATE tables and databases. They can DROP tables, databases, and views. They can create and alter INDEXes. They can ALTER table structures. They can use CREATE TEMPORARY TABLE. And finally, they can LOCK TABLES that they have SELECT privileges on. In this case, the user can do this on any table in this database (fsdb1) and from any host.
grant LOCK TABLES, SELECT,ALTER,INSERT,CREATE ON `databasetoupgrade%`.* to 'someuser'#'localhost';
those are the privileges I gave a users that needs to be able to ALTER a table (add columns, ...)
the mysql documentation states that alter, insert, create is needed, but even with lock tables and select permissions, I still get the error that the user does not have enough permissions to do ALTER.
When I give the user all privileges on those tables/databases is works.
Does anyone know what the EXACT privileges are that I need to do ALTER? Of which one did I forget in the list above?
This post can be closed, this fixed it:
grant ALTER, LOCK TABLES, SELECT, INSERT, CREATE
I might have screwed up somewhere in my previous commands...
These grants now work fine (for backups) + ALTER command:
grant ALTER, LOCK TABLES, SELECT, INSERT, CREATE