21 нояб. 2020
РедактироватьDskr.dev: Настройка github webhooks
В предыдущей статье я рассказал как перенёс статьи в отдельный репозиторий. Многие заметили что в этом решении есть проблема. Чтоб понять что добавилась новая статья, я раз в минуту делаю запросы и сверяю время модификации репозитория. Для таких случаев правильнее использовать webhooks.
Настроить webhook в гитхабе достаточно просто. Нужно написать немного кода для обработки и верификации webhook`а.
import { config } from "dotenv";
import Koa from "koa";
import Router from "@koa/router";
import parser from "koa-bodyparser";
import { createHmac } from "crypto";
config();
const app = new Koa();
const router = new Router();
app.use(parser());
router.post("/hooks/github", (ctx) => {
// Подписываем body запроса нашим секретом.
const key = createHmac("sha256", process.env.WEBHOOK_SECRET as string)
.update(JSON.stringify(ctx.request.body))
.digest("hex");
// Сверяем получившуюся подпись, с подписью указанной в заголовке запроса.
if (ctx.request.headers["x-hub-signature-256"] !== "sha256=" + key) {
return 404;
}
// Тут будет наш код который должен вызываться по webhook`у.
// Отвечаем что-нибудь гитхабу. Главное чтоб код ответа был 200.
ctx.body = { status: "ok" };
});
app.use(router.routes());
app.listen(8000);
Секретный ключ не должен хранится в репозитории, а значит и в коде приложения.
Правильным вариантом будет хранить его в .env файле. А для загрузки переменных
окружения можно использовать dotenv
.
Чтобы убедится, что запрос приходит от гитхаба и по пути его никто не мог модифицировать, используется криптографическая подпись HMAC. Гитхаб при отправке сообщения подписывает body секретным ключом, который мы указываем при настройке webhook`а. А в коде приложения мы подписываем пришедший в запросе body и сверяем получившуюся подпись. Если подпись совпадает, то мы можем быть уверенны, что тот кто отправил этот запрос знает наш секрет, соответственно ему можно доверять.
В моём случае проверка подписи на самом деле не очень нужна, так как я использую webhook только для того, чтобы понять что в репозитории что-то изменилось и нужно пойти и обновить посты. Единственная угроза которая может быть, это то что злоумышленник заставит моё приложение очень часто обновлять посты, и у меня кончится лимит запросов к гитхабу.
В самом интерфейсе гитхаба в настройках репозитория со статьями нужно добавить webhook.
Payload URL
- урл по которому мы будем обрабатывать webhook, желательно чтоб
это был https.
Content type
- в большинстве случаев лучше выбрать json
.
Secret
- тот самый секрет который мы записали в .env
. Это может быть любая
строка, для генерации лучше воспользоваться генератором паролей, я использую
Bitwarden. Строка из 40 символов, включая большие и маленькие буквы и цифры
достаточно безопасна.
Единственная сложность которая может возникнуть при разработке приложения с webhook, это необходимость белого ip адреса для тестирования. Но если его нет, то можно воспользоваться сервисом ngrok. Он позволяет задать публичный url для локальной разработки и тестирования.