MySQL: What effect does DEFINER have on procedures and functions? - mysql

I use SQLyog to write procedures and functions in a remote MySQL database I am developing. The database has only one username/password. It is accessed via a front end executable application that I have written in Delphi and which is used by a couple of dozen different people, all using the same username.
When I use SQLYog to write a procedure using, for example,
CREATE PROCEDURE age_frequency_count(IN bin_size INT)
The resulting procedure gets the definer put in whether I like it or not, resulting in
CREATE DEFINER=<the_user_name>#<my_IP_address> PROCEDURE age_frequency_count(IN bin_size INT)
(I think this is being done by MySQL, not by the SQLYog DBMS.)
From reading the documentation and from posts here on SO, I have a rough, but rather confused idea of how the definer is used to say what permissions are needed to execute, or maybe alter, the procedure and what the procedure is allowed to do, but I would welcome some clarification.
Question
If my IP address is in the definer, can the procedure still be executed by other people who will be logging in from a different IP address (although with the same username)?
Can someone please clarify what the definer is doing? i.e. what can a connection from my IP address do that connections from other IP addresses can't?

I use the DEFINER clause to create a stored procedure with the security privileges of a powerful user that also has UPDATE, DELETE, SELECT, and INSERT rights to a particular database table. Then, I only grant EXECUTE on that stored procedure to a minon user (some people call it a www user, versus the more powerful wwwproxy user).
In this way, the minion can only execute designated stored procedures and has no UPDATE, DELETE, SELECT, INSERT, or other rights on a database table.
I hope that helps frame the idea behind the DEFINER clause. Use it to separate power from tasks.
You are correct, by default, MySQL uses the identity of the current user as the DEFINER when creating a stored procedure. This identity could be the identity of the front-end application (so to speak), or, like I said, you can use a proxy user that has normal table privileges. Then the application user would be the minion with only one privilege on the stored procedure, EXECUTE.
In short, if the default DEFINER user does not represent what the front end application uses to login to the database, and you want it to, then you need to change the stored procedure with ALTER, if possible.
On the other hand, the better idea would be to use the minon/proxy scenario. Application users on the Internet have no bearing on the IP that ends up in the stored procedures DEFINER clause. All that matters is the IP of where your app is logging in from to MySQL. Your app is talking to the database, not user agents on peoples' computers. However, that notion is, generally, a point of initial confusion. You are fine!
Hope that helps.

Related

mysql Stored procedures can be seen but cannot be executed by authorised user

I have created a small DB (MariaDB, in a XAMPP environment) for my group, and we are currently using phpmyadmin to interact with the DB. I have created users and given them different permissions depending on their specific usage needs; and this works fine for tables and views. However something seems wrong with stored procedures. I need to give the user Global SELECT and EXECUTE privileges in order for them to run them. If I do it at the database level procedures can be seen but cannot be executed.
I normally create the procedures from mysql workbench, and the look like this:
CREATE DEFINER=`root`#`localhost` PROCEDURE `proc_name`()
BEGIN
...
END
And users are like:user1#% although I have also tried creating user like user1#localhost but it doesn't help.
Any idea why this is happening? Does it have to do with the DEFINER?
Many thanks in advance!

MySQL: Only allow users to execute procedures, but avoid access to any other resources such as tables?

How can I tell MySQL that a given user is only allowed the execution of stored procedures, and not to read or write tables directly?
I want to limit the type and scope of all operations that a user can make in order to protect the database.
If there are better ways to do this I am also opened to suggestions :)
Thanks!
The owner of the table and procedure always can ACCESS them, create a another user for the Database Connection Pool of your program, grant execute to it.

Does MySQL support interior mutability or sticky bit?

Say, I have a complex MySQL procedure. The procedure is basically a complex SELECT query that use data inside a table to output some records.
For convenience, the procedure need to write to a temporary table to calculate the final result.
So can I grant properly so that a user that can only read the database can call this procedure to get its output, although the procedure actually need to write to the database? Because essentially this procedure don't intend to write, it just cache some data to a specific table with a name start with underscore so it shouldn't break anything seriously, beside costing storage of disk.
A stored program or view that executes in definer security context executes with the privileges of the account named by its DEFINER attribute. These privileges may be entirely different from those of the invoking user.
https://dev.mysql.com/doc/refman/5.7/en/stored-programs-security.html
As long as the user defining the procedure has the necessary permissions and doesn't explicitly force the procedure to run in INVOKER context, the permissions of the invoking user have no impact on what the procedure can do. The permissions of the defining user apply to the procedure's actions.
The invoking user only needs to be able to run it. No special arrangements are necessary, because this is the default behavior.
The DEFINER defaults to the user creating the procedure. If that account has the SUPER privilege, they can actually declare a different definer account whose privileges will apply.
Typically, stored procedures in MySQL operate with privileges associated with the procedure's definer, not the user who invokes the procedure, who only needs execute privilege on the procedure.
A stored procedure can be configured to run in invoker context, thus executing with same privilege as the invoking user, but this is not common.
Just make sure when you define the procedure the definer has appropriate permission to do everything that needs to be done during execution.

