Search code examples
mysqlsecuritystored-proceduresdockersql-grant

Provide only GRANT EXECUTE 'procedure' to a user (No select or insert permissions)


I was wondering if it's possible to grant EXECUTE permissions to a user without granting SELECT, INSERT etc. permissions on the table that a procedure runs on?

Using it for a Logins table for a webapp. MySQL is running in a Docker container. SQL for creating procedures is copied across as part of the docker build process (when run, the sql is used in entrypoint.sh). Login_db is created when running the container (-e flag).

I'd like to remove the GRANT SELECT line from below so, no matter what happens, the webapp server can never run a SELECT query - such as doing SELECT * FROM logins.

CREATE USER 'logins'@'172.24.0.7' IDENTIFIED BY 'some-password';
GRANT SELECT, INSERT, UPDATE on logins_db.login TO 'logins'@'172.24.0.7';
GRANT EXECUTE ON PROCEDURE logins_db.sp_login16 TO 'logins'@'172.24.0.7';
FLUSH PRIVILEGES;

This doesn't solve it - as being the table owner would expose the same privileges:

Execute stored proc fails with GRANT EXECUTE because of table permissions

This might explain why I can't, but the table names are a bit odd to me (MySQL newbie - I'm under the impression that mysql.proc is a system table, so not sure if it applies):

How to grant execute on specific stored procedure to user

Could it be that root doesn't have SELECT privileges when creating the procedure and so the the logins user cannot run it? (Because Docker MySQL runs entrypoint.sh and then the environment variable)?

The procedure code is here (I know, not the most elegant) - could I GRANT and then REVOKE privileges for the logins user within this, considering the DEFINER is root ?

CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_login16`(
IN p_email VARCHAR(120),
IN p_password VARCHAR(120))
BEGIN
SELECT user_id,user_password FROM login WHERE user_email = p_email;

Solution

  • Added a new user ADMIN@localhost with SELECT, INSERT and UPDATE privileges. ADMIN then became the DEFINER for all the procedures, with 'logins'@'172.24.0.7' only being granted EXECUTE permissions. Runs perfectly now!

    Apparently you can't use root in the way I was trying to. Kudos to @Shadow for pointing me in the right direction.

    Setting up the admin user:

    CREATE USER 'admin'@'localhost' IDENTIFIED BY '<password>';
    GRANT SELECT, INSERT, UPDATE, DELETE ON db.table_name TO 'admin'@'localhost';
    GRANT ALTER ROUTINE, CREATE ROUTINE, EXECUTE ON *.* TO 'admin'@'localhost'; 
    FLUSH PRIVILEGES;
    

    Defining a stored procedure that creates a entry using the limited admin user

    DELIMITER $$
    CREATE DEFINER=`admin`@`localhost` PROCEDURE `sp_createTableEntry`(
    
        IN value_one VARCHAR(120),
        IN value_two VARCHAR(200)
    )
    BEGIN
        IF ( select exists (select 1 from table_name where column_one = value_one) ) THEN
         
            select 'Column One Exists !!';
         
        ELSE
         
            insert into table_name
            (  
                column_one,
                column_two
            )
            values
            (
                value_one,
                value_two
            );
        END IF ;
    END $$
    DELIMITER ;