使用 Webhooks 为 VerneMQ 实施 ACL
Implementing ACL with webhooks for VerneMQ
我正在尝试通过为 VerneMQ 实施我自己的 webhook 来获得 ACL 行为。为此,我正在使用 express
和 apicache
节点包。我希望代码对非 javascript 程序员也有意义。
在我的 vernemq.conf
中,我设置了我的钩子,它们被正确调用:
$ vmq-admin webhooks show
+-----------------+------------------------------+-------------+
| hook | endpoint |base64payload|
+-----------------+------------------------------+-------------+
|auth_on_subscribe|http://127.0.0.1:3000/vmq/sub | true |
|auth_on_register |http://127.0.0.1:3000/vmq/auth| true |
| auth_on_publish |http://127.0.0.1:3000/vmq/pub | true |
+-----------------+------------------------------+-------------+
我还禁用了所有其他插件并禁用了匿名登录。
我在 express
中的 webhooks 实现(简化):
const express = require('express');
const apicache = require('apicache');
const bodyparser = require('body-parser');
// short cache times for demonstration
const authcache = apicache.middleware('15 seconds');
const pubcache = apicache.middleware('5 seconds');
const subcache = apicache.middleware('10 seconds');
const app = express();
const jsonparser = bodyparser.json();
app.use((req, res, next) => {
console.log(`${req.connection.remoteAddress}:${req.connection.remotePort} ${req.method} ${req.path}`);
return next();
});
app.post('/vmq/auth', authcache, (req, res) => {
return res.status(200).json({result: 'ok'});
});
app.post('/vmq/pub', pubcache, jsonparser, (req, res) => {
// this gets ignored most of the time because of caching
if (req.body.topic === 'only/allowed/topic') {
return res.status(200).json({result: 'ok'});
}
return res.status(401).end();
});
app.post('/vmq/sub', subcache, (req, res) => {
return res.status(200).json({result: 'ok'});
});
app.use((req, res, next) => {
return res.status(404).end();
});
app.use((err, res, req, next) => {
console.error(err);
return res.status(500).end();
});
const server = app.listen(3000, 'localhost', () => {
const address = server.address();
return console.log(`listening on ${address.address}:${address.port} ...`);
});
使用mqtt.js
我写了一个客户端(简体):
const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://localhost');
client.on('connect', () => {
setInterval(() => {
client.publish('only/allowed/topic', 'working');
client.publish('some/disallowed/topic', 'working too :(');
}, 500);
return client.subscribe('some/disallowed/topic');
});
client.on('message', (topic, message) => {
return console.log(`${topic}:${message}`);
});
发生的事情是客户端成功验证然后发布到 only/allowed/topic
,这是允许的,并被 VerneMQ 缓存为成功。但是,由于现在缓存了对 /vmq/pub
的成功调用,因此发布到 some/disallowed/topic
也可以。如果我改变发布顺序,两者都会失败。
我本来希望 VerneMQ 将缓存的结果映射到调用中的所有参数,当然除了有效负载,而不仅仅是客户端连接。然而事实并非如此。 在使用缓存的同时通过 webhooks 实现 ACL 的可能方法是什么?不使用缓存是不可能的,因为这会降低我的性能,文档通常建议使用缓存。
此外,拥有 1500+ 代表的人会这么好心并创建标签 vernemq
吗? :)
我误解了 apicache
的工作原理以及它的实际作用。正如 VerneMQ 文档中所述,我需要做的只是为缓存设置适当的 header。显然 apicache
存储实际结果,而 returns 在指定的时间范围内询问时,无论客户端实际请求什么。
这是现在的工作代码:
const express = require('express');
const bodyparser = require('body-parser');
const app = express();
// short cache times for demonstration (in seconds)
const authcachetime = 15;
const pubcachetime = 5;
const subcachetime = 10;
const jsonparser = bodyparser.json();
app.use((req, res, next) => {
console.log(`${req.connection.remoteAddress}:${req.connection.remotePort} ${req.method} ${req.path}`);
return next();
});
app.post('/vmq/auth', (req, res) => {
res.set('cache-control', `max-age=${authcachetime}`);
return res.status(200).json({result: 'ok'});
});
app.post('/vmq/pub', jsonparser, (req, res) => {
res.set('cache-control', `max-age=${pubcachetime}`);
if (req.body.topic === 'only/allowed/topic') {
return res.status(200).json({result: 'ok'});
}
return res.status(401).end();
});
app.post('/vmq/sub', (req, res) => {
res.set('cache-control', `max-age=${subcachetime}`);
return res.status(200).json({result: 'ok'});
});
app.use((req, res, next) => {
return res.status(404).end();
});
app.use((err, res, req, next) => {
console.error(err);
return res.status(500).end();
});
const server = app.listen(3000, 'localhost', () => {
const address = server.address();
return console.log(`listening on ${address.address}:${address.port} ...`);
});
正如预期的那样,客户端现在在尝试发布到非法主题时会收到错误消息。
我正在尝试通过为 VerneMQ 实施我自己的 webhook 来获得 ACL 行为。为此,我正在使用 express
和 apicache
节点包。我希望代码对非 javascript 程序员也有意义。
在我的 vernemq.conf
中,我设置了我的钩子,它们被正确调用:
$ vmq-admin webhooks show
+-----------------+------------------------------+-------------+
| hook | endpoint |base64payload|
+-----------------+------------------------------+-------------+
|auth_on_subscribe|http://127.0.0.1:3000/vmq/sub | true |
|auth_on_register |http://127.0.0.1:3000/vmq/auth| true |
| auth_on_publish |http://127.0.0.1:3000/vmq/pub | true |
+-----------------+------------------------------+-------------+
我还禁用了所有其他插件并禁用了匿名登录。
我在 express
中的 webhooks 实现(简化):
const express = require('express');
const apicache = require('apicache');
const bodyparser = require('body-parser');
// short cache times for demonstration
const authcache = apicache.middleware('15 seconds');
const pubcache = apicache.middleware('5 seconds');
const subcache = apicache.middleware('10 seconds');
const app = express();
const jsonparser = bodyparser.json();
app.use((req, res, next) => {
console.log(`${req.connection.remoteAddress}:${req.connection.remotePort} ${req.method} ${req.path}`);
return next();
});
app.post('/vmq/auth', authcache, (req, res) => {
return res.status(200).json({result: 'ok'});
});
app.post('/vmq/pub', pubcache, jsonparser, (req, res) => {
// this gets ignored most of the time because of caching
if (req.body.topic === 'only/allowed/topic') {
return res.status(200).json({result: 'ok'});
}
return res.status(401).end();
});
app.post('/vmq/sub', subcache, (req, res) => {
return res.status(200).json({result: 'ok'});
});
app.use((req, res, next) => {
return res.status(404).end();
});
app.use((err, res, req, next) => {
console.error(err);
return res.status(500).end();
});
const server = app.listen(3000, 'localhost', () => {
const address = server.address();
return console.log(`listening on ${address.address}:${address.port} ...`);
});
使用mqtt.js
我写了一个客户端(简体):
const mqtt = require('mqtt');
const client = mqtt.connect('mqtt://localhost');
client.on('connect', () => {
setInterval(() => {
client.publish('only/allowed/topic', 'working');
client.publish('some/disallowed/topic', 'working too :(');
}, 500);
return client.subscribe('some/disallowed/topic');
});
client.on('message', (topic, message) => {
return console.log(`${topic}:${message}`);
});
发生的事情是客户端成功验证然后发布到 only/allowed/topic
,这是允许的,并被 VerneMQ 缓存为成功。但是,由于现在缓存了对 /vmq/pub
的成功调用,因此发布到 some/disallowed/topic
也可以。如果我改变发布顺序,两者都会失败。
我本来希望 VerneMQ 将缓存的结果映射到调用中的所有参数,当然除了有效负载,而不仅仅是客户端连接。然而事实并非如此。 在使用缓存的同时通过 webhooks 实现 ACL 的可能方法是什么?不使用缓存是不可能的,因为这会降低我的性能,文档通常建议使用缓存。
此外,拥有 1500+ 代表的人会这么好心并创建标签 vernemq
吗? :)
我误解了 apicache
的工作原理以及它的实际作用。正如 VerneMQ 文档中所述,我需要做的只是为缓存设置适当的 header。显然 apicache
存储实际结果,而 returns 在指定的时间范围内询问时,无论客户端实际请求什么。
这是现在的工作代码:
const express = require('express');
const bodyparser = require('body-parser');
const app = express();
// short cache times for demonstration (in seconds)
const authcachetime = 15;
const pubcachetime = 5;
const subcachetime = 10;
const jsonparser = bodyparser.json();
app.use((req, res, next) => {
console.log(`${req.connection.remoteAddress}:${req.connection.remotePort} ${req.method} ${req.path}`);
return next();
});
app.post('/vmq/auth', (req, res) => {
res.set('cache-control', `max-age=${authcachetime}`);
return res.status(200).json({result: 'ok'});
});
app.post('/vmq/pub', jsonparser, (req, res) => {
res.set('cache-control', `max-age=${pubcachetime}`);
if (req.body.topic === 'only/allowed/topic') {
return res.status(200).json({result: 'ok'});
}
return res.status(401).end();
});
app.post('/vmq/sub', (req, res) => {
res.set('cache-control', `max-age=${subcachetime}`);
return res.status(200).json({result: 'ok'});
});
app.use((req, res, next) => {
return res.status(404).end();
});
app.use((err, res, req, next) => {
console.error(err);
return res.status(500).end();
});
const server = app.listen(3000, 'localhost', () => {
const address = server.address();
return console.log(`listening on ${address.address}:${address.port} ...`);
});
正如预期的那样,客户端现在在尝试发布到非法主题时会收到错误消息。