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

Безопасность голосового провайдера

Версия v2.3.1 · Обновлено

Безопасность голосового провайдера#

Пользовательские провайдеры — это исполняемый Python-код.

Устанавливайте провайдеры только из доверенных источников.

Права доступа к каталогу#

Рекомендуемые права доступа:

sudo mkdir -p /usr/local/lib/incidentrelay/voice_providers
sudo chown root:root /usr/local/lib/incidentrelay/voice_providers
sudo chmod 755 /usr/local/lib/incidentrelay/voice_providers

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

  • пользователю веб-сервера;
  • пользователю приложения IncidentRelay;
  • недоверенным пользователям;
  • из интерфейса IncidentRelay.

Секреты#

Не задавайте секреты жёстко в файлах провайдеров.

Плохо:

api_token = "secret-token"

Хорошо:

"provider_config": {
  "api_token": "${VOICE_API_TOKEN}"
}

Затем настройте переменную окружения для сервиса IncidentRelay:

export VOICE_API_TOKEN="secret-token"

Для systemd используйте файл окружения или конфигурацию окружения сервиса.

Пример:

Environment="VOICE_API_TOKEN=secret-token"

Журналирование#

Провайдеры могут журналировать полезную операционную информацию, но не должны журналировать секреты или полные номера телефонов.

Хорошо:

import logging

logger = logging.getLogger("oncall.voice")


def mask_phone(phone):
    if not phone:
        return None

    value = str(phone)

    if len(value) <= 4:
        return "****"

    return f"***{value[-4:]}"


logger.info(
    "placing voice call",
    extra={
        "extra": {
            "provider": self.name,
            "phone": mask_phone(request.phone),
            "alert_id": request.alert_id,
            "event_type": request.event_type,
        }
    },
)

Плохо:

logger.info(f"calling {request.phone} with token {self.config['api_token']}")

Секреты колбэков#

Секреты колбэков должны быть уникальными и трудно угадываемыми.

Используйте секреты на уровне канала, когда это возможно:

{
  "callback_secret": "long-random-secret"
}

Избегайте коротких секретов:

test
123
secret
change-me

Подписи вебхуков провайдера#

Если ваш провайдер подписывает колбэки, проверяйте подпись внутри parse_callback().

Пример:

def parse_callback(self, payload, headers=None, raw_body=None, query_args=None):
    signature = headers.get("X-Provider-Signature") if headers else None

    if not self._is_valid_signature(raw_body or b"", signature):
        raise RuntimeError("invalid provider callback signature")

    ...

Рекомендуемые правила#

- The providers directory must not be writable by the web server user.
- The providers directory must not be writable from the IncidentRelay UI.
- Provider files should be reviewed before installation.
- Secrets should be passed through environment variables.
- Provider logs must not contain API tokens, passwords or full phone numbers.
- Callback secrets should be unique and hard to guess.
- Provider-specific webhook signatures should be validated when supported.

Не позволяйте недоверенным пользователям загружать файлы провайдеров.