Jelajahi Sumber

feat: support env value interpolation for secret file path

zmstone 1 tahun lalu
induk
melakukan
962e840d32

+ 3 - 3
apps/emqx/src/emqx_schema.erl

@@ -3422,7 +3422,8 @@ naive_env_interpolation(Other) ->
     Other.
     Other.
 
 
 split_path(Path) ->
 split_path(Path) ->
-    split_path(Path, []).
+    {Name0, Tail} = split_path(Path, []),
+    {string:trim(Name0, both, "{}"), Tail}.
 
 
 split_path([], Acc) ->
 split_path([], Acc) ->
     {lists:reverse(Acc), []};
     {lists:reverse(Acc), []};
@@ -3431,8 +3432,7 @@ split_path([Char | Rest], Acc) when Char =:= $/ orelse Char =:= $\\ ->
 split_path([Char | Rest], Acc) ->
 split_path([Char | Rest], Acc) ->
     split_path(Rest, [Char | Acc]).
     split_path(Rest, [Char | Acc]).
 
 
-resolve_env(Name0) ->
-    Name = string:trim(Name0, both, "{}"),
+resolve_env(Name) ->
     Value = os:getenv(Name),
     Value = os:getenv(Name),
     case Value =/= false andalso Value =/= "" of
     case Value =/= false andalso Value =/= "" of
         true ->
         true ->

+ 3 - 4
apps/emqx/src/emqx_secret_loader.erl

@@ -28,12 +28,11 @@
 load({file, <<"file://", Path/binary>>}) ->
 load({file, <<"file://", Path/binary>>}) ->
     file(Path);
     file(Path);
 load({file, "file://" ++ Path}) ->
 load({file, "file://" ++ Path}) ->
-    file(Path);
-load({file, Filename}) ->
-    file(Filename).
+    file(Path).
 
 
 -spec file(file:filename_all()) -> binary() | no_return().
 -spec file(file:filename_all()) -> binary() | no_return().
-file(Filename) ->
+file(Filename0) ->
+    Filename = emqx_schema:naive_env_interpolation(Filename0),
     case file:read_file(Filename) of
     case file:read_file(Filename) of
         {ok, Secret} ->
         {ok, Secret} ->
             string:trim(Secret, trailing);
             string:trim(Secret, trailing);

+ 29 - 6
apps/emqx/test/emqx_secret_tests.erl

@@ -39,21 +39,41 @@ wrap_unwrap_load_test_() ->
         fun(Filename) ->
         fun(Filename) ->
             ?_assertEqual(
             ?_assertEqual(
                 Secret,
                 Secret,
-                emqx_secret:unwrap(emqx_secret:wrap_load({file, Filename}))
+                emqx_secret:unwrap(emqx_secret:wrap_load(file_ref(Filename)))
             )
             )
         end
         end
     }.
     }.
 
 
+wrap_unwrap_load_path_env_interpolate_test_() ->
+    Secret = <<"111">>,
+    {
+        setup,
+        fun() -> write_temp_file(Secret) end,
+        fun(Filename) -> file:delete(Filename) end,
+        fun(Filename) ->
+            fun() ->
+                os:putenv("SECRETFILEPATH", Filename),
+                File = "file://${SECRETFILEPATH}",
+                try
+                    ?assertEqual(
+                        Secret,
+                        emqx_secret:unwrap(emqx_secret:wrap_load({file, File}))
+                    )
+                after
+                    os:unsetenv("SECRETFILEPATH")
+                end
+            end
+        end
+    }.
+
 wrap_load_term_test() ->
 wrap_load_term_test() ->
-    ?assertEqual(
-        {file, "no/such/file/i/swear"},
-        emqx_secret:term(emqx_secret:wrap_load({file, "no/such/file/i/swear"}))
-    ).
+    Ref = file_ref("no/such/file/i/swear"),
+    ?assertEqual(Ref, emqx_secret:term(emqx_secret:wrap_load(Ref))).
 
 
 wrap_unwrap_missing_file_test() ->
 wrap_unwrap_missing_file_test() ->
     ?assertThrow(
     ?assertThrow(
         #{msg := failed_to_read_secret_file, reason := "No such file or directory"},
         #{msg := failed_to_read_secret_file, reason := "No such file or directory"},
-        emqx_secret:unwrap(emqx_secret:wrap_load({file, "no/such/file/i/swear"}))
+        emqx_secret:unwrap(emqx_secret:wrap_load(file_ref("no/such/file/i/swear")))
     ).
     ).
 
 
 wrap_term_test() ->
 wrap_term_test() ->
@@ -74,3 +94,6 @@ write_temp_file(Bytes) ->
     Filename = filename:join("/tmp", ?MODULE_STRING ++ integer_to_list(-Ts)),
     Filename = filename:join("/tmp", ?MODULE_STRING ++ integer_to_list(-Ts)),
     ok = file:write_file(Filename, Bytes),
     ok = file:write_file(Filename, Bytes),
     Filename.
     Filename.
+
+file_ref(Path) ->
+    {file, "file://" ++ Path}.