emqx_auth_pgsql.erl 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2020 EMQ Technologies Co., Ltd. All Rights Reserved.
  3. %%
  4. %% Licensed under the Apache License, Version 2.0 (the "License");
  5. %% you may not use this file except in compliance with the License.
  6. %% You may obtain a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing, software
  11. %% distributed under the License is distributed on an "AS IS" BASIS,
  12. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. %% See the License for the specific language governing permissions and
  14. %% limitations under the License.
  15. %%--------------------------------------------------------------------
  16. -module(emqx_auth_pgsql).
  17. -include("emqx_auth_pgsql.hrl").
  18. -include_lib("emqx/include/emqx.hrl").
  19. -include_lib("emqx/include/logger.hrl").
  20. -export([ register_metrics/0
  21. , check/3
  22. , description/0
  23. ]).
  24. -spec(register_metrics() -> ok).
  25. register_metrics() ->
  26. lists:foreach(fun emqx_metrics:ensure/1, ?AUTH_METRICS).
  27. %%--------------------------------------------------------------------
  28. %% Auth Module Callbacks
  29. %%--------------------------------------------------------------------
  30. check(ClientInfo = #{password := Password}, AuthResult,
  31. #{auth_query := {AuthSql, AuthParams},
  32. super_query := SuperQuery,
  33. hash_type := HashType,
  34. pool := Pool}) ->
  35. CheckPass = case emqx_auth_pgsql_cli:equery(Pool, AuthSql, AuthParams, ClientInfo) of
  36. {ok, _, [Record]} ->
  37. check_pass(erlang:append_element(Record, Password), HashType);
  38. {ok, _, []} ->
  39. {error, not_found};
  40. {error, Reason} ->
  41. ?LOG(error, "[Postgres] query '~p' failed: ~p", [AuthSql, Reason]),
  42. {error, not_found}
  43. end,
  44. case CheckPass of
  45. ok ->
  46. emqx_metrics:inc(?AUTH_METRICS(success)),
  47. {stop, AuthResult#{is_superuser => is_superuser(Pool, SuperQuery, ClientInfo),
  48. anonymous => false,
  49. auth_result => success}};
  50. {error, not_found} ->
  51. emqx_metrics:inc(?AUTH_METRICS(ignore)), ok;
  52. {error, ResultCode} ->
  53. ?LOG(error, "[Postgres] Auth from pgsql failed: ~p", [ResultCode]),
  54. emqx_metrics:inc(?AUTH_METRICS(failure)),
  55. {stop, AuthResult#{auth_result => ResultCode, anonymous => false}}
  56. end.
  57. %%--------------------------------------------------------------------
  58. %% Is Superuser?
  59. %%--------------------------------------------------------------------
  60. -spec(is_superuser(atom(),undefined | {string(), list()}, emqx_types:client()) -> boolean()).
  61. is_superuser(_Pool, undefined, _Client) ->
  62. false;
  63. is_superuser(Pool, {SuperSql, Params}, ClientInfo) ->
  64. case emqx_auth_pgsql_cli:equery(Pool, SuperSql, Params, ClientInfo) of
  65. {ok, [_Super], [{true}]} ->
  66. true;
  67. {ok, [_Super], [_False]} ->
  68. false;
  69. {ok, [_Super], []} ->
  70. false;
  71. {error, _Error} ->
  72. false
  73. end.
  74. check_pass(Password, HashType) ->
  75. case emqx_passwd:check_pass(Password, HashType) of
  76. ok -> ok;
  77. {error, _Reason} -> {error, not_authorized}
  78. end.
  79. description() -> "Authentication with PostgreSQL".