acl.conf 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. %%-------------- Default ACL rules -------------------------------------------------------
  2. {allow, {username, {re, "^dashboard$"}}, subscribe, ["$SYS/#"]}.
  3. {allow, {ipaddr, "127.0.0.1"}, all, ["$SYS/#", "#"]}.
  4. {deny, all, subscribe, ["$SYS/#", {eq, "#"}]}.
  5. {allow, all}.
  6. %% NOTE! when deploy in production:
  7. %% - Change the last rule to `{deny, all}.`
  8. %% - Set config `authorization.no_match = deny`
  9. %% See docs below
  10. %%
  11. %% ------------ The formal spec ----------------------------------------------------------
  12. %%
  13. %% -type ipaddr() :: {ipaddr, string()}.
  14. %% -type ipaddrs() :: {ipaddrs, [string()]}.
  15. %% -type username() :: {user | username, string()} | {user | username, {re, regex()}}.
  16. %% -type clientid() :: {client | clientid, string()} | {client | clientid, {re, regex()}}.
  17. %% -type who() :: ipaddr() | ipaddrs() | username() | clientid() |
  18. %% {'and', [ipaddr() | ipaddrs() | username() | clientid()]} |
  19. %% {'or', [ipaddr() | ipaddrs() | username() | clientid()]} |
  20. %% all.
  21. %% -type simple_action() :: subscribe | publish | all.
  22. %% -type complex_action() :: {simple_action(), [{qos, 0..2}, {retain, true|false|all}]}.
  23. %% -type action() :: simple_action() | complex_action().
  24. %% -type topic() :: string().
  25. %% -type topic_filter() :: string().
  26. %% -type topic_match() :: topic() | topic_filter() | {eq, topic() | topic_filter()}.
  27. %% -type perm() :: allow | deny.
  28. %% -type rule() :: {perm(), who(), action(), [topic_match()]} | {perm(), all}.
  29. %%-------------- Viusal aid for the spec -------------------------------------------------
  30. %%
  31. %% rule()
  32. %% ├── {perm(), who(), action(), [topic_match()]}
  33. %% │ │ │ │ ├── topic() :: string()
  34. %% │ │ │ │ ├── topic_filter() :: string()
  35. %% │ │ │ │ └── {eq, topic() | topic_filter()}
  36. %% │ │ │ │
  37. %% │ │ │ ├── simple_action()
  38. %% │ │ │ │ ├── publish
  39. %% │ │ │ │ ├── subscribe
  40. %% │ │ │ │ └── all
  41. %% │ │ │ └── {simple_action(), [{qos,0..2},{retain,true|false|all}]}
  42. %% │ │ │
  43. %% │ │ ├── ipaddr()
  44. %% │ │ │ └── {ipaddr, string()}
  45. %% │ │ ├── ipaddrs()
  46. %% │ │ │ └── {ipaddrs, [string()]}
  47. %% │ │ ├── username()
  48. %% │ │ │ ├── {user | username, string()}
  49. %% │ │ │ └── {user | username, {re, regex()}}
  50. %% │ │ ├── clientid()
  51. %% │ │ │ ├── {client | clientid, string()}
  52. %% │ │ │ └── {client | clientid, {re, regex()}}
  53. %% │ │ ├── {'and', [ipaddr() | ipaddrs() | username() | clientid()]}
  54. %% │ │ ├── {'or', [ipaddr() | ipaddrs() | username() | clientid()]}
  55. %% │ │ └── all
  56. %% │ │
  57. %% │ ├── allow
  58. %% │ └── deny
  59. %% │
  60. %% └── {perm(), all}
  61. %%
  62. %% This file defines a set of ACL rules for MQTT client pub/sub authorization.
  63. %% The content is of Erlang-term format.
  64. %% Each Erlang-term is a tuple `{...}` terminated by dot `.`
  65. %%
  66. %% NOTE: When deploy to production, the last rule should be changed to {deny, all}.
  67. %%
  68. %% NOTE: It's a good practice to keep the nubmer of rules small, because in worst case
  69. %% scenarios, all rules have to be traversed for each message publish.
  70. %%
  71. %% A rule is a 4-element tuple.
  72. %% For example, `{allow, {username, "Jon"}, subscribe, ["#"]}` allows Jon to subscribe to
  73. %% any topic they want.
  74. %%
  75. %% Below is an explanation:
  76. %%
  77. %% - `perm()`: The permission.
  78. %% Defines whether this is an `allow` or `deny` rule.
  79. %%
  80. %% - `who()`: The MQTT client matching condition.
  81. %% - `all`: A rule which applies to all clients.
  82. %% - `{ipaddr, IpAddress}`: Matches a client by source IP address. CIDR notation is allowed.
  83. %% - `{ipaddrs, [IpAddress]}`: Matches clients by a set of IP addresses. CIDR notation is allowed.
  84. %% - `{clientid, ClientID}`: Matches a client by ID.
  85. %% - `{username, Username}`: Matches a client by username.
  86. %% - `{..., {re, ..}}`: Regular expression to match either clientid or username.
  87. %% - `{'and', [...]}`: Combines a list of matching conditions.
  88. %% - `{'or', [...]}`: Combines a list of matching conditions.
  89. %%
  90. %% - `action()`: Matches publish or subscribe actions (or both).
  91. %% Applies the rule to `publish` or `subscribe` actions.
  92. %% The special value `all` denotes allowing or denying both `publish` and `subscribe`.
  93. %% It can also be associated with `qos` and `retain` flags to match the action with
  94. %% more specifics. For example, `{publish, [{qos,0},{retain,false}]}` should only
  95. %% match the `publish` action when the message has QoS 0, and without retained flag set.
  96. %%
  97. %% - `[topic_match()]`:
  98. %% A list of topics, topic-filters, or template rendering to match the topic being
  99. %% subscribed to or published.
  100. %% For example, `{allow, {username, "Jan"}, publish, ["jan/#"]}` permits Jan to publish
  101. %% to any topic matching the wildcard pattern "jan/#".
  102. %% A special tuple `{eq, topic_match()}` is useful to allow or deny the specific wildcard
  103. %% subscription instead of performing a topic match.
  104. %% A `topic_match()` can also contain a placeholder rendered with actual value at runtime,
  105. %% for example, `{allow, all, publish, "${clientid}/#"}` allows all clients to publish to
  106. %% topics prefixed by their own client ID.
  107. %%
  108. %% Supported placeholders are:
  109. %% - `${cn}`: TLS certificate common name.
  110. %% - `${clientid}`: The client ID.
  111. %% - `${username}`: The username.
  112. %% - `${client_attrs.NAME}`: A client attribute named `NAME`, which can be initialized by
  113. %% `mqtt.client_attrs_init` config or extended by certain authentication backends.
  114. %% NOTE: Placeholder is not rendered as empty string if the referencing value is not
  115. %% foud. For example, `${client_attrs.group}/#` is not rendered as `/#` if the
  116. %% client does not have a `group` attribute.