MySQL: How do I lock individual rows in a table? - mysql

To increase the security of the app I'm working on, I want to be able to protect against any sort of db modification. I know I can lock entire tables from mysql users, but what about individual rows?
Would I still be able to add new rows to the table? maybe for just one particular table, only the SELECT and INSERT commands are allowed?

It sounds like you want to permit inserting new rows and querying existing rows, but you do not want to permit updating or deleting rows. If that is correct, then you'll want to create a MySQL user that has only INSERT and SELECT privileges on the table(s) in question. Do not grant UPDATE and DELETE privileges.
To grant INSERT and SELECT privileges to user foo on my_table:
GRANT SELECT, INSERT ON my_table TO 'foo'#'localhost';
To revoke UPDATE and DELETE privileges from user foo on my_table:
REVOKE UPDATE, DELETE ON my_table FROM 'foo'#'localhost';

This would be "Row level security". MySQL doesn't have it, so you'd need to implement yourself.
For example, an "AddedBy" column can be used to restrict data changes to other members in the same group. Of course, if the Addedby user changes group you have to track this
To restrict allow INSERT and SELECT only, just GRANT these permissions.
Otherwise, please add more use cases

You could use a specific database users for your application with limited rights (No INSERT, DELETE) for the desired tables.

Related

Is there a way to make a specific column in MySQL only allow INSERT, but not UPDATE or DELETE?

For example, I have a table called stuff and it has a column called name.
I want my users to be able to INSERT into the name column, but not UPDATE or DELETE.
I know I can control this from the middle-tier business logic code, but is there some way to also prevent this at the MySQL database level for extra security?
I did see an old answer on SO about triggers but it's from 2013 and is probably out of date. I'm looking for a MySQL 8 answer.
A possible solution is to implement permissions on users or groups:
https://dev.mysql.com/doc/refman/8.0/en/grant.html#grant-column-privileges
GRANT SELECT (col1), INSERT (col1, col2) ON mydb.mytbl TO 'someuser'#'somehost';
So you your case it would be something like:
REVOKE ALL PRIVILEGES on mydb.stuff to 'userorgroup'#'somehost'
GRANT INSERT(name) ON mydb.stuff TO 'userorgroup'#'somehost'

MySQL - 'Drop User' vs 'delete from user'

I need to delete database access from some hosts. There are two options:
This option appears to be the best as I don't need to delete individual users
use mysql;
delete from user where host='myhost';
In second option below, I need to delete individual users.
drop user 'user1'#'myhost';
drop user 'user2'#'myhost';
drop user 'user3'#'myhost';
Any idea what is the difference between these options? Any pro and cons?
Thanks
When you use DROP USER Statement it removed one/more accounts + their accounts privileges.
When you use DELETE User it's just an SQL command which effects for table(s).
DROP is always more powerful than delete
Or You can use REVOKE to remove all permeation granted
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'user'#'myhost';
Privileges are
ALL PRIVILEGES – grants all privileges to the MySQL user
CREATE – allows the user to create databases and tables
DROP - allows the user to drop databases and tables
DELETE - allows the user to delete rows from specific MySQL table
INSERT - allows the user to insert rows into specific MySQL table
SELECT – allows the user to read the database
UPDATE - allows the user to update table rows
Read More about DROP USER Statement
Modifying the database tables requires a flush privileges call to refresh the cached data. Also, you have to make sure that you manually delete all user AND privileges (e.g., for tables, columns) manually.
Grant/drop user work immediately.
Cf. https://dev.mysql.com/doc/refman/8.0/en/privilege-changes.html

How to do with INSERT but deny updating some column in MySQL?

I am using MySQL 5.6 under Linux.
I have a table of 3 columns (COLUMN1, COLUMN2 and COLUMN3) where COLUMN3 is a 1-char column containing confirmation information Y or N (default is N).
I want to implement a simple maker-checker mechanism.
I want to have STOCKING department staff to have INSERT privilege to add new records. Then, they can input COLUMN1 and COLUMN2. They should NOT change the value of COLUMN3.
Then, the ACCOUNTING department staff to have UPDATE privilege on COLUMN3 to update it from N to Y.
However, I found out that, once the new record is inserted, the STOCKING staff can UPDATE the COLUMN3. Actually, I do not want them to be able to change it. It should still be using the default value N after the insert.
It seems to me that, once inserting the new records, the user can do everything on every columns of the new record.
The REVOKE action in MySQL cannot help in this situation.
Look like that there is no DENY UPDATE mechanism in MySQL.
Does anyone have similar experience and share a way of how to do so ?
Thanks in advance
You might have known about GRANT statement. Since you have not talked about how you are 'granting' the privileges to your department, I am assuming you might be providing entire database privileges.
There are many privileges you can assign using GRANT statement like Database Privileges, Column Privileges etc. Your requirement shows that you need to assign column privileges which can be done as follows:
GRANT SELECT (col1), INSERT (col1,col2) ON mydb.mytbl TO 'someuser'#'somehost';
which will only give INSERT privileges to the user and not update.

MySql: Restrict update permission on one column in one table

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

Write once, read many mysql field

Can you restrict a field from being updated without granting any additional user privileges ?
Basically a value in a row can only be set during an insert statement.
Yes. If you grant only insert and select privileges. Like:
grant select, insert, update(message, time) on hibtest.message to 'worm'#'localhost' identified by 'worm'
... this way the user can only update message and time columns.
You can use an update trigger to prevent the value from being updated.
Mysql differentiate between insert privileges and update privileges, which would give a user the option to insert, but not update later on.
see this link: http://dev.mysql.com/doc/refman/5.5/en/privileges-provided.html
Not an exact fit for your question: If you run mysqlisampack on the table, the table will become read-only.
This is good if you have a datawharehouse that is reference only, but not good if you just want to make a "live" column read-only.