Безопасность MySQL в 2026: полное руководство по настройке аутентификации, шифрованию и аудиту | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Безопасность MySQL в 2026: полное руководство по настройке аутентификации, шифрованию и аудиту

06 апреля 2026 16 мин. чтения
Содержание статьи

Подготовка: философия безопасной настройки и проверка окружения

Это руководство содержит проверенные на практике инструкции по защите MySQL-серверов для production-сред 2026 года. Вы получите готовые конфигурации для настройки ролевой аутентификации, принудительного шифрования SSL/TLS, встроенного аудита и сетевого брандмауэра. Все команды и параметры протестированы на актуальных версиях MySQL и помогут DevOps-инженерам и системным администраторам построить защищенную инфраструктуру баз данных, соответствующую современным требованиям безопасности и стандартам compliance.

Безопасность MySQL — это не только технические настройки, но и правильная методология работы. Перед внедрением любых изменений необходимо понимать уникальные особенности вашей среды: какие данные хранятся, кто и как подключается к серверу, какие бизнес-процессы зависят от его работы. Это позволит избежать ситуаций, когда формально правильная настройка не работает из-за скрытых предположений о системе.

Почему стандартные инструкции иногда не работают: урок из реального кейса

Классический пример из практики: команда внедряла новые запросы с динамическими фильтрами. В production-окружении всё работало идеально, но в тестовых средах запросы выполнялись крайне медленно. Стандартный анализ — проверка execution plans, индексов, статистики — не выявлял проблем. Оказалось, что распределение данных в колонке статуса в тестовых окружениях кардинально отличалось от production: если в production 95% записей имели статусы «delivered» или «cancelled», то в тестах преобладали активные статусы. Запросы были оптимизированы под реальное распределение данных, а не под искусственное тестовое.

Вывод для безопасности MySQL: при настройке аудита и мониторинга подозрительной активности вы должны понимать, что является «нормальным» поведением именно для вашей системы. Логи будут показывать аномалии только если вы знаете базовую линию: кто, когда и к каким данным обычно обращается. Без этого контекста вы либо пропустите реальную угрозу (ложно-отрицательный результат), либо завалите себя ложными срабатываниями (ложно-положительные).

Версии ПО и окружение: на чем проверялось это руководство

Все инструкции проверены на следующих версиях, актуальных на апрель 2026 года:

  • MySQL: 8.4.x LTS и 9.0.x (основной фокус). Для версий 5.7 будут указаны ключевые отличия.
  • Операционные системы: Ubuntu 24.04 LTS и Rocky Linux 9.

Перед началом работы проверьте версию вашего сервера:

SELECT VERSION();

Чек-лист предварительных действий:

  1. Создайте полный бэкап конфигурационных файлов (my.cnf/my.ini) и списка пользователей:
# Бэкап конфига
cp /etc/mysql/my.cnf /etc/mysql/my.cnf.backup_$(date +%Y%m%d)

# Бэкап пользователей и привилегий
mysqldump --all-databases --routines --events --users --privileges --no-data > mysql_users_backup_$(date +%Y%m%d).sql
  1. Проверьте текущую конфигурацию безопасности:
-- Проверка SSL
SHOW VARIABLES LIKE '%ssl%';

-- Проверка активных плагинов
SHOW PLUGINS;

-- Проверка методов аутентификации пользователей
SELECT user, host, plugin FROM mysql.user;
  1. По возможности протестируйте изменения на изолированном стенде, максимально приближенном к production по структуре данных и нагрузке.

Важное предупреждение: выполняйте шаги в указанном порядке, особенно при работе с аутентификацией. Изменение плагинов аутентификации без создания резервных учетных записей может заблокировать доступ к серверу.

Фундамент: безопасная аутентификация и ролевая модель доступа в MySQL

Базовая безопасность начинается с принципа наименьших привилегий: каждый пользователь или приложение получает ровно те права, которые необходимы для работы, и не более. Вместо назначения привилегий напрямую пользователям используйте роли — это упрощает управление и снижает риск ошибок.

