1
0
Fork 0
mirror of https://github.com/fog/fog-aws.git synced 2022-11-09 13:50:52 -05:00

Merge pull request #45 from ehowe/assumerole

get signin token for federation
This commit is contained in:
Wesley Beary 2015-02-02 15:31:51 -06:00
commit a37bb7e439
18 changed files with 325 additions and 46 deletions

1
.gitignore vendored
View file

@ -12,3 +12,4 @@
*.o
*.a
mkmf.log
tests/.fog

View file

@ -19,6 +19,7 @@ require 'fog/aws/dynamodb'
require 'fog/aws/elasticache'
require 'fog/aws/elb'
require 'fog/aws/emr'
require 'fog/aws/federation'
require 'fog/aws/glacier'
require 'fog/aws/iam'
require 'fog/aws/rds'

View file

@ -21,6 +21,7 @@ module Fog
service(:elasticache, 'Elasticache')
service(:elb, 'ELB')
service(:emr, 'EMR')
service(:federation, 'Federation')
service(:glacier, 'Glacier')
service(:iam, 'IAM')
service(:rds, 'RDS')
@ -109,7 +110,7 @@ module Fog
end
end
body.chop!
headers['Authorization'] = options[:signer].sign({:method => options[:method], :headers => headers, :body => body, :query => {}, :path => options[:path]}, date)
return body, headers

58
lib/fog/aws/federation.rb Normal file
View file

@ -0,0 +1,58 @@
require 'fog/aws/core'
module Fog
module AWS
class Federation < Fog::Service
extend Fog::AWS::CredentialFetcher::ServiceMethods
recognizes :instrumentor, :instrumentor_name
request_path 'fog/aws/requests/federation'
request 'get_signin_token'
class Mock
def self.data
@data ||= {}
end
def self.reset
@data = nil
end
def initialize(options={})
end
def data
self.class.data
end
def reset_data
self.class.reset
end
end
class Real
include Fog::AWS::CredentialFetcher::ConnectionMethods
def initialize(options={})
@instrumentor = options[:instrumentor]
@instrumentor_name = options[:instrumentor_name] || 'fog.aws.federation'
@connection_options = options[:connection_options] || {}
@host = 'signin.aws.amazon.com'
@path = '/federation'
@scheme = 'https'
@connection = Excon.new("#{@scheme}://#{@host}#{@path}")
end
def request(action, session)
response = @connection.get(
:query => "Action=#{action}&SessionType=json&Session=#{session}",
:expects => 200
).body
Fog::JSON.decode(response)
end
end
end
end
end

View file

@ -25,7 +25,7 @@ module Fog
request :create_role
request :create_user
request :delete_access_key
request :delete_account_password_policy
request :delete_account_password_policy
request :delete_account_alias
request :delete_group
request :delete_group_policy
@ -120,6 +120,27 @@ module Fog
:created_at => Time.now,
:policies => {}
}
end,
:roles => Hash.new do |rhash, rkey|
rhash[rkey] = {
:role_id => Fog::AWS::Mock.key_id,
:arn => "arn:aws:iam:#{Fog::AWS::Mock.owner_id}:role/#{rkey}",
:create_date => Time.now,
:assume_role_policy_document => {
"Version" => "2012-10-17",
"Statement" => [
{
"Effect" => "Allow",
"Principal" => {
"Service" => [
"ec2.amazonaws.com"
]
},
"Action" => ["sts:AssumeRole"]
}
]
},
}
end
}
end

View file

@ -0,0 +1,20 @@
module Fog
module Parsers
module AWS
module STS
class AssumeRoleWithWithWebIdentity < Fog::Parsers::Base
def reset
@response = {}
end
def end_element(name)
case name
when 'AssumedRoleUser', 'Audience', 'Credentials', 'PackedPolicySize', 'Provider', 'SubjectFromWebIdentityToken'
@response[name] = @value.strip
end
end
end
end
end
end
end

View file

@ -0,0 +1,20 @@
module Fog
module AWS
class Federation
class Real
def get_signin_token(session)
request('getSigninToken', CGI.escape(Fog::JSON.encode(session)))
end
end
class Mock
def get_signin_token(session)
{
'SigninToken' => Fog::Mock.random_base64(752)
}
end
end
end
end
end

View file

