Procházet zdrojové kódy

fix(authz): placehodler regular escape

JimMoen před 4 roky
rodič
revize
b41c41570a

+ 0 - 1
apps/emqx/src/emqx_topic.erl

@@ -218,4 +218,3 @@ parse(TopicFilter = <<"$share/", Rest/binary>>, Options) ->
     end;
 parse(TopicFilter, Options) ->
     {TopicFilter, Options}.
-

+ 3 - 2
apps/emqx/test/emqx_topic_SUITE.erl

@@ -20,6 +20,7 @@
 -compile(nowarn_export_all).
 
 -include_lib("eunit/include/eunit.hrl").
+-include_lib("emqx/include/emqx_placeholder.hrl").
 
 -import(emqx_topic,
         [ wildcard/1
@@ -183,9 +184,9 @@ t_feed_var(_) ->
     ?assertEqual(<<"$queue/client/clientId">>,
                  feed_var(<<"$c">>, <<"clientId">>, <<"$queue/client/$c">>)),
     ?assertEqual(<<"username/test/client/x">>,
-                 feed_var(<<"%u">>, <<"test">>, <<"username/%u/client/x">>)),
+                 feed_var(?PH_USERNAME, <<"test">>, <<"username/", ?PH_USERNAME/binary, "/client/x">>)),
     ?assertEqual(<<"username/test/client/clientId">>,
-                 feed_var(<<"%c">>, <<"clientId">>, <<"username/test/client/%c">>)).
+                 feed_var(?PH_CLIENTID, <<"clientId">>, <<"username/test/client/", ?PH_CLIENTID/binary>>)).
 
 long_topic() ->
     iolist_to_binary([[integer_to_list(I), "/"] || I <- lists:seq(0, 66666)]).

+ 3 - 3
apps/emqx_authz/README.md

@@ -23,7 +23,7 @@ authz:{
                 keyfile: "etc/certs/client-key.pem"
               }
            }
