В приложении PHP, которое я пишу, я бы не хотел раскрывать учетные данные производственной БД другим разработчикам.
Я прочитал здесь несколько вопросов и ответов о SO, например в следующей ветке есть много интересных мыслей по теме:
Как защитить пароли к базе данных в PHP?
Я решил, что хочу переместить учетные данные в файле за пределы корня приложения. Предположим, что я использую PDO и в своем контейнере приложения я создаю свой экземпляр PDO:
<?php
// ...
require_once __DIR__ . '/../db_pdo_outside_document_root.php';
$containerConfig = [
'db_connection' => function() {
return new PDO(DB_PDO_DSN, DB_PDO_USER, DB_PDO_PASSWD, DB_PDO_OPTIONS);
}
];
$appContainer = new ApplicationContainer($containerConfig);
// Use the container and handle the request...
Все константы DB_PDO_*, переданные конструктору PDO, происходят из файла db_pdo_outside_document_root.php, который находится вне корня документа:
<?php
// db_pdo_outside_document_root.php
define('DB_PDO_DSN', 'mysql:host=localhost;dbname=app_database');
define('DB_PDO_USER', 'db_user');
define('DB_PDO_PASSWD', 'db_fancy_passwd');
define('DB_PDO_OPTIONS', [
PDO::ATTR_PERSISTENT => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
Все идет нормально. Однако это мало помогает, потому что, если кто-то захочет повторить содержимое констант, он может легко это сделать:
<?php
// In some PHP file used by the application...
echo DB_PDO_PASSWD; // echoes the DB password.
//mail('[email protected]', 'Subject', DB_PDO_PASSWD); // Or send it by email
Сейчас, конечно, нужно доверять коллегам, с которыми вы работаете, но кто знает, бывает, что сотрудник увольняется, может, его увольняют и так далее. И мы не хотим, чтобы у них была возможность каким-либо образом хранить учетные данные производственной БД на своих компьютерах.
Поэтому я подумал, что, возможно, вместо определения констант в файле сам файл может возвращать объект PDO, который, в свою очередь, не раскрывает учетные данные, которые он использует для подключения к базе данных:
<?php
// ...
var_dump($appContainer->get('db_connection'))
Выводит что-то вроде:
/path/to/htdocs/file.php:4:
object(PDO)[13]
Таким образом, я бы получил что-то вроде этого в коде начальной загрузки моего приложения:
<?php
// ...
$containerConfig = [
'db_connection' => function() {
return require_once __DIR__ . '/../db_pdo_outside_document_root.php';
}
];
$appContainer = new ApplicationContainer($containerConfig);
// Use the container and handle the request...
И внутри внешнего файла:
<?php
// db_pdo_outside_document_root.php
return new PDO('mysql:host=localhost;dbname=app_database',
'db_user', 'db_fancy_passwd', [
PDO::ATTR_PERSISTENT => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);;
Но я не знаю, достаточно ли этого или есть некоторые предостережения, о которых я должен знать (помимо того факта, что этот «обходной путь» немного уродлив).
Как вы думаете, смогут ли другие разработчики каким-либо образом прочитать учетные данные из возвращаемого значения $appContainer->get('db_connection') (предполагая, что он возвращает указанный выше объект PDO)?
Я также пробовал с ReflectionClass, и я не вижу никаких свойств этого объекта:
<?php
//...
$ref = new ReflectionClass($appContainer->get('db_connection'));
var_dump($ref->getProperties());
Выходы:
/path/to/htdocs/file.php:4:
array (size=0)
empty
Что вы думаете об этом подходе? Не изобретение века, но похоже, что оно делает свое дело. Или, может быть, все еще есть способ получить доступ к учетным данным в коде приложения, о котором я не знаю.
Хотелось бы узнать ваше мнение.
Спасибо за внимание.
EDI: как указал @IsThisJavascript, код приложения, конечно, все еще может получить содержимое файла и, следовательно, получить доступ к учетным данным, поэтому все мои рассуждения были неправильными, поскольку он не рассматривал этот очень простой случай. Думаю, мне нужно найти другую стратегию, если она существует ...
Должен был подумать об этом, так просто ахах
Тогда я могу отказаться от всего отправляемого кода, который каким-то образом обращается к этому файлу. Хотя это нетривиально и кажется немного сложным.
Честно говоря, я думаю, тебе стоит рискнуть. Если разработчик собирается злонамеренно, то он стреляет себе в ногу. Я не совсем уверен в способе решения вашей проблемы, которое было бы не слишком сложным.
Сказав это, вы должны настроить промежуточный сервер, который не использует учетные данные базы данных. Тогда вы будете отвечать за то, чтобы заставить все жить. Разработчикам не нужно работать на prod server - это вызывает слишком много проблем по мере роста вашей кодовой базы.
+1 за «разработчики никогда не касаются производства». Разработчики любят говорить что-то вроде «Мне просто нужно сделать одну вещь в продукте» без тестирования или документации, а затем, даже если он сразу не сломается, у вас есть эта мина, которая ждет, когда вы наступите на нее в следующий раз вы развертываете.






Вашим разработчикам не нужно знать пароль производственной БД, если у вас есть сервер разработки и рабочий сервер. Если ваши разработчики работают прямо на производственном сервере, вы действительно не сможете предотвратить вашу проблему. Обычно только системный администратор / DevOps знает пароль БД и устанавливает его на рабочем сервере. У ваших разработчиков не должно быть доступа к этому.
Но как я могу запретить им добавлять строки кода, которые, если они будут опубликованы в производстве, будут иметь доступ к файлу, содержащему учетные данные, которые PHP использует для подключения к БД, как в моем примере выше и как указано в @isThisJavascript? Я могу думать только о имени файла, которое неизвестно разработчикам и которое они почему-то не могли угадать.
@tonix Если ваши разработчики работают только на сервере разработки, у вас (или вашего системного администратора / DevOps) будет возможность проверить код, если он имеет злонамеренные намерения, прежде чем отправлять этот код в производство. Это то, что вы должны делать в любом случае: вся работа ваших разработчиков должна быть проверена / протестирована, прежде чем переходить к производственному серверу.
@tonix не может доверять вашим разработчикам на этом уровне - это проблема уровня 8, которая обычно решается с помощью политик управления / кадров и / или угроз насилия. Попытки взломать базу данных prod подобным образом являются серьезным нарушением.
Я знаю, и обычно никто этого не делает. Но подумайте о компании, разработчики которой работают удаленно и распределены по всему миру, в настоящее время нельзя всем доверять.
Может быть, в этом случае поможет АОП? Если я регистрирую уровень АОП поверх приложения и перед вызовом каждой функции проверяю, является ли один из параметров файлом, в котором хранится создание экземпляра PDO, я могу прервать выполнение программы с исключением. Таким образом, приложение даже не пройдет промежуточную фазу, когда тесты выполняются перед развертыванием кода ... Но тогда у меня, как я предполагаю, будут нетривиальные накладные расходы, я не знаю, я просто думаю о возможностях .
Наиболее распространенное решение - использовать файл .env для хранения учетных данных, необходимых для кодовой базы.
Разработчики получают (/ make / customize) файл .env с учетными данными для разработки, производственные учетные данные доступны только в производственной среде.
Этот файл .env хранится в корне документа, но не распространяется с кодом: он не добавляется в репозиторий (git / svn)
Обычно файл .env.example включен в базовые переменные разработки, такие как пути к тестовым средам для внешних API-интерфейсов и образцы учетных данных баз данных для их локальных баз данных. В отличие от .env, .env.exampleявляется добавлен в репозиторий системы контроля версий.
Что касается кода, вы можете использовать такую библиотеку, как dotenv, для чтения значений файла .env.
Предполагая, что вы хотите защитить себя от бэкдоров отдельных разработчиков со злонамеренными намерениями, вы можете использовать обзоры кода, чтобы предотвратить такие попытки. В современных компаниях, занимающихся производством программного обеспечения, а также в проектах с открытым исходным кодом, стандартной практикой является разрешить объединение только проверенного кода в основную ветку.
У обзоров кода есть и много других преимуществ: дополнительный контроль каждой части кода предотвращает ошибки и побуждает разработчиков учиться друг у друга.
Когда вы следуете такому протоколу, отдельный разработчик практически не может получить доступ к производственным учетным данным.
Файлы .env представляют собой обычный текст. Переменные среды обычно также представляют собой обычный текст. Это может быть обычное решение, но оно не является безопасным.
Вы можете совместить 2 тактики:
1. Разделите среду разработки и рабочую среду.
Проще всего сделать так, чтобы они «включали» расположение базы данных, используемую учетную запись и пароли из файла конфигурации, которые различаются в части производства и разработки.
-> таким образом разработчики вообще не узнают важные детали производственной стороны вещей.
2. предоставить пользователям индивидуальные учетные записи
Предоставьте своим разработчикам индивидуальные учетные записи на сервере базы данных разработки, чтобы они получили (отдельные) базы данных, с которыми они могут делать все, в то время как у вас все еще могут быть среды тестирования, в которых интеграция может выполняться с использованием баз данных, которые больше похожи на производственные (и, следовательно, более контролируемые в том, что с ними может случиться)
Это требует некоторого управления пользователями для каждого вновь нанятого разработчика и некоторых действий, когда они уходят, но на самом деле не так уж и сложно, чтобы ваш внутренний персонал ИТ-поддержки добавил еще один элемент в свои контрольные списки вместе с созданием / удалением адреса электронной почты и т. д.
Это работает лучше всего, если на стороне разработки вы даете им отдельные файлы конфигурации для включения, и все они готовы в конечном итоге перейти к производству.
-> это дает разработчикам область, где они могут делать все, что им нравится, не влияя друг на друга, и как только они уйдут, вы можете заархивировать все это и перевести в автономный режим.
maybe there is still a way to access the credentials in the application's code I am not aware of.Если у них есть доступ к серверу, то все, что им нужно сделать, это использоватьfile_get_contentsна__DIR__ . '/../db_pdo_outside_document_root.php';.