16
ACL Design
victorclaessen edited this page 2018-07-03 23:08:01 +02:00

Overview

An implementation may restrict access to Server resources based on information provided by the Client such as User Name, Client Identifier, the hostname/IP address of the Client, or the outcome of authentication mechanisms.

MQTT Client

A MQTT Client identified by IpAddr, ClientId and Username.

-record(mqtt_client, {
    clientid    :: binary(),
    username    :: binary() | undefined,
    ipaddr      :: inet:ip_address()
}).

Access Rule

Rule

{allow, all}.

{deny, all}.

{allow | deny, Who, Access, TopicFilters}.

Who :: all | ClientId | {client, ClientId} | {ipaddr, IpAddr} | {user, Username}

ClientId :: string() | all

IpAddr :: string()

Username :: string() | all

Access :: publish | subscribe | pubsub

TopicFilter :: [Topic]

Topic :: string()

Examples

{allow, {ipaddr, "127.0.0.1"}, subscribe, ["$SYS/#", "#"]}.

{allow, {user, "testuser"}, subscribe, ["a/b/c", "d/e/f/#"]}.

{allow, {user, "admin"}, pubsub, ["a/b/c", "d/e/f/#"]}.

{allow, {client, "testClient"}, subscribe, ["testTopics/testClient"]}.

{allow, all, subscribe, ["clients/%c"]}.

{allow, all, pubsub, ["users/%u/#"]}.

{deny, all, subscribe, ["$SYS/#", {eq, "#"}]}.

{deny, all}.

'eq' Tag

{deny, all, subscribe, [{eq, "$SYS/#"}, {eq, "#"}]}.

Means all cannot subscribe "$SYS/#", "#". But:

{deny, all, subscribe, ["$SYS/#", "#"]}.

Means that all cannot subscribe any topics.

etc/acl.config

Default config only allow localhost to subscribe '$SYS/#', '#':

%%%-----------------------------------------------------------------------------
%%
%% [ACL Design](https://github.com/emqtt/emqttd/wiki/ACL)
%%
%% -type who() :: all | binary() |
%%               {ipaddr, esockd_access:cidr()} |
%%               {client, binary()} |
%%               {user, binary()}.
%%
%% -type access() :: subscribe | publish | pubsub.
%%
%% -type topic() :: binary().
%%
%% -type rule() :: {allow, all} |
%%                {allow, who(), access(), list(topic())} |
%%                {deny, all} |
%%                {deny, who(), access(), list(topic())}.
%%
%%%-----------------------------------------------------------------------------

{allow, {ipaddr, "127.0.0.1"}, pubsub, ["$SYS/#", "#"]}.

{deny, all, subscribe, [{eq, "$SYS/#"}, {eq, "#"}]}.

{allow, all}.

etc/app.config

    {access, [
        %% Authetication. , Anonymous Default
        ......
        %% ACL config
        {acl, [
            %% User internal ACL module
            {internal,  [{file, "etc/acl.config"}, {nomatch, allow}]}
        ]}

Access API

Defined in emqttd_access_control.erl:

-spec check_acl(Client, PubSub, Topic) -> allow | deny when
      Client :: mqtt_client(),
      PubSub :: pubsub(),
      Topic  :: binary().
check_acl(Client, PubSub, Topic) when PubSub =:= publish orelse PubSub =:= subscribe ->
    ......

emqttd_acl_mod behaviour

-callback init(AclOpts :: list()) -> {ok, State :: any()}.

-callback check_acl({Client, PubSub, Topic}, State :: any()) -> allow | deny | ignore when
    Client   :: mqtt_client(),
    PubSub   :: pubsub(),
    Topic    :: binary().

-callback reload_acl(State :: any()) -> ok | {error, any()}.

-callback description() -> string().