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.
* Add rabbitmq_aws:api_post_request/4, README cleanup

(cherry picked from commit 251405c4e8)
This commit is contained in:
Sunny Katkuri 2025-09-18 15:47:53 +00:00 committed by Mergify
parent 056efd2e30
commit 717a8730b2
10 changed files with 150 additions and 86 deletions

View File

@ -1,15 +0,0 @@
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
[Makefile]
indent_style = tab
# 2 space indentation
[{*.erl, *.hrl, *.md}]
indent_style = space
indent_size = 2

View File

@ -7,9 +7,11 @@ define PROJECT_ENV
[] []
endef endef
BUILD_DEPS = rabbit
TEST_DEPS = meck rabbitmq_ct_helpers rabbitmq_ct_client_helpers
LOCAL_DEPS = crypto inets ssl xmerl public_key LOCAL_DEPS = crypto inets ssl xmerl public_key
BUILD_DEPS = rabbit_common
TEST_DEPS = meck rabbit rabbitmq_ct_helpers rabbitmq_ct_client_helpers PLT_APPS = rabbit
DEP_EARLY_PLUGINS = rabbit_common/mk/rabbitmq-early-plugin.mk DEP_EARLY_PLUGINS = rabbit_common/mk/rabbitmq-early-plugin.mk
DEP_PLUGINS = rabbit_common/mk/rabbitmq-plugin.mk DEP_PLUGINS = rabbit_common/mk/rabbitmq-plugin.mk

View File

