Как безопасно хранить параметры доступа к базе данных (логин, пароль, хост) в приложении?

«Как безопасно хранить параметры доступа к базе данных (логин, пароль, хост) в приложении?» — вопрос из категории Безопасность, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Хранение чувствительных данных, таких как учетные данные БД, требует соблюдения принципа «секреты вне кода». Вот методы, которые я использую, от наиболее к наименее предпочтительным:

1. Менеджер секретов / Переменные окружения (Наиболее безопасно) Секреты никогда не коммитятся в Git и предоставляются приложению через среду выполнения.

  • В Kubernetes: Использую объекты Secret.
    # secret.yaml
    apiVersion: v1
    kind: Secret
    metadata:
    name: app-db-secret
    type: Opaque
    data:
    db-host: YmFy # echo -n 'bar' | base64
    db-name: YmFy
    db-user: YmFy
    db-password: c3VwZXJfc2VjcmV0X3Bhc3N3b3Jk # super_secret_password
    ---
    # deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    spec:
    template:
    spec:
      containers:
      - name: app
        image: myapp:latest
        env:
        - name: DB_HOST
          valueFrom:
            secretKeyRef:
              name: app-db-secret
              key: db-host
        # ... остальные переменные
  • В облачных средах (AWS, GCP, Azure): Использую нативные сервисы (AWS Secrets Manager, GCP Secret Manager, Azure Key Vault). Приложение получает секреты через их SDK или sidecar-контейнер.
  • Для локальной разработки: Использую .env файл, который находится в .gitignore. Загружаю его с помощью библиотеки python-dotenv или аналогичной.
    
    # .env (НЕ КОММИТИТЬ!)
    DB_HOST=localhost
    DB_NAME=mydb
    DB_USER=app_user
    DB_PASSWORD=dev_password

app.py

from dotenv import load_dotenv import os load_dotenv() # Загружает переменные из .env в os.environ

db_host = os.getenv('DB_HOST') db_pass = os.getenv('DB_PASSWORD')

Подключение к БД...


**2. Конфигурационные файлы вне корня веб-сервера**
Если по какой-то причине нельзя использовать переменные окружения, конфиг-файл должен находиться за пределами публичной директории (например, `/etc/myapp/config.ini`). Права доступа должны быть строгими (`chmod 600`).

```php
// config/db.inc.php (расположен НЕ в public_html/)
<?php
// Этот файл подключается main.php, который лежит на уровень выше.
return [
    'host' => getenv('DB_HOST') ?: 'localhost', // fallback для dev
    'name' => 'app_db',
    'user' => 'app_user',
    'pass' => file_get_contents('/run/secrets/db_password') // Чтение из Docker Secret
];

3. Шифрование секретов в системе контроля версий (Менее безопасно, но лучше plain-text) Инструменты вроде SOPS (Secrets OPerationS) или git-crypt позволяют хранить зашифрованные файлы в Git. Ключ дешифрования хранится отдельно (в CI/CD, у разработчиков).

Чего я НИКОГДА не делаю:

  • Не храню пароли в коде приложения, особенно в виде plain text.
  • Не использую конфигурационные файлы внутри корневой директории веб-сервера (/var/www/html/config.php).
  • Не коммичу файлы .env или любые другие файлы с секретами в Git.
  • Не использую одинаковые пароли для разных сред (dev/stage/prod).