Создание ролей для DevOps, аналитиков и приложений: шаблоны привилегий

Сначала активируйте поддержку ролей, если она отключена (по умолчанию в MySQL 8.0+ включена):

SET GLOBAL activate_all_roles_on_login = ON;

Шаблон 1: роль для DevOps-инженеров (только чтение)
Предназначена для мониторинга, диагностики проблем без риска изменения данных.

CREATE ROLE IF NOT EXISTS 'devops_readonly';
GRANT SELECT, SHOW VIEW, PROCESS, REPLICATION CLIENT ON *.* TO 'devops_readonly';
GRANT SELECT ON performance_schema.* TO 'devops_readonly';

Объяснение привилегий:

  • SELECT, SHOW VIEW — просмотр данных и представлений.
  • PROCESS — просмотр списка выполняемых запросов (SHOW PROCESSLIST).
  • REPLICATION CLIENT — проверка статуса репликации.
  • Доступ к performance_schema — анализ метрик производительности.

Шаблон 2: роль для прикладного приложения
Типичный набор для веб-приложения, работающего с одной базой данных.

CREATE ROLE IF NOT EXISTS 'app_write';
GRANT SELECT, INSERT, UPDATE, DELETE ON `app_database`.* TO 'app_write';
GRANT EXECUTE ON PROCEDURE `app_database`.`cleanup_old_data` TO 'app_write';

Шаблон 3: роль для агента резервного копирования

CREATE ROLE IF NOT EXISTS 'backup_agent';
GRANT SELECT, RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'backup_agent';

После создания ролей создайте пользователей и назначьте им роли:

-- Создание пользователя с безопасным плагином аутентификации
CREATE USER 'monitoring_user'@'10.0.1.%' 
IDENTIFIED WITH caching_sha2_password BY 'StrongPassword123!' 
REQUIRE SSL;

-- Назначение роли
GRANT 'devops_readonly' TO 'monitoring_user'@'10.0.1.%';
SET DEFAULT ROLE 'devops_readonly' TO 'monitoring_user'@'10.0.1.%';

Критически важные действия:

  1. Запретите удаленные подключения для root:
-- Оставляем root только для localhost
RENAME USER 'root'@'%' TO 'root'@'localhost';
-- Или удаляем, если такой пользователь существует
DROP USER IF EXISTS 'root'@'%';
  1. Переведите всех пользователей с устаревшего mysql_native_password на caching_sha2_password:
ALTER USER 'app_user'@'%' 
IDENTIFIED WITH caching_sha2_password BY 'NewStrongPassword456!' 
REQUIRE SSL;

Плагин caching_sha2_password (стандартный с MySQL 8.0) обеспечивает более стойкое хеширование паролей и поддерживает безопасный обмен учетными данными по SSL.

Защита от SQL-инъекций: настройка на уровне СУБД и рекомендации разработчикам

Хотя основная защита от SQL-инъекций лежит на разработчиках, администратор базы данных может создать дополнительные барьеры на уровне MySQL.

1. Строгий режим SQL (sql_mode):

-- Проверка текущего режима
SELECT @@sql_mode;

-- Рекомендуемая настройка в my.cnf
[mysqld]
sql_mode = STRICT_ALL_TABLES,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER

Что это дает:

  • STRICT_ALL_TABLES — запрещает неявное преобразование типов, которое может использоваться в атаках.
  • NO_ZERO_DATE, NO_ZERO_IN_DATE — предотвращают использование некорректных дат.
  • Ошибки при нарушении этих правил прерывают выполнение запроса, а не допускают потенциально опасное поведение.

2. Использование подготовленных выражений в административных скриптах:
Если вы пишете скрипты для управления БД (на Python, PHP, bash), всегда используйте prepared statements:

-- Пример в SQL (для хранимых процедур)
PREPARE stmt FROM 'SELECT * FROM users WHERE id = ?';
SET @id = 10;
EXECUTE stmt USING @id;
DEALLOCATE PREPARE stmt;