@ -5,13 +5,13 @@ A fork of [gmr/httpc-aws](https://github.com/gmr/httpc-aws) for use in building
## Supported Erlang Versions ## Supported Erlang Versions
[Same as RabbitMQ](http://www.rabbitmq.com/which-erlang.html) [Same as RabbitMQ](http://www.rabbitmq.com/which-erlang.html)
## Configuration ## Configuration
Configuration for *rabbitmq-aws* is can be provided in multiple ways. It is designed Configuration for *rabbitmq-aws* is can be provided in multiple ways. It is designed
to behave similarly to the [AWS Command Line Interface](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html) to behave similarly to the [AWS Command Line Interface](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html)
with respect to providing region and configuration information. Additionally it with respect to providing region and configuration information. Additionally it
has two methods, ``rabbitmq_aws:set_region/1`` and ``rabbitmq_aws:set_credentials/2`` has two methods, `rabbitmq_aws:set_region/1` and `rabbitmq_aws:set_credentials/2`
to allow for application specific configuration, bypassing the automatic configuration to allow for application specific configuration, bypassing the automatic configuration
behavior. behavior.
@ -40,36 +40,36 @@ and [adds defenses against additional vulnerabilities](https://aws.amazon.com/bl
AWS recommends adopting IMDSv2 and disabling IMDSv1 [by configuring the Instance Metadata Service on the EC2 instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html). AWS recommends adopting IMDSv2 and disabling IMDSv1 [by configuring the Instance Metadata Service on the EC2 instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html).
By default *rabbitmq-aws* will attempt to use IMDSv2 first and will fallback to use IMDSv1 if calls to IMDSv2 fail. This behavior can be overridden By default *rabbitmq-aws* will attempt to use IMDSv2 first and will fallback to use IMDSv1 if calls to IMDSv2 fail. This behavior can be overridden
by setting the ``aws.prefer_imdsv2`` setting to ``false``. by setting the `aws.prefer_imdsv2` setting to `false`.
### Environment Variables ### Environment Variables
As with the AWS CLI, the following environment variables can be used to provide As with the AWS CLI, the following environment variables can be used to provide
configuration or to impact configuration behavior: configuration or to impact configuration behavior:
- ``AWS_DEFAULT_PROFILE`` - `AWS_DEFAULT_PROFILE`
- ``AWS_DEFAULT_REGION`` - `AWS_DEFAULT_REGION`
- ``AWS_CONFIG_FILE`` - `AWS_CONFIG_FILE`
- ``AWS_SHARED_CREDENTIALS_FILE`` - `AWS_SHARED_CREDENTIALS_FILE`
- ``AWS_ACCESS_KEY_ID`` - `AWS_ACCESS_KEY_ID`
- ``AWS_SECRET_ACCESS_KEY`` - `AWS_SECRET_ACCESS_KEY`
## API Functions ## API Functions
Method | Description Method | Description
---------------------------------------|-------------------------------------------------------------------------------------------- -------------------------------------------|--------------------------------------------------------------------------------------------
``rabbitmq_aws:set_region/1`` | Manually specify the AWS region to make requests to. `rabbitmq_aws:set_region/1` | Manually specify the AWS region to make requests to.
``rabbitmq_aws:set_credentials/2`` | Manually specify the request credentials to use. `rabbitmq_aws:set_credentials/2` | Manually specify the request credentials to use.
``rabbitmq_aws:refresh_credentials/0`` | Refresh the credentials from the environment, filesystem, or EC2 Instance Metadata Service. `rabbitmq_aws:refresh_credentials/0` | Refresh the credentials from the environment, filesystem, or EC2 Instance Metadata Service.
``rabbitmq_aws:ensure_imdsv2_token_valid/0`` | Make sure EC2 IMDSv2 token is active and valid. `rabbitmq_aws:ensure_imdsv2_token_valid/0` | Make sure EC2 IMDSv2 token is active and valid.
``rabbitmq_aws:api_get_request/2`` | Perform an AWS service API request. `rabbitmq_aws:get/2` | Perform a GET request to the API specifying the service and request path.
``rabbitmq_aws:get/2`` | Perform a GET request to the API specifying the service and request path. `rabbitmq_aws:get/3` | Perform a GET request specifying the service, path, and headers.
``rabbitmq_aws:get/3`` | Perform a GET request specifying the service, path, and headers. `rabbitmq_aws:post/4` | Perform a POST request specifying the service, path, headers, and body.
``rabbitmq_aws:post/4`` | Perform a POST request specifying the service, path, headers, and body. `rabbitmq_aws:request/5` | Perform a request specifying the service, method, path, headers, and body.
``rabbitmq_aws:request/5`` | Perform a request specifying the service, method, path, headers, and body. `rabbitmq_aws:request/6` | Perform a request specifying the service, method, path, headers, body, and `httpc:http_options().`
``rabbitmq_aws:request/6`` | Perform a request specifying the service, method, path, headers, body, and ``httpc:http_options().`` `rabbitmq_aws:request/7` | Perform a request specifying the service, method, path, headers, body, `httpc:http_options()`, and override the API endpoint.
``rabbitmq_aws:request/7`` | Perform a request specifying the service, method, path, headers, body, ``httpc:http_options()``, and override the API endpoint. `rabbitmq_aws:api_get_request/2` | Perform an AWS service API request with retries.
`rabbitmq_aws:api_post_request/2` | Perform an AWS service API request with retries.
## Example Usage ## Example Usage
@ -80,8 +80,7 @@ you're using the EC2 Instance Metadata Service for credentials:
application:start(rabbitmq_aws). application:start(rabbitmq_aws).
{ok, {Headers, Response}} = rabbitmq_aws:get("ec2","/?Action=DescribeTags&Version=2015-10-01"). {ok, {Headers, Response}} = rabbitmq_aws:get("ec2","/?Action=DescribeTags&Version=2015-10-01").
``` ```
To configure credentials, invoke `rabbitmq_aws:set_credentials/2`:
To configure credentials, invoke ``rabbitmq_aws:set_credentials/2``:
```erlang ```erlang
application:start(rabbitmq_aws). application:start(rabbitmq_aws).
@ -90,8 +89,8 @@ rabbitmq_aws:set_credentials("AKIDEXAMPLE", "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMP
RequestHeaders = [{"Content-Type", "application/x-amz-json-1.0"}, RequestHeaders = [{"Content-Type", "application/x-amz-json-1.0"},
{"X-Amz-Target", "DynamoDB_20120810.ListTables"}], {"X-Amz-Target", "DynamoDB_20120810.ListTables"}],
{ok, {Headers, Response}} = rabbitmq_aws:post("dynamodb", "/", {ok, {Headers, Response}} = rabbitmq_aws:post("dynamodb", "/",
"{\"Limit\": 20}", "{\"Limit\": 20}",
RequestHeaders). RequestHeaders).
``` ```

View File

@ -15,5 +15,5 @@
%% When false, EC2 IMDSv1 will be used first and no attempt will be made to use EC2 IMDSv2. %% When false, EC2 IMDSv1 will be used first and no attempt will be made to use EC2 IMDSv2.
%% See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html. %% See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html.
{mapping, "aws.prefer_imdsv2", "rabbit.aws_prefer_imdsv2", {mapping, "aws.prefer_imdsv2", "rabbitmq_aws.aws_prefer_imdsv2",
[{datatype, {enum, [true, false]}}]}. [{datatype, {enum, [true, false]}}]}.

View File

@ -15,10 +15,12 @@
refresh_credentials/0, refresh_credentials/0,
request/5, request/6, request/7, request/5, request/6, request/7,
set_credentials/2, set_credentials/2,
set_credentials/3,
has_credentials/0, has_credentials/0,
set_region/1, set_region/1,
ensure_imdsv2_token_valid/0, ensure_imdsv2_token_valid/0,
api_get_request/2 api_get_request/2,
api_post_request/4
]). ]).
%% gen-server exports %% gen-server exports
@ -158,6 +160,12 @@ set_credentials(NewState) ->
set_credentials(AccessKey, SecretAccessKey) -> set_credentials(AccessKey, SecretAccessKey) ->
gen_server:call(rabbitmq_aws, {set_credentials, AccessKey, SecretAccessKey}). gen_server:call(rabbitmq_aws, {set_credentials, AccessKey, SecretAccessKey}).
-spec set_credentials(access_key(), secret_access_key(), security_token()) -> ok.
%% @doc Manually set the access credentials with session token for requests.
%% @end
set_credentials(AccessKey, SecretAccessKey, SessionToken) ->
gen_server:call(rabbitmq_aws, {set_credentials, AccessKey, SecretAccessKey, SessionToken}).
-spec set_region(Region :: string()) -> ok. -spec set_region(Region :: string()) -> ok.
%% @doc Manually set the AWS region to perform API requests to. %% @doc Manually set the AWS region to perform API requests to.
%% @end %% @end
@ -224,6 +232,14 @@ handle_msg({set_credentials, AccessKey, SecretAccessKey}, State) ->
expiration = undefined, expiration = undefined,
error = undefined error = undefined
}}; }};
handle_msg({set_credentials, AccessKey, SecretAccessKey, SessionToken}, State) ->
{reply, ok, State#state{
access_key = AccessKey,
secret_access_key = SecretAccessKey,
security_token = SessionToken,
expiration = undefined,
error = undefined
}};
handle_msg({set_credentials, NewState}, State) -> handle_msg({set_credentials, NewState}, State) ->
{reply, ok, State#state{ {reply, ok, State#state{
access_key = NewState#state.access_key, access_key = NewState#state.access_key,
@ -607,8 +623,10 @@ ensure_credentials_valid() ->
case has_credentials(State) of case has_credentials(State) of
true -> true ->
case expired_credentials(State#state.expiration) of case expired_credentials(State#state.expiration) of
true -> refresh_credentials(State); true ->
_ -> ok refresh_credentials(State);
_ ->
ok
end; end;
_ -> _ ->
refresh_credentials(State) refresh_credentials(State)
@ -618,19 +636,42 @@ ensure_credentials_valid() ->
%% @doc Invoke an API call to an AWS service. %% @doc Invoke an API call to an AWS service.
%% @end %% @end
api_get_request(Service, Path) -> api_get_request(Service, Path) ->
?LOG_DEBUG("Invoking AWS request {Service: ~tp; Path: ~tp}...", [Service, Path]), ?LOG_DEBUG("invoking AWS get request {Service: ~tp; Path: ~tp}...", [Service, Path]),
api_get_request_with_retries(Service, Path, ?MAX_RETRIES, ?LINEAR_BACK_OFF_MILLIS). api_request_with_retries(Service, get, Path, "", [],
?MAX_RETRIES, ?LINEAR_BACK_OFF_MILLIS).
-spec api_get_request_with_retries(string(), path(), integer(), integer()) -> -spec api_post_request(
Service :: string(),
Path :: path(),
Body :: body(),
Headers :: headers()
) -> result().
%% @doc Perform a HTTP Post request to the AWS API for the specified service. The
%% response will automatically be decoded if it is either in JSON or XML
%% format.
%% @end
api_post_request(Service, Path, Body, Headers) ->
?LOG_DEBUG("invoking AWS post request {Service: ~tp; Path: ~tp}...", [Service, Path]),
api_request_with_retries(Service, post, Path, Body, Headers,
?MAX_RETRIES, ?LINEAR_BACK_OFF_MILLIS).
-spec api_request_with_retries(
Service :: string(),
Method :: method(),
Path :: path(),
Body :: body(),
Headers :: headers(),
Retries :: integer(),
WaitTime :: integer()) ->
{'ok', list()} | {'error', term()}. {'ok', list()} | {'error', term()}.
%% @doc Invoke an API call to an AWS service with retries. %% @doc Invoke an API call to an AWS service with retries.
%% @end %% @end
api_get_request_with_retries(_, _, 0, _) -> api_request_with_retries(_, _, _, _, _, 0, _) ->
?LOG_WARNING("Request to AWS service has failed after ~b retries", [?MAX_RETRIES]), ?LOG_ERROR("Request to AWS service has failed after ~b retries", [?MAX_RETRIES]),
{error, "AWS service is unavailable"}; {error, "AWS service is unavailable"};
api_get_request_with_retries(Service, Path, Retries, WaitTimeBetweenRetries) -> api_request_with_retries(Service, Method, Path, Body, Headers, Retries, WaitTime) ->
ensure_credentials_valid(), ok = ensure_credentials_valid(),
case get(Service, Path) of case request(Service, Method, Path, Body, Headers) of
{ok, {_Headers, Payload}} -> {ok, {_Headers, Payload}} ->
?LOG_DEBUG("AWS request: ~ts~nResponse: ~tp", [Path, Payload]), ?LOG_DEBUG("AWS request: ~ts~nResponse: ~tp", [Path, Payload]),
{ok, Payload}; {ok, Payload};
@ -645,6 +686,6 @@ api_get_request_with_retries(Service, Path, Retries, WaitTimeBetweenRetries) ->
ok ok
end, end,
?LOG_WARNING("Will retry AWS request, remaining retries: ~b", [Retries]), ?LOG_WARNING("Will retry AWS request, remaining retries: ~b", [Retries]),
timer:sleep(WaitTimeBetweenRetries), timer:sleep(WaitTime),
api_get_request_with_retries(Service, Path, Retries - 1, WaitTimeBetweenRetries) api_request_with_retries(Service, Method, Path, Body, Headers, Retries - 1, WaitTime)
end. end.

View File

@ -134,7 +134,8 @@ credentials(Profile) ->
lookup_credentials( lookup_credentials(
Profile, Profile,
os:getenv("AWS_ACCESS_KEY_ID"), os:getenv("AWS_ACCESS_KEY_ID"),
os:getenv("AWS_SECRET_ACCESS_KEY") os:getenv("AWS_SECRET_ACCESS_KEY"),
os:getenv("AWS_SESSION_TOKEN")
). ).
-spec region() -> {ok, string()}. -spec region() -> {ok, string()}.
@ -452,32 +453,39 @@ instance_id_url() ->
-spec lookup_credentials( -spec lookup_credentials(
Profile :: string(), Profile :: string(),
AccessKey :: string() | false, AccessKey :: string() | false,
SecretKey :: string() | false SecretKey :: string() | false,
SessionToken :: string() | false
) -> ) ->
security_credentials(). security_credentials().
%% @doc Return the access key and secret access key if they are set in %% @doc Return the access key and secret access key if they are set in
%% environment variables, otherwise lookup the credentials from the config %% environment variables, otherwise lookup the credentials from the config
%% file for the specified profile. %% file for the specified profile.
%% @end %% @end
lookup_credentials(Profile, false, _) -> lookup_credentials(Profile, false, _, _) ->
lookup_credentials_from_config( lookup_credentials_from_config(
Profile, Profile,
value(Profile, aws_access_key_id), value(Profile, aws_access_key_id),
value(Profile, aws_secret_access_key) value(Profile, aws_secret_access_key),
value(Profile, aws_session_token)
); );
lookup_credentials(Profile, _, false) -> lookup_credentials(Profile, _, false, _) ->
lookup_credentials_from_config( lookup_credentials_from_config(
Profile, Profile,
value(Profile, aws_access_key_id), value(Profile, aws_access_key_id),
value(Profile, aws_secret_access_key) value(Profile, aws_secret_access_key),
value(Profile, aws_session_token)
); );
lookup_credentials(_, AccessKey, SecretKey) -> lookup_credentials(_, AccessKey, SecretKey, SessionToken) ->
{ok, AccessKey, SecretKey, undefined, undefined}. case SessionToken of
false -> {ok, AccessKey, SecretKey, undefined, undefined};
SessionToken -> {ok, AccessKey, SecretKey, undefined, SessionToken}
end.
-spec lookup_credentials_from_config( -spec lookup_credentials_from_config(
Profile :: string(), Profile :: string(),
access_key() | {error, Reason :: atom()}, access_key() | {error, Reason :: atom()},
secret_access_key() | {error, Reason :: atom()} secret_access_key() | {error, Reason :: atom()},
security_token() | {error, Reason :: atom()}
) -> ) ->
security_credentials(). security_credentials().
%% @doc Return the access key and secret access key if they are set in %% @doc Return the access key and secret access key if they are set in
@ -485,10 +493,13 @@ lookup_credentials(_, AccessKey, SecretKey) ->
%% not exist or the profile is not set or the values are not set in the %% not exist or the profile is not set or the values are not set in the
%% profile, look up the values in the shared credentials file %% profile, look up the values in the shared credentials file
%% @end %% @end
lookup_credentials_from_config(Profile, {error, _}, _) -> lookup_credentials_from_config(Profile, {error, _}, _, _) ->
lookup_credentials_from_file(Profile, credentials_file_data()); lookup_credentials_from_file(Profile, credentials_file_data());
lookup_credentials_from_config(_, AccessKey, SecretKey) -> lookup_credentials_from_config(_, AccessKey, SecretKey, SessionToken) ->
{ok, AccessKey, SecretKey, undefined, undefined}. case SessionToken of
{error, _} -> {ok, AccessKey, SecretKey, undefined, undefined};
SessionToken -> {ok, AccessKey, SecretKey, undefined, SessionToken}
end.
-spec lookup_credentials_from_file( -spec lookup_credentials_from_file(
Profile :: string(), Profile :: string(),
@ -518,22 +529,24 @@ lookup_credentials_from_section(undefined) ->
lookup_credentials_from_section(Credentials) -> lookup_credentials_from_section(Credentials) ->
AccessKey = proplists:get_value(aws_access_key_id, Credentials, undefined), AccessKey = proplists:get_value(aws_access_key_id, Credentials, undefined),
SecretKey = proplists:get_value(aws_secret_access_key, Credentials, undefined), SecretKey = proplists:get_value(aws_secret_access_key, Credentials, undefined),
lookup_credentials_from_proplist(AccessKey, SecretKey). SessionToken = proplists:get_value(aws_session_token, Credentials, undefined),
lookup_credentials_from_proplist(AccessKey, SecretKey, SessionToken).
-spec lookup_credentials_from_proplist( -spec lookup_credentials_from_proplist(
AccessKey :: access_key(), AccessKey :: access_key(),
SecretAccessKey :: secret_access_key() SecretAccessKey :: secret_access_key(),
SessionToken :: security_token()
) -> ) ->
security_credentials(). security_credentials().
%% @doc Process the contents of the Credentials proplists checking if the %% @doc Process the contents of the Credentials proplists checking if the
%% access key and secret access key are both set. %% access key and secret access key are both set.
%% @end %% @end
lookup_credentials_from_proplist(undefined, _) -> lookup_credentials_from_proplist(undefined, _, _) ->
lookup_credentials_from_instance_metadata(); lookup_credentials_from_instance_metadata();
lookup_credentials_from_proplist(_, undefined) -> lookup_credentials_from_proplist(_, undefined, _) ->
lookup_credentials_from_instance_metadata(); lookup_credentials_from_instance_metadata();
lookup_credentials_from_proplist(AccessKey, SecretKey) -> lookup_credentials_from_proplist(AccessKey, SecretKey, SessionToken) ->
{ok, AccessKey, SecretKey, undefined, undefined}. {ok, AccessKey, SecretKey, undefined, SessionToken}.
-spec lookup_credentials_from_instance_metadata() -> -spec lookup_credentials_from_instance_metadata() ->
security_credentials(). security_credentials().
@ -773,7 +786,7 @@ load_imdsv2_token() ->
%% @doc Return headers used for instance metadata service requests. %% @doc Return headers used for instance metadata service requests.
%% @end %% @end
instance_metadata_request_headers() -> instance_metadata_request_headers() ->
case application:get_env(rabbit, aws_prefer_imdsv2) of case application:get_env(rabbitmq_aws, aws_prefer_imdsv2) of
{ok, false} -> {ok, false} ->
[]; [];
%% undefined or {ok, true} %% undefined or {ok, true}

View File

@ -1,15 +1,17 @@
[ [
{rabbitmq_aws_prefer_imdsv2_false, {rabbitmq_aws_prefer_imdsv2_false,
"aws.prefer_imdsv2 = false", "aws.prefer_imdsv2 = false",
[{rabbit, [ [{rabbitmq_aws, [
{aws_prefer_imdsv2, false} {aws_prefer_imdsv2, false}
]}], ]}
],
[rabbitmq_aws]}, [rabbitmq_aws]},
{rabbitmq_aws_prefer_imdsv2_true, {rabbitmq_aws_prefer_imdsv2_true,
"aws.prefer_imdsv2 = true", "aws.prefer_imdsv2 = true",
[{rabbit, [ [{rabbitmq_aws, [
{aws_prefer_imdsv2, true} {aws_prefer_imdsv2, true}
]}], ]}
],
[rabbitmq_aws]} [rabbitmq_aws]}
]. ].

View File

@ -135,6 +135,15 @@ credentials_test_() ->
rabbitmq_aws_config:credentials() rabbitmq_aws_config:credentials()
) )
end}, end},
{"from environment variables with session token", fun() ->
os:putenv("AWS_ACCESS_KEY_ID", "Sésame"),
os:putenv("AWS_SECRET_ACCESS_KEY", "ouvre-toi"),
os:putenv("AWS_SESSION_TOKEN", "session42"),
?assertEqual(
{ok, "Sésame", "ouvre-toi", undefined, "session42"},
rabbitmq_aws_config:credentials()
)
end},
{"from config file with default profile", fun() -> {"from config file with default profile", fun() ->
setup_test_config_env_var(), setup_test_config_env_var(),
?assertEqual( ?assertEqual(
@ -187,6 +196,13 @@ credentials_test_() ->
rabbitmq_aws_config:credentials("development") rabbitmq_aws_config:credentials("development")
) )
end}, end},
{"from credentials file with session token", fun() ->
setup_test_credentials_env_var(),
?assertEqual(
{ok, "foo3", "bar3", undefined, "session42"},
rabbitmq_aws_config:credentials("with-session-token")
)
end},
{"from credentials file with bad profile", fun() -> {"from credentials file with bad profile", fun() ->
setup_test_credentials_env_var(), setup_test_credentials_env_var(),
meck:expect(rabbitmq_aws, ensure_imdsv2_token_valid, 0, undefined), meck:expect(rabbitmq_aws, ensure_imdsv2_token_valid, 0, undefined),

View File

@ -16,6 +16,7 @@ init_test_() ->
end, end,
[ [
{"ok", fun() -> {"ok", fun() ->
os:unsetenv("AWS_SESSION_TOKEN"),
os:putenv("AWS_ACCESS_KEY_ID", "Sésame"), os:putenv("AWS_ACCESS_KEY_ID", "Sésame"),
os:putenv("AWS_SECRET_ACCESS_KEY", "ouvre-toi"), os:putenv("AWS_SECRET_ACCESS_KEY", "ouvre-toi"),
{ok, Pid} = rabbitmq_aws:start_link(), {ok, Pid} = rabbitmq_aws:start_link(),
@ -604,7 +605,7 @@ api_get_request_test_() ->
{ok, Pid} = rabbitmq_aws:start_link(), {ok, Pid} = rabbitmq_aws:start_link(),
rabbitmq_aws:set_region("us-east-1"), rabbitmq_aws:set_region("us-east-1"),
rabbitmq_aws:set_credentials(State), rabbitmq_aws:set_credentials(State),
Result = rabbitmq_aws:api_get_request_with_retries("AWS", "API", 3, 1), Result = rabbitmq_aws:api_request_with_retries("AWS", get, "API", "", [], 3, 1),
ok = gen_server:stop(Pid), ok = gen_server:stop(Pid),
?assertEqual({error, "AWS service is unavailable"}, Result), ?assertEqual({error, "AWS service is unavailable"}, Result),
meck:validate(httpc) meck:validate(httpc)
@ -637,7 +638,7 @@ api_get_request_test_() ->
{ok, Pid} = rabbitmq_aws:start_link(), {ok, Pid} = rabbitmq_aws:start_link(),
rabbitmq_aws:set_region("us-east-1"), rabbitmq_aws:set_region("us-east-1"),
rabbitmq_aws:set_credentials(State), rabbitmq_aws:set_credentials(State),
Result = rabbitmq_aws:api_get_request_with_retries("AWS", "API", 3, 1), Result = rabbitmq_aws:api_request_with_retries("AWS", get, "API", "", [], 3, 1),
ok = gen_server:stop(Pid), ok = gen_server:stop(Pid),
?assertEqual({ok, [{"data", "value"}]}, Result), ?assertEqual({ok, [{"data", "value"}]}, Result),
meck:validate(httpc) meck:validate(httpc)

View File

@ -6,6 +6,11 @@ aws_secret_access_key=bar1
aws_access_key_id=foo2 aws_access_key_id=foo2
aws_secret_access_key=bar2 aws_secret_access_key=bar2
[with-session-token]
aws_access_key_id=foo3
aws_secret_access_key=bar3
aws_session_token=session42
[only-key] [only-key]
aws_access_key_id = foo3 aws_access_key_id = foo3