Перейти к содержанию

Загрузчик настроек

Модуль loader предоставляет функционал для безопасной загрузки настроек и секретов из защищенного хранилища в переменные окружения приложения. Использует паттерн "Провайдер секретов" для абстракции источника данных.

Особенности

  • Гибкая система загрузки секретов через абстрактный интерфейс ISecretsProvider
  • Поддержка различных провайдеров секретов (по умолчанию используется Vault)
  • Потокобезопасная работа с переменными окружения
  • Детальное логирование операций
  • Обработка ошибок с конкретными типами исключений

Документация API

SettingsLoader

Загружает секреты из хранилища секретов в переменные окружения.

Source code in src/config/loader.py
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class SettingsLoader:
    """Загружает секреты из хранилища секретов в переменные окружения."""

    def __init__(self, secrets_provider: ISecretsProvider | None = None) -> None:
        try:
            self._sp = secrets_provider or VaultClient()
            logger.info(f'{SettingsLoader.__name__} успешно инициализирован')
        except Exception as e:
            logger.exception(f'Ошибка при инициализации {SettingsLoader.__name__}')
            raise SettingsLoaderInitializationError(
                f'Ошибка при инициализации {SettingsLoader.__name__}: {e}',
            ) from e

    async def load(self) -> None:
        """Загружает секреты из хранилища секретов в env."""
        secret_paths = [
            'eebook/users',
        ]
        for path in secret_paths:
            data = await self._sp.get_secret(path)
            for key, value in data.items():
                os.environ[key] = str(value)
        logger.info('Секреты успешно загружены в окружение')

load() -> None async

Загружает секреты из хранилища секретов в env.

Source code in src/config/loader.py
24
25
26
27
28
29
30
31
32
33
async def load(self) -> None:
    """Загружает секреты из хранилища секретов в env."""
    secret_paths = [
        'eebook/users',
    ]
    for path in secret_paths:
        data = await self._sp.get_secret(path)
        for key, value in data.items():
            os.environ[key] = str(value)
    logger.info('Секреты успешно загружены в окружение')

Примеры использования

Базовое использование с Vault по умолчанию

from src.config.loader import SettingsLoader

# Создание загрузчика с провайдером по умолчанию (Vault)
loader = SettingsLoader()

# Загрузка секретов в переменные окружения
await loader.load()

# Теперь секреты доступны через os.environ
import os
print(os.environ['DATABASE_URL'])  # Пример использования загруженного секрета

Использование с кастомным провайдером

from src.config.loader import SettingsLoader
from my_secrets_provider import MyCustomSecretsProvider

# Инициализация с пользовательским провайдером
custom_provider = MyCustomSecretsProvider()
loader = SettingsLoader(secrets_provider=custom_provider)

# Загрузка секретов
await loader.load()

Рекомендации по использованию

  1. Инициализация
  2. Создавайте экземпляр SettingsLoader на ранних этапах инициализации приложения
  3. Используйте внедрение зависимостей для передачи провайдера секретов

  4. Безопасность

  5. Никогда не храните реальные секреты в коде или системе контроля версий
  6. Используйте минимально необходимые права доступа для токенов Vault
  7. Регулярно обновляйте токены доступа

  8. Обработка ошибок

    try:
        loader = SettingsLoader()
        await loader.load()
    except SettingsLoaderInitializationError as e:
        # Обработка ошибок инициализации
        logger.error(f'Ошибка инициализации загрузчика: {e}')
        raise
    except Exception as e:
        # Обработка прочих ошибок
        logger.error(f'Неизвестная ошибка при загрузке настроек: {e}')
        raise
    

  9. Тестирование

  10. Используйте моки для ISecretsProvider в тестах
  11. Тестируйте различные сценарии ошибок
  12. Проверяйте корректность загрузки секретов в окружение

Ограничения

  • Поддерживается только асинхронный API
  • По умолчанию загружаются только секреты из пути 'eebook/users'
  • Все значения преобразуются в строки при загрузке в окружение