Skip to content

Commit c57a562

Browse files
sunfinitelukebakken
authored andcommitted
Add support for AWS_SESSION_TOKEN
* Add comprehensive tests for the `rabbitmq_aws` cuttlefish schema. * Move `aws_prefer_imdsv2` setting to the `rabbitmq_aws` application. * Use AWS session token when present in env or config file. It was only used with IMDSv2 previously.
1 parent 2714c7f commit c57a562

File tree

9 files changed

+82
-27
lines changed

9 files changed

+82
-27
lines changed

deps/rabbitmq_aws/.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ indent_style = tab
1212
# 2 space indentation
1313
[{*.erl, *.hrl, *.md}]
1414
indent_style = space
15-
indent_size = 2
15+
indent_size = 4

deps/rabbitmq_aws/Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@ define PROJECT_ENV
77
[]
88
endef
99

10+
BUILD_DEPS = rabbit
11+
DEPS = rabbit_common
12+
TEST_DEPS = meck rabbitmq_ct_helpers rabbitmq_ct_client_helpers
1013
LOCAL_DEPS = crypto inets ssl xmerl public_key
11-
BUILD_DEPS = rabbit_common
12-
TEST_DEPS = meck rabbit rabbitmq_ct_helpers rabbitmq_ct_client_helpers
14+
15+
PLT_APPS = rabbit
1316

1417
DEP_EARLY_PLUGINS = rabbit_common/mk/rabbitmq-early-plugin.mk
1518
DEP_PLUGINS = rabbit_common/mk/rabbitmq-plugin.mk

deps/rabbitmq_aws/priv/schema/rabbitmq_aws.schema

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@
1515
%% When false, EC2 IMDSv1 will be used first and no attempt will be made to use EC2 IMDSv2.
1616
%% See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html.
1717

