Рубрики
Uncategorized

Дежол не должно быть сложно: составление отчетов

Ранее нам удалось сделать наше приложение повторно развертываться на каждом фиксации. Как вы можете вспомнить, мы получаем статую … Помечено JavaScript, Node, Devops.

DEVOPS (3 серии части)

Раньше нам удалось Сделайте наше приложение повторно развертываем на каждый коммит . Как вы можете вспомнить, мы получаем статус развертывания путем обработки результатов выполнения скриптов. Итак, давайте использовать его, чтобы отправить уведомление о себе каждый раз, когда мы развертываем наш код.

В этом отношении мы создадим еще одно приложение Node.js Server на нашем VPS. Вы можете продлить приложение, которое мы создали для непрерывного развертывания, хотя я не рекомендую это. Вместо этого мы можем сделать этот путь Unix, где каждое приложение делает свою работу и делает это хорошо. Кроме того, мы можем использовать сервер отчетности, чтобы уведомить нас о развертывании других частей нашего приложения, например, внешний интерфейс.

Как вы можете догадаться, нам нужно будет реализовать как клиент, так и серверные стороны приложения. Во-первых, нам понадобится клиент (наш сервер CD), который отправит запрос после успешного (или неудачного) развертывания. Во-вторых, мы сделаем сервер, который будет прослушивать эти запросы и отправлять его в дополнение к поставщику сообщений.

Говоря о том, какую услугу использовать для отправки этих сообщений, то есть 100% до. Лично я пользуюсь ботом Telegram для доставки сообщений мне, поэтому я буду использовать это в качестве примера, но этот дизайн позволяет использовать любой метод для доставки сообщений, таких как SMS, электронная почта, слабые или другие.

Клиент

Как и в случае с сервером CD, нам понадобится способ проверить аутентичность источника. На этот раз мы будем использовать JWT или JSON Web Tookens, чтобы подписать наши сообщения. Кроме того, на этот раз мы будем реализовывать как подписание, так и проверку.

Давайте начнем с помощью двух функций помощника, которые будут иметь дело с поколением JWT.

function _getHash(params) {
    const paramString = JSON.stringify(params);
    const hash = crypto
        .createHash('sha256')
        .update(paramString)
        .digest('hex');
    return hash;
}

function _sign(hash, secret) {
    const payload = {
        iss: 'server',
        sha256: hash,
    };
    const token = jwt.sign(payload, secret);
    return token;
}

Здесь _Gethash Создает хэш Sha256 тела сообщения и _sign Хорошо, подписывает его, используя секрет. Давайте использовать его в нашем клиенте.

const axios = require('axios');
const crypto = require('crypto');
const jwt = require('jsonwebtoken');

const client = axios.create({
    baseURL: 'https://our.reporting.server.url',
});

async function sendSuccess(app) {
    const params = {
        success: true,
        app,
    }
    const secret = process.env.SECRET;
    const hash = _getHash(params);
    const token = _sign(hash, secret);
    await client.post('/cd/server', params, {
        headers: {
            'X-Signature': token,
        },
    });
}

Здесь мы получаем наш секрет от .env Файл, используйте его, чтобы подписать тело запроса, а затем отправить его на наш сервер отчетности.

Несколько вещей, которые следует отметить:

  • URL, на котором находится сервер отчетов, замените oe.reporting.server.url с вашим.
  • конечная точка, которую мы отправляем запрос; Я использую /CD/Server Поскольку у меня есть другие источники, такие как NetLify, чтобы получать обновления, но вы можете использовать все, включая / Отказ
  • X-Signature заголовок Опять же, это может быть почти все, но я бы предложил прилипать к чему-то похожему, так как это вроде стандартное.

И это наш клиент. Давайте посмотрим на сервер сейчас.

Сервер

Опять же, мы начинаем с функции помощника.

function checkSignature(data, signature, secret, issuer) {
    if (signature == undefined) {
        return false;
    }
    let decoded;
    try {
        decoded = jwt.verify(signature, secret);
    } catch(e) {
        return false;
    }
    const dataString = JSON.stringify(data);
    const hash = crypto
        .createHash('sha256')
        .update(dataString)
        .digest('hex');
    const hashMatches = decoded.sha256 == hash;
    const issuerMatches = decoded.iss == issuer;
    if (!hashMatches || !issuerMatches) {
        return false;
    }
    return true;
}

Подобно одному в статье на сервере CD, это Checksignature Функция подтверждает, что подпись подлинной.

Вот остальная часть сервера.

const crypto = require('crypto');
const jwt = require('jsonwebtoken');

