From ab3d331e02113993b8d268d0983f52c40b77bb3b Mon Sep 17 00:00:00 2001 From: Mathieu Gilet Date: Mon, 6 Jan 2025 16:51:29 +0100 Subject: [PATCH] feat: add disable rule management in slack interactive endpoint --- config.js | 1 + run/controllers/slack.js | 8 +- test/acceptance/run/slack_test.js | 123 ++++++++++++++++++++++++++++++ 3 files changed, 131 insertions(+), 1 deletion(-) diff --git a/config.js b/config.js index e8fd6caa..e7aab814 100644 --- a/config.js +++ b/config.js @@ -189,6 +189,7 @@ const configuration = (function () { config.baleen.protectedFrontApps = ['Pix_Test']; config.slack.blockedAccessesChannelId = 'C08700JG7QU'; + config.slack.botToken = 'fakeToken'; config.datadog.token = 'token'; diff --git a/run/controllers/slack.js b/run/controllers/slack.js index 554b490d..c5eddfdc 100644 --- a/run/controllers/slack.js +++ b/run/controllers/slack.js @@ -4,6 +4,8 @@ import { getAppStatusFromScalingo } from '../services/slack/app-status-from-scal import * as commands from '../services/slack/commands.js'; import shortcuts from '../services/slack/shortcuts.js'; import viewSubmissions from '../services/slack/view-submissions.js'; +import blockActions from '../services/slack/block-actions.js'; +import { AutomaticRule } from '../models/AutomaticRule.js'; function _getDeployStartedMessage(release, appName) { return `Commande de déploiement de la release "${release}" pour ${appName} en production bien reçue.`; @@ -154,8 +156,12 @@ const slack = { return viewSubmissions.submitCreateAppOnScalingoConfirmation(payload); } return null; - case 'view_closed': case 'block_actions': + if (payload?.actions[0]?.action_id === AutomaticRule.DISABLE) { + return blockActions.disableAutomaticRule(payload); + } + return null; + case 'view_closed': default: logger.info({ event: 'slack', message: 'This kind of interaction is not yet supported by Pix Bot.' }); return null; diff --git a/test/acceptance/run/slack_test.js b/test/acceptance/run/slack_test.js index 215f7cc5..1942e4dd 100644 --- a/test/acceptance/run/slack_test.js +++ b/test/acceptance/run/slack_test.js @@ -5,8 +5,12 @@ import { nock, nockGithubWithConfigChanges, nockGithubWithNoConfigChanges, + sinon, StatusCodes, } from '../../test-helper.js'; +import dayjs from 'dayjs'; +import { config } from '../../../config.js'; +import { AutomaticRule } from '../../../run/models/AutomaticRule.js'; describe('Acceptance | Run | Slack', function () { describe('POST /run/slack/interactive-endpoint', function () { @@ -453,5 +457,124 @@ describe('Acceptance | Run | Slack', function () { }); }); }); + + describe('when using the block action disable-automatic-rule', function () { + let clock; + let now; + + beforeEach(function () { + now = new Date('2024-01-01'); + clock = sinon.useFakeTimers({ now, toFake: ['Date'] }); + }); + + afterEach(function () { + clock.restore(); + }); + + it('should disable rule in CDN and update slack message', async function () { + // given + const ip = '127.0.0.1'; + const ja3 = '9709730930'; + const date = dayjs(now); + const rules = [ + { namespaceKey: 'namespaceKey1', ruleId: 'ruleId1' }, + { namespaceKey: 'namespaceKey2', ruleId: 'ruleId2' }, + ]; + const messageTimestamp = '1735836582.877169'; + + const body = { + type: 'block_actions', + message: { + ts: messageTimestamp, + attachments: [ + { + blocks: [ + { fields: [{ text: 'IP' }, { text: ip }] }, + { fields: [{ text: 'JA3' }, { text: ja3 }] }, + { elements: [{ text: `At ${date.format('DD/MM/YYYY HH:mm:ss')}` }] }, + ], + }, + ], + }, + actions: [ + { + action_id: AutomaticRule.DISABLE, + value: JSON.stringify(rules), + }, + ], + }; + + for (const rule of rules) { + nock('https://console.baleen.cloud/api', { + reqheaders: { + 'X-Api-Key': config.baleen.pat, + 'Content-type': 'application/json', + Cookie: `baleen-namespace=${rule.namespaceKey}`, + }, + }) + .patch(`/configs/custom-static-rules/${rule.ruleId}`, { + enabled: false, + }) + .reply(200); + } + + nock('https://slack.com', { + reqheaders: { + 'Content-type': 'application/json', + Authorization: 'Bearer fakeToken', + }, + }) + .post(`/api/chat.update`, { + channel: 'C08700JG7QU', + ts: '1735836582.877169', + as_user: true, + text: 'Règle de blocage mise en place sur Baleen.', + attachments: [ + { + color: '#106c1f', + blocks: [ + { + fields: [ + { type: 'mrkdwn', text: 'IP' }, + { type: 'mrkdwn', text: '127.0.0.1' }, + ], + type: 'section', + }, + { + fields: [ + { type: 'mrkdwn', text: 'JA3' }, + { type: 'mrkdwn', text: '9709730930' }, + ], + type: 'section', + }, + { elements: [{ type: 'mrkdwn', text: 'At 01/01/2024 01:00:00' }], type: 'context' }, + { type: 'divider' }, + { + fields: [ + { type: 'mrkdwn', text: 'Règle désactivée le' }, + { type: 'mrkdwn', text: '01/01/2024 01:00:00' }, + ], + type: 'section', + }, + ], + fallback: 'Règle de blocage mise en place sur Baleen.', + }, + ], + }) + .reply(200); + + // when + const res = await server.inject({ + method: 'POST', + url: '/run/slack/interactive-endpoint', + headers: createSlackWebhookSignatureHeaders(JSON.stringify(body)), + payload: body, + }); + + // then + expect(res.statusCode).to.equal(200); + expect(nock.isDone()).to.be.true; + }); + }); }); });