18-
{mapping, "aws.prefer_imdsv2", "rabbit.aws_prefer_imdsv2",
18+
{mapping, "aws.prefer_imdsv2", "rabbitmq_aws.aws_prefer_imdsv2",
1919
[{datatype, {enum, [true, false]}}]}.

deps/rabbitmq_aws/src/rabbitmq_aws.erl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
refresh_credentials/0,
1616
request/5, request/6, request/7,
1717
set_credentials/2,
18+
set_credentials/3,
1819
has_credentials/0,
1920
set_region/1,
2021
ensure_imdsv2_token_valid/0,
@@ -158,6 +159,12 @@ set_credentials(NewState) ->
158159
set_credentials(AccessKey, SecretAccessKey) ->
159160
gen_server:call(rabbitmq_aws, {set_credentials, AccessKey, SecretAccessKey}).
160161

162+
-spec set_credentials(access_key(), secret_access_key(), security_token()) -> ok.
163+
%% @doc Manually set the access credentials with session token for requests.
164+
%% @end
165+
set_credentials(AccessKey, SecretAccessKey, SessionToken) ->
166+
gen_server:call(rabbitmq_aws, {set_credentials, AccessKey, SecretAccessKey, SessionToken}).
167+
161168
-spec set_region(Region :: string()) -> ok.
162169
%% @doc Manually set the AWS region to perform API requests to.
163170
%% @end
@@ -224,6 +231,14 @@ handle_msg({set_credentials, AccessKey, SecretAccessKey}, State) ->
224231
expiration = undefined,
225232
error = undefined
226233
}};
234+
handle_msg({set_credentials, AccessKey, SecretAccessKey, SessionToken}, State) ->
235+
{reply, ok, State#state{
236+
access_key = AccessKey,
237+
secret_access_key = SecretAccessKey,
238+
security_token = SessionToken,
239+
expiration = undefined,
240+
error = undefined
241+
}};
227242
handle_msg({set_credentials, NewState}, State) ->
228243
{reply, ok, State#state{
229244
access_key = NewState#state.access_key,

deps/rabbitmq_aws/src/rabbitmq_aws_config.erl

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ credentials(Profile) ->
134134
lookup_credentials(
135135
Profile,
136136
os:getenv("AWS_ACCESS_KEY_ID"),
137-
os:getenv("AWS_SECRET_ACCESS_KEY")
137+
os:getenv("AWS_SECRET_ACCESS_KEY"),
138+
os:getenv("AWS_SESSION_TOKEN")
138139
).
139140

140141
-spec region() -> {ok, string()}.
@@ -452,43 +453,53 @@ instance_id_url() ->
452453
-spec lookup_credentials(
453454
Profile :: string(),
454455
AccessKey :: string() | false,
455-
SecretKey :: string() | false
456+
SecretKey :: string() | false,
457+
SessionToken :: string() | false
456458
) ->
457459
security_credentials().
458460
%% @doc Return the access key and secret access key if they are set in
459461
%% environment variables, otherwise lookup the credentials from the config
460462
%% file for the specified profile.
461463
%% @end
462-
lookup_credentials(Profile, false, _) ->
464+
lookup_credentials(Profile, false, _, _) ->
463465
lookup_credentials_from_config(
464466
Profile,
465467
value(Profile, aws_access_key_id),
466-
value(Profile, aws_secret_access_key)
468+
value(Profile, aws_secret_access_key),
469+
value(Profile, aws_session_token)
467470
);
468-
lookup_credentials(Profile, _, false) ->
471+
lookup_credentials(Profile, _, false, _) ->
469472
lookup_credentials_from_config(
470473
Profile,
471474
value(Profile, aws_access_key_id),
472-
value(Profile, aws_secret_access_key)
475+
value(Profile, aws_secret_access_key),
476+
value(Profile, aws_session_token)
473477
);
474-
lookup_credentials(_, AccessKey, SecretKey) ->
475-
{ok, AccessKey, SecretKey, undefined, undefined}.
478+
lookup_credentials(_, AccessKey, SecretKey, SessionToken) ->
479+
case SessionToken of
480+
false -> {ok, AccessKey, SecretKey, undefined, undefined};
481+
SessionToken -> {ok, AccessKey, SecretKey, undefined, SessionToken}
482+
end.
476483

477484
-spec lookup_credentials_from_config(
478485
Profile :: string(),
479486
access_key() | {error, Reason :: atom()},
480-
secret_access_key() | {error, Reason :: atom()}
487+
secret_access_key() | {error, Reason :: atom()},
488+
security_token() | {error, Reason :: atom()}
481489
) ->
482490
security_credentials().
483491
%% @doc Return the access key and secret access key if they are set in
484492
%% for the specified profile in the config file, if it exists. If it does
485493
%% not exist or the profile is not set or the values are not set in the
486494
%% profile, look up the values in the shared credentials file
487495
%% @end
488-
lookup_credentials_from_config(Profile, {error, _}, _) ->
496+
lookup_credentials_from_config(Profile, {error, _}, _, _) ->
489497
lookup_credentials_from_file(Profile, credentials_file_data());
490-
lookup_credentials_from_config(_, AccessKey, SecretKey) ->
491-
{ok, AccessKey, SecretKey, undefined, undefined}.
498+
lookup_credentials_from_config(_, AccessKey, SecretKey, SessionToken) ->
499+
case SessionToken of
500+
{error, _} -> {ok, AccessKey, SecretKey, undefined, undefined};
501+
SessionToken -> {ok, AccessKey, SecretKey, undefined, SessionToken}
502+
end.
492503

493504
-spec lookup_credentials_from_file(
494505
Profile :: string(),
@@ -518,22 +529,24 @@ lookup_credentials_from_section(undefined) ->
518529
lookup_credentials_from_section(Credentials) ->
519530
AccessKey = proplists:get_value(aws_access_key_id, Credentials, undefined),
520531
SecretKey = proplists:get_value(aws_secret_access_key, Credentials, undefined),
521-
lookup_credentials_from_proplist(AccessKey, SecretKey).
532+
SessionToken = proplists:get_value(aws_session_token, Credentials, undefined),
533+
lookup_credentials_from_proplist(AccessKey, SecretKey, SessionToken).
522534

523535
-spec lookup_credentials_from_proplist(
524536
AccessKey :: access_key(),
525-
SecretAccessKey :: secret_access_key()
537+
SecretAccessKey :: secret_access_key(),
538+
SessionToken :: security_token()
526539
) ->
527540
security_credentials().
528541
%% @doc Process the contents of the Credentials proplists checking if the
529542
%% access key and secret access key are both set.
530543
%% @end
531-
lookup_credentials_from_proplist(undefined, _) ->
544+
lookup_credentials_from_proplist(undefined, _, _) ->
532545
lookup_credentials_from_instance_metadata();
533-
lookup_credentials_from_proplist(_, undefined) ->
546+
lookup_credentials_from_proplist(_, undefined, _) ->
534547
lookup_credentials_from_instance_metadata();
535-
lookup_credentials_from_proplist(AccessKey, SecretKey) ->
536-
{ok, AccessKey, SecretKey, undefined, undefined}.
548+
lookup_credentials_from_proplist(AccessKey, SecretKey, SessionToken) ->
549+
{ok, AccessKey, SecretKey, undefined, SessionToken}.
537550

538551
-spec lookup_credentials_from_instance_metadata() ->
539552
security_credentials().
@@ -773,7 +786,7 @@ load_imdsv2_token() ->
773786
%% @doc Return headers used for instance metadata service requests.
774787
%% @end
775788
instance_metadata_request_headers() ->
776-
case application:get_env(rabbit, aws_prefer_imdsv2) of
789+
case application:get_env(rabbitmq_aws, aws_prefer_imdsv2) of
777790
{ok, false} ->
778791
[];
779792
%% undefined or {ok, true}
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
[
22
{rabbitmq_aws_prefer_imdsv2_false,
33
"aws.prefer_imdsv2 = false",
4-
[{rabbit, [
4+
[{rabbitmq_aws, [
55
{aws_prefer_imdsv2, false}
6-
]}],
6+
]}
7+
],
78
[rabbitmq_aws]},
89

910
{rabbitmq_aws_prefer_imdsv2_true,
1011
"aws.prefer_imdsv2 = true",
11-
[{rabbit, [
12+
[{rabbitmq_aws, [
1213
{aws_prefer_imdsv2, true}
13-
]}],
14+
]}
15+
],
1416
[rabbitmq_aws]}
1517
].

deps/rabbitmq_aws/test/rabbitmq_aws_config_tests.erl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,15 @@ credentials_test_() ->
135135
rabbitmq_aws_config:credentials()
136136
)
137137
end},
138+
{"from environment variables with session token", fun() ->
139+
os:putenv("AWS_ACCESS_KEY_ID", "Sésame"),
140+
os:putenv("AWS_SECRET_ACCESS_KEY", "ouvre-toi"),
141+
os:putenv("AWS_SESSION_TOKEN", "session42"),
142+
?assertEqual(
143+
{ok, "Sésame", "ouvre-toi", undefined, "session42"},
144+
rabbitmq_aws_config:credentials()
145+
)
146+
end},
138147
{"from config file with default profile", fun() ->
139148
setup_test_config_env_var(),
140149
?assertEqual(
@@ -187,6 +196,13 @@ credentials_test_() ->
187196
rabbitmq_aws_config:credentials("development")
188197
)
189198
end},
199+
{"from credentials file with session token", fun() ->
200+
setup_test_credentials_env_var(),
201+
?assertEqual(
202+
{ok, "foo3", "bar3", undefined, "session42"},
203+
rabbitmq_aws_config:credentials("with-session-token")
204+
)
205+
end},
190206
{"from credentials file with bad profile", fun() ->
191207
setup_test_credentials_env_var(),
192208
meck:expect(rabbitmq_aws, ensure_imdsv2_token_valid, 0, undefined),

deps/rabbitmq_aws/test/rabbitmq_aws_tests.erl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ init_test_() ->
1616
end,
1717
[
1818
{"ok", fun() ->
19+
os:unsetenv("AWS_SESSION_TOKEN"),
1920
os:putenv("AWS_ACCESS_KEY_ID", "Sésame"),
2021
os:putenv("AWS_SECRET_ACCESS_KEY", "ouvre-toi"),
2122
{ok, Pid} = rabbitmq_aws:start_link(),

deps/rabbitmq_aws/test/test_aws_credentials.ini

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ aws_secret_access_key=bar1
66
aws_access_key_id=foo2
77
aws_secret_access_key=bar2
88

9+
[with-session-token]
10+
aws_access_key_id=foo3
11+
aws_secret_access_key=bar3
12+
aws_session_token=session42
13+
914
[only-key]
1015
aws_access_key_id = foo3
1116

0 commit comments

Comments
 (0)