fix(authz): refine authz-http api with default headers
This commit is contained in:
parent
c67e565755
commit
341973880d
|
@ -0,0 +1,20 @@
|
|||
%%--------------------------------------------------------------------
|
||||
%% Copyright (c) 2022 EMQ Technologies Co., Ltd. All Rights Reserved.
|
||||
%%
|
||||
%% Licensed under the Apache License, Version 2.0 (the "License");
|
||||
%% you may not use this file except in compliance with the License.
|
||||
%% You may obtain a copy of the License at
|
||||
%%
|
||||
%% http://www.apache.org/licenses/LICENSE-2.0
|
||||
%%
|
||||
%% Unless required by applicable law or agreed to in writing, software
|
||||
%% distributed under the License is distributed on an "AS IS" BASIS,
|
||||
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
%% See the License for the specific language governing permissions and
|
||||
%% limitations under the License.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% config root name all auth providers have to agree on.
|
||||
-define(EMQX_AUTHORIZATION_CONFIG_ROOT_NAME, "authorization").
|
||||
-define(EMQX_AUTHORIZATION_CONFIG_ROOT_NAME_ATOM, authorization).
|
||||
-define(EMQX_AUTHORIZATION_CONFIG_ROOT_NAME_BINARY, <<"authorization">>).
|
|
@ -24,6 +24,7 @@
|
|||
-elvis([{elvis_style, invalid_dynamic_call, disable}]).
|
||||
|
||||
-include("emqx_authentication.hrl").
|
||||
-include("emqx_access_control.hrl").
|
||||
-include_lib("typerefl/include/types.hrl").
|
||||
|
||||
-type duration() :: integer().
|
||||
|
@ -159,9 +160,9 @@ roots(high) ->
|
|||
)},
|
||||
%% NOTE: authorization schema here is only to keep emqx app prue
|
||||
%% the full schema for EMQX node is injected in emqx_conf_schema.
|
||||
{"authorization",
|
||||
{?EMQX_AUTHORIZATION_CONFIG_ROOT_NAME,
|
||||
sc(
|
||||
ref("authorization"),
|
||||
ref(?EMQX_AUTHORIZATION_CONFIG_ROOT_NAME),
|
||||
#{}
|
||||
)}
|
||||
];
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
%% limitations under the License.
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
-include_lib("emqx/include/emqx_access_control.hrl").
|
||||
|
||||
-define(APP, emqx_authz).
|
||||
|
||||
-define(ALLOW_DENY(A),
|
||||
|
@ -45,6 +47,11 @@
|
|||
|
||||
-define(RE_PLACEHOLDER, "\\$\\{[a-z0-9_]+\\}").
|
||||
|
||||
%% has to be the same as the root field name defined in emqx_schema
|
||||
-define(CONF_NS, ?EMQX_AUTHORIZATION_CONFIG_ROOT_NAME).
|
||||
-define(CONF_NS_ATOM, ?EMQX_AUTHORIZATION_CONFIG_ROOT_NAME_ATOM).
|
||||
-define(CONF_NS_BINARY, ?EMQX_AUTHORIZATION_CONFIG_ROOT_NAME_BINARY).
|
||||
|
||||
%% API examples
|
||||
-define(USERNAME_RULES_EXAMPLE, #{
|
||||
username => user1,
|
||||
|
|
|
@ -16,36 +16,32 @@
|
|||
|
||||
-module(emqx_authz_api_schema).
|
||||
|
||||
-include("emqx_authz.hrl").
|
||||
-include_lib("typerefl/include/types.hrl").
|
||||
-include_lib("emqx_connector/include/emqx_connector.hrl").
|
||||
|
||||
-import(hoconsc, [mk/2, enum/1]).
|
||||
-import(emqx_schema, [mk_duration/2]).
|
||||
|
||||
-export([fields/1, authz_sources_types/1]).
|
||||
-export([
|
||||
fields/1,
|
||||
authz_sources_types/1
|
||||
]).
|
||||
|
||||
fields(http) ->
|
||||
authz_common_fields(http) ++
|
||||
[
|
||||
{url, fun url/1},
|
||||
{method, #{
|
||||
type => enum([get, post]),
|
||||
default => get,
|
||||
required => true
|
||||
}},
|
||||
{headers, fun headers/1},
|
||||
{body, map([{fuzzy, term(), binary()}])},
|
||||
{request_timeout, mk_duration("Request timeout", #{default => "30s"})}
|
||||
] ++
|
||||
maps:to_list(
|
||||
maps:without(
|
||||
[
|
||||
base_url,
|
||||
pool_type
|
||||
],
|
||||
maps:from_list(emqx_connector_http:fields(config))
|
||||
)
|
||||
);
|
||||
%%------------------------------------------------------------------------------
|
||||
%% Hocon Schema
|
||||
%%------------------------------------------------------------------------------
|
||||
|
||||
fields(http_get) ->
|
||||
[
|
||||
{method, #{type => get, default => get, required => true}},
|
||||
{headers, fun headers_no_content_type/1}
|
||||
] ++ authz_http_common_fields();
|
||||
fields(http_post) ->
|
||||
[
|
||||
{method, #{type => post, default => post, required => true}},
|
||||
{headers, fun headers/1}
|
||||
] ++ authz_http_common_fields();
|
||||
fields(built_in_database) ->
|
||||
authz_common_fields(built_in_database);
|
||||
fields(mongo_single) ->
|
||||
|
@ -101,6 +97,23 @@ fields(position) ->
|
|||
%%------------------------------------------------------------------------------
|
||||
%% http type funcs
|
||||
|
||||
authz_http_common_fields() ->
|
||||
authz_common_fields(http) ++
|
||||
[
|
||||
{url, fun url/1},
|
||||
{body, map([{fuzzy, term(), binary()}])},
|
||||
{request_timeout, mk_duration("Request timeout", #{default => "30s"})}
|
||||
] ++
|
||||
maps:to_list(
|
||||
maps:without(
|
||||
[
|
||||
base_url,
|
||||
pool_type
|
||||
],
|
||||
maps:from_list(emqx_connector_http:fields(config))
|
||||
)
|
||||
).
|
||||
|
||||
url(type) -> binary();
|
||||
url(validator) -> [?NOT_EMPTY("the value of the field 'url' cannot be empty")];
|
||||
url(required) -> true;
|
||||
|
@ -119,6 +132,19 @@ headers(default) ->
|
|||
headers(_) ->
|
||||
undefined.
|
||||
|
||||
headers_no_content_type(type) ->
|
||||
map();
|
||||
headers_no_content_type(desc) ->
|
||||
"List of HTTP headers.";
|
||||
headers_no_content_type(converter) ->
|
||||
fun(Headers) ->
|
||||
maps:merge(default_headers_no_content_type(), transform_header_name(Headers))
|
||||
end;
|
||||
headers_no_content_type(default) ->
|
||||
default_headers_no_content_type();
|
||||
headers_no_content_type(_) ->
|
||||
undefined.
|
||||
|
||||
%% headers
|
||||
default_headers() ->
|
||||
maps:put(
|
||||
|
@ -208,9 +234,11 @@ enable(_) -> undefined.
|
|||
authz_sources_types(Type) ->
|
||||
case Type of
|
||||
simple ->
|
||||
[mongodb, redis];
|
||||
[http, mongodb, redis];
|
||||
detailed ->
|
||||
[
|
||||
http_get,
|
||||
http_post,
|
||||
mongo_single,
|
||||
mongo_rs,
|
||||
mongo_sharded,
|
||||
|
@ -220,7 +248,6 @@ authz_sources_types(Type) ->
|
|||
]
|
||||
end ++
|
||||
[
|
||||
http,
|
||||
built_in_database,
|
||||
mysql,
|
||||
postgresql,
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
-module(emqx_authz_schema).
|
||||
|
||||
-include("emqx_authz.hrl").
|
||||
-include_lib("typerefl/include/types.hrl").
|
||||
-include_lib("emqx_connector/include/emqx_connector.hrl").
|
||||
|
||||
|
@ -40,9 +41,6 @@
|
|||
headers/1
|
||||
]).
|
||||
|
||||
-import(emqx_schema, [mk_duration/2]).
|
||||
-include_lib("hocon/include/hoconsc.hrl").
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Hocon Schema
|
||||
%%--------------------------------------------------------------------
|
||||
|
@ -197,7 +195,9 @@ http_common_fields() ->
|
|||
[
|
||||
{url, fun url/1},
|
||||
{request_timeout,
|
||||
mk_duration("Request timeout", #{default => "30s", desc => "Request timeout."})},
|
||||
emqx_schema:mk_duration("Request timeout", #{
|
||||
default => "30s", desc => "Request timeout."
|
||||
})},
|
||||
{body, #{type => map(), required => false, desc => "HTTP request body."}}
|
||||
] ++
|
||||
maps:to_list(
|
||||
|
@ -232,8 +232,7 @@ mongo_common_fields() ->
|
|||
|
||||
validations() ->
|
||||
[
|
||||
{check_ssl_opts, fun check_ssl_opts/1},
|
||||
{check_headers, fun check_headers/1}
|
||||
{check_ssl_opts, fun check_ssl_opts/1}
|
||||
].
|
||||
|
||||
headers(type) ->
|
||||
|
@ -259,6 +258,13 @@ headers_no_content_type(converter) ->
|
|||
end;
|
||||
headers_no_content_type(default) ->
|
||||
default_headers_no_content_type();
|
||||
headers_no_content_type(validator) ->
|
||||
fun(Headers) ->
|
||||
case lists:keyfind(<<"content-type">>, 1, Headers) of
|
||||
false -> ok;
|
||||
_ -> {error, do_not_include_content_type}
|
||||
end
|
||||
end;
|
||||
headers_no_content_type(_) ->
|
||||
undefined.
|
||||
|
||||
|
@ -297,6 +303,7 @@ transform_header_name(Headers) ->
|
|||
Headers
|
||||
).
|
||||
|
||||
%% TODO: fix me, not work
|
||||
check_ssl_opts(Conf) ->
|
||||
case hocon_maps:get("config.url", Conf) of
|
||||
undefined ->
|
||||
|
@ -315,25 +322,6 @@ check_ssl_opts(Conf) ->
|
|||
end
|
||||
end.
|
||||
|
||||
check_headers(Conf) ->
|
||||
case hocon_maps:get("config.method", Conf) of
|
||||
undefined ->
|
||||
true;
|
||||
Method0 ->
|
||||
Method = to_bin(Method0),
|
||||
Headers = hocon_maps:get("config.headers", Conf),
|
||||
case Method of
|
||||
<<"post">> ->
|
||||
true;
|
||||
_ when Headers =:= undefined -> true;
|
||||
_ when is_list(Headers) ->
|
||||
case lists:member(<<"content-type">>, Headers) of
|
||||
false -> true;
|
||||
true -> {Method0, do_not_include_content_type}
|
||||
end
|
||||
end
|
||||
end.
|
||||
|
||||
union_array(Item) when is_list(Item) ->
|
||||
hoconsc:array(hoconsc:union(Item)).
|
||||
|
||||
|
@ -376,10 +364,3 @@ to_list(A) when is_atom(A) ->
|
|||
atom_to_list(A);
|
||||
to_list(B) when is_binary(B) ->
|
||||
binary_to_list(B).
|
||||
|
||||
to_bin(A) when is_atom(A) ->
|
||||
atom_to_binary(A);
|
||||
to_bin(B) when is_binary(B) ->
|
||||
B;
|
||||
to_bin(L) when is_list(L) ->
|
||||
list_to_binary(L).
|
||||
|
|
Loading…
Reference in New Issue