Privilege error while creating MySQL trigger - mysql

I want to execute the following trigger in the dev environment. This trigger works fine locally (local user does not have super privilege and log bin is enabled). Here is the trigger
DELIMITER $$
USE `myschema`$$
CREATE
DEFINER=`user`#`localhost`
TRIGGER `myschema`.`roles_BEFORE_INSERT`
BEFORE INSERT ON `myschema`.`roles`
FOR EACH ROW
BEGIN
IF (NEW.role_id IS NULL) THEN
-- Find max existed role id
SELECT
MAX(role_id) INTO #max_role_id
FROM
roles;
IF (#max_role_id IS NULL) THEN
-- Set first role id
SET NEW.role_id = CONCAT('RID', '0001');
ELSE
-- Set next role id
SET NEW.role_id = CONCAT(SUBSTR(#max_role_id, 1, 3), LPAD(SUBSTR(#max_role_id, 4) + 1, 4, '0'));
END IF;
END IF;
END$$
I am getting the following error while executing the above script in dev environment where I do not have access to check whether user has what privileges and log bin is enabled or not. Could you please tell me is there any way I can specify super privilege or setting the log bin enable query along with the above script itself. I am having a hard time as the issue is not reproducible in local environment. Any help is appreciated.
SQL State : HY000
Error Code : 1419
Message : You do not have the SUPER privilege and binary logging is enabled
(you might want to use the less safe log_bin_trust_function_creators variable)

Someone who has SUPER privilege must grant it to you, or create your trigger themselves. It's the same kind of thing as Administrator priv on Windows or root priv on *nix.

To check current user grants:
login with user in mysql and
mysql> show grants;
to check supper user:
mysql>select user,host from mysql.user where super_priv='y';
to check bonlog:
mysql> show global variables like "log_bin";
Fix:
you can fix it by enabling log_bin_trust_function_creators
mysql> set global log_bin_trust_function_creators =ON;
read the official doc for more details.
https://dev.mysql.com/doc/refman/5.7/en/replication-options-binary-log.html#sysvar_log_bin_trust_function_creators

Related

Restrict permissions to execute a stored procedure

Here is the context.
two databases, database1 and database2.
an asp.net web application that accesses database1 using user user1 (SQL Server authentication).
a stored procedure sp1 in database1 that needs to modify some sensitive data in database2 through a stored procedure sp2 defined in database2. In other words sp1 calls database2..sp2.
I created a SQL Server user2 login that is mapped to user2 in database1 and user2 database2. user2 in database2 has the permission to execute sp2.
I want user1 to be able to modify the database2 only through the sp1. I don't want user1 to be able to run: exec database2..sp2.
Here is some code that I tried:
USE [database2];
GO
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
CREATE PROCEDURE [dbo].[sp2]
WITH
EXEC AS CALLER AS
SELECT current_user
GO
GRANT EXECUTE ON [dbo].[sp2] TO [user2]
GO
In database1 I ran:
use database1
go
drop procedure sp1
go
create procedure sp1
as
declare #m nvarchar(4000)
select current_user as usr
execute as login='user2'
begin try
execute database2.dbo.sp2
end try
begin catch
set #m = error_message()
print #m
revert
end catch
go
grant execute on dbo.sp1 to user1
go
execute as login='user1'
go
execute dbo.sp1
go
revert
go
Unfortunately this (i.e. exec dbo.sp1 in the context of login='user1') doesn't work, it returns:
Cannot execute as the server principal because the principal "user2" does not exist, this type of principal cannot be impersonated, or you do not have permission
I also tried to compile sp1 with with execute as 'user2', however, it doesn't work.
Is there another way I can make this work?
Thanks
Update:
If I run this:
GRANT IMPERSONATE ON User::user2 to [User1];
GO
then the script works but it means User1 can now execute Database2..sp2.
What I want in a way is something like this: grant impersonate on User::user2 to [sp1], i.e grant the impersonation permission to a procedure but I am not sure it's possible.
I found this thread which I think it is relevant to my case as well.
ok, based on the thread I mentioned it is possible.
Here are the scripts to achieve this:
use database1
go
CREATE CERTIFICATE [PermissionsCert]
AUTHORIZATION [dbo]
ENCRYPTION BY PASSWORD = 'WeakPassword'
WITH SUBJECT = 'Used to test granting permissions to code',
EXPIRY_DATE = '2099-12-31';
ADD SIGNATURE TO [dbo].[sp1]
BY CERTIFICATE [PermissionsCert]
WITH PASSWORD = 'WeakPassword';
BACKUP CERTIFICATE [PermissionsCert] TO FILE = 'k:\Sql_Backup\PermissionsCert.cer'
use database2
go
CREATE CERTIFICATE PermissionsCert
FROM FILE = 'k:\Sql_Backup\PermissionsCert.cer'
CREATE USER [PermissionsUser] FROM CERTIFICATE [PermissionsCert];
grant execute on dbo.sp2 to [PermissionsUser]
go
I modified sp1 as follows:
alter procedure sp1
as
declare #m nvarchar(4000)
select current_user as usr
--execute as user='user2'
begin try
execute Database2.dbo.sp2
end try
begin catch
set #m = error_message()
print #m
revert
end catch
go
This works now:
execute as login='user1'
go
execute dbo.sp1
go
revert
go
However, this fails, which is what I want:
execute as login='user1'
go
execute database2.dbo.sp2
go
revert
go

ERROR 1465 "Triggers can not be created on system tables" after restore from SQL created by mysqldump

I'm running a mysql 5.6 server on amazon RDS and set up a read replica I use to create backups using mysqldump.
I tried with the "--all-databases" option, but when I'm trying to import the SQL created by mysqldump, I end up with this error from the mysql command client:
ERROR 1465 "Triggers can not be created on system tables"
I used "--all-databases" because I basically want to restore everything in RDS as it was before in case of a crash.
Maybe that's wrong, and I should only select my schemas (plus the mysql.users table)? But what is "--all-databases" for in the first place, if it would never work? Or am I using it wrong?
After a longer conversation with the amazon support, this is what I came up with:
The trigger problem can be solved by temporarily setting the mysql config setting log_bin_trust_function_creators to 1
They do not recommend to take a full snapshot, but rather select individual databases.
That means you have to do two steps in an recovery:
Create Schema
Create Users and grant necessary rights to them
Import dumped data
With views, you might run into the error message
ERROR 1227 (42000) at line xxx: Access denied; you need (at least one of) the SUPER privilege(s) for this operation
Which is displayed because mysqldump creates a definer statement into the create view (and even your root user doesn't have enough privileges to set this). As described here, the only way to get rid of them is filtering, which I do like this:
sed -i 's/^/..50013 DEFINER=.* SQL SECURITY DEFINER ..$/-- removed security definer statement/g'
It's embarrassing that there is so much manual work needed to get database backups out of RDS, and also back in. Under no circumstances you should rely on the backups which are automatically made by RDS only, as those could be easily deleted by a malicious attacker that gained access to your AWS account.
Import with mysql -f to skip the offending proc.
In my case the skipped definition was this little gem:
DELIMITER ;;
/*!50003 CREATE*/ /*!50017 DEFINER=`rdsadmin`#`localhost`*/ /*!50003 trigger block_proc_u before update on proc
for each row
BEGIN
DECLARE foo varchar(255);
if old.Definer = "rdsadmin#localhost" then
select `ERROR (RDS): CANNOT MODIFY RDSDMIN OBJECT` into foo;
end if;
END */;;
Plus another four very similar ones (total five skipped).

Can't alter MySql routine

I am logging in with my main DB user, into Phpmyadmin page/ workbench remote access application and I have permissions issues.
It all started when I tried to alter routines that I have stored in the DB. when trying to alter those routines from the workbench applications nothing just happens.
I can call these routines and execute them, but not alter or get to the scripts.
I searched for hours in distinct forums and get some answers regarding grant access commands
but then I got again permissions issues with error #1142 , command denied to user(main user).
I am really lost here, and already lost hours of work in order to get to the scripts of my routines.
one last note - I have created these routines while I was connected with the same user but from different remote connection (different IP address).
Would really appreciate the help.
here is a solution how I fixed this:
1) Add "mysql" database to the user, you are logged in with
Advice: now you can alter functions and procedures
2) Add the global privilege "SUPER" to your user
Advice: otherwise you will get the following error if you save the procedure/function: "ERROR 1227: Access denied; you need (at least one of) the SUPER privilege(s) for this operation"
CREATE DEFINER = 'admin'#'localhost' PROCEDURE account_count()
SQL SECURITY INVOKER
BEGIN
SELECT 'Number of accounts:', COUNT(*) FROM mysql.user;
END;
See the above example.
You need to login using super user and change the definer parameter in the procedure based on your new username and hostname. The same definer who created can edit the stored procedure.

Unable to create trigger on mysql system table [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
mysql: Cant we create triggers on system tables?
We are using MySQL ver 5.1.59 on rhel 6.1 (64 bit). We want to monitor the deletion of databases and for that trying to create a trigger on the db table of mysql database. We are creating the trigger by logging in as root user. the trigger written is as follows:
DELIMITER |
CREATE
/*[DEFINER = { user | CURRENT_USER }]*/
TRIGGER `mysql`.`test` BEFORE DELETE
ON `mysql`.`db`
FOR EACH ROW BEGIN
INSERT INTO cescnet.db_monitor (DB_name,user_name,dateandtime,operation_type) VALUES (mysql.db.Db,CURRENT_USER(),NOW(),'Delete');
END;|
But we are getting the error:
Error Code : 1465
Triggers can not be created on system tables
As we are working as root user, we think we have all the permissions on the system. The global privilege for root user from any host including local host includes the SUPER permission. Can anyone help us please?
I'm going to take a wild guess and say the reason you're getting that error message is that triggers can not be created on system tables.
Oh, perhaps I can add "regardless of privileges"
In short : You can not do.
I have also tried things like
See (All) and (Super) Privileges Provided by mySql
After trying all type of privileges like
grant super on *.* to root#localhost
grant all on *.* to root#localhost
I have tried simplest trigger and get same error
Triggers can not be created on system tables
If you found anywhere that triggers can be created on system tables, simply that is wrong

grant trigger to schema not working

I need to give an user TRIGGER permission for an whole schema in mysql to import mysql workbench backup.
I tried with:
grant trigger ON `schemaname`.* TO `user`#`localhost`
But while importing there comes the error that the user haven't the permissions.
ERROR 1142 (42000) at line 53: TRIGGER command denied to user 'user'#'localhost' for table 'table'
I tried to give the user TRIGGER permission to the table - that works, but of course only for that table, for the others still came the error.
Is there any way to give an user trigger permission to an schema without giving him the permission for every table separately?
From MySQL Docs
In MySQL 5.0 CREATE TRIGGER requires the SUPER privilege.
So you need to give SUPER privileges to the User. While importing, there will be command like "Create Trigger..." which is throwing an error.
Check your MySQL version and definer value as well for trigger in the importing file.
Edit:
For version 5.1, follow MySQL docs, that says:
CREATE TRIGGER requires the TRIGGER privilege for the table associated with the
trigger. The statement might also require the SUPER privilege, depending on
the DEFINER value, as described later in this section. If binary logging is
enabled, CREATE TRIGGER might require the SUPER privilege, as described in
Section 19.7, “Binary Logging of Stored Programs”. (Before MySQL 5.1.6, there is
no TRIGGER privilege and this statement requires the SUPER privilege in all cases)
The DEFINER clause determines the security context to be used when checking access
privileges at trigger activation time.
So, you need to check Definer value for importing trigger. It might have something like : DEFINER = root. Try removing the definer then try importing. Hope it works...
In MySQL docs:
To relax the preceding conditions on function creation (that you must have the
SUPER privilege and that a function must be declared deterministic or to not
modify data), set the global log_bin_trust_function_creators system variable
to 1. By default, this variable has a value of 0, but you can change it like
this:
mysql> SET GLOBAL log_bin_trust_function_creators = 1;
You can also set this variable by using the
--log-bin-trust-function-creators=1
option when starting the server.
Set the global variable and reopened the session I was able to insert the trigger