-           sql: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = '%a' or username = '%u' or clientid = '%c'"
+           sql: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = ${peerhost} or username = ${username} or clientid = ${clientid}"
        },
        {
            type: postgresql
@@ -36,7 +36,7 @@ authz:{
               auto_reconnect: true
               ssl: {enable: false}
            }
-           sql: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'"
+           sql: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = ${peerhost} or username = ${username} or username = '$all' or clientid = ${clientid}"
        },
        {
            type: redis
@@ -48,7 +48,7 @@ authz:{
               auto_reconnect: true
               ssl: {enable: false}
            }
-           cmd: "HGETALL mqtt_authz:%u"
+           cmd: "HGETALL mqtt_authz:${username}"
        },
        {
            principal: {username: "^admin?"}

+ 4 - 4
apps/emqx_authz/etc/emqx_authz.conf

@@ -22,7 +22,7 @@ authorization {
        #       certfile: "{{ platform_etc_dir }}/certs/client-cert.pem"
        #       keyfile: "{{ platform_etc_dir }}/certs/client-key.pem"
        #     }
-       #     query: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = '%a' or username = '%u' or clientid = '%c'"
+       #     query: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = ${peerhost} or username = ${username} or clientid = ${clientid}"
        # },
        # {
        #     type: postgresql
@@ -33,7 +33,7 @@ authorization {
        #     password: public
        #     auto_reconnect: true
        #     ssl: {enable: false}
-       #     query: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = '%a' or username = '%u' or username = '$all' or clientid = '%c'"
+       #     query: "select ipaddress, username, clientid, action, permission, topic from mqtt_authz where ipaddr = ${peerhost} or username = ${username} or username = '$all' or clientid = ${clientid}"
        # },
        # {
        #     type: redis
@@ -43,7 +43,7 @@ authorization {
        #     password: public
        #     auto_reconnect: true
        #     ssl: {enable: false}
-       #     cmd: "HGETALL mqtt_authz:%u"
+       #     cmd: "HGETALL mqtt_authz:${username}"
        # },
        # {
        #     type: mongodb
@@ -53,7 +53,7 @@ authorization {
        #     database: mqtt
        #     ssl: {enable: false}
        #     collection: mqtt_authz
-       #     selector: { "$or": [ { "username": "%u" }, { "clientid": "%c" } ] }
+       #     selector: { "$or": [ { "username": "${username}" }, { "clientid": "${clientid}" } ] }
        # },
        {
             type: built-in-database

+ 5 - 0
apps/emqx_authz/src/emqx_authz.erl

@@ -40,6 +40,8 @@
 
 -export([acl_conf_file/0]).
 
+-export([ph_to_re/1]).
+
 -spec(register_metrics() -> ok).
 register_metrics() ->
     lists:foreach(fun emqx_metrics:ensure/1, ?AUTHZ_METRICS).
@@ -386,3 +388,6 @@ type(Unknown) -> error({unknown_authz_source_type, Unknown}). % should never hap
 %% @doc where the acl.conf file is stored.
 acl_conf_file() ->
     filename:join([emqx:data_dir(), "authz", "acl.conf"]).
+
+ph_to_re(VarPH) ->
+    re:replace(VarPH, "[\\$\\{\\}]", "\\\\&", [global, {return, list}]).

+ 7 - 7
apps/emqx_authz/src/emqx_authz_http.erl

@@ -87,19 +87,19 @@ replvar(Str0, PubSub, Topic,
          }) when is_list(Str0);
                  is_binary(Str0) ->
     NTopic = emqx_http_lib:uri_encode(Topic),
-    Str1 = re:replace( Str0, ?PH_S_CLIENTID
+    Str1 = re:replace( Str0, emqx_authz:ph_to_re(?PH_S_CLIENTID)
                      , Clientid, [global, {return, binary}]),
-    Str2 = re:replace( Str1, ?PH_S_USERNAME
+    Str2 = re:replace( Str1, emqx_authz:ph_to_re(?PH_S_USERNAME)
                      , bin(Username), [global, {return, binary}]),
-    Str3 = re:replace( Str2, ?PH_S_HOST
+    Str3 = re:replace( Str2, emqx_authz:ph_to_re(?PH_S_HOST)
                      , inet_parse:ntoa(IpAddress), [global, {return, binary}]),
-    Str4 = re:replace( Str3, ?PH_S_PROTONAME
+    Str4 = re:replace( Str3, emqx_authz:ph_to_re(?PH_S_PROTONAME)
                      , bin(Protocol), [global, {return, binary}]),
-    Str5 = re:replace( Str4, ?PH_S_MOUNTPOINT
+    Str5 = re:replace( Str4, emqx_authz:ph_to_re(?PH_S_MOUNTPOINT)
                      , Mountpoint, [global, {return, binary}]),
-    Str6 = re:replace( Str5, ?PH_S_TOPIC
+    Str6 = re:replace( Str5, emqx_authz:ph_to_re(?PH_S_TOPIC)
                      , NTopic, [global, {return, binary}]),
-    Str7 = re:replace( Str6, ?PH_S_ACTION
+    Str7 = re:replace( Str6, emqx_authz:ph_to_re(?PH_S_ACTION)
                      , bin(PubSub), [global, {return, binary}]),
     Str7.
 

+ 3 - 3
apps/emqx_authz/src/emqx_authz_mongodb.erl

@@ -76,11 +76,11 @@ replvar(Selector, #{clientid := Clientid,
                                 end || M <- V],
                            AccIn);
               InFun(K, V, AccIn) when is_binary(V) ->
-                  V1 = re:replace( V,  ?PH_S_CLIENTID
+                  V1 = re:replace( V,  emqx_authz:ph_to_re(?PH_S_CLIENTID)
                                  , bin(Clientid), [global, {return, binary}]),
-                  V2 = re:replace( V1, ?PH_S_USERNAME
+                  V2 = re:replace( V1, emqx_authz:ph_to_re(?PH_S_USERNAME)
                                  , bin(Username), [global, {return, binary}]),
-                  V3 = re:replace( V2, ?PH_S_HOST
+                  V3 = re:replace( V2, emqx_authz:ph_to_re(?PH_S_HOST)
                                  , inet_parse:ntoa(IpAddress), [global, {return, binary}]),
                   maps:put(K, V3, AccIn);
               InFun(K, V, AccIn) -> maps:put(K, V, AccIn)

+ 5 - 4
apps/emqx_authz/src/emqx_authz_redis.erl

@@ -71,8 +71,9 @@ replvar(Cmd, Client = #{username := Username}) ->
 replvar(Cmd, _) ->
     Cmd.
 
-repl(S, _Var, undefined) ->
+repl(S, _VarPH, undefined) ->
     S;
-repl(S, Var, Val) ->
-    NVal = re:replace(Val, "&", "\\\\&", [global, {return, list}]),
-    re:replace(S, Var, NVal, [{return, list}]).
+repl(S, VarPH, Val) ->
+    NVal   = re:replace(Val, "&", "\\\\&", [global, {return, list}]),
+    NVarPH = emqx_authz:ph_to_re(VarPH),
+    re:replace(S, NVarPH, NVal, [{return, list}]).