can i generate a mysql trigger without a definer clause? - mysql

Question is dead simple. I want to add a trigger to my database, any simple one like:
CREATE TRIGGER before_user_update BEFORE UPDATE ON `users`
FOR EACH ROW
BEGIN
SET NEW.user_id = NEW.old_user_id_column;
END
Unfortunately when i do that i always get a DEFINER clause in the dump with host and username, which is very troublesome because i need to use this on different environments on which this definer will be completely different?
Is there any workaround?
I guess this question could be asked: how to use the same query trigger in multiple environments?
(im using rails)
I know i can just remove the definer part from the schema manually, but it will cause problems to my coworkers who are going to run a migration and still get the clause in their schema

No, you cannot create a trigger without the definer clause.
As mysql documentation on create trigger says:
If the DEFINER clause is omitted, the default definer is the user who executes the CREATE TRIGGER statement. This is the same as specifying DEFINER = CURRENT_USER explicitly.
So, even if you omit the definer, mysql will give you one. So, you either create the same mysql user across the different environments or you save the trigger code with DEFINER = CURRENT_USER. Unfortunately, when you run the create trigger code, mysql will substitute the current user's name into the definer clause.

Related

SQL Trigger on database to restrict drop/alter/create syntax error, despite following tutorial, ON is not valid at this position?

Working on a security DDL trigger for a database and want to restrict non-admins from creating/dropping database, I have created this trigger and put it below all the other code (create tables etc) in the database script.
CREATE TRIGGER alert_table
ON DATABASE
FOR CREATE_TABLE, DROP_TABLE, ALTER_TABLE
AS
BEGIN
IF IS_MEMBER ('admin') = 0
BEGIN
PRINT 'Please contact your Database Admin'
ROLLBACK TRANSACTION;
END
END
GO
CREATE
Note:
USER 'admin'#'localhost'
It says "ON is not valid at that position, expecting: BEFORE or AFTER", and something similar for "END". Thanks!
You followed a tutorial for Microsoft SQL Server, commonly abbreviated as mssql server, while you are using mysql.
Mssql server has DDL triggers which syntax follows the one in your question.
Mysql's create trigger syntax is different and does not have DDL triggers at all, so you cannot use triggers to handle table creation events.

MYSQL Definer Issue

There is a very strange issue. I have one procedure with a definer named as admin.
There was a case where we had to remove the user "dbadlys". So in order to do so we updated the mysql.proc table with the new account "admin#%" before deletion of account dbadlys and did the flush privileges as well.
I also verified the definer name from information_schema.routines and I saw that new definer name is now admin#%.
Issue:
Even though the definer name was now updated to new name when the code was calling the procedure it was using the old definer name dbadlys and was giving the below error:
The user specified as a definer does not exist
Upon further investigation, I found out that when we reconnect the instance then there was no error, however if we change the definer name and try to execute the procedure again then it doesn't reflect it.
My questions:
Is there anything else which I need to do in this situation or am missing anything?
if there is nothing missing then is there a way that application should see the changes?
Should I restart the application server?
If you have dba privilege, try recreating the SP without definer.
Definers are optional, unless you have a very specific need you don't need to use them.

Restrict insert permissions on a single table in MySQL

I have a MySQL table that needs restricted permissions for INSERT.
Specifically, I have written a stored function that handles all INSERT operations, and I need to restrict permissions so ONLY this stored function is allowed to insert rows in this specific table.
"But why would you do that?"
Because MySQL doesn't support Microsoft's INSTEAD OF INSERT triggers, and a custom stored function/procedure for insertion is the only viable workaround.
And I need it to work like a trigger - guaranteed to execute for every INSERT operation, with no exceptions or loopholes.
The function returns 0 if no errors, 1 if invalid parameters, 2 if unique index collision, etc.
(Or maybe the function will include an INSERT ... ON DUPLICATE KEY UPDATE statement, I haven't decided yet.)
"But why do you need INSTEAD OF INSERT triggers?"
For the same reason that Microsoft SQL Server developers need it ... because it does the job that needs to be done ...
Specifically, because my code includes GET_LOCK before insertion, and RELEASE_LOCK after insertion ... and I don't want a BEFORE INSERT trigger to end without releasing the lock (seems like a very bad idea).
You can create MySQL stored functions (and stored procedures) including the clause SQL SECURITY DEFINER . Then, they'll run with the permissions of the definer, not the user. Your definition might look like this:
CREATE PROCEDURE proc()
SQL SECURITY DEFINER
BEGIN
INSERT INTO tbl whatever....;
END;
When you do this, log in to MySQL with an administrator's account, not a user's account.
Then use MySQL's permission system to grant INSERT access for that table to the administrator's account and revoke it for other users' accounts.
GRANT SELECT, UPDATE, INSERT, DELETE mydatabase.mytable TO admin;
REVOKE INSERT ON mydatabase.mytable FROM user1;
REVOKE INSERT ON mydatabase.mytable FROM user2;
Then, INSERT queries from other users' accounts will fail, but the stored function will succeed. This is more-or-less conventional SQL stored code privilege handling.
MySQL triggers, of any flavor, can't start or end transactions.

Can a DEFINER be a role instead of a user?

In MSSQL I'm used to using roles for security and permissions but in MySQL/MariaDB it seems that users are a staple that you can't really get around. One specific case I'm wondering about is a DEFINER on a view or stored procedure. I essentially can't script that object without knowing what user it should run as ahead of time, in my case. Is there a way to define it with a specific role instead of a user?
You can use
CREATE DEFINER=`your role` PROCEDURE / FUNCTION ()
SQL SECURITY DEFINER -- that's the default
begin
....
end
'Your role' must have execute permission for the procedure und all the privileges needed inside the procedure.

how to remove definer in mysql create trigger function or add multiple definer

currently in my mysql triggers there are delimeters and it is only limited to one account, but I have multiple account and I wan't to be able to use all of them in my trigger, so I'm wondering if you can remove a delimeter, or add multiple accounts in a delimeter