Packages
erlcloud
2.0.0
3.8.3
3.8.2
3.8.1
3.7.6
3.7.4
3.7.3
3.7.2
3.7.1
3.7.0
3.6.8
3.6.7
3.6.5
3.6.4
3.6.3
3.6.2
3.6.1
3.6.0
3.5.16
3.5.15
3.5.14
3.5.13
3.5.12
3.5.11
3.5.10
3.5.9
3.5.8
3.5.7
3.5.6
3.5.5
3.5.4
3.5.3
3.5.2
3.5.1
3.5.0
3.4.5
3.4.3
3.4.1
3.4.0
3.3.9
3.3.8
3.3.7
3.3.6
3.3.5
3.3.4
3.3.3
3.3.2
3.3.1
3.3.0
3.2.18
3.2.17
3.2.16
3.2.15
3.2.14
3.2.13
3.2.12
3.2.11
3.2.10
3.2.7
3.2.6
3.2.5
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
3.1.17
3.1.16
3.1.14
3.1.13
3.1.12
3.1.11
3.1.9
3.1.8
3.1.7
3.1.6
3.1.5
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
2.2.16
2.2.15
2.2.14
2.2.13
2.2.12
2.2.11
2.2.10
2.2.9
2.2.8
2.2.7
2.2.6
2.2.5
2.2.4
2.2.2
2.2.1
2.2.0
2.1.0
2.0.5
2.0.4
2.0.3
2.0.0
0.13.10
0.13.9
0.13.8
0.13.6
0.13.5
0.13.4
0.13.3
0.13.2
0.13.0
0.12.0
0.11.0
0.9.2
0.9.2-rc.1
0.9.1
0.9.0
AWS APIs library for Erlang
Current section
Files
Jump to
Current section
Files
src/erlcloud_sts.erl
%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
-module(erlcloud_sts).
-include("erlcloud.hrl").
-include("erlcloud_aws.hrl").
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
-endif.
-export([assume_role/4, assume_role/5,
get_federation_token/3,
get_federation_token/4]).
-define(API_VERSION, "2011-06-15").
-define(UTC_TO_GREGORIAN, 62167219200).
assume_role(AwsConfig, RoleArn, RoleSessionName, DurationSeconds) ->
assume_role(AwsConfig, RoleArn, RoleSessionName, DurationSeconds, undefined).
% See http://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html
-spec assume_role(#aws_config{}, string(), string(), 900..3600, undefined | string()) -> {#aws_config{}, proplist()}.
assume_role(AwsConfig, RoleArn, RoleSessionName, DurationSeconds, ExternalId)
when length(RoleArn) >= 20,
length(RoleSessionName) >= 2, length(RoleSessionName) =< 32,
DurationSeconds >= 900, DurationSeconds =< 3600 ->
Params =
[
{"RoleArn", RoleArn},
{"RoleSessionName", RoleSessionName},
{"DurationSeconds", DurationSeconds}
],
ExternalIdPart =
case ExternalId of
undefined -> [];
_ when length(ExternalId) >= 2, length(ExternalId) =< 96 -> [{"ExternalId", ExternalId}]
end,
Xml = sts_query(AwsConfig, "AssumeRole", Params ++ ExternalIdPart),
Creds = erlcloud_xml:decode(
[
{access_key_id , "AssumeRoleResult/Credentials/AccessKeyId" , text},
{secret_access_key, "AssumeRoleResult/Credentials/SecretAccessKey", text},
{session_token , "AssumeRoleResult/Credentials/SessionToken" , text},
{expiration , "AssumeRoleResult/Credentials/Expiration" , time}
],
Xml),
ExpireTS = expiration_tosecs( proplists:get_value(expiration, Creds) ),
AssumedConfig =
AwsConfig#aws_config {
access_key_id = proplists:get_value(access_key_id, Creds),
secret_access_key = proplists:get_value(secret_access_key, Creds),
security_token = proplists:get_value(session_token, Creds),
expiration = ExpireTS
},
{AssumedConfig, Creds}.
get_federation_token(AwsConfig, DurationSeconds, Name) ->
get_federation_token(AwsConfig, DurationSeconds, Name, undefined).
% See http://docs.aws.amazon.com/STS/latest/APIReference/API_GetFederationToken.html
-spec get_federation_token(#aws_config{}, 900..129600, string(), undefined | string()) -> {#aws_config{}, proplist()}.
get_federation_token(AwsConfig, DurationSeconds, Name, Policy)
when length(Name) >= 2, length(Name) =< 32,
DurationSeconds >= 900, DurationSeconds =< 129600 ->
Params =
[
{"DurationSeconds", DurationSeconds},
{"Name", Name}
],
PolicyList =
case Policy of
undefined -> [];
_ -> [{"Policy", Policy}]
end,
Xml = sts_query(AwsConfig, "GetFederationToken", Params ++ PolicyList),
Creds = erlcloud_xml:decode(
[
{access_key_id , "GetFederationTokenResult/Credentials/AccessKeyId", text},
{secret_access_key , "GetFederationTokenResult/Credentials/SecretAccessKey", text},
{session_token , "GetFederationTokenResult/Credentials/SessionToken" , text},
{expiration , "GetFederationTokenResult/Credentials/Expiration", time},
{federated_user_arn , "GetFederationTokenResult/FederatedUser/Arn", text},
{federated_user_id , "GetFederationTokenResult/FederatedUser/FederatedUserId", text}
],
Xml),
ExpireTS = expiration_tosecs( proplists:get_value(expiration, Creds) ),
FederatedConfig =
AwsConfig#aws_config {
access_key_id = proplists:get_value(access_key_id, Creds),
secret_access_key = proplists:get_value(secret_access_key, Creds),
security_token = proplists:get_value(session_token, Creds),
expiration = ExpireTS
},
{FederatedConfig, Creds}.
sts_query(AwsConfig, Action, Params) ->
sts_query(AwsConfig, Action, Params, ?API_VERSION).
sts_query(AwsConfig, Action, Params, ApiVersion) ->
case erlcloud_aws:aws_request_xml4(post,
AwsConfig#aws_config.sts_host,
"/",
[{"Action", Action}, {"Version", ApiVersion} | Params],
"sts", AwsConfig)
of
{ok, Body} ->
Body;
{error, Reason} ->
erlang:error({aws_error, Reason})
end.
expiration_tosecs( Datetime ) when is_tuple(Datetime) ->
GregorianSeconds = calendar:datetime_to_gregorian_seconds( Datetime ),
(GregorianSeconds - ?UTC_TO_GREGORIAN);
expiration_tosecs( Timestamp ) ->
{ok, [Year,Month,Day,Hour,Min,Sec,_Ms],[]} =
io_lib:fread( "~4d-~2d-~2dT~2d:~2d:~2d.~3dZ", Timestamp ),
expiration_tosecs( {{Year,Month,Day},{Hour,Min,Sec}} ).
-ifdef(TEST).
expiration_tosecs_test() ->
Timestamp = "2011-07-15T23:28:33.359Z",
?assertEqual( 1310772513, expiration_tosecs( Timestamp ) ).
-endif.