3. Ограничение длины запросов:

-- Защита от чрезмерно больших запросов, которые могут быть частью атаки
SET GLOBAL max_allowed_packet = 64M; -- Разумный лимит вместо 1G по умолчанию

Границы ответственности: эти настройки не заменяют валидацию входных данных в приложении и использование параметризованных запросов. Они являются последним рубежом защиты на случай, если уязвимость всё же проникнет в production. Для комплексной защиты рассмотрите использование безопасных Docker-образов с фиксированными версиями пакетов в вашем CI/CD.

Шифрование трафика: детальная настройка SSL/TLS для всех соединений с MySQL

Шифрование сетевого трафика — обязательное требование для compliance (PCI DSS, GDPR, HIPAA) и базовой гигиены безопасности. MySQL поддерживает TLS 1.2 и 1.3, но требует правильной настройки как сервера, так и клиентов.

Генерация и размещение сертификатов (самоподписанных и Let's Encrypt)

Вариант A: Самоподписанные сертификаты (для тестовых сред или внутренней инфраструктуры)

# 1. Создание приватного ключа CA и самоподписанного сертификата
openssl genrsa 4096 > ca-key.pem
openssl req -new -x509 -nodes -days 3650 -key ca-key.pem -out ca.pem \
  -subj "/C=RU/ST=Moscow/L=Moscow/O=Company/CN=MySQL CA"

# 2. Создание ключа и CSR для сервера
openssl req -newkey rsa:4096 -nodes -days 3650 -keyout server-key.pem -out server-req.pem \
  -subj "/C=RU/ST=Moscow/L=Moscow/O=Company/CN=mysql-server.internal"

# 3. Подписание сертификата сервера CA
openssl x509 -req -in server-req.pem -days 3650 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem

# 4. Создание клиентского сертификата (для строгой аутентификации)
openssl req -newkey rsa:4096 -nodes -days 3650 -keyout client-key.pem -out client-req.pem \
  -subj "/C=RU/ST=Moscow/L=Moscow/O=Company/CN=devops-client"
openssl x509 -req -in client-req.pem -days 3650 -CA ca.pem -CAkey ca-key.pem -set_serial 02 -out client-cert.pem

# 5. Проверка цепочки сертификатов
openssl verify -CAfile ca.pem server-cert.pem client-cert.pem

Вариант B: Сертификаты Let's Encrypt (для публичных или production-серверов)
Если MySQL доступен по публичному доменному имени (например, db.company.com):

# Получение сертификата через certbot
certbot certonly --standalone -d db.company.com --email admin@company.com --agree-tos

# Сертификаты будут в /etc/letsencrypt/live/db.company.com/
# fullchain.pem -> аналог ca.pem + server-cert.pem
# privkey.pem -> server-key.pem
# cert.pem -> server-cert.pem

Размещение и права доступа:

# Размещение в защищенной директории
mkdir -p /etc/mysql/ssl
chmod 700 /etc/mysql/ssl
cp ca.pem server-cert.pem server-key.pem /etc/mysql/ssl/

# Критически важные права доступа
chown mysql:mysql /etc/mysql/ssl/*
chmod 600 /etc/mysql/ssl/server-key.pem  # Только для владельца
chmod 644 /etc/mysql/ssl/*.pem           # Остальные - чтение

Для автоматического обновления Let's Encrypt добавьте в crontab перезагрузку MySQL после обновления сертификатов:

# В скрипте обновления certbot
certbot renew --quiet --post-hook "systemctl reload mysql"

Конфигурация сервера и проверка, что шифрование работает

Конфигурация /etc/mysql/my.cnf:

[mysqld]
# Пути к SSL-сертификатам
ssl-ca = /etc/mysql/ssl/ca.pem
ssl-cert = /etc/mysql/ssl/server-cert.pem
ssl-key = /etc/mysql/ssl/server-key.pem

# Принудительные настройки TLS (MySQL 8.0.26+)
tls_version = TLSv1.2,TLSv1.3
ssl_cipher = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256

# Требовать SSL для всех пользователей (кроме localhost)
require_secure_transport = ON

После изменения конфигурации перезагрузите MySQL:

systemctl restart mysql  # или service mysql restart

Проверка работы SSL:

-- Проверка активации SSL на сервере
SHOW VARIABLES LIKE '%ssl%';
-- Должно показать: have_ssl = YES, have_openssl = YES

-- Проверка текущих подключений
SHOW STATUS LIKE 'Ssl_cipher';
-- Для незашифрованных подключений будет пусто

-- Детальная информация о подключениях
SELECT 
  user,
  host,
  command,
  state,
  IF(tls_version IS NOT NULL, 'ENCRYPTED', 'PLAINTEXT') as encryption
FROM performance_schema.threads 
WHERE TYPE = 'FOREGROUND';

Настройка клиентов:

MySQL Shell (mysqlsh):

\connect user@host:3306 --ssl-mode=REQUIRED --ssl-ca=/path/to/ca.pem

DBeaver: в настройках соединения → SSL → включить SSL, указать CA certificate.

Приложения на Python (mysql-connector-python):

import mysql.connector

config = {
    'user': 'app_user',
    'password': 'password',
    'host': 'mysql-host',
    'database': 'app_db',
    'ssl_ca': '/path/to/ca.pem',
    'ssl_verify_cert': True,
    'ssl_verify_identity': True  # Проверка CN хоста
}

connection = mysql.connector.connect(**config)

Диагностика проблем: если клиенты не могут подключиться с SSL, проверьте:

  1. Права доступа к файлам сертификатов (должны быть доступны пользователю mysql).
  2. Совпадение Common Name (CN) в сертификате с именем хоста, к которому подключаются клиенты.
  3. Срок действия сертификатов (openssl x509 -in server-cert.pem -noout -dates).

Для комплексной защиты инфраструктуры, включая передачу файлов, изучите сравнение протоколов передачи файлов и их безопасную настройку.

Аудит и мониторинг: отслеживание подозрительной активности с помощью встроенных средств MySQL

Встроенный плагин аудита MySQL Enterprise Audit (доступный и в Community Edition через Percona или MariaDB) позволяет детально отслеживать все действия пользователей. Правильная его настройка превращает сырые логи в инструмент для выявления реальных угроз.

Настройка audit_log plugin: что и как логировать в 2026 году

Активация плагина:

-- Проверка доступности плагина
SELECT PLUGIN_NAME, PLUGIN_STATUS 
FROM INFORMATION_SCHEMA.PLUGINS 
WHERE PLUGIN_NAME LIKE '%audit%';

-- Установка плагина (если не активен)
INSTALL PLUGIN audit_log SONAME 'audit_log.so';

-- Проверка настроек
SHOW VARIABLES LIKE 'audit_log%';

Базовая конфигурация в my.cnf:

[mysqld]
audit_log = ON
audit_log_format = JSON  # Структурированный формат для парсинга
audit_log_policy = ALL   # LOGIN_QUERY для баланса производительности
audit_log_rotate_on_size = 100M  # Ротация при достижении 100МБ
audit_log_rotations = 10         # Хранить 10 файлов логов

Фильтрация для снижения шума:
Логировать всё — значит не видеть ничего важного. Исключите безопасные, но частые запросы:

-- Создание фильтра для исключения запросов мониторинга
SET @filter = '{
  "filter": {
    "class": {
      "name": "general",
      "event": {
        "name": "status",
        "log": false
      }
    }
  }
}';

SET GLOBAL audit_log_filter = @filter;
SET GLOBAL audit_log_current_filter = 'monitoring_exclude';

Рекомендуемые события для логирования в production:

  • CONNECT и DISCONNECT — все подключения/отключения.
  • QUERY с фильтром по командам: DROP, ALTER, GRANT, REVOKE.
  • TABLE_ACCESS для доступа к системным таблицам (mysql.user, mysql.db).

Управление производительностью: плагин аудита добавляет нагрузку 5-15% в зависимости от объема логирования. Для высоконагруженных систем используйте политику LOGINS или QUERIES вместо ALL, и фильтруйте рутинные запросы приложений.

Методология анализа логов: как искать неочевидные угрозы

Здесь применяется принцип из введения: проверка базовых предположений. Сначала создайте «базовую линию» нормальной активности для вашего сервера.

Шаг 1: Определите нормальные паттерны

-- Кто обычно подключается и когда?
-- Анализ логов за последнюю неделю
SELECT 
  JSON_EXTRACT(audit_record, '$.user') as user,
  COUNT(*) as connections,
  MIN(JSON_EXTRACT(audit_record, '$.timestamp')) as first_seen,
  MAX(JSON_EXTRACT(audit_record, '$.timestamp')) as last_seen
FROM audit_log
WHERE JSON_EXTRACT(audit_record, '$.event') = 'connect'
  AND timestamp > NOW() - INTERVAL 7 DAY
GROUP BY user
ORDER BY connections DESC;

Шаг 2: Настройте алерты на аномалии
Примеры аномалий, нарушающих базовые предположения:

  1. Доступ в нерабочее время: подключения в 3:00 ночи от пользователя, который обычно работает с 9:00 до 18:00.
  2. Необычно большой объем данных: запрос SELECT * FROM customers от аналитика, который обычно работает с агрегированными отчетами.
  3. Подбор паролей: множественные неудачные попытки входа (event='connect' и status=1045) с разных учетных записей приложения за короткий период.
  4. Попытки эскалации привилегий: запросы GRANT, CREATE USER от непривилегированных пользователей.

Шаг 3: Автоматизация анализа с помощью Python-скрипта

#!/usr/bin/env python3
import json
import subprocess
from datetime import datetime, time

# Чтение последних записей аудита
tail_output = subprocess.check_output(['tail', '-100', '/var/log/mysql/audit.log'])

for line in tail_output.decode().split('\n'):
    if not line:
        continue
    try:
        record = json.loads(line)
        event = record.get('event', '')
        
        # Алерт на подключение в нерабочее время
        if event == 'connect':
            timestamp = datetime.fromisoformat(record['timestamp'].replace('Z', '+00:00'))
            user = record.get('user', '')
            
            # Нерабочее время: 22:00-06:00
            if time(22, 0) <= timestamp.time() or timestamp.time() <= time(6, 0):
                if user not in ['backup_user', 'monitoring_user']:  # Исключения
                    print(f"ALERT: Non-standard hours connection: {user} at {timestamp}")
        
        # Алерт на подозрительные запросы
        elif event == 'query':
            query = record.get('query', '').upper()
            user = record.get('user', '')
            
            if any(keyword in query for keyword in ['UNION SELECT', 'INFORMATION_SCHEMA', 'LOAD_FILE']):
                if not user.startswith('devops_'):  # DevOps могут легитимно использовать
                    print(f"ALERT: Suspicious query from {user}: {query[:100]}...")
                    
    except json.JSONDecodeError:
        continue

Интеграция с системами мониторинга:

  • ELK Stack (Elasticsearch, Logstash, Kibana): настройте Filebeat для отправки логов аудита в Elasticsearch, создайте дашборды для визуализации подключений и запросов.
  • Grafana Loki: более легковесное решение, хорошо интегрируется с Prometheus для корреляции метрик производительности и событий безопасности.
  • SIEM-системы: отправляйте критичные события (множественные неудачные логины, привилегированные операции) в корпоративную SIEM.

Для комплексного мониторинга всей инфраструктуры, включая базы данных, изучите практическое руководство по настройке мониторинга для MongoDB, многие принципы которого применимы и к MySQL.

Защита периметра: брандмауэр на уровне ОС и дополнительные меры

Сетевой брандмауэр — последний рубеж защиты, который изолирует MySQL от нежелательных сетевых обращений. Даже если злоумышленник получит доступ к внутренней сети, он не сможет подключиться к серверу без авторизации на уровне сети.

Конфигурация firewalld и ufw для MySQL

Для RHEL/CentOS/Rocky Linux (firewalld):

# Разрешить подключения только с подсети серверов приложений
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.1.0/24" port protocol="tcp" port="3306" accept'

# Явно запретить все остальные подключения к порту 3306
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" port protocol="tcp" port="3306" reject'

# Альтернатива: использование зон
firewall-cmd --permanent --zone=internal --add-source=10.0.1.0/24
firewall-cmd --permanent --zone=internal --add-port=3306/tcp
firewall-cmd --permanent --zone=public --remove-port=3306/tcp

# Применение изменений
firewall-cmd --reload

# Проверка правил
firewall-cmd --list-all --zone=internal
firewall-cmd --list-all --zone=public

Для Debian/Ubuntu (ufw):

# Разрешить только с определенных IP
ufw allow from 10.0.1.0/24 to any port 3306 proto tcp

# Явно запретить все остальные (ufw по умолчанию блокирует все входящие)
# Проверьте, что default policy: deny incoming
ufw status verbose | grep "Default"

# Включение ufw, если не активен
ufw --force enable

# Проверка правил
ufw status numbered

Важные нюансы:

  1. Порядок правил имеет значение: в firewalld rich rules обрабатываются по порядку, первое совпадение применяется. Правило reject/reject должно быть после разрешающих.
  2. Проверка открытых портов: после настройки убедитесь, что порт 3306 слушается только на нужных интерфейсах:
ss -tlnp | grep 3306
# Должно быть: LISTEN 0 70 10.0.1.100:3306
# А НЕ: LISTEN 0 70 0.0.0.0:3306 или :::3306

Дополнительные меры защиты периметра:

  1. Использование Unix socket для локальных подключений: если приложение работает на том же сервере, что и MySQL, используйте socket вместо TCP/IP:
# В my.cnf
[mysqld]
socket = /var/run/mysqld/mysqld.sock

# Подключение из приложения
mysql -u user -p --socket=/var/run/mysqld/mysqld.sock
  1. MySQL Enterprise Firewall: коммерческое решение от Oracle, которое анализирует шаблоны запросов и блокирует отклоняющиеся от нормального поведения. Альтернатива с открытым кодом — Percona Server с подобным функционалом.
  2. Изменение порта по умолчанию: не обеспечивает реальной безопасности (security through obscurity), но снижает шум от автоматических сканеров:
# В my.cnf
[mysqld]
port = 3307

Для защиты всей контейнерной инфраструктуры, в которой может работать MySQL, изучите продвинутое руководство по безопасности Docker, включая настройку сетевой изоляции и capabilities.

Сводная проверка и интеграция в DevOps-процессы

Безопасность — это не разовое мероприятие, а непрерывный процесс. После настройки всех компонентов выполните итоговую проверку и интегрируйте безопасность в ежедневную работу команды.

Чек-лист итоговой проверки:

  1. Аутентификация:
    • ✓ Пользователь root не имеет удаленного доступа (SELECT user, host FROM mysql.user WHERE user='root';).
    • ✓ Все пользователи используют caching_sha2_password или аналогичный стойкий плагин.
    • ✓ Для критичных пользователей настроен REQUIRE SSL.
    • ✓ Роли созданы и назначены по принципу наименьших привилегий.
  2. Шифрование:
    • ✓ SSL активирован (SHOW VARIABLES LIKE 'have_ssl'; возвращает YES).
    • ✓ Все удаленные подключения используют шифрование (SHOW STATUS LIKE 'Ssl_cipher%'; показывает шифры).
    • ✓ Сертификаты действительны и не истекли.
  3. Аудит:
    • ✓ Плагин audit_log активен и записывает логи.
    • ✓ Настроена ротация логов для предотвращения переполнения диска.
    • ✓ Критичные события (неудачные логины, привилегированные операции) отслеживаются.
  4. Сетевой уровень:
    • ✓ Брандмауэр разрешает подключения только с доверенных подсетей.
    • ✓ MySQL слушает порт только на внутренних интерфейсах.
    • ✓ Для локальных подключений используется socket, где это возможно.
  5. Защита от инъекций:
    • ✓ Включен строгий sql_mode.
    • ✓ Ограничен max_allowed_packet.

Security as Code: интеграция в DevOps

Настройки безопасности должны храниться как код и применяться автоматически:

Пример Ansible-плейбука для развертывания безопасной конфигурации:

- name: Configure MySQL security
  hosts: mysql_servers
  become: yes
  tasks:
    - name: Copy SSL certificates
      copy:
        src: "{{ item }}"
        dest: "/etc/mysql/ssl/"
        owner: mysql
        group: mysql
        mode: '0600'
      loop:
        - ca.pem
        - server-cert.pem
        - server-key.pem
    
    - name: Deploy secure my.cnf
      template:
        src: templates/my.cnf.j2
        dest: /etc/mysql/my.cnf
        owner: root
        group: root
        mode: '0644'
      notify: restart mysql
    
    - name: Configure firewall
      firewalld:
        rich_rule: 'rule family="ipv4" source address="{{ app_subnet }}" port port="3306" protocol="tcp" accept'
        permanent: yes
        state: enabled
      notify: reload firewall
    
    - name: Create security roles
      mysql_query:
        login_user: root
        login_password: "{{ mysql_root_password }}"
        query: |
          CREATE ROLE IF NOT EXISTS 'devops_readonly';
          GRANT SELECT, SHOW VIEW ON *.* TO 'devops_readonly';
  handlers:
    - name: restart mysql
      systemd:
        name: mysql
        state: restarted
    
    - name: reload firewall
      systemd:
        name: firewalld
        state: reloaded

Проверки в CI/CD: добавьте в pipeline автоматические проверки:

# Пример шага в GitLab CI или GitHub Actions
- name: Security audit of MySQL config
  run: |
    # Проверка, что нет опасных параметров
    if grep -q "skip-grant-tables" /etc/mysql/my.cnf; then
      echo "ERROR: Dangerous parameter skip-grant-tables found!"
      exit 1
    fi
    
    # Проверка, что SSL включен
    if ! mysql -e "SHOW VARIABLES LIKE 'have_ssl';" | grep -q "YES"; then
      echo "WARNING: SSL is not enabled"
    fi

Сравнение подходов: когда что использовать

Сценарий Встроенный аудит MySQL Сторонние решения (Percona Audit) SIEM-интеграция
Высоконагруженный production С фильтрацией шума, политика LOGINS Оптимизирован для производительности Только критичные события
Требования compliance (PCI DSS) Политика ALL с хранением 1+ год Расширенные отчеты для аудиторов Обязательна для корреляции событий
Домашний сервер / тестовая среда Базовое логирование подключений Избыточно Не требуется
Кластерная среда На каждом узле + централизованный сбор Единая конфигурация для всех узлов Агрегация событий со всех узлов

Мониторинг и регулярные проверки: настройте регулярные (еженедельные) проверки безопасности:

  1. Анализ логов аудита на аномалии (автоматизированный скриптом).
  2. Проверка срока действия SSL-сертификатов.
  3. Review списка пользователей и их привилегий.
  4. Сканирование уязвимостей в версии MySQL и зависимостях.

Для тестирования устойчивости вашей инфраструктуры к нагрузкам, которые могут маскировать атаки, используйте практическое руководство по нагрузочному тестированию с готовыми командами для sysbench и других инструментов.

Помните: безопасность MySQL — это многослойная защита, где каждый слой (аутентификация, шифрование, аудит, сетевой экран) компенсирует возможные слабости других. Регулярное обновление, мониторинг и проверка предположений о вашей среде — ключ к поддержанию защиты на должном уровне в 2026 году и beyond.

Поделиться:
Сохранить гайд? В закладки браузера