Saturday, December 16, 2023

 

Problem statement: Data and logic often exist as close to each other as possible. Take MySQL server, for instance, or any relational database server and there is convenience to query and process the data stored. In fact, SQL is not just a language but a standard for structured storage and data that does not fit in a spreadsheet continues to be saved in tables. Many SQL server instances were created on-premises and usually in a central department or company headquarters but with the move to cloud they became universally reachable and demanded more from authentication and authorization. The de facto directory in the cloud for any organization continues to be the active directory aka AD and most SQL logins saved in the MySQL server, are now replaced by users and groups in the AD so that they can authenticate as themselves. But the onboarding of every user continues to draw up chores that an administrator must take in the form of SQL statements such as for audit or assignment. How do we automate this?

 

Solution: Every runtime, host, and cloud, provide management features for authentication and authorization that determine principal, role, and permissions to allow the control to pass over these barriers successfully before data is accessed. Out of these, the inner most circle has the data and logins saved so any automation can be successfully applied there. One of the features of the MySQL runtime is that it supports triggers that can execute INSERT, REPLACE, UPDATE and DELETE. System events where a trigger can run include STARTUP, SHUTDOWN, SERVERERROR, LOGON, LOGOFF, CREATE, DROP and ALTER. MySQL provides hooks for init_connect, init_file, and init_slave. In the my.cnf file, we can add a SQL script file which can be executed on database startup (init_file). These three hooks can be used to build the LOGON and the STARTUP trigger.

The implementation of a logon trigger requires writing a procedure that will execute on each LOGON event.

 

-- DROP PROCEDURE test.logon_trigger;

DELIMITER //

CREATE PROCEDURE test.logon_trigger()

     SQL SECURITY DEFINER

BEGIN

CREATE AADUSER CURRENT_USER()

flush privileges;

-- Create roles

CREATE ROLE 'ReadOnlyGroup';

-- Grant permissions to that role

GRANT SELECT ON testdb.* TO 'ReadOnlyGroup';

-- Assign roles to the AD Service Principal.

GRANT 'ReadOnlyGroup' TO CURRENT_USER()

END;

//

DELIMITER;

 

The CURRENT_USER() / CONNECTION_PROPERTY(‘user’) can be replaced with a caller supplied parameter.

 

The trigger can be tested with:

SHOW GLOBAL VARIABLES LIKE 'init%';

CALL test.logon_trigger;

 

When everything works fine, the hook must be connected to the procedure to build the trigger:

SET GLOBAL init_connect=’CALL test.logon_trigger()’;

 

A caveat here must be mentioned that just like all stored procedures, permissions must be granted to execute the logon trigger.

This can be done with:

 

GRANT EXECUTE TO PROCEDURE test.logon_trigger TO ‘*’;

 

The hook in the my.cnf file must be fixed otherwise it is not activated in the next system restart.

 

It is also possible to put the call procedure statement in a .sql file so that this script can be accessed from remote.

 

Finally, if the administrator centric duties must not be invoked as part of every logon event, the same trigger can be run as a procedure over a batch of user accounts belonging to the team as a one-time event and invoked specifically by the administrator on an adhoc or scheduled basis.

 

Automation with a cloud runbook that call azure cli commands on the target mysql instance is also possible and provides convenience to the end users but the SQL statements cannot be avoided and must be passed to the runbook in some form of script/file that can be run as part of the runbook. This makes logon triggers and such stored procedures convenient to encapsulate and run the statements.

 

Previous articles: https://1drv.ms/w/s!Ashlm-Nw-wnWhNNf6kdqJbe7IHHQEA?e=wqZK1g

 

No comments:

Post a Comment