Skip to content

Commit 152fd1f

Browse files
Merge pull request #9777 from rabbitmq/mergify/bp/v3.12.x/pr-9767
AMQP 1.0 Erlang client: integrate credentials_obfuscation (backport #9767)
2 parents 5e18d89 + e3facbd commit 152fd1f

File tree

4 files changed

+50
-15
lines changed

4 files changed

+50
-15
lines changed

deps/amqp10_client/BUILD.bazel

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,10 @@ rabbitmq_app(
7474
],
7575
license_files = [":license_files"],
7676
priv = [":priv"],
77-
deps = ["//deps/amqp10_common:erlang_app"],
77+
deps = [
78+
"//deps/amqp10_common:erlang_app",
79+
"@credentials_obfuscation//:erlang_app",
80+
],
7881
)
7982

8083
xref(

deps/amqp10_client/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ endef
2929
PACKAGES_DIR ?= $(abspath PACKAGES)
3030

3131
BUILD_DEPS = rabbit_common elvis_mk
32-
DEPS = amqp10_common
32+
DEPS = amqp10_common credentials_obfuscation
3333
TEST_DEPS = rabbit rabbitmq_amqp1_0 rabbitmq_ct_helpers
3434
LOCAL_DEPS = ssl inets crypto public_key
3535

deps/amqp10_client/src/amqp10_client.erl

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@
8787
-spec open_connection(inet:socket_address() | inet:hostname(),
8888
inet:port_number()) -> supervisor:startchild_ret().
8989
open_connection(Addr, Port) ->
90+
_ = ensure_started(),
9091
open_connection(#{address => Addr, port => Port, notify => self(),
9192
sasl => anon}).
9293

@@ -97,14 +98,19 @@ open_connection(Addr, Port) ->
9798
-spec open_connection(connection_config()) ->
9899
supervisor:startchild_ret().
99100
open_connection(ConnectionConfig0) ->
101+
_ = ensure_started(),
102+
100103
Notify = maps:get(notify, ConnectionConfig0, self()),
101104
NotifyWhenOpened = maps:get(notify_when_opened, ConnectionConfig0, self()),
102105
NotifyWhenClosed = maps:get(notify_when_closed, ConnectionConfig0, self()),
103-
amqp10_client_connection:open(ConnectionConfig0#{
106+
ConnectionConfig1 = ConnectionConfig0#{
104107
notify => Notify,
105108
notify_when_opened => NotifyWhenOpened,
106109
notify_when_closed => NotifyWhenClosed
107-
}).
110+
},
111+
Sasl = maps:get(sasl, ConnectionConfig1),
112+
ConnectionConfig2 = ConnectionConfig1#{sasl => amqp10_client_connection:encrypt_sasl(Sasl)},
113+
amqp10_client_connection:open(ConnectionConfig2).
108114

109115
%% @doc Opens a connection using a connection_config map
110116
%% This is asynchronous and will notify completion to the caller using
@@ -497,6 +503,8 @@ try_to_existing_atom(L) when is_list(L) ->
497503
throw({non_existent_atom, L})
498504
end.
499505

506+
ensure_started() ->
507+
_ = application:ensure_all_started(credentials_obfuscation).
500508

501509
-ifdef(TEST).
502510
-include_lib("eunit/include/eunit.hrl").

deps/amqp10_client/src/amqp10_client_connection.erl

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
socket_ready/2,
3131
protocol_header_received/5,
3232
begin_session/1,
33-
heartbeat/1]).
33+
heartbeat/1,
34+
encrypt_sasl/1,
35+
decrypt_sasl/1]).
3436

3537
%% gen_fsm callbacks.
3638
-export([init/1,
@@ -56,6 +58,9 @@
5658

5759
-type address() :: inet:socket_address() | inet:hostname().
5860

61+
-type encrypted_sasl() :: {plaintext, binary()} | {encrypted, binary()}.
62+
-type decrypted_sasl() :: none | anon | {plain, User :: binary(), Pwd :: binary()}.
63+
5964
-type connection_config() ::
6065
#{container_id => binary(), % AMQP container id
6166
hostname => binary(), % the dns name of the target host
@@ -72,7 +77,9 @@
7277
% set to a negative value to allow a sender to "overshoot" the flow
7378
% control by this margin
7479
transfer_limit_margin => 0 | neg_integer(),
75-
sasl => none | anon | {plain, User :: binary(), Pwd :: binary()},
80+
%% These credentials_obfuscation-wrapped values have the type of
81+
%% decrypted_sasl/0
82+
sasl => encrypted_sasl() | decrypted_sasl(),
7683
notify => pid(),
7784
notify_when_opened => pid() | none,
7885
notify_when_closed => pid() | none
@@ -92,7 +99,9 @@
9299
}).
93100