app.post('/cd/server', async (req, res) {
    const data = req.body;
    const signature = req.header('X-Signature');

    const secret = process.env.SERVER_SECRET;
    const issuer = 'server';
    if (!checkSignature(data, signature, secret, issuer)) {
        res.status(403).end();
    }
    const success = data.success;
    const app = data.app;
    const error = data.error;
    bot.cd('Server', app, success);
    res.send('Hello server!');
});

Что мы здесь делаем, проверяйте подпись и отправьте сообщение. Сообщение отправляется через поставщик по вашему выбору. Здесь это телеграмма бота ( Bot.cd («сервер», приложение, успешное); ).

Бонус: NetLify

В качестве другого примера, давайте попробуем отправить сообщение каждый раз, когда наш Frestend обновляется в NetLify.

Теперь NetLify, очевидно, не нужно бить наш сервер CD, так как он сам CD. Вместо этого WebHook NetLify поедет прямо в наш отчетливый сервер.

К счастью, здесь мы можем повторно использовать большую часть кода, который мы писали ранее (NetLify использует JWT для подписания запросов WebHook).

app.post('/cd/netlify', async (req, res) {
    const data = req.body;
    const signature = req.header('X-Webhook-Signature');
    const secret = process.env.NETLIFY_SECRET;
    const issuer = 'netlify';
    if (!checkSignature(data, signature, secret, issuer)) {
        res.status(403).end();
    }
    const success = data.state == 'ready';
    const app = data.name;
    bot.cd('Netlify', app, success);
    res.send('Hello Netlify!');
});

Здесь мы извлекаем подпись от заголовка, сопоставьте его с нашим локально сохраненным ключом и отправьте сообщение, если подпись действительна.

Примечание : Netlify_secret и Server_Secret Не есть быть другим, но я настоятельно рекомендую сделать их так. В противном случае, если один ключ утечка (скажем, хакерской атакой на NetLify), другой также будет скомпрометирован, что делает ваш стек менее безопасным.

Чтобы добавить веб-капли в NetLify, откройте проект, затем нажмите Настройки -> Build & Deploy -> Развернуть уведомления Затем нажмите Добавить уведомление -> Исходящие веб -ook Отказ Вы можете добавить веб-капли для успешных или неудачных сборки среди других событий.

Бонус 2: Обработка ошибок

Хорошо, я знаю, что теперь вы устали, но есть еще одна захватывающая вещь, которую я хочу поделиться с вами: регистрация ошибок. Другими словами, это позволит вам получать уведомления каждый раз, когда у вас есть ошибка в вашем приложении.

По сути, очень похоже на отправку запроса с сервера CD, только на этот раз мы отправим ошибку.

В вашем приложении Node.js добавьте пользовательский обработчик ошибок:

function errorWatcher(err, req, res, next) {
    if (process.env.ENV == 'dev') {
        console.log(err);
    }
    if (process.env.ENV == 'prod') {
        _sendRuntimeFailure(err.toString());
    }
    next(err);
}

async function _sendRuntimeFailure(error) {
    const app = 'my-app';
    const params = {
        app,
        error,
    };
    const hash = _getHash(params);
    const secret = process.env.SECRET;
    const token = _sign(hash, secret);
    await client.post('/runtime', params, {
        headers: {
            'X-Signature': token,
        },
    });
}

Функции _gethash. и _sign такие же, как мы использовали выше. Мы также используем .env.env. Чтобы установить переменную ENV в дев или продлицо . Таким образом, вам будет отправлено только производственные ошибки.

Единственное, что осталось, — сказать Express о нашем обработке.

app.use(errorWatcher);

Нам также нужно будет обернуть наши асинхронные маршруты, чтобы убедиться, что ошибка передана нашему обработчику.

app.get('/endpoint', wrapAsync(router.endpoint));

// Helper function to pass error down the middleware chain
function wrapAsync(fn) {
    return function(req, res, next) {
        fn(req, res, next).catch(next);
    };
}

Вот и все. На стороне сервера отчетности это на 100% идентична для того, что мы использовали для сервера CD и NetLify: получите подпись, проверьте его, и отправить сообщение подпись действительна.

Упаковка

Здесь мы создали другой микросервер, на этот раз для отчетности. Сервер собирает события из нескольких источников и направляет их в одно место, например, Телеграмма. Нам удалось отправлять события на основе вашего сервера CD, NetLify и Express.js Обработчик ошибок приложения.

DEVOPS (3 серии части)

Оригинал: «https://dev.to/destiner/devops-shouldn-t-be-hard-reporting-1a1b»