How can i see the definer of a table?

I am currently trying to make a dump of my production database and deploy it in my development database.
Before i do so, i am willing to add a script that will change the definer of the database's tables to a definer that is used in my development database after the deployment is complete.
Is there a way to tell what is the current definer for a table?
Iv'e tried SHOW CREATE TABLE but it doesn't give me the definer of that table.
Note that i already have a script that does so for another schema, but i am not sure if the definer for the other schema is the same.
Also, i couldn't find an answer to this over the internet, so i am asking this here.
Thanks.
Databases and tables do not have a 'definer' (or DBO) in MySQL.
"users" are "GRANTed" permissions to access databases and/or tables. Will having different GRANTs solve whatever you are trying to solve?
A related topic... Stored Routines execute as the "invoker" or a specified "user" (your choice when creating the routine), but I don't think that is what you are asking about.
You, or others lead to this question, may be thinking of procedures/functions/triggers/events/views that may be correlated with the tables you're attempting to find definers for.
Stored Object Access Control
Stored programs (procedures, functions, triggers, and events) and views are defined prior to use and, when referenced, execute within a security context that determines their privileges. The privileges applicable to execution of a stored object are controlled by its DEFINER attribute and SQL SECURITY characteristic.
In which case, you may find the following queries helpful:
SHOW CREATE PROCEDURE proc_name
SHOW CREATE FUNCTION func_name
SHOW TRIGGERS FROM db_name
SHOW CREATE EVENT event_name
SHOW CREATE VIEW view_name

Creating stored procedure again in MySQL DB

I created a stored procedure, 'myProc', in a MySQL database.
Then I dropped this procedure.
I wanna create again a procedure with the same name to the before.
I create the procedure again and name it 'myProc'.
CALL myProc();
But, when I execute this procedure, it is an error like that "PROCEDURE myProc does not exit".
Also code is same to the before one.
Unable to call a stored procedure in MySQL
You've created a procedure in MySQL 5. You've granted EXECUTE privileges to your application's user account. But when your application prepares a statement to call that procedure, an exception is thrown. Perhaps it's a NullPointerException deep inside of ConnectorJ. Perhaps the exception claims that the procedure does not exist. Or perhaps you've gotten lucky enough to get the exception that leads you down the right path(Driver requires declaration of procedure to either contain a ''\nbegin'' or ''\n'' to follow argument declaration, or SELECT privilege on mysql.proc to parse column types). Here are the troubleshooting steps that I've gleaned from hours of searching the MySQL forums.
First, open two console windows. In one, log into MySQL as the application user. In the other, log in as root. In your app window, list the databases.
SHOW DATABASES;
If your application's database does not appear, then you should go to your root window and grant database privileges.
USE mydatabase;
GRANT ALL ON mydatabase TO appuser;
Now go back to the app window. List the databases again to ensure that it appears. Now that it does, go into it.
USE mydatabase;
Once you're in, try to view the procedure.
SHOW CREATE PROCEDURE myproc /G
One of three things will happen. If you get a message saying "PROCEDURE myproc does not exist" then the app user does not have privileges for it. Go back to the root window and grant them.
GRANT EXECUTE ON PROCEDURE myproc TO appuser;
The second thing that might happen is that the procedure will be found, but the body will not be listed. Instead, it will say "Create Procedure: NULL". If so, go back to the root window and take care of that.
GRANT SELECT ON mysql.proc TO appuser;
The third thing that could happen is what you want to happen; the body of the procedure will be listed. Now you should be able to call the procedure from your application.
Warnings
You may be tempted to take a couple of short-cuts to resolve problems like these. Please don't. Shortcuts may cause bigger problems down the road.
The first thing you might try is to use the root account from within your application. This is extremely dangerous. Security comes in layers. While you should use stored procedures and prepared statements to avoid SQL injection attacks, you should also apply the principle of least privilege just in case they occur anyway. Allowing your application to connect as root gives an attacker access to your most valuable resource: your data. But giving each part of the application a separate account with only the privilege that it requires quarantines the bad guy.
The second thing that you might try after hours of research is to set the "noAccessToProcedureBodies" flag in the ConnectorJ connection string. Please avoid this flag, as it circumvents the parameter type checking that the JDBC driver provides for you. This flag causes ConnectorJ to convert all of the parameters to strings, which MySQL will then convert back to the required type.
But by walking through the problem step-by-step, these short-cuts should not be necessary.
Reference
http://adventuresinsoftware.com/blog/?p=74