Skip to main content
Мы публикуем частые обновления нашей документации, и перевод этой страницы может все еще выполняться. Актуальные сведения см. в документации на английском языке.
В настоящее время GitHub AE находится в ограниченном выпуске.

Защита веб-перехватчиков

Убедитесь, что сервер получает только ожидаемые запросы GitHub по соображениям безопасности.

После настройки сервера для получения полезных данных он будет ожидать передачи всех полезных данных, отправляемых в настроенную конечную точку. Из соображений безопасности можно разрешить только запросы, поступающие из GitHub. Это можно сделать несколькими способами (например, разрешить запросы с IP-адреса GitHub), но гораздо проще настроить секретный маркер и проверить информацию.

REST API можно использовать для управления веб-перехватчиками репозитория, организации и приложения. Вы можете перечислить доставку веб-перехватчиков для веб-перехватчика или получить и повторно получить отдельную доставку для веб-перехватчика, которую можно интегрировать во внешнее приложение или службу. Вы также можете использовать REST API для изменения конфигурации веб-перехватчика. Например, можно изменить URL-адрес полезных данных, тип контента, проверку SSL и секрет. Дополнительные сведения см. в разделе:

Настройка секретного маркера

Вам потребуется настроить секретный маркер в двух местах: в GitHub и на сервере.

Чтобы задать маркер в GitHub, выполните следующие действия.

  1. Перейдите в репозиторий, в котором вы настраиваете веб-перехватчик.

  2. Под именем репозитория щелкните Параметры. Если вкладка "Параметры" не отображается, выберите раскрывающееся меню и нажмите кнопку Параметры.

    Снимок экрана: заголовок репозитория с вкладками. Вкладка "Параметры" выделена темно-оранжевым контуром.

  3. На левой боковой панели щелкните веб-перехватчики .

  4. Рядом с веб-перехватчиком нажмите кнопку Изменить.

  5. В поле "Секрет" введите случайную строку с высокой энтропией. Например, можно создать строку с помощью ruby -rsecurerandom -e 'puts SecureRandom.hex(20)' в терминале.

  6. Щелкните Обновить веб-перехватчик.

Затем настройте переменную среды на сервере, в которой хранится этот маркер. Как правило, для этого достаточно просто выполнить:

$ export SECRET_TOKEN=YOUR-TOKEN

Никогда не применяйте жесткое кодирование маркера в приложении!

Проверка полезных данных из GitHub

При установке секретного маркера GitHub AE будет использовать его для создания хэш-подписи для каждой полезной нагрузки. Эта хэш-подпись включается в заголовки каждого запроса как x-hub-signature-256.

Необходимо вычислить хэш с помощью SECRET_TOKENи убедиться, что результат соответствует хэшу из GitHub AE. GitHub AE использует хэш-хэш HMAC.

Примечание. Полезные данные веб-перехватчика могут содержать символы Юникода. Если в реализации языка и сервера указана кодировка символов, убедитесь, что полезные данные обрабатываются как символы UTF-8.

Реализации языка и сервера могут отличаться от приведенных ниже примеров. Однако есть ряд важных моментов, которые следует учесть:

  • Независимо от используемой реализации хэш-подпись начинается с sha256=, используя ключ секретного маркера и текстовую область полезных данных.

  • Использовать обычный оператор == не рекомендуется. Такой метод, как secure_compare, выполняет сравнение "постоянных во времени" строк, что позволяет снизить определенные атаки по времени на регулярные операторы равенства.

Пример Ruby

Например, можно определить следующую verify_signature функцию:

def verify_signature(payload_body)
  signature = 'sha256=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), ENV['SECRET_TOKEN'], payload_body)
  return halt 500, "Signatures didn't match!" unless Rack::Utils.secure_compare(signature, request.env['HTTP_X_HUB_SIGNATURE_256'])
end

Затем его можно вызвать при получении полезных данных веб-перехватчика:

post '/payload' do
  request.body.rewind
  payload_body = request.body.read
  verify_signature(payload_body)
  push = JSON.parse(payload_body)
  "I got some JSON: #{push.inspect}"
end

Пример на Python

Например, можно определить следующую verify_signature функцию и вызвать ее при получении полезных данных веб-перехватчика:

import hashlib
import hmac
def verify_signature(payload_body, secret_token, signature_header):
    """Verify that the payload was sent from GitHub by validating SHA256.
    
    Raise and return 403 if not authorized.
    
    Args:
        payload_body: original request body to verify (request.body())
        secret_token: GitHub app webhook token (WEBHOOK_SECRET)
        signature_header: header received from GitHub (x-hub-signature-256)
    """
    if not signature_header:
        raise HTTPException(status_code=403, detail="x-hub-signature-256 header is missing!")
    hash_object = hmac.new(secret_token.encode('utf-8'), msg=payload_body, digestmod=hashlib.sha256)
    expected_signature = "sha256=" + hash_object.hexdigest()
    if not hmac.compare_digest(expected_signature, signature_header):
        raise HTTPException(status_code=403, detail="Request signatures didn't match!")

Пример Typescript

Например, можно определить следующую verify_signature функцию и вызвать ее при получении полезных данных веб-перехватчика:

JavaScript
import * as crypto from "crypto";

const WEBHOOK_SECRET: string = process.env.WEBHOOK_SECRET;

const verify_signature = (req: Request) => {
  const signature = crypto
    .createHmac("sha256", WEBHOOK_SECRET)
    .update(JSON.stringify(req.body))
    .digest("hex");
  return `sha256=${signature}` === req.headers.get("x-hub-signature-256");
};

const handleWebhook = (req: Request, res: Response) => {
  if (!verify_signature(req)) {
    res.status(401).send("Unauthorized");
    return;
  }
  // The rest of your logic here
};