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.
Related
In simplification, I have a MySQL procedure get_data(), which selects filtered data for users. Customized filter conditions are stored in database table. Procedure get_data() should gets conditions for current user and select only his data by adding a WHERE clause.
But when I defined procedure with SQL SECURITY DEFINER characteristic, detection current user (invoker) in procedure body is not possible because function current_user() returns definer's name, and when I defined procedure with SQL SECURITY INVOKER characteristic, the procedure failed because invoker haven't SELECT privileges on source table.
Is it possible to create a procedure in MySQL, which selects customized data for user from table not accessible for user?
Currently, I have defined views (one for each user), but the maintenance of this in a situation where conditions in queries are constantly changing is hard.
Have you tried using user() instead of current_user()?
i have two databases, db1 and db2.
User man1 had all privileges to db1 but only executing provileges for all functions and procedures in db2.
Calling function db2.getValue from db1 is successful and returns correct values, also if call for db2.getValue is nested in a stored procedure.
Now i create a stored Procedure proc1 and within this procedure i use a cursor to fetch values (_val1, _val2,--) from a table in db1 and call db2.getValue(_val1).
Now somthing really strange happens:
The first loop from the cursor finish, but the value from db2.getValue is empty. At the end of this loop, the loop ends and stops.
Does anyone have a hint where the problem could be here? Calling db1.getValue(_val1) instead of db2.getValue(_val1) works fine.
Therefore my idea was that within the cursor, the privileges for db2 might be not the same?
Kind Regards Solick
Yes, by design, a cursor can behave differently than the same SELECT query might behave if it were executed by the user who called the procedure.
Stored programs and views are defined prior to use and, when referenced, execute within a security context that determines their privileges. These privileges are controlled by their DEFINER attribute, and, if there is one, their SQL SECURITY characteristic.
— http://dev.mysql.com/doc/refman/5.6/en/stored-programs-security.html
If you don't specify a DEFINER when you create a stored program (proc, function, trigger, or event) or a view, then the object, when accessed, runs with the privileges of the user who originally defined it, not the user who invoked it.
You have three options, here:
Verify or possibly modify the permissions of the current DEFINER user if appropriate; or,
Specify a different DEFINER user when defining the stored program or view... you can do this as long as you (the person creating the object) have the SUPER privilege, and users invoking (accessing) the object will temporarily have the rights of that DEFINER user instead; or,
Add SQL SECURITY INVOKER to the definition of procedures, functions, and views (though not triggers or events), causing the object to run with the privileges of the user who invoked it, instead of the definer, which is the default behavior.
To see the permissions the existing definer has, for example if you see DEFINER=`someguy`#`localhost`:
mysql> SHOW GRANTS FOR 'someguy'#'localhost';
You can find the current definer in the definition of the procedure, with SHOW CREATE PROCEDURE procedure_name;.
I create my database and user navid in my shared server with cpanel (databases -> mySQL# Databases -> add new user),and then selected ALL PRIVILEGES for user navid.
I was importing mydatabase.sql when I was confronted with this error.
how do i fix the error? store procedure worked fine in localhost.
what is SUPER privilege?
Error
SQL query:
DELIMITER $$--
-- Procedures
--
CREATE DEFINER = `navid`#`%` PROCEDURE `d_answer` ( OUT `sp_out` INT( 11 ) , IN `sp_id` INT( 11 ) ) NO SQL BEGIN DELETE FROM `tblname` WHERE `a_id` = sp_id;
SET sp_out = ROW_COUNT( ) ;
END$$
MySQL said: Documentation
#1227 - Access denied; you need (at least one of) the SUPER privilege(s) for this operation
From the documentation (my emphasis):
The SUPER privilege enables an account to use CHANGE MASTER TO, KILL
or mysqladmin kill to kill threads belonging to other accounts (you
can always kill your own threads), PURGE BINARY LOGS, configuration
changes using SET GLOBAL to modify global system variables, the
mysqladmin debug command, enabling or disabling logging, performing
updates even if the read_only system variable is enabled, starting and
stopping replication on slave servers, specification of any account
in the DEFINER attribute of stored programs and views, and enables
you to connect (once) even if the connection limit controlled by the
max_connections system variable is reached.
Since you are already navid to the database, you do not need to set the DEFINER attribute in your stored procedure; adding this line is causing the error to show up. If you remove this statement, your procedure will be created and you won't get the permissions error.
You only need to set DEFINER if you are setting up the stored procedure for some other user, by default the stored procedure gets the same security context as the user that is creating it:
All stored programs (procedures, functions, and triggers) and views
can have a DEFINER attribute that names a MySQL account. If the
DEFINER attribute is omitted from a stored program or view definition,
the default account is the user who creates the object.
I got the problem too and fixed it thus in MySQL Workbench.
In my case it is because the "Send to SQL Editor > Create Statement" has extra stuff in there that prevents from being used without modification.
Something like this:
CREATE ALGORITHM=UNDEFINED DEFINER=schemax#localhost SQL
SECURITY DEFINER VIEW viewName AS SELECT ....
Change it to this:
CREATE VIEW viewName AS SELECT ....
Seems to work now, no need to update permissions.
**I am the only user of my database..
I had the same issue - on my local dev server it was fine but on my hosted server (through PHPMyAdmin) it gave me the above error.
Removing the definer attribute seemed to be the easiest way to fix the problem if you're happy with the definer being the current user.
just remove the DEFINER attribute and with it's value, example:
CREATE ALGORITHM=UNDEFINED SQL SECURITY DEFINER VIEW ...
Don't rely on default values, if emptying the definer field in phpMyAdmin or other programs won't solve, check the definer, should not be username#localhost unless explicitly needed, but username#%.
I want to store the activity of each session user at very high level into a table.
I wrote a procedure "audit.login_trigger". I have created the schema needed(audit DB and Table). It is some thing like this.
CREATE PROCEDURE audit.login_trigger()
SQL SECURITY DEFINER
BEGIN
INSERT INTO audit.audit_connect (thread_id, user, login_ts)
VALUES (CONNECTION_ID(), USER(), NOW());
END;
I have place this inside "init_connect".
SET GLOBAL init_connect="CALL audit.login_trigger()";
I want this to be executed for every user connection. I gave EXECUTE privileges on this PROCEDURE to root user but when the root user logged in, it is not populating the audit schema as expected. What might went wrong here ?
Thanks in advance.
Since this user is named "root" I wonder if it has super privileges. If it does, then note that init_connect doesn't fire for super users.
I've written all of MySQL procedures as root#localhost:
CREATE DEFINER=`root`#`localhost` PROCEDURE `p_add_user`(...)
Trouble is, when deploying to another server, I have to replace root with current user and replace localhost with current IP, which is annoying.
Is there any way to write procedures so that someone who wants to use my database and procedures would not have to modify the definer of each procedure?
As stated in MySQL documentation here
CREATE
[DEFINER = { user | CURRENT_USER }]
PROCEDURE sp_name ([proc_parameter[,...]])
[characteristic ...] routine_body
So, the DEFINER part is not mandatory, just CREATE PROCEDURE should work.
[EDIT: updated ref page]
You can specify execution privileges by adding the following statement in the procedure body (after declaration):
SQL SECURITY INVOKER
Example:
CREATE DEFINER=`root`#`localhost` PROCEDURE `p_add_user`()
SQL SECURITY INVOKER
(...)
Doing so, the actual invoker privileges are applied and the DEFINER part is omitted (even when it is auto-added during schema import).
Full reference here:
https://dev.mysql.com/doc/refman/5.7/en/stored-objects-security.html
CREATE DEFINER=[your_web_user]#% PROCEDURE p_add_user(...)
Check it.. probably this will help you, if you want to define the user in your procedure...