Базы данных — это Святой Грааль для хакеров, поэтому их необходимо защищать с особой тщательностью. Это первая из серии статей, в которых мы дадим обзор best practice в обеспечении безопасности баз данных. Мы начнем с одной из самых популярных СУБД с открытым исходным кодом, PostgreSQL, и рассмотрим несколько уровней безопасности, о которых стоит задуматься:   Безопасность на сетевом уровне Безопасность на транспортном уровне Безопасность на уровне базы данных В идеале ваш сервер PostgreSQL должен быть полностью изолированным и не допускать никаких входящих подключений, SSH или psql. К сожалению, PostgreSQL не поддерживает стандартную настройку такого типа.   Следующий способ, который можно предпринять для повышения безопасности сервера базы данных, — это заблокировать доступ к узлу, на котором работает база данных, на уровне порта, с помощью брандмауэра. По умолчанию, PostgreSQL прослушивает TCP-порт 5432. В зависимости от операционной системы существуют разные способы блокировки других портов. В Linux можно использовать iptables -  наиболее доступную утилиту для управления файрволом: Примечание. При обновлении правил iptables рекомендуется использовать iptables-apply, который автоматически откатывает изменения в случае, если вы случайно заблокируете себя.   Приведенное выше правило PostgreSQL позволит любому подключаться к порту 5432. Его можно сделать более строгим, принимая подключения только с определенных IP-адресов или подсетей: Возвращаясь к нашему идеальному сценарию, возможность полностью предотвратить входящие подключения к порту 5432 потребует своего рода локального агента, который поддерживает постоянное исходящее соединение с клиентским узлом (-ами) и имеет возможность проксировать трафик на локальный экземпляр PostgreSQL.   Такой метод называется «обратным туннелированием». Его можно продемонстрировать при помощи удаленного перенаправления портов. Вы можете открыть обратный туннель, выполнив следующую команду с узла, на котором работает база данных PostgreSQL: Конечно, <client-host> должен быть доступным из узла PostgreSQL и иметь запущенного SSH-демона. Команда перенаправит порт 5432 на сервере базы данных на порт 5432 на клиентском компьютере, и вы сможете подключиться к базе данных через туннель:    Хорошей практикой является ограничение адресов, которые прослушивает сервер для клиентских подключений, с помощью параметра listen_addresses файла конфигурации. Если узел, на котором работает PostgreSQL, имеет несколько сетевых интерфейсов, используйте этот параметр, чтобы убедиться, что сервер прослушивает только те интерфейсы, через который клиенты будут подключаться к нему:   Если клиенты, подключающиеся к базе данных, всегда находятся на одном и том же узле (или, скажем, совместно расположены в одном поде Kubernetes с PostgreSQL, работающим в качестве дополнительного контейнера), отключение прослушивания сокетов TCP может полностью исключить сеть из рассматриваемой картины. Запись пустой строки в параметр прослушиваемых адресов заставляет сервер принимать только соединения сокетов домена Unix:  Поскольку большая часть всемирной паутины переходит на HTTPS, найдется мало оправданий тому, чтобы не использовать надежное шифрование для соединений с базой данных. PostgreSQL поддерживает TLS (который по-прежнему называется SSL в документации, конфигурации и CLI по legacy-причинам) и позволяет использовать его для аутентификации как сервера, так и клиента.   Для аутентификации сервера сначала необходимо получить сертификат, который сервер будет предоставлять подключающимся клиентам. Let's Encrypt упрощает получение бесплатных сертификатов X.509, например, с помощью инструмента CLI certbot: Учтите, что по умолчанию certbot использует вызов HTTP-01 ACME для проверки запроса сертификата, который требует действительного DNS для запрошенного домена, указывающего на узел, и порт 80, который должен быть открыт.   Если по какой-то причине вы не можете использовать Let's Encrypt и хотите сгенерировать все сертификаты локально, то можно использовать openssl CLI: Конечно, в производственной среде необходимо убедиться, что эти сертификаты обновлены вовремя.   Аутентификация клиента по сертификату позволяет серверу проверить личность подключающегося, подтверждая, что сертификат X.509, представленный клиентом, подписан доверенным центром сертификации (CA).   Рекомендуется использовать разные центры сертификации для выдачи сертификатов клиенту и серверу, поэтому давайте создадим клиентский CA и воспользуемся им для подписи сертификата клиента: Обратите внимание, что поле CommonName (CN) сертификата клиента должно содержать имя учетной записи базы данных, к которой подключается клиент. Сервер PostgreSQL будет использовать его для идентификации клиента.   Собрав все части вместе, теперь вы можете настроить сервер PostgreSQL для приема соединений TLS: Последняя часть настройки — обновить файл host-based аутентификации сервера PostgreSQL (pg_hba.conf), чтобы требовать TLS для всех подключений и аутентифицировать клиентов с помощью сертификатов X.509:  Теперь пользователи, подключающиеся к серверу, должны будут предоставить действительный сертификат, подписанный клиентским CA: Стоит обратить внимание, что по умолчанию psql не будет выполнять проверку сертификата сервера, поэтому для параметра sslmode необходимо установить значение verify-full или verify-ca, в зависимости от того, подключаетесь ли вы к серверу PostgreSQL, используя то же имя хоста, которое закодировано в поле CN его сертификата X.509.   Чтобы уменьшить размер команд и не вводить пути к сертификатам TLS каждый раз, когда вы хотите подключиться к базе данных, вы можете использовать файл службы подключения PostgreSQL. Он позволяет группировать параметры подключения в «службы», на которые затем можно ссылаться в строке подключения через параметр «служба». Создайте ~/.pg_service.conf со следующим содержанием: Теперь при подключении к базе данных вам нужно будет только указать имя службы и имя базы данных, к которой вы хотите подключиться: До сих пор мы рассматривали, как защитить сервер базы данных PostgreSQL от неавторизованных сетевых подключений, использовать шифрование и убедиться, что сервер и клиенты могут доверять друг другу с помощью взаимной аутентификации TLS. Еще одна часть головоломки — выяснить, что пользователи могут делать и к чему у них есть доступ после подключения к базе данных и подтверждения своей личности. Обычно такая процедура называется авторизацией.   PostgreSQL имеет комплексную систему прав пользователя, основанную на концепции ролей. В современных версиях PostgreSQL (8.1 и новее) «роль» является синонимом «пользователя», поэтому любое имя учетной записи базы данных, которое вы используете, скажем, с psql (например, «user = alice»), на самом деле является ролью с LOGIN атрибутом, который позволяет ей подключаться к базе данных. Фактически, следующие команды SQL эквивалентны: Помимо возможности входа в систему, роли могут иметь иные атрибуты, позволяющие им обходить все проверки прав доступа (SUPERUSER), создавать базы данных (CREATEDB), создавать другие роли (CREATEROLE) и другие.   Помимо атрибутов, ролям могут быть предоставлены права доступа, которые можно разделить на две категории: членство в других ролях и привилегии на объекты базы данных. Давайте посмотрим, как они работают.  В нашем воображаемом примере мы будем отслеживать инвентаризацию серверов:  По умолчанию, конфигурация PostgreSQL включает роль суперпользователя (обычно называемую «postgres»), используемую для начальной загрузки базы данных. Использование этой роли для всех операций с базой данных было бы эквивалентно постоянному использованию «root» в Linux, что никогда не являлось хорошей идеей. Вместо этого давайте создадим непривилегированную роль и при необходимости назначим ей права доступа, следуя принципу наименьших привилегий.   Вместо того, чтобы назначать привилегии/роли  каждому новому пользователю индивидуально, можно создать «групповую роль» и предоставить другим ролям (сопоставление с отдельными пользователями) членство в этой группе. Скажем, вы хотите разрешить вашим разработчикам, Алисе и Бобу, просматривать список серверов, но не изменять его: Теперь при подключении к базе данных и Алиса, и Боб унаследуют привилегии групповой роли «разработчик» и смогут выполнять запросы к таблице инвентаризации сервера.   Привилегия SELECT распространяется на все столбцы таблицы по умолчанию, хотя так быть не должно. Скажем, вы всего лишь хотели разрешить своим стажерам просматривать общую информацию об инвентаризации серверов, не позволяя им подключаться, скрывая IP-адрес: Другие наиболее часто используемые привилегии объектов базы данных — INSERT, UPDATE, DELETE и TRUNCATE аналогичны соответствующим SQL выражениями. Также вы можете назначить права для подключения к определенным базам данных, создания новых схем или объектов в схеме, выполнения функции и так далее. Взгляните на раздел Privileges документации PostgreSQL, чтобы увидеть весь список.   Одной из наиболее продвинутых функций системы привилегий PostgreSQL является безопасность на уровне строк, которая позволяет вам предоставлять привилегии подмножеству строк в таблице. Сюда входят как строки, которые могут быть запрошены с помощью оператора SELECT, так и строки, которые могут быть результатами операторов INSERT, UPDATE и DELETE.   Чтобы начать использовать безопасность на уровне строк, вам нужны две вещи: включить ее для таблицы и определить политику, которая будет контролировать доступ на уровне строк. Основываясь на предыдущем примере, предположим, что вы хотите разрешить пользователям обновлять только свои собственные серверы. Сначала включите RLS в таблице: Без какой-либо определенной политики PostgreSQL по умолчанию использует политику «запретить», что означает, что никакая роль (кроме владельца таблицы, который обычно является ролью, создавшей таблицу) не имеет к ней доступа.   Политика безопасности строк — это логическое выражение, которое PostgreSQL будет применять для каждой строки, которая должна быть возвращена или обновлена. Строки, возвращаемые оператором SELECT, проверяются на соответствие выражению, указанному в разделе USING, в то время как строки, обновленные операторами INSERT, UPDATE или DELETE , проверяются на соответствие с WITH CHECK выражением. Давайте определим пару настроек, которые позволяют пользователям видеть все серверы, но обновлять только свои собственные, определенные полем «владелец»: Обратите внимание, что только владелец таблицы может создавать или обновлять для нее политику безопасности строк.   До сих пор мы в основном говорили о превентивных мерах безопасности. Следуя краеугольным принципам безопасности — defence in depth, мы рассмотрели, как они накладываются друг на друга, чтобы замедлить продвижение гипотетического злоумышленника через систему.   Ведение подробного контрольного журнала — одна из опций безопасности системы, которое часто упускается из виду. Мониторинг доступа на уровне сети или на уровне узла для вашего сервера базы данных выходит за рамки этой статьи, но давайте посмотрим, какие у нас есть возможности, когда дело касается самого сервера PostgreSQL. Самое простое, что можно сделать для улучшения видимости того, что происходит в базе данных, — это включить подробное ведение журнала. Добавьте следующие параметры в файл конфигурации сервера, чтобы включить ведение журнала всех попыток подключения и всех выполненных операторов SQL: К сожалению, это практически всё, что можно сделать с помощью стандартной self-hosted установки PostgreSQL из коробки. Конечно, это лучше, чем ничего, но данный метод не масштабируется дальше нескольких серверов баз данных и простого «grepping».   Для более продвинутого аудита PostgreSQL вы можете использовать сторонние решения, такие как pgAudit . Если вы используете self-hosted экземпляр PostgreSQL, вам придется установить расширение вручную. Некоторые размещенные версии, такие как AWS RDS, поддерживают его прямо «из коробки», поэтому вам просто нужно включить его. pgAudit привносит большую структуризацию и детализацию в используемые операторы. Однако имейте в виду, что он по-прежнему основан на журналах, что затрудняет использование, если вы хотите отправить свои журналы аудита в структурированном формате во внешнюю SIEM систему для подробного анализа. Как и в случае с любой системой, разработанной с учетом требований безопасности, надлежащая защита доступа к экземпляру базы данных требует принятия защитных мер на нескольких уровнях стека.   В этой статье мы рассмотрели best practices в обеспечении безопасности базы данных PostgreSQL на нескольких уровнях, начиная с сетевой и транспортной безопасности, и изучили, как использовать гибкую систему привилегий пользователей PostgreSQL. Дата-центр ITSOFT — услуги размещения и аренды серверов и стоек в двух дата-центрах в Москве. За последние годы UPTIME 100%. Размещение GPU-ферм и ASIC-майнеров, аренда GPU-серверов, лицензии связи, SSL-сертификаты, администрирование серверов и поддержка сайтов.