plugins.rst 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. .. _plugins:
  2. =======
  3. Plugins
  4. =======
  5. The emqttd broker could be extended by plugins. Users could develop plugins to customize authentication, ACL and functions of the broker, or integrate the broker with other systems.
  6. The plugins that emqtt project released:
  7. +---------------------------+---------------------------+
  8. | Plugin | Description |
  9. +===========================+===========================+
  10. | `emqttd_plugin_template`_ | Template Plugin |
  11. +---------------------------+---------------------------+
  12. | `emqttd_dashboard`_ | Web Dashboard |
  13. +---------------------------+---------------------------+
  14. | `emqttd_plugin_mysql`_ | MySQL Auth/ACL Plugin |
  15. +---------------------------+---------------------------+
  16. | `emqttd_plugin_pgsql`_ | PostgreSQL Auth/ACL Plugin|
  17. +---------------------------+---------------------------+
  18. | `emqttd_plugin_redis`_ | Redis Auth/ACL Plugin |
  19. +---------------------------+---------------------------+
  20. | `emqttd_stomp`_ | STOMP Protocol Plugin |
  21. +---------------------------+---------------------------+
  22. | `emqttd_sockjs`_ | STOMP over SockJS Plugin |
  23. +---------------------------+---------------------------+
  24. | `emqttd_recon`_ | Recon Plugin |
  25. +---------------------------+---------------------------+
  26. ----------------------------------------
  27. emqttd_plugin_template - Template Plugin
  28. ----------------------------------------
  29. A plugin is just a normal Erlang application under the 'emqttd/plugins' folder. Each plugin has e configuration file: 'etc/plugin.config'.
  30. plugins/emqttd_plugin_template is a demo plugin. The folder structure:
  31. +------------------------+---------------------------+
  32. | File | Description |
  33. +========================+===========================+
  34. | etc/plugin.config | Plugin config file |
  35. +------------------------+---------------------------+
  36. | ebin/ | Erlang program files |
  37. +------------------------+---------------------------+
  38. Load, unload Plugin
  39. -------------------
  40. Use 'bin/emqttd_ctl plugins' CLI to load, unload a plugin::
  41. ./bin/emqttd_ctl plugins load <PluginName>
  42. ./bin/emqttd_ctl plugins unload <PluginName>
  43. ./bin/emqttd_ctl plugins list
  44. -----------------------------------
  45. emqttd_dashboard - Dashboard Plugin
  46. -----------------------------------
  47. The Web Dashboard for emqttd broker. The plugin will be loaded automatically when the broker started successfully.
  48. +------------------+---------------------------+
  49. | Address | http://localhost:18083 |
  50. +------------------+---------------------------+
  51. | Default User | admin |
  52. +------------------+---------------------------+
  53. | Default Password | public |
  54. +------------------+---------------------------+
  55. .. image:: _static/images/dashboard.png
  56. Configure Dashboard
  57. -------------------
  58. emqttd_dashboard/etc/plugin.config::
  59. [
  60. {emqttd_dashboard, [
  61. {default_admin, [
  62. {login, "admin"},
  63. {password, "public"}
  64. ]},
  65. {listener,
  66. {emqttd_dashboard, 18083, [
  67. {acceptors, 4},
  68. {max_clients, 512}]}
  69. }
  70. ]}
  71. ].
  72. -------------------------------------------
  73. emqttd_plugin_mysql - MySQL Auth/ACL Plugin
  74. -------------------------------------------
  75. MQTT Authentication, ACL with MySQL database.
  76. MQTT User Table
  77. ---------------
  78. .. code:: sql
  79. CREATE TABLE `mqtt_user` (
  80. `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  81. `username` varchar(100) DEFAULT NULL,
  82. `password` varchar(100) DEFAULT NULL,
  83. `salt` varchar(20) DEFAULT NULL,
  84. `created` datetime DEFAULT NULL,
  85. PRIMARY KEY (`id`),
  86. UNIQUE KEY `mqtt_username` (`username`)
  87. ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
  88. MQTT ACL Table
  89. --------------
  90. .. code:: sql
  91. CREATE TABLE `mqtt_acl` (
  92. `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  93. `allow` int(1) DEFAULT NULL COMMENT '0: deny, 1: allow',
  94. `ipaddr` varchar(60) DEFAULT NULL COMMENT 'IpAddress',
  95. `username` varchar(100) DEFAULT NULL COMMENT 'Username',
  96. `clientid` varchar(100) DEFAULT NULL COMMENT 'ClientId',
  97. `access` int(2) NOT NULL COMMENT '1: subscribe, 2: publish, 3: pubsub',
  98. `topic` varchar(100) NOT NULL DEFAULT '' COMMENT 'Topic Filter',
  99. PRIMARY KEY (`id`)
  100. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  101. Configure emqttd_plugin_mysql/etc/plugin.config
  102. -----------------------------------------------
  103. Configure MySQL host, username, password and database::
  104. [
  105. {emqttd_plugin_mysql, [
  106. {mysql_pool, [
  107. %% ecpool options
  108. {pool_size, 4},
  109. {auto_reconnect, 3},
  110. %% mysql options
  111. {host, "localhost"},
  112. {port, 3306},
  113. {user, ""},
  114. {password, ""},
  115. {database, "mqtt"},
  116. {encoding, utf8}
  117. ]},
  118. %% select password only
  119. {authquery, "select password from mqtt_user where username = '%u' limit 1"},
  120. %% hash algorithm: md5, sha, sha256, pbkdf2?
  121. {password_hash, sha256},
  122. %% select password with salt
  123. %% {authquery, "select password, salt from mqtt_user where username = '%u'"},
  124. %% sha256 with salt prefix
  125. %% {password_hash, {salt, sha256}},
  126. %% sha256 with salt suffix
  127. %% {password_hash, {sha256, salt}},
  128. %% comment this query, the acl will be disabled
  129. {aclquery, "select * from mqtt_acl where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'"},
  130. %% If no rules matched, return...
  131. {acl_nomatch, allow}
  132. ]}
  133. ].
  134. Load emqttd_plugin_mysql plugin
  135. -------------------------------
  136. .. code::
  137. ./bin/emqttd_ctl plugins load emqttd_plugin_mysql
  138. ------------------------------------------------
  139. emqttd_plugin_pgsql - PostgreSQL Auth/ACL Plugin
  140. ------------------------------------------------
  141. MQTT Authentication, ACL with PostgreSQL Database.
  142. MQTT User Table
  143. ---------------
  144. .. code:: sql
  145. CREATE TABLE mqtt_user (
  146. id SERIAL primary key,
  147. username character varying(100),
  148. password character varying(100),
  149. salt character varying(40)
  150. );
  151. MQTT ACL Table
  152. --------------
  153. .. code:: sql
  154. CREATE TABLE mqtt_acl (
  155. id SERIAL primary key,
  156. allow integer,
  157. ipaddr character varying(60),
  158. username character varying(100),
  159. clientid character varying(100),
  160. access integer,
  161. topic character varying(100)
  162. );
  163. INSERT INTO mqtt_acl (id, allow, ipaddr, username, clientid, access, topic)
  164. VALUES
  165. (1,1,NULL,'$all',NULL,2,'#'),
  166. (2,0,NULL,'$all',NULL,1,'$SYS/#'),
  167. (3,0,NULL,'$all',NULL,1,'eq #'),
  168. (5,1,'127.0.0.1',NULL,NULL,2,'$SYS/#'),
  169. (6,1,'127.0.0.1',NULL,NULL,2,'#'),
  170. (7,1,NULL,'dashboard',NULL,1,'$SYS/#');
  171. Configure emqttd_plugin_pgsql/etc/plugin.config
  172. -----------------------------------------------
  173. Configure host, username, password and database of PostgreSQL::
  174. [
  175. {emqttd_plugin_pgsql, [
  176. {pgsql_pool, [
  177. %% ecpool options
  178. {pool_size, 4},
  179. {auto_reconnect, 3},
  180. %% pgsql options
  181. {host, "localhost"},
  182. {port, 5432},
  183. {username, "feng"},
  184. {password, ""},
  185. {database, "mqtt"},
  186. {encoding, utf8}
  187. ]},
  188. %% select password only
  189. {authquery, "select password from mqtt_user where username = '%u' limit 1"},
  190. %% hash algorithm: md5, sha, sha256, pbkdf2?
  191. {password_hash, sha256},
  192. %% select password with salt
  193. %% {authquery, "select password, salt from mqtt_user where username = '%u'"},
  194. %% sha256 with salt prefix
  195. %% {password_hash, {salt, sha256}},
  196. %% sha256 with salt suffix
  197. %% {password_hash, {sha256, salt}},
  198. %% Comment this query, the acl will be disabled. Notice: don't edit this query!
  199. {aclquery, "select allow, ipaddr, username, clientid, access, topic from mqtt_acl
  200. where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'"},
  201. %% If no rules matched, return...
  202. {acl_nomatch, allow}
  203. ]}
  204. ].
  205. Load emqttd_plugin_pgsql Plugin
  206. -------------------------------
  207. .. code:: shell
  208. ./bin/emqttd_ctl plugins load emqttd_plugin_pgsql
  209. -------------------------------------------
  210. emqttd_plugin_redis - Redis Auth/ACL Plugin
  211. -------------------------------------------
  212. MQTT Authentication, ACL with Redis.
  213. Configure emqttd_plugin_redis/etc/plugin.config
  214. -----------------------------------------------
  215. .. code:: erlang
  216. [
  217. {emqttd_plugin_redis, [
  218. {eredis_pool, [
  219. %% ecpool options
  220. {pool_size, 8},
  221. {auto_reconnect, 2},
  222. %% eredis options
  223. {host, "127.0.0.1"},
  224. {port, 6379},
  225. {database, 0},
  226. {password, ""}
  227. ]},
  228. %% HMGET mqtt_user:%u password
  229. {authcmd, ["HGET", "mqtt_user:%u", "password"]},
  230. %% Password hash algorithm: plain, md5, sha, sha256, pbkdf2?
  231. {password_hash, sha256},
  232. %% SMEMBERS mqtt_acl:%u
  233. {aclcmd, ["SMEMBERS", "mqtt_acl:%u"]},
  234. %% If no rules matched, return...
  235. {acl_nomatch, deny},
  236. %% Store subscriptions to redis when SUBSCRIBE packets received.
  237. {subcmd, ["HMSET", "mqtt_subs:%u"]},
  238. %% Load Subscriptions form Redis when client connected.
  239. {loadsub, ["HGETALL", "mqtt_subs:%u"]},
  240. %% Remove subscriptions from redis when UNSUBSCRIBE packets received.
  241. {unsubcmd, ["HDEL", "mqtt_subs:%u"]}
  242. ]}
  243. ].
  244. Load emqttd_plugin_redis Plugin
  245. -------------------------------
  246. .. code:: console
  247. ./bin/emqttd_ctl plugins load emqttd_plugin_redis
  248. -----------------------------
  249. emqttd_stomp - STOMP Protocol
  250. -----------------------------
  251. Support STOMP 1.0/1.1/1.2 clients to connect to emqttd broker and communicate with MQTT Clients.
  252. Configure emqttd_stomp/etc/plugin.config
  253. ----------------------------------------
  254. .. NOTE:: Default Port for STOMP Protocol: 61613
  255. .. code:: erlang
  256. [
  257. {emqttd_stomp, [
  258. {default_user, [
  259. {login, "guest"},
  260. {passcode, "guest"}
  261. ]},
  262. {allow_anonymous, true},
  263. %%TODO: unused...
  264. {frame, [
  265. {max_headers, 10},
  266. {max_header_length, 1024},
  267. {max_body_length, 8192}
  268. ]},
  269. {listeners, [
  270. {emqttd_stomp, 61613, [
  271. {acceptors, 4},
  272. {max_clients, 512}
  273. ]}
  274. ]}
  275. ]}
  276. ].
  277. Load emqttd_stomp Plugin
  278. ------------------------
  279. .. code::
  280. ./bin/emqttd_ctl plugins load emqttd_stomp
  281. -----------------------------------
  282. emqttd_sockjs - STOMP/SockJS Plugin
  283. -----------------------------------
  284. emqttd_sockjs plugin enables web browser to connect to emqttd broker and communicate with MQTT clients.
  285. .. NOTE:: Default TCP Port: 61616
  286. Configure emqttd_sockjs
  287. -----------------------
  288. .. code:: erlang
  289. [
  290. {emqttd_sockjs, [
  291. {sockjs, []},
  292. {cowboy_listener, {stomp_sockjs, 61616, 4}},
  293. ]}
  294. ].
  295. Load emqttd_sockjs Plugin
  296. -------------------------
  297. .. NOTE:: emqttd_stomp Plugin required.
  298. .. code:: console
  299. ./bin/emqttd_ctl plugins load emqttd_stomp
  300. ./bin/emqttd_ctl plugins load emqttd_sockjs
  301. SockJS Demo Page
  302. ----------------
  303. http://localhost:61616/index.html
  304. ---------------------------
  305. emqttd_recon - Recon Plugin
  306. ---------------------------
  307. The plugin loads `recon`_ library on a running emqttd broker. Recon libray helps debug and optimize an Erlang application.
  308. Load emqttd_recon Plugin
  309. ------------------------
  310. .. code:: console
  311. ./bin/emqttd_ctl plugins load emqttd_recon
  312. Recon CLI
  313. ---------
  314. .. code:: console
  315. ./bin/emqttd_ctl recon
  316. recon memory #recon_alloc:memory/2
  317. recon allocated #recon_alloc:memory(allocated_types, current|max)
  318. recon bin_leak #recon:bin_leak(100)
  319. recon node_stats #recon:node_stats(10, 1000)
  320. recon remote_load Mod #recon:remote_load(Mod)
  321. ------------------------
  322. Plugin Development Guide
  323. ------------------------
  324. Create a Plugin Project
  325. -----------------------
  326. Clone emqttd source from github.com::
  327. git clone https://github.com/emqtt/emqttd.git
  328. Create a plugin project under 'plugins' folder::
  329. cd plugins && mkdir emqttd_my_plugin
  330. cd emqttd_my_plugin && rebar create-app appid=emqttd_my_plugin
  331. Template Plugin: https://github.com/emqtt/emqttd_plugin_template
  332. Register Auth/ACL Modules
  333. -------------------------
  334. emqttd_auth_demo.erl - demo authentication module:
  335. .. code:: erlang
  336. -module(emqttd_auth_demo).
  337. -behaviour(emqttd_auth_mod).
  338. -include("../../../include/emqttd.hrl").
  339. -export([init/1, check/3, description/0]).
  340. init(Opts) -> {ok, Opts}.
  341. check(#mqtt_client{client_id = ClientId, username = Username}, Password, _Opts) ->
  342. io:format("Auth Demo: clientId=~p, username=~p, password=~p~n",
  343. [ClientId, Username, Password]),
  344. ok.
  345. description() -> "Demo Auth Module".
  346. emqttd_acl_demo.erl - demo ACL module:
  347. .. code:: erlang
  348. -module(emqttd_acl_demo).
  349. -include("../../../include/emqttd.hrl").
  350. %% ACL callbacks
  351. -export([init/1, check_acl/2, reload_acl/1, description/0]).
  352. init(Opts) ->
  353. {ok, Opts}.
  354. check_acl({Client, PubSub, Topic}, Opts) ->
  355. io:format("ACL Demo: ~p ~p ~p~n", [Client, PubSub, Topic]),
  356. allow.
  357. reload_acl(_Opts) ->
  358. ok.
  359. description() -> "ACL Module Demo".
  360. emqttd_plugin_template_app.erl - Register the auth/ACL modules:
  361. .. code:: erlang
  362. ok = emqttd_access_control:register_mod(auth, emqttd_auth_demo, []),
  363. ok = emqttd_access_control:register_mod(acl, emqttd_acl_demo, []),
  364. Register Callbacks for Hooks
  365. -----------------------------
  366. The plugin could register callbacks for hooks. The hooks will be run by the broker when a client connected/disconnected, a topic subscribed/unsubscribed or a message published/delivered:
  367. +------------------------+---------------------------------------+
  368. | Name | Description |
  369. +------------------------+---------------------------------------+
  370. | client.connected | Run when a client connected to the |
  371. | | broker successfully |
  372. +------------------------+---------------------------------------+
  373. | client.subscribe | Run before a client subscribes topics |
  374. +------------------------+---------------------------------------+
  375. | client.subscribe.after | Run after a client subscribed topics |
  376. +------------------------+---------------------------------------+
  377. | client.unsubscribe | Run when a client unsubscribes topics |
  378. +------------------------+---------------------------------------+
  379. | message.publish | Run when a message is published |
  380. +------------------------+---------------------------------------+
  381. | message.delivered | Run when a message is delivered |
  382. +------------------------+---------------------------------------+
  383. | message.acked | Run when a message(qos1/2) is acked |
  384. +------------------------+---------------------------------------+
  385. | client.disconnected | Run when a client is disconnnected |
  386. +----------------------- +---------------------------------------+
  387. emqttd_plugin_template.erl for example::
  388. %% Called when the plugin application start
  389. load(Env) ->
  390. emqttd:hook('client.connected', fun ?MODULE:on_client_connected/3, [Env]),
  391. emqttd:hook('client.disconnected', fun ?MODULE:on_client_disconnected/3, [Env]),
  392. emqttd:hook('client.subscribe', fun ?MODULE:on_client_subscribe/3, [Env]),
  393. emqttd:hook('client.subscribe.after', fun ?MODULE:on_client_subscribe_after/3, [Env]),
  394. emqttd:hook('client.unsubscribe', fun ?MODULE:on_client_unsubscribe/3, [Env]),
  395. emqttd:hook('message.publish', fun ?MODULE:on_message_publish/2, [Env]),
  396. emqttd:hook('message.delivered', fun ?MODULE:on_message_delivered/3, [Env]),
  397. emqttd:hook('message.acked', fun ?MODULE:on_message_acked/3, [Env]).
  398. Register CLI Modules
  399. --------------------
  400. emqttd_cli_demo.erl:
  401. .. code:: erlang
  402. -module(emqttd_cli_demo).
  403. -include("../../../include/emqttd_cli.hrl").
  404. -export([cmd/1]).
  405. cmd(["arg1", "arg2"]) ->
  406. ?PRINT_MSG("ok");
  407. cmd(_) ->
  408. ?USAGE([{"cmd arg1 arg2", "cmd demo"}]).
  409. emqttd_plugin_template_app.erl - register the CLI module to emqttd broker:
  410. .. code:: erlang
  411. emqttd_ctl:register_cmd(cmd, {emqttd_cli_demo, cmd}, []).
  412. There will be a new CLI after the plugin loaded::
  413. ./bin/emqttd_ctl cmd arg1 arg2
  414. .. _emqttd_dashboard: https://github.com/emqtt/emqttd_dashboard
  415. .. _emqttd_plugin_mysql: https://github.com/emqtt/emqttd_plugin_mysql
  416. .. _emqttd_plugin_pgsql: https://github.com/emqtt/emqttd_plugin_pgsql
  417. .. _emqttd_plugin_redis: https://github.com/emqtt/emqttd_plugin_redis
  418. .. _emqttd_stomp: https://github.com/emqtt/emqttd_stomp
  419. .. _emqttd_sockjs: https://github.com/emqtt/emqttd_sockjs
  420. .. _emqttd_recon: https://github.com/emqtt/emqttd_recon
  421. .. _emqttd_plugin_template: https://github.com/emqtt/emqttd_plugin_template
  422. .. _recon: http://ferd.github.io/recon/