更新时间:2024-04-17 GMT+08:00
分享

源代码

redis认证

-module(emqx_authz_redis).
-include("emqx_authz.hrl").
-include_lib("emqx/include/emqx.hrl").
-include_lib("emqx/include/logger.hrl").
-include_lib("emqx/include/emqx_placeholder.hrl").
-behaviour(emqx_authz).
%% AuthZ Callbacks
-export([
    description/0,
    create/1,
    update/1,
    destroy/1,
    authorize/4
]).
-ifdef(TEST).
-compile(export_all).
-compile(nowarn_export_all).
-endif.
-define(PLACEHOLDERS, [
    ?PH_CERT_CN_NAME,
    ?PH_CERT_SUBJECT,
    ?PH_PEERHOST,
    ?PH_CLIENTID,
    ?PH_USERNAME
]).
description() ->
    "AuthZ with Redis".
create(#{cmd := CmdStr} = Source) ->
    Cmd = tokens(CmdStr),
    ResourceId = emqx_authz_utils:make_resource_id(?MODULE),
    CmdTemplate = emqx_authz_utils:parse_deep(Cmd, ?PLACEHOLDERS),
    {ok, _Data} = emqx_authz_utils:create_resource(ResourceId, emqx_connector_redis, Source),
    Source#{annotations => #{id => ResourceId}, cmd_template => CmdTemplate}.
update(#{cmd := CmdStr} = Source) ->
    Cmd = tokens(CmdStr),
    CmdTemplate = emqx_authz_utils:parse_deep(Cmd, ?PLACEHOLDERS),
    case emqx_authz_utils:update_resource(emqx_connector_redis, Source) of
        {error, Reason} ->
            error({load_config_error, Reason});
        {ok, Id} ->
            Source#{annotations => #{id => Id}, cmd_template => CmdTemplate}
    end.
destroy(#{annotations := #{id := Id}}) ->
    ok = emqx_resource:remove_local(Id).
authorize(
    Client,
    PubSub,
    Topic,
    #{
        cmd_template := CmdTemplate,
        annotations := #{id := ResourceID}
    }
) ->
    Cmd = emqx_authz_utils:render_deep(CmdTemplate, Client),
    case emqx_resource:query(ResourceID, {cmd, Cmd}) of
        {ok, []} ->
            nomatch;
        {ok, Rows} ->
            do_authorize(Client, PubSub, Topic, Rows);
        {error, Reason} ->
            ?SLOG(error, #{
                msg => "query_redis_error",
                reason => Reason,
                cmd => Cmd,
                resource_id => ResourceID
            }),
            nomatch
    end.
do_authorize(_Client, _PubSub, _Topic, []) ->
    nomatch;
do_authorize(Client, PubSub, Topic, [TopicFilter, Action | Tail]) ->
    case
        emqx_authz_rule:match(
            Client,
            PubSub,
            Topic,
            emqx_authz_rule:compile({allow, all, Action, [TopicFilter]})
        )
    of
        {matched, Permission} -> {matched, Permission};
        nomatch -> do_authorize(Client, PubSub, Topic, Tail)
    end.
tokens(Query) ->
    Tokens = binary:split(Query, <<" ">>, [global]),
    [Token || Token <- Tokens, size(Token) > 0].

相关文档