feat(authz api): support read cert file for api

This commit is contained in:
zhanghongtong 2021-09-02 10:44:04 +08:00 committed by Rory Z
parent 07dcd9e705
commit b8ee977d9d
2 changed files with 45 additions and 16 deletions

View File

@ -325,7 +325,7 @@ sources(get, _) ->
_ -> _ ->
NSource1#{annotations => #{status => unhealthy}} NSource1#{annotations => #{status => unhealthy}}
end, end,
lists:append(AccIn, [NSource2]); lists:append(AccIn, [read_cert(NSource2)]);
(Source, AccIn) -> (Source, AccIn) ->
lists:append(AccIn, [Source#{annotations => #{status => healthy}}]) lists:append(AccIn, [Source#{annotations => #{status => healthy}}])
end, [], emqx_authz:lookup()), end, [], emqx_authz:lookup()),
@ -340,7 +340,7 @@ sources(post, #{body := #{<<"type">> := <<"file">>, <<"rules">> := Rules, <<"ena
messgae => atom_to_binary(Reason)}} messgae => atom_to_binary(Reason)}}
end; end;
sources(post, #{body := Body}) when is_map(Body) -> sources(post, #{body := Body}) when is_map(Body) ->
case emqx_authz:update(head, [save_cert(Body)]) of case emqx_authz:update(head, [write_cert(Body)]) of
{ok, _} -> {204}; {ok, _} -> {204};
{error, Reason} -> {error, Reason} ->
{400, #{code => <<"BAD_REQUEST">>, {400, #{code => <<"BAD_REQUEST">>,
@ -353,7 +353,7 @@ sources(put, #{body := Body}) when is_list(Body) ->
Filename = filename:join([emqx:get_config([node, data_dir]), "authorization_rules.conf"]), Filename = filename:join([emqx:get_config([node, data_dir]), "authorization_rules.conf"]),
write_file(Filename, erlang:list_to_bitstring([<<Rule/binary, "\n">> || Rule <- Rules])), write_file(Filename, erlang:list_to_bitstring([<<Rule/binary, "\n">> || Rule <- Rules])),
#{type => file, enable => Enable, path => Filename}; #{type => file, enable => Enable, path => Filename};
_ -> save_cert(Source) _ -> write_cert(Source)
end end
end || Source <- Body], end || Source <- Body],
case emqx_authz:update(replace, NBody) of case emqx_authz:update(replace, NBody) of
@ -392,7 +392,7 @@ source(get, #{bindings := #{type := Type}}) ->
_ -> _ ->
NSource1#{annotations => #{status => unhealthy}} NSource1#{annotations => #{status => unhealthy}}
end, end,
{200, NSource2} {200, read_cert(NSource2)}
end; end;
source(put, #{bindings := #{type := file}, body := #{<<"type">> := <<"file">>, <<"rules">> := Rules, <<"enable">> := Enable}}) -> source(put, #{bindings := #{type := file}, body := #{<<"type">> := <<"file">>, <<"rules">> := Rules, <<"enable">> := Enable}}) ->
#{path := Path} = emqx_authz:lookup(file), #{path := Path} = emqx_authz:lookup(file),
@ -404,7 +404,7 @@ source(put, #{bindings := #{type := file}, body := #{<<"type">> := <<"file">>, <
messgae => atom_to_binary(Reason)}} messgae => atom_to_binary(Reason)}}
end; end;
source(put, #{bindings := #{type := Type}, body := Body}) when is_map(Body) -> source(put, #{bindings := #{type := Type}, body := Body}) when is_map(Body) ->
case emqx_authz:update({replace_once, Type}, save_cert(Body)) of case emqx_authz:update({replace_once, Type}, write_cert(Body)) of
{ok, _} -> {204}; {ok, _} -> {204};
{error, not_found_source} -> {error, not_found_source} ->
{404, #{code => <<"NOT_FOUND">>, {404, #{code => <<"NOT_FOUND">>,
@ -431,7 +431,27 @@ move_source(post, #{bindings := #{type := Type}, body := #{<<"position">> := Pos
messgae => atom_to_binary(Reason)}} messgae => atom_to_binary(Reason)}}
end. end.
save_cert(#{<<"config">> := #{<<"ssl">> := #{<<"enable">> := true} = SSL} = Config} = Body) -> read_cert(#{config := #{ssl := #{enable := true} = SSL} = Config} = Source) ->
CaCert = case file:read_file(maps:get(cacertfile, SSL, "")) of
{ok, CaCert0} -> CaCert0;
_ -> ""
end,
Cert = case file:read_file(maps:get(certfile, SSL, "")) of
{ok, Cert0} -> Cert0;
_ -> ""
end,
Key = case file:read_file(maps:get(keyfile, SSL, "")) of
{ok, Key0} -> Key0;
_ -> ""
end,
Source#{config => Config#{ssl => SSL#{cacertfile => CaCert,
certfile => Cert,
keyfile => Key
}}
};
read_cert(Source) -> Source.
write_cert(#{<<"config">> := #{<<"ssl">> := #{<<"enable">> := true} = SSL} = Config} = Source) ->
CertPath = filename:join([emqx:get_config([node, data_dir]), "certs"]), CertPath = filename:join([emqx:get_config([node, data_dir]), "certs"]),
CaCert = case maps:is_key(<<"cacertfile">>, SSL) of CaCert = case maps:is_key(<<"cacertfile">>, SSL) of
true -> true ->
@ -439,24 +459,24 @@ save_cert(#{<<"config">> := #{<<"ssl">> := #{<<"enable">> := true} = SSL} = Conf
maps:get(<<"cacertfile">>, SSL)); maps:get(<<"cacertfile">>, SSL));
false -> "" false -> ""
end, end,
Cert = case maps:is_key(<<"certfile">>, SSL) of Cert = case maps:is_key(<<"certfile">>, SSL) of
true -> true ->
write_file(filename:join([CertPath, "cert-" ++ emqx_rule_id:gen() ++".pem"]), write_file(filename:join([CertPath, "cert-" ++ emqx_rule_id:gen() ++".pem"]),
maps:get(<<"certfile">>, SSL)); maps:get(<<"certfile">>, SSL));
false -> "" false -> ""
end, end,
Key = case maps:is_key(<<"keyfile">>, SSL) of Key = case maps:is_key(<<"keyfile">>, SSL) of
true -> true ->
write_file(filename:join([CertPath, "key-" ++ emqx_rule_id:gen() ++".pem"]), write_file(filename:join([CertPath, "key-" ++ emqx_rule_id:gen() ++".pem"]),
maps:get(<<"keyfile">>, SSL)); maps:get(<<"keyfile">>, SSL));
false -> "" false -> ""
end, end,
Body#{<<"config">> := Config#{<<"ssl">> => SSL#{<<"cacertfile">> => CaCert, Source#{<<"config">> := Config#{<<"ssl">> => SSL#{<<"cacertfile">> => CaCert,
<<"certfile">> => Cert, <<"certfile">> => Cert,
<<"keyfile">> => Key} <<"keyfile">> => Key}
} }
}; };
save_cert(Body) -> Body. write_cert(Source) -> Source.
write_file(Filename, Bytes) -> write_file(Filename, Bytes) ->
ok = filelib:ensure_dir(Filename), ok = filelib:ensure_dir(Filename),

