2020-02-09 17:01:43 +02:00
|
|
|
const crypto = require('crypto');
|
|
|
|
const axios = require('axios');
|
|
|
|
|
|
|
|
const verifySignature = event => {
|
|
|
|
const timestamp = Number(event.headers['x-slack-request-timestamp']);
|
|
|
|
const time = Math.floor(Date.now() / 1000);
|
|
|
|
if (time - timestamp > 60 * 5) {
|
|
|
|
throw new Error(`Failed verifying signature. Timestamp too old '${timestamp}'`);
|
|
|
|
}
|
|
|
|
const body = event.body;
|
|
|
|
const sigString = `v0:${timestamp}:${body}`;
|
|
|
|
const actualSignature = event.headers['x-slack-signature'];
|
|
|
|
const secret = process.env.SLACK_SIGNING_SECRET;
|
|
|
|
|
|
|
|
const hash = crypto
|
|
|
|
.createHmac('sha256', secret)
|
|
|
|
.update(sigString, 'utf8')
|
|
|
|
.digest('hex');
|
|
|
|
|
|
|
|
const expectedSignature = `v0=${hash}`;
|
|
|
|
|
|
|
|
const signaturesMatch = crypto.timingSafeEqual(
|
|
|
|
Buffer.from(actualSignature, 'utf8'),
|
|
|
|
Buffer.from(expectedSignature, 'utf8'),
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!signaturesMatch) {
|
|
|
|
throw new Error(
|
|
|
|
`Signatures don't match. Expected: '${expectedSignature}', actual: '${actualSignature}'`,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.handler = async function(event) {
|
|
|
|
try {
|
2022-09-28 20:04:00 -06:00
|
|
|
console.info(
|
2020-04-01 14:41:55 +03:00
|
|
|
JSON.stringify(
|
|
|
|
{
|
|
|
|
event,
|
|
|
|
env: {
|
|
|
|
PUBLISH_COMMAND: process.env.PUBLISH_COMMAND,
|
|
|
|
ALLOWED_USERS: process.env.ALLOWED_USERS,
|
|
|
|
GITHUB_REPO: process.env.GITHUB_REPO,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
null,
|
|
|
|
2,
|
|
|
|
),
|
|
|
|
);
|
2020-02-09 17:01:43 +02:00
|
|
|
verifySignature(event);
|
|
|
|
|
|
|
|
const params = new URLSearchParams(event.body);
|
|
|
|
const command = params.get('command');
|
|
|
|
const userId = params.get('user_id');
|
|
|
|
|
|
|
|
const allowedUsers = (process.env.ALLOWED_USERS || '').split(',');
|
|
|
|
if (!allowedUsers.includes(userId)) {
|
|
|
|
throw new Error(`User '${params.get('user_name')}' is not allowed to run command`);
|
|
|
|
}
|
|
|
|
|
|
|
|
const expectedCommand = process.env.PUBLISH_COMMAND;
|
|
|
|
if (expectedCommand && expectedCommand == command) {
|
|
|
|
const githubToken = process.env.GITHUB_TOKEN;
|
|
|
|
const repo = process.env.GITHUB_REPO;
|
|
|
|
await axios({
|
|
|
|
headers: { Authorization: `token ${githubToken}` },
|
|
|
|
method: 'post',
|
|
|
|
url: `https://api.github.com/repos/${repo}/dispatches`,
|
|
|
|
data: { event_type: 'on-demand-github-action' },
|
|
|
|
});
|
|
|
|
const message = 'Dispatched event to GitHub';
|
|
|
|
return { status: 200, body: message };
|
|
|
|
} else {
|
|
|
|
throw new Error(`Command is not allowed. Expected: ${expectedCommand}. Actual: ${command}`);
|
|
|
|
}
|
|
|
|
} catch (e) {
|
2022-09-28 20:04:00 -06:00
|
|
|
console.info(e);
|
2020-02-09 17:01:43 +02:00
|
|
|
const response = {
|
|
|
|
body: 'Unauthorized',
|
|
|
|
status: 401,
|
|
|
|
};
|
|
|
|
return response;
|
|
|
|
}
|
|
|
|
};
|