@ -50,6 +50,30 @@ module Fog
)
end
end
class Mock
def create_role(role_name, assume_role_policy_document, path = '/')
if data[:roles].key?(role_name)
raise Fog::AWS::IAM::EntityAlreadyExists.new("Role with name #{role_name} already exists")
else
data[:roles][role_name][:path] = path
Excon::Response.new.tap do |response|
response.body = {
'Role' => {
'Arn' => data[:roles][role_name][:arn].strip,
'AssumeRolePolicyDocument' => Fog::JSON.encode(data[:roles][role_name][:assume_role_policy_document]),
'CreateDate' => data[:roles][role_name][:create_date],
'Path' => path,
'RoleId' => data[:roles][role_name][:role_id].strip,
'RoleName' => role_name,
},
'RequestId' => Fog::AWS::Mock.request_id
}
response.status = 200
end
end
end
end
end
end
end

View file

@ -25,6 +25,22 @@ module Fog
)
end
end
class Mock
def delete_role(role_name)
role = data[:roles][role_name]
if role
data[:roles].delete(role_name)
Excon::Response.new.tap do |response|
response.status = 200
response.body = { 'RequestId' => Fog::AWS::Mock.request_id }
end
else
raise Fog::AWS::IAM::NotFound.new("The role with name #{role_name} cannot be found.")
end
end
end
end
end
end

View file

@ -31,6 +31,29 @@ module Fog
)
end
end
class Mock
def get_role(role_name)
role = self.data[:roles][role_name]
raise Fog::AWS::IAM::NotFound.new("The role with name #{role_name} cannot be found") unless role
Excon::Response.new.tap do |response|
response.body = {
'Role' => {
'Arn' => role[:arn].strip,
'AssumeRolePolicyDocument' => Fog::JSON.encode(role[:assume_role_policy_document]),
'CreateDate' => role[:create_date],
'Path' => role[:path],
'RoleId' => role[:role_id].strip,
'RoleName' => role_name,
},
'RequestId' => Fog::AWS::Mock.request_id
}
response.status = 200
end
end
end
end
end
end

View file

@ -36,6 +36,28 @@ module Fog
}.merge!(options))
end
end
class Mock
def list_roles(options={})
Excon::Response.new.tap do |response|
response.body = {
'Roles' => data[:roles].map do |role, data|
{
'Arn' => data[:arn].strip,
'AssumeRolePolicyDocument' => Fog::JSON.encode(data[:assume_role_policy_document]),
'RoleId' => data[:role_id],
'Path' => data[:path],
'RoleName' => role,
'CreateDate' => data[:create_date],
}
end,
'RequestId' => Fog::AWS::Mock.request_id,
'IsTruncated' => false,
}
response.status = 200
end
end
end
end
end
end

View file

@ -0,0 +1,45 @@
module Fog
module AWS
class STS
class Real
require 'fog/aws/parsers/sts/assume_role_with_web_identity'
def assume_role_with_web_identity(role_arn, web_identity_token, role_session_name, options={})
request_unsigned(
'Action' => 'AssumeRoleWithWebIdentity',
'RoleArn' => role_arn,
'RoleSessionName' => role_session_name,
'DurationSeconds' => options[:duration] || 3600,
:idempotent => true,
:parser => Fog::Parsers::AWS::STS::AssumeRoleWithWebIdentity.new
)
end
end
class Mock
def assume_role_with_web_identity(role_arn, web_identity_token, role_session_name, options={})
role = options[:iam].data[:roles].values.detect { |r| r[:arn] == role_arn }
Excon::Response.new.tap do |response|
response.body = {
'AssumedRoleUser' => {
'Arn' => role[:arn],
'AssumedRoleId' => role[:role_id]
},
'Audience' => 'fog',
'Credentials' => {
'AccessKeyId' => Fog::AWS::Mock.key_id(20),
'Expiration' => options[:expiration] || Time.now + 3600,
'SecretAccessKey' => Fog::AWS::Mock.key_id(40),
'SessionToken' => Fog::Mock.random_hex(8)
},
'Provider' => 'fog',
'SubjectFromWebIdentityToken' => Fog::Mock.random_hex(8)
}
response.status = 200
end
end
end
end
end
end

View file

@ -16,6 +16,7 @@ module Fog
request :get_session_token
request :assume_role
request :assume_role_with_saml
request :assume_role_with_web_identity
class Mock
def self.data

View file

@ -0,0 +1,11 @@
Shindo.tests('AWS::Federation | signin tokens', ['aws']) do
@signin_token_format = {
'SigninToken' => String
}
tests("#get_signin_token").formats(@signin_token_format) do
pending unless Fog.mocking?
Fog::AWS[:federation].get_signin_token("test_policy")
end
end

View file

