diff --git a/lib/fog/aws/parsers/sts/assume_role.rb b/lib/fog/aws/parsers/sts/assume_role.rb new file mode 100644 index 000000000..2c28fce2c --- /dev/null +++ b/lib/fog/aws/parsers/sts/assume_role.rb @@ -0,0 +1,30 @@ +module Fog + module Parsers + module AWS + module STS + + class AssumeRole < Fog::Parsers::Base + + def reset + @response = {} + end + + def end_element(name) + case name + when 'SessionToken', 'SecretAccessKey', 'Expiration', 'AccessKeyId' + @response[name] = @value.strip + when 'Arn', 'AssumedRoleId' + @response[name] = @value.strip + when 'PackedPolicySize' + @response[name] = @value + when 'RequestId' + @response[name] = @value + end + end + + end + + end + end + end +end diff --git a/lib/fog/aws/requests/sts/assume_role.rb b/lib/fog/aws/requests/sts/assume_role.rb new file mode 100644 index 000000000..afe393293 --- /dev/null +++ b/lib/fog/aws/requests/sts/assume_role.rb @@ -0,0 +1,46 @@ +module Fog + module AWS + class STS + class Real + + require 'fog/aws/parsers/sts/assume_role' + + # Assume Role + # + # ==== Parameters + # * role_session_name<~String> - An identifier for the assumed role. + # * role_arn<~String> - The ARN of the role the caller is assuming. + # * external_id<~String> - An optional unique identifier required by the assuming role's trust identity. + # * policy<~String> - An optional JSON policy document + # * duration<~Integer> - Duration (of seconds) for the assumed role credentials to be valid (default 3600) + # + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + # * 'Arn'<~String>: The ARN of the assumed role/user + # * 'AccessKeyId'<~String>: The AWS access key of the temporary credentials for the assumed role + # * 'SecretAccessKey'<~String>: The AWS secret key of the temporary credentials for the assumed role + # * 'SessionToken'<~String>: The AWS session token of the temporary credentials for the assumed role + # * 'Expiration'<~Time>: The expiration time of the temporary credentials for the assumed role + # + # ==== See Also + # http://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html + # + + def assume_role(role_session_name, role_arn, external_id=nil, policy=nil, duration=3600) + request({ + 'Action' => 'AssumeRole', + 'RoleSessionName' => role_session_name, + 'RoleArn' => role_arn, + 'Policy' => policy && Fog::JSON.encode(policy), + 'DurationSeconds' => duration, + 'ExternalId' => external_id, + :idempotent => true, + :parser => Fog::Parsers::AWS::STS::AssumeRole.new + }) + end + + end + end + end +end diff --git a/lib/fog/aws/sts.rb b/lib/fog/aws/sts.rb index 8a8af8816..171fc14ac 100644 --- a/lib/fog/aws/sts.rb +++ b/lib/fog/aws/sts.rb @@ -3,16 +3,18 @@ require 'fog/aws' module Fog module AWS class STS < Fog::Service + extend Fog::AWS::CredentialFetcher::ServiceMethods class EntityAlreadyExists < Fog::AWS::STS::Error; end class ValidationError < Fog::AWS::STS::Error; end requires :aws_access_key_id, :aws_secret_access_key - recognizes :host, :path, :port, :scheme, :persistent + recognizes :host, :path, :port, :scheme, :persistent, :aws_session_token, :use_iam_profile, :aws_credentials_expire_at request_path 'fog/aws/requests/sts' request :get_federation_token request :get_session_token + request :assume_role class Mock def self.data @@ -33,7 +35,8 @@ module Fog end def initialize(options={}) - @aws_access_key_id = options[:aws_access_key_id] + @use_iam_profile = options[:use_iam_profile] + setup_credentials(options) end def data @@ -43,10 +46,14 @@ module Fog def reset_data self.class.data.delete(@aws_access_key_id) end + + def setup_credentials(options) + @aws_access_key_id = options[:aws_access_key_id] + end end class Real - + include Fog::AWS::CredentialFetcher::ConnectionMethods # Initialize connection to STS # # ==== Notes @@ -67,10 +74,10 @@ module Fog def initialize(options={}) require 'fog/core/parser' - @aws_access_key_id = options[:aws_access_key_id] - @aws_secret_access_key = options[:aws_secret_access_key] + @use_iam_profile = options[:use_iam_profile] + setup_credentials(options) @connection_options = options[:connection_options] || {} - @hmac = Fog::HMAC.new('sha256', @aws_secret_access_key) + @host = options[:host] || 'sts.amazonaws.com' @path = options[:path] || '/' @persistent = options[:persistent] || false @@ -85,6 +92,14 @@ module Fog private + def setup_credentials(options) + @aws_access_key_id = options[:aws_access_key_id] + @aws_secret_access_key = options[:aws_secret_access_key] + @aws_session_token = options[:aws_session_token] + @aws_credentials_expire_at = options[:aws_credentials_expire_at] + @hmac = Fog::HMAC.new('sha256', @aws_secret_access_key) + end + def request(params) idempotent = params.delete(:idempotent) parser = params.delete(:parser) @@ -93,6 +108,7 @@ module Fog params, { :aws_access_key_id => @aws_access_key_id, + :aws_session_token => @aws_session_token, :hmac => @hmac, :host => @host, :path => @path, diff --git a/tests/aws/requests/sts/assume_role_tests.rb b/tests/aws/requests/sts/assume_role_tests.rb new file mode 100644 index 000000000..3b8fa3e51 --- /dev/null +++ b/tests/aws/requests/sts/assume_role_tests.rb @@ -0,0 +1,19 @@ +Shindo.tests('AWS::STS | assume role', ['aws']) do + + @policy = {"Statement" => [{"Effect" => "Allow", "Action" => "*", "Resource" => "*"}]} + + @response_format = { + 'SessionToken' => String, + 'SecretAccessKey' => String, + 'Expiration' => String, + 'AccessKeyId' => String, + 'Arn' => String, + 'RequestId' => String + } + + tests("#assume_role('rolename', 'assumed_role_session', 'external_id', #{@policy.inspect}, 900)").formats(@response_format) do + pending if Fog.mocking? + Fog::AWS[:sts].assume_role("rolename","assumed_role_session","external_id", @policy, 900).body + end + +end