Chapter 8: Security and User Management
September 28, 2025 ยท View on GitHub
User Account Management
Creating Users
-- Create user with password
CREATE USER 'john'@'localhost' IDENTIFIED BY 'SecurePass123!';
-- Create user accessible from any host
CREATE USER 'app_user'@'%' IDENTIFIED BY 'AppPass456!';
-- Create user from specific IP
CREATE USER 'admin'@'192.168.1.100' IDENTIFIED BY 'AdminPass789!';
Modifying Users
-- Change password
ALTER USER 'john'@'localhost' IDENTIFIED BY 'NewPass123!';
-- Rename user
RENAME USER 'john'@'localhost' TO 'john_doe'@'localhost';
-- Drop user
DROP USER 'john_doe'@'localhost';
Privileges
Granting Privileges
-- Grant all privileges on database
GRANT ALL PRIVILEGES ON mydb.* TO 'john'@'localhost';
-- Grant specific privileges
GRANT SELECT, INSERT, UPDATE ON mydb.customers TO 'app_user'@'%';
-- Grant column-level privileges
GRANT SELECT (name, email), UPDATE (email) ON mydb.users TO 'support'@'localhost';
-- Grant with grant option
GRANT SELECT ON mydb.* TO 'manager'@'localhost' WITH GRANT OPTION;
-- Apply changes
FLUSH PRIVILEGES;
Revoking Privileges
-- Revoke specific privileges
REVOKE INSERT, DELETE ON mydb.* FROM 'app_user'@'%';
-- Revoke all privileges
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'john'@'localhost';
Viewing Privileges
-- Show user privileges
SHOW GRANTS FOR 'john'@'localhost';
-- Current user privileges
SHOW GRANTS FOR CURRENT_USER();
-- All users
SELECT user, host FROM mysql.user;
Roles (MySQL 8.0+)
-- Create role
CREATE ROLE 'app_read', 'app_write';
-- Grant privileges to role
GRANT SELECT ON mydb.* TO 'app_read';
GRANT INSERT, UPDATE, DELETE ON mydb.* TO 'app_write';
-- Assign role to user
GRANT 'app_read' TO 'john'@'localhost';
GRANT 'app_read', 'app_write' TO 'admin'@'localhost';
-- Activate roles
SET DEFAULT ROLE ALL TO 'john'@'localhost';
Password Security
Password Validation Plugin
-- Install plugin
INSTALL PLUGIN validate_password SONAME 'validate_password.so';
-- Configure password policy
SET GLOBAL validate_password.length = 12;
SET GLOBAL validate_password.mixed_case_count = 2;
SET GLOBAL validate_password.special_char_count = 2;
Password Expiration
-- Set password expiration
ALTER USER 'john'@'localhost' PASSWORD EXPIRE INTERVAL 90 DAY;
-- Force password change
ALTER USER 'john'@'localhost' PASSWORD EXPIRE;
SSL/TLS Connections
-- Require SSL for user
CREATE USER 'secure_user'@'%' IDENTIFIED BY 'pass' REQUIRE SSL;
-- Require specific certificate
CREATE USER 'cert_user'@'%' IDENTIFIED BY 'pass'
REQUIRE SUBJECT '/CN=client/O=MyOrg';
-- Check SSL status
SHOW VARIABLES LIKE '%ssl%';
Data Encryption
Transparent Data Encryption (TDE)
-- Enable encryption for new tables
ALTER INSTANCE ROTATE INNODB MASTER KEY;
-- Create encrypted table
CREATE TABLE sensitive_data (
id INT PRIMARY KEY,
data VARCHAR(255)
) ENCRYPTION='Y';
Column Encryption
-- Using AES encryption
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(50),
password_hash VARCHAR(255),
ssn VARBINARY(255)
);
-- Insert encrypted data
INSERT INTO users (username, password_hash, ssn)
VALUES ('john', SHA2('password', 256), AES_ENCRYPT('123-45-6789', 'secret_key'));
-- Retrieve decrypted data
SELECT username, AES_DECRYPT(ssn, 'secret_key') AS ssn
FROM users;
Auditing
Audit Plugin
-- Install audit plugin
INSTALL PLUGIN audit_log SONAME 'audit_log.so';
-- Configure audit log
SET GLOBAL audit_log_policy = 'ALL';
SET GLOBAL audit_log_format = 'JSON';
Manual Audit Tables
CREATE TABLE audit_log (
id INT AUTO_INCREMENT PRIMARY KEY,
user VARCHAR(50),
action VARCHAR(50),
table_name VARCHAR(50),
record_id INT,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
details JSON
);
-- Trigger for auditing
CREATE TRIGGER audit_customer_changes
AFTER UPDATE ON customers
FOR EACH ROW
INSERT INTO audit_log (user, action, table_name, record_id, details)
VALUES (USER(), 'UPDATE', 'customers', NEW.id, JSON_OBJECT('old', OLD.email, 'new', NEW.email));
SQL Injection Prevention
Use Prepared Statements
-- Prepared statement example
PREPARE stmt FROM 'SELECT * FROM users WHERE username = ? AND password = ?';
SET @user = 'john';
SET @pass = 'password';
EXECUTE stmt USING @user, @pass;
DEALLOCATE PREPARE stmt;
Input Validation
- Always validate input in application layer
- Use parameterized queries
- Escape special characters
- Limit input length
- Use stored procedures where appropriate
Security Best Practices
- Principle of Least Privilege: Grant only necessary permissions
- Strong Passwords: Enforce complexity requirements
- Regular Updates: Keep MySQL server updated
- Remove Default Accounts: Delete test users and databases
- Network Security: Use firewalls and VPNs
- Backup Encryption: Encrypt backup files
- Monitor Access: Review logs regularly
- Separate Environments: Don't use production credentials in development