94101
-export_type([connection_config/0,
95-
amqp10_socket/0]).
102+
amqp10_socket/0,
103+
encrypted_sasl/0,
104+
decrypted_sasl/0]).
96105

97106
%% -------------------------------------------------------------------
98107
%% Public API.
@@ -125,6 +134,18 @@ open(Config) ->
125134
close(Pid, Reason) ->
126135
gen_statem:cast(Pid, {close, Reason}).
127136

137+
-spec encrypt_sasl(decrypted_sasl()) -> encrypted_sasl().
138+
encrypt_sasl(none) ->
139+
credentials_obfuscation:encrypt(none);
140+
encrypt_sasl(DecryptedSasl) ->
141+
credentials_obfuscation:encrypt(term_to_binary(DecryptedSasl)).
142+
143+
-spec decrypt_sasl(encrypted_sasl()) -> decrypted_sasl().
144+
decrypt_sasl(none) ->
145+
credentials_obfuscation:decrypt(none);
146+
decrypt_sasl(EncryptedSasl) ->
147+
binary_to_term(credentials_obfuscation:decrypt(EncryptedSasl)).
148+
128149
%% -------------------------------------------------------------------
129150
%% Private API.
130151
%% -------------------------------------------------------------------
@@ -166,8 +187,9 @@ init([Sup, Config0]) ->
166187
expecting_socket(_EvtType, {socket_ready, Socket},
167188
State = #state{config = Cfg}) ->
168189
State1 = State#state{socket = Socket},
169-
case Cfg of
170-
#{sasl := none} ->
190+
Sasl = credentials_obfuscation:decrypt(maps:get(sasl, Cfg)),
191+
case Sasl of
192+
none ->
171193
ok = socket_send(Socket, ?AMQP_PROTOCOL_HEADER),
172194
{next_state, hdr_sent, State1};
173195
_ ->
@@ -193,16 +215,17 @@ sasl_hdr_sent({call, From}, begin_session,
193215

194216
sasl_hdr_rcvds(_EvtType, #'v1_0.sasl_mechanisms'{
195217
sasl_server_mechanisms = {array, symbol, Mechs}},
196-
State = #state{config = #{sasl := Sasl}}) ->
197-
SaslBin = {symbol, sasl_to_bin(Sasl)},
218+
State = #state{config = #{sasl := EncryptedSasl}}) ->
219+
DecryptedSasl = decrypt_sasl(EncryptedSasl),
220+
SaslBin = {symbol, decrypted_sasl_to_bin(DecryptedSasl)},
198221
case lists:any(fun(S) when S =:= SaslBin -> true;
199222
(_) -> false
200223
end, Mechs) of
201224
true ->
202-
ok = send_sasl_init(State, Sasl),
225+
ok = send_sasl_init(State, DecryptedSasl),
203226
{next_state, sasl_init_sent, State};
204227
false ->
205-
{stop, {sasl_not_supported, Sasl}, State}
228+
{stop, {sasl_not_supported, DecryptedSasl}, State}
206229
end;
207230
sasl_hdr_rcvds({call, From}, begin_session,
208231
#state{pending_session_reqs = PendingSessionReqs} = State) ->
@@ -522,8 +545,9 @@ translate_err(#'v1_0.error'{condition = Cond, description = Desc}) ->
522545
amqp10_event(Evt) ->
523546
{amqp10_event, {connection, self(), Evt}}.
524547

525-
sasl_to_bin({plain, _, _}) -> <<"PLAIN">>;
526-
sasl_to_bin(anon) -> <<"ANONYMOUS">>.
548+
decrypted_sasl_to_bin({plain, _, _}) -> <<"PLAIN">>;
549+
decrypted_sasl_to_bin(anon) -> <<"ANONYMOUS">>;
550+
decrypted_sasl_to_bin(none) -> <<"ANONYMOUS">>.
527551

528552
config_defaults() ->
529553
#{sasl => none,

0 commit comments

Comments
 (0)