View File

@ -126,7 +126,7 @@ init_per_suite(Config) ->
ok = emqx_config:init_load(emqx_authz_schema, ?CONF_DEFAULT), ok = emqx_config:init_load(emqx_authz_schema, ?CONF_DEFAULT),
ok = emqx_ct_helpers:start_apps([emqx_authz, emqx_dashboard], fun set_special_configs/1), ok = emqx_ct_helpers:start_apps([emqx_authz, emqx_dashboard], fun set_special_configs/1),
{ok, _} = emqx:update_config([authorization, cache, enable], false), {ok, _} = emqx:update_config([authorization, cache, enable], false),
{ok, _} = emqx:update_config([authorization, no_match], deny), {ok, _} = emqx:update_config([authorization, no_match], deny),
@ -208,6 +208,10 @@ t_api(_) ->
?assertMatch(#{<<"type">> := <<"http">>, <<"enable">> := false}, jsx:decode(Result4)), ?assertMatch(#{<<"type">> := <<"http">>, <<"enable">> := false}, jsx:decode(Result4)),
#{<<"config">> := Config} = ?SOURCE2, #{<<"config">> := Config} = ?SOURCE2,
dbg:tracer(),dbg:p(all,c),
dbg:tpl(emqx_authz_api_sources, read_cert, cx),
dbg:tpl(emqx_authz_api_sources, write_cert, cx),
{ok, 204, _} = request(put, uri(["authorization", "sources", "mongo"]), {ok, 204, _} = request(put, uri(["authorization", "sources", "mongo"]),
?SOURCE2#{<<"config">> := Config#{<<"ssl">> := #{ ?SOURCE2#{<<"config">> := Config#{<<"ssl">> := #{
<<"enable">> => true, <<"enable">> => true,
@ -218,7 +222,12 @@ t_api(_) ->
}}}), }}}),
{ok, 200, Result5} = request(get, uri(["authorization", "sources", "mongo"]), []), {ok, 200, Result5} = request(get, uri(["authorization", "sources", "mongo"]), []),
?assertMatch(#{<<"type">> := <<"mongo">>, ?assertMatch(#{<<"type">> := <<"mongo">>,
<<"config">> := #{<<"ssl">> := #{<<"enable">> := true}} <<"config">> := #{<<"ssl">> := #{<<"enable">> := true,
<<"cacertfile">> := <<"fake cacert file">>,
<<"certfile">> := <<"fake cert file">>,
<<"keyfile">> := <<"fake key file">>,
<<"verify">> := false
}}
}, jsx:decode(Result5)), }, jsx:decode(Result5)),
?assert(filelib:is_file(filename:join([emqx:get_config([node, data_dir]), "certs", "cacert-fake.pem"]))), ?assert(filelib:is_file(filename:join([emqx:get_config([node, data_dir]), "certs", "cacert-fake.pem"]))),
?assert(filelib:is_file(filename:join([emqx:get_config([node, data_dir]), "certs", "cert-fake.pem"]))), ?assert(filelib:is_file(filename:join([emqx:get_config([node, data_dir]), "certs", "cert-fake.pem"]))),