@ -2,42 +2,32 @@ Shindo.tests('AWS::IAM | role requests', ['aws']) do
tests('success') do
@role = {
'Arn' => String,
'Arn' => String,
'AssumeRolePolicyDocument' => String,
'CreateDate' => Time,
'Path' => String,
'RoleId' => String,
'RoleName' => String
'CreateDate' => Time,
'Path' => String,
'RoleId' => String,
'RoleName' => String
}
@role_format = {
'Role' => @role,
'RequestId' => String
}
tests("#create_role('fogrole')").formats(@role_format) do
pending if Fog.mocking?
Fog::AWS[:iam].create_role('fogrole', Fog::AWS::IAM::EC2_ASSUME_ROLE_POLICY).body
end
tests("#get_role('fogrole')").formats(@role_format) do
pending if Fog.mocking?
Fog::AWS[:iam].get_role('fogrole').body
end
@list_roles_format = {
'Roles' => [{
'Arn' => String,
'AssumeRolePolicyDocument' => String,
'CreateDate' => Time,
'Path' => String,
'RoleId' => String,
'RoleName' => String
}],
'RequestId' => String,
'Roles' => [@role],
'RequestId' => String,
'IsTruncated' => Fog::Boolean,
}
tests("#list_roles").formats(@list_roles_format) do
pending if Fog.mocking?
body = Fog::AWS[:iam].list_roles.body
returns(true){!! body['Roles'].find {|role| role['RoleName'] == 'fogrole'}}
body
@ -159,7 +149,6 @@ Shindo.tests('AWS::IAM | role requests', ['aws']) do
end
tests("#delete_role('fogrole'").formats(AWS::IAM::Formats::BASIC) do
pending if Fog.mocking?
Fog::AWS[:iam].delete_role('fogrole').body
end
end

View file

@ -1,19 +1,19 @@
Shindo.tests('AWS::STS | assume role', ['aws']) do
@policy = {"Statement" => [{"Effect" => "Allow", "Action" => "*", "Resource" => "*"}]}
@policy = {"Statement" => [{"Effect" => "Allow", "Action" => "*", "Resource" => "*"}]}
@response_format = {
'SessionToken' => String,
'SecretAccessKey' => String,
'Expiration' => String,
'AccessKeyId' => String,
'Arn' => String,
'RequestId' => String
}
@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
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

View file

@ -1,18 +1,18 @@
Shindo.tests('AWS::STS | assume role with SAML', ['aws']) do
@policy = {"Statement" => [{"Effect" => "Allow", "Action" => "*", "Resource" => "*"}]}
@policy = {"Statement" => [{"Effect" => "Allow", "Action" => "*", "Resource" => "*"}]}
@response_format = {
'SessionToken' => String,
'SecretAccessKey' => String,
'Expiration' => String,
'AccessKeyId' => String,
'Arn' => String,
'RequestId' => String
}
@response_format = {
'SessionToken' => String,
'SecretAccessKey' => String,
'Expiration' => String,
'AccessKeyId' => String,
'Arn' => String,
'RequestId' => String
}
tests("#assume_role_with_saml('role_arn', 'principal_arn', 'saml_assertion', #{@policy.inspect}, 900)").formats(@response_format) do
pending if Fog.mocking?
Fog::AWS[:sts].assume_role_with_saml("role_arn","principal_arn","saml_assertion", @policy, 900).body
end
tests("#assume_role_with_saml('role_arn', 'principal_arn', 'saml_assertion', #{@policy.inspect}, 900)").formats(@response_format) do
pending if Fog.mocking?
Fog::AWS[:sts].assume_role_with_saml("role_arn","principal_arn","saml_assertion", @policy, 900).body
end
end

View file

@ -0,0 +1,26 @@
Shindo.tests('AWS::STS | assume role with web identity', ['aws']) do
@sts = Fog::AWS[:sts]
@iam = Fog::AWS[:iam]
@role = @iam.create_role('sts', Fog::AWS::IAM::EC2_ASSUME_ROLE_POLICY).body['Role']
@token = Fog::AWS::Mock.key_id
@response_format = {
'AssumedRoleUser' => {
'Arn' => String,
'AssumedRoleId' => String,
},
'Audience' => String,
'Credentials' => {
'AccessKeyId' => String,
'Expiration' => Time,
'SecretAccessKey' => String,
'SessionToken' => String,
},
'Provider' => String,
'SubjectFromWebIdentityToken' => String,
}
tests("#assume_role_with_web_identity('#{@role['Arn']}', '#{@token}', 'fog')").formats(@response_format) do
@sts.assume_role_with_web_identity(@role['Arn'], @token, 'fog', :iam => @iam).body
end
end