From cf115fef7279ac53a5cc946b7dac43845ebba69c Mon Sep 17 00:00:00 2001 From: Siim Mardus Date: Mon, 27 May 2024 15:16:37 +0300 Subject: [PATCH 1/4] Change path in escript Previously the path to ebin did not work properly when a different folder structure was used. This makes sure that it targets the correct folder. (In future commits, this could even be a parameter, for better configurability) --- src/pact_escript.escript | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pact_escript.escript b/src/pact_escript.escript index 601b34c..8bc45d3 100755 --- a/src/pact_escript.escript +++ b/src/pact_escript.escript @@ -2,8 +2,8 @@ main([Module, Function | Args]) -> - code:add_pathz("../../lib/pact_erlang/ebin"), - code:add_pathz("../../../lib/pact_erlang/ebin"), + {ok, Dir} = file:get_cwd(), + code:add_pathz(Dir ++ "/_build/test/lib/pact_erlang/ebin"), ModuleAtom = list_to_atom(Module), FunctionAtom = list_to_atom(Function), ArgsList = From ae0b4f027b6158413fab6fe52d848706d1fbcdc8 Mon Sep 17 00:00:00 2001 From: Siim Mardus Date: Mon, 27 May 2024 15:21:30 +0300 Subject: [PATCH 2/4] Log out the output from pact verifying OutputLog contains useful information about what happens with Pact verification. --- src/pact_verifier.erl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pact_verifier.erl b/src/pact_verifier.erl index f552e34..cf0b4a0 100644 --- a/src/pact_verifier.erl +++ b/src/pact_verifier.erl @@ -199,9 +199,10 @@ verify_pacts(VerifierRef, ProviderOpts, ProviderPortDetails) -> "", Args ), - {Output, _OutputLog} = pact_utils:run_executable_async( + {Output, OutputLog} = pact_utils:run_executable_async( EscriptPath ++ " pactffi_nif verify_file_pacts " ++ ArgsString ), + io:format(OutputLog), Output end, Output2 = @@ -246,9 +247,10 @@ verify_pacts(VerifierRef, ProviderOpts, ProviderPortDetails) -> "", Args1 ), - {Output3, _OutputLog3} = pact_utils:run_executable_async( + {Output3, OutputLog3} = pact_utils:run_executable_async( EscriptPath ++ " pactffi_nif verify_broker_pacts " ++ ArgsString1 ), + io:format(OutputLog3), Output3 end, case Protocol of From d75d6bae1ca459287ab841d54c003b068bd9c6bf Mon Sep 17 00:00:00 2001 From: Siim Mardus Date: Wed, 29 May 2024 15:25:58 +0300 Subject: [PATCH 3/4] Allow adding custom auth token for pact verification This is useful if the provider wants to use real authentication flow for the contract tests. Disclaimer: `pactffi_verifier_add_custom_header` function unfortunately is not able to override an existing header, so using this requires the pact to not include the authorization header in the first place. This can either be done by simply not using it on the consumer-side test or removing it somehow before publishing the pact. Although I worked through the following issues: - https://github.com/pact-foundation/pact-net/issues/460 - https://github.com/pact-foundation/pact-reference/issues/275 from which the latter is actually marked as closed, and the fix is allegedly included in the pact-ffi version that we use, it still did not override an existing header. I tried bumping to a higher version as well but without any luck. I will create an issue to pact-foundation to try to get clarity on this. --- c_src/pactffi_nif.c | 17 ++++++++++++----- src/pact_escript.escript | 2 +- src/pact_verifier.erl | 4 ++++ src/pactffi_nif.erl | 20 ++++++++++---------- 4 files changed, 27 insertions(+), 16 deletions(-) diff --git a/c_src/pactffi_nif.c b/c_src/pactffi_nif.c index 8b428a7..e67aa7f 100644 --- a/c_src/pactffi_nif.c +++ b/c_src/pactffi_nif.c @@ -699,12 +699,19 @@ static ERL_NIF_TERM verify_via_file(ErlNifEnv *env, int argc, const ERL_NIF_TERM pactffi_verifier_set_no_pacts_is_error(verifierhandle, 0); pactffi_verifier_set_provider_info(verifierhandle, name, scheme, host, port, path); pactffi_verifier_add_provider_transport(verifierhandle, protocol, port, path, scheme); - if (!enif_is_binary(env, argv[9])) + + char *auth_token_type = convert_erl_binary_to_c_string(env, argv[9]); + char *auth_token_value = convert_erl_binary_to_c_string(env, argv[10]); + char *auth_header = (char *)malloc((strlen(auth_token_type) + strlen(auth_token_value) + 1) * sizeof(char)); + sprintf(auth_header, "%s %s", auth_token_type, auth_token_value); + pactffi_verifier_add_custom_header(verifierhandle, "authorization", auth_header); + free(auth_header); + + if (!enif_is_binary(env, argv[11])) { return enif_make_badarg(env); } - - char *state_path = convert_erl_binary_to_c_string(env, argv[9]); + char *state_path = convert_erl_binary_to_c_string(env, argv[11]); if (state_path[0] != '\0') { pactffi_verifier_set_provider_state(verifierhandle, state_path, 0, 1); @@ -875,10 +882,10 @@ static ErlNifFunc nif_funcs[] = {"msg_given_with_param", 4, msg_given_with_param}, {"msg_with_contents", 3, msg_with_contents}, {"reify_message", 1, reify_message}, - {"schedule_async_file_verify", 10, schedule_async_file_verify}, + {"schedule_async_file_verify", 12, schedule_async_file_verify}, {"schedule_async_broker_verify", 15, schedule_async_broker_verify}, {"verify_via_broker", 15, verify_via_broker}, - {"verify_via_file", 10, verify_via_file} + {"verify_via_file", 12, verify_via_file} }; ERL_NIF_INIT(pactffi_nif, nif_funcs, NULL, NULL, NULL, NULL) diff --git a/src/pact_escript.escript b/src/pact_escript.escript index 8bc45d3..3bfc572 100755 --- a/src/pact_escript.escript +++ b/src/pact_escript.escript @@ -24,7 +24,7 @@ main([Module, Function | Args]) -> {[], 0}, Args ), - case length(AList) < 10 of + case length(AList) < 12 of true -> AList ++ [<<"">>]; false -> diff --git a/src/pact_verifier.erl b/src/pact_verifier.erl index cf0b4a0..62350e4 100644 --- a/src/pact_verifier.erl +++ b/src/pact_verifier.erl @@ -161,6 +161,8 @@ verify_pacts(VerifierRef, ProviderOpts, ProviderPortDetails) -> } = ProviderOpts, Protocol = maps:get(protocol, ProviderOpts, <<"http">>), BaseUrl = maps:get(base_url, ProviderOpts, <<"/">>), + AuthTokenType = maps:get(auth_token_type, ProviderOpts, <<"Bearer">>), + AuthTokenValue = maps:get(auth_token_value, ProviderOpts, <<"Token">>), StateChangeUrl = maps:get(state_change_url, ProviderOpts, <<"">>), Scheme = maps:get(scheme, ProviderOpts, <<"http">>), FilePath = maps:get(file_path, PactSourceOpts, undefined), @@ -182,6 +184,8 @@ verify_pacts(VerifierRef, ProviderOpts, ProviderPortDetails) -> Branch, FilePath, Protocol, + AuthTokenType, + AuthTokenValue, StateChangeUrl ], ArgsString = diff --git a/src/pactffi_nif.erl b/src/pactffi_nif.erl index 9ebd83d..a690fef 100644 --- a/src/pactffi_nif.erl +++ b/src/pactffi_nif.erl @@ -34,12 +34,12 @@ msg_with_contents/3, reify_message/1, get_reified_message/1, - verify_file_pacts/10, + verify_file_pacts/12, verify_broker_pacts/14, schedule_async_broker_verify/15, - schedule_async_file_verify/10, + schedule_async_file_verify/12, verify_via_broker/15, - verify_via_file/10 + verify_via_file/12 ]). % Import the NIF functions from the C library @@ -70,10 +70,10 @@ msg_given_with_param/4, msg_with_contents/3, reify_message/1, - schedule_async_file_verify/10, + schedule_async_file_verify/12, schedule_async_broker_verify/15, verify_via_broker/15, - verify_via_file/10 + verify_via_file/12 ]). -on_load(init/0). @@ -186,30 +186,30 @@ msg_with_contents(_, _, _) -> reify_message(_) -> erlang:nif_error("NIF library not loaded"). -schedule_async_file_verify(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) -> +schedule_async_file_verify(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) -> erlang:nif_error("NIF library not loaded"). schedule_async_broker_verify(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) -> erlang:nif_error("NIF library not loaded"). -verify_via_file(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) -> +verify_via_file(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) -> erlang:nif_error("NIF library not loaded"). verify_via_broker(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) -> erlang:nif_error("NIF library not loaded"). verify_file_pacts( - Name, Scheme, Host, Port, Path, Version, Branch, FilePath, Protocol, StatePath + Name, Scheme, Host, Port, Path, Version, Branch, FilePath, Protocol, AuthTokenType, AuthTokenValue, StatePath ) -> verify_via_file( - Name, Scheme, Host, Port, Path, Version, Branch, FilePath, Protocol, StatePath + Name, Scheme, Host, Port, Path, Version, Branch, FilePath, Protocol, AuthTokenType, AuthTokenValue, StatePath ). % receive % Output -> % Output % end. % verify_via_file( -% Name, Scheme, Host, Port, Path, Version, Branch, FilePath, Protocol, Pid, StatePath +% Name, Scheme, Host, Port, Path, Version, Branch, FilePath, Protocol, Pid, AuthTokenType, AuthTokenValue, StatePath % ). verify_broker_pacts( From df5df77a017485c174d5ef916d106c4a360f5eba Mon Sep 17 00:00:00 2001 From: Siim Mardus Date: Wed, 5 Jun 2024 12:20:21 +0300 Subject: [PATCH 4/4] Revert "Allow adding custom auth token for pact verification" This reverts commit d75d6bae1ca459287ab841d54c003b068bd9c6bf. Reason: I actually found anther way of replacing the authorization header: - Use `fromProviderState` Matcher function on consumer side for auth header. Match `Bearer ${authToken}`, use JWT regex - On provider side, in state change URL endpoint, generate the token and return it in the callback under `authToken` - The provider-generated auth token will be used in the request. I am leaving this as commit + revert for future reference purposes. --- c_src/pactffi_nif.c | 17 +++++------------ src/pact_escript.escript | 2 +- src/pact_verifier.erl | 4 ---- src/pactffi_nif.erl | 20 ++++++++++---------- 4 files changed, 16 insertions(+), 27 deletions(-) diff --git a/c_src/pactffi_nif.c b/c_src/pactffi_nif.c index e67aa7f..8b428a7 100644 --- a/c_src/pactffi_nif.c +++ b/c_src/pactffi_nif.c @@ -699,19 +699,12 @@ static ERL_NIF_TERM verify_via_file(ErlNifEnv *env, int argc, const ERL_NIF_TERM pactffi_verifier_set_no_pacts_is_error(verifierhandle, 0); pactffi_verifier_set_provider_info(verifierhandle, name, scheme, host, port, path); pactffi_verifier_add_provider_transport(verifierhandle, protocol, port, path, scheme); - - char *auth_token_type = convert_erl_binary_to_c_string(env, argv[9]); - char *auth_token_value = convert_erl_binary_to_c_string(env, argv[10]); - char *auth_header = (char *)malloc((strlen(auth_token_type) + strlen(auth_token_value) + 1) * sizeof(char)); - sprintf(auth_header, "%s %s", auth_token_type, auth_token_value); - pactffi_verifier_add_custom_header(verifierhandle, "authorization", auth_header); - free(auth_header); - - if (!enif_is_binary(env, argv[11])) + if (!enif_is_binary(env, argv[9])) { return enif_make_badarg(env); } - char *state_path = convert_erl_binary_to_c_string(env, argv[11]); + + char *state_path = convert_erl_binary_to_c_string(env, argv[9]); if (state_path[0] != '\0') { pactffi_verifier_set_provider_state(verifierhandle, state_path, 0, 1); @@ -882,10 +875,10 @@ static ErlNifFunc nif_funcs[] = {"msg_given_with_param", 4, msg_given_with_param}, {"msg_with_contents", 3, msg_with_contents}, {"reify_message", 1, reify_message}, - {"schedule_async_file_verify", 12, schedule_async_file_verify}, + {"schedule_async_file_verify", 10, schedule_async_file_verify}, {"schedule_async_broker_verify", 15, schedule_async_broker_verify}, {"verify_via_broker", 15, verify_via_broker}, - {"verify_via_file", 12, verify_via_file} + {"verify_via_file", 10, verify_via_file} }; ERL_NIF_INIT(pactffi_nif, nif_funcs, NULL, NULL, NULL, NULL) diff --git a/src/pact_escript.escript b/src/pact_escript.escript index 3bfc572..8bc45d3 100755 --- a/src/pact_escript.escript +++ b/src/pact_escript.escript @@ -24,7 +24,7 @@ main([Module, Function | Args]) -> {[], 0}, Args ), - case length(AList) < 12 of + case length(AList) < 10 of true -> AList ++ [<<"">>]; false -> diff --git a/src/pact_verifier.erl b/src/pact_verifier.erl index 62350e4..cf0b4a0 100644 --- a/src/pact_verifier.erl +++ b/src/pact_verifier.erl @@ -161,8 +161,6 @@ verify_pacts(VerifierRef, ProviderOpts, ProviderPortDetails) -> } = ProviderOpts, Protocol = maps:get(protocol, ProviderOpts, <<"http">>), BaseUrl = maps:get(base_url, ProviderOpts, <<"/">>), - AuthTokenType = maps:get(auth_token_type, ProviderOpts, <<"Bearer">>), - AuthTokenValue = maps:get(auth_token_value, ProviderOpts, <<"Token">>), StateChangeUrl = maps:get(state_change_url, ProviderOpts, <<"">>), Scheme = maps:get(scheme, ProviderOpts, <<"http">>), FilePath = maps:get(file_path, PactSourceOpts, undefined), @@ -184,8 +182,6 @@ verify_pacts(VerifierRef, ProviderOpts, ProviderPortDetails) -> Branch, FilePath, Protocol, - AuthTokenType, - AuthTokenValue, StateChangeUrl ], ArgsString = diff --git a/src/pactffi_nif.erl b/src/pactffi_nif.erl index a690fef..9ebd83d 100644 --- a/src/pactffi_nif.erl +++ b/src/pactffi_nif.erl @@ -34,12 +34,12 @@ msg_with_contents/3, reify_message/1, get_reified_message/1, - verify_file_pacts/12, + verify_file_pacts/10, verify_broker_pacts/14, schedule_async_broker_verify/15, - schedule_async_file_verify/12, + schedule_async_file_verify/10, verify_via_broker/15, - verify_via_file/12 + verify_via_file/10 ]). % Import the NIF functions from the C library @@ -70,10 +70,10 @@ msg_given_with_param/4, msg_with_contents/3, reify_message/1, - schedule_async_file_verify/12, + schedule_async_file_verify/10, schedule_async_broker_verify/15, verify_via_broker/15, - verify_via_file/12 + verify_via_file/10 ]). -on_load(init/0). @@ -186,30 +186,30 @@ msg_with_contents(_, _, _) -> reify_message(_) -> erlang:nif_error("NIF library not loaded"). -schedule_async_file_verify(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) -> +schedule_async_file_verify(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) -> erlang:nif_error("NIF library not loaded"). schedule_async_broker_verify(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) -> erlang:nif_error("NIF library not loaded"). -verify_via_file(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) -> +verify_via_file(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) -> erlang:nif_error("NIF library not loaded"). verify_via_broker(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) -> erlang:nif_error("NIF library not loaded"). verify_file_pacts( - Name, Scheme, Host, Port, Path, Version, Branch, FilePath, Protocol, AuthTokenType, AuthTokenValue, StatePath + Name, Scheme, Host, Port, Path, Version, Branch, FilePath, Protocol, StatePath ) -> verify_via_file( - Name, Scheme, Host, Port, Path, Version, Branch, FilePath, Protocol, AuthTokenType, AuthTokenValue, StatePath + Name, Scheme, Host, Port, Path, Version, Branch, FilePath, Protocol, StatePath ). % receive % Output -> % Output % end. % verify_via_file( -% Name, Scheme, Host, Port, Path, Version, Branch, FilePath, Protocol, Pid, AuthTokenType, AuthTokenValue, StatePath +% Name, Scheme, Host, Port, Path, Version, Branch, FilePath, Protocol, Pid, StatePath % ). verify_broker_pacts(