Skip to content
This repository was archived by the owner on Jun 23, 2023. It is now read-only.

Commit 0f681db

Browse files
author
radekk
authoredNov 18, 2021
Feature/webhook secret (#79)
* fix: Do not run triggers by default * fix: Rename output file for Lambda deployment * fix: Do not return stack on error * feature: Add debug mode * fix: Normalize lambda event headers * feat: Add support for webhook secret * fix: Update path variable name for Lambda * fix: Update package lock file * fix: Point tests to proper lambda handler file * refactor: Failing early on the signature check
1 parent 9bbc327 commit 0f681db

File tree

9 files changed

+9415
-1133
lines changed

9 files changed

+9415
-1133
lines changed
 

‎config/main.json‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@
3434
"lambdaEventObjectNotFound": "Invalid request, event not found",
3535
"githubTokenNotProvided": "GITHUB_TOKEN is not set",
3636
"jwtTokenNotProvided": "JWT_SECRET is not set",
37-
"invalidReportID": "Report not found, invalid ID"
37+
"invalidReportID": "Report not found, invalid ID",
38+
"invalidWebhookSecret": "Webhook secret is not valid"
3839
},
39-
"runTriggers": true,
40+
"runTriggers": false,
4041
"triggerTextFormat": "mrkdwn",
4142
"triggerMessages": {
4243
"falsePositiveReported": ":warning: False positive reported (%s): %s",

‎config/webpack.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ const cliConfigLight = Object.assign({}, config, {
6060

6161
const lambdaConfigFull = Object.assign({}, config, {
6262
entry: {
63-
'./awslambda': './src/index.js'
63+
'./index': './src/index.js'
6464
},
6565
output: {
6666
filename: '[name].js',
@@ -71,7 +71,7 @@ const lambdaConfigFull = Object.assign({}, config, {
7171

7272
const lambdaConfigLight = Object.assign({}, config, {
7373
entry: {
74-
'./awslambda.light': './src/index.js'
74+
'./index.light': './src/index.js'
7575
},
7676
output: {
7777
filename: '[name].js',

‎package-lock.json‎

Lines changed: 9371 additions & 1122 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"build": "rm ./dist/* 2> /dev/null; webpack --config config/webpack.js && npm run package",
88
"cli": "node dist/cli.js",
99
"lint": "eslint src/ config/ --quiet",
10-
"package": "zip -j ./dist/awslambda.zip ./dist/awslambda.js",
10+
"package": "zip -j ./dist/awslambda.zip ./dist/index.js",
1111
"test": "npm run lint && mocha",
1212
"validate": "npm run lint && npm outdated --depth 0",
1313
"watch": "./bin/webpack --config config/webpack.js --watch --bail --display-error-details"
@@ -28,6 +28,7 @@
2828
},
2929
"dependencies": {
3030
"@octokit/rest": "^16.43.2",
31+
"@octokit/webhooks-methods": "^2.0.0",
3132
"acorn": "^5.7.3",
3233
"an-array-of-english-words": "^1.3.1",
3334
"handlebars": "^4.7.7",

‎src/dispatcher/index.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,12 @@ module.exports = async (payload, event, github, viewer, res, isFalsePositiveRepo
6767
return Promise.resolve(res(SUCCESS_MESSAGE));
6868
} catch (e) {
6969
const httpCode = Number.isSafeInteger(e.status) ? e.status : http.STATUS_CODE.ERROR;
70-
if (httpCode === 401) return res(e.stack, httpCode);
70+
if (httpCode === 401) return res(e.message, httpCode);
7171

7272
if (updateCIStatus) {
7373
status.setFailure(e.message);
7474
}
7575

76-
return res(e.stack, httpCode);
76+
return res(e.message, httpCode);
7777
}
7878
};

‎src/helpers/url.js‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ module.exports = {
66
if (!event.headers) return null;
77

88
return url.format({
9-
protocol: event.headers['X-Forwarded-Proto'],
10-
host: event.headers.Host,
11-
pathname: event.path
9+
protocol: event.headers['x-forwarded-proto'],
10+
host: event.headers.host,
11+
pathname: event.rawPath
1212
}).replace(/\/+$/g, '');
1313
},
1414
getRepoURL: (owner, repo) => `${config.githubUrl}/${owner}/${repo}`,

‎src/index.js‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,37 @@ const token = require('./helpers/jwt');
1010

1111
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
1212
const JWT_SECRET = process.env.JWT_SECRET;
13+
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET;
14+
const DEBUG = process.env.DEBUG;
1315

1416
const returnErrorResponse = message => Promise.resolve(http.response(message, http.STATUS_CODE.ERROR));
1517

1618
async function lambda(event) {
19+
if (DEBUG) console.log(event);
20+
1721
if (!GITHUB_TOKEN) { return returnErrorResponse(config.responseMessages.githubTokenNotProvided); }
1822
if (!JWT_SECRET) { return returnErrorResponse(config.responseMessages.jwtTokenNotProvided); }
1923
if (!event) { return returnErrorResponse(config.responseMessages.lambdaEventObjectNotFound); }
2024

2125
let requestBody;
2226
let requestParams = {};
2327

28+
/**
29+
* It seems like there are two types of Event object headers naming conventions.
30+
*
31+
* REST Private API: Camel-Case
32+
* REST Public API: lower-case
33+
*/
34+
if (event.headers) {
35+
const normalizedHeaders = {};
36+
37+
Object.keys(event.headers).forEach((id) => {
38+
normalizedHeaders[id.toLowerCase()] = event.headers[id];
39+
});
40+
41+
event.headers = normalizedHeaders;
42+
}
43+
2444
if (event.queryStringParameters) {
2545
requestParams = {
2646
isFalsePositiveReport: !!([1, '1', 'true', true].indexOf(event.queryStringParameters.false_positive) > -1),
@@ -81,6 +101,13 @@ async function lambda(event) {
81101
}
82102

83103
if (config.pullRequests.allowedActions.indexOf(requestBody.action) > -1) {
104+
if (WEBHOOK_SECRET && event.headers[service.HTTP_SIGNATURE_HEADER]) {
105+
const signature = event.headers[service.HTTP_SIGNATURE_HEADER];
106+
const isSigValid = await service.webhooks.verify(WEBHOOK_SECRET, event.body, signature);
107+
108+
if (!isSigValid) return returnErrorResponse(config.responseMessages.invalidWebhookSecret);
109+
}
110+
84111
return dispatcher(requestBody, event, service, view, http.response);
85112
}
86113

‎src/lib/github/index.js‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const Octokit = require('@octokit/rest').Octokit;
2+
const Webhook = require('@octokit/webhooks-methods');
23

34
module.exports = (apiToken) => {
45
const client = new Octokit({
@@ -9,5 +10,8 @@ module.exports = (apiToken) => {
910
}
1011
});
1112

13+
client.webhooks = Webhook;
14+
client.HTTP_SIGNATURE_HEADER = 'x-hub-signature-256';
15+
1216
return client;
1317
};

‎test/integration/src/awslambda.handler.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable object-shorthand */
22
/* eslint-disable max-len */
33
/* eslint-disable no-unused-expressions */
4-
const lambdaModule = './../../../dist/awslambda.light';
4+
const lambdaModule = './../../../dist/index.light';
55
const handler = require(lambdaModule).handler;
66
const config = require('./../../../config/main.json');
77
const http = require('./../../../src/helpers/http');

0 commit comments

Comments
 (0)
This repository has been archived.