Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 15 additions & 10 deletions lib/fog/aws/iam.rb
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,9 @@ def self.server_certificate_id
end

def initialize(options={})
@use_iam_profile = options[:use_iam_profile]
@use_iam_profile = options[:use_iam_profile]
@aws_credentials_expire_at = Time::now + 20

setup_credentials(options)
end

Expand All @@ -173,11 +174,16 @@ def data

def reset_data
self.class.data.delete(@aws_access_key_id)
current_user
end

def setup_credentials(options)
@aws_access_key_id = options[:aws_access_key_id]
end

def current_user
self.data[:users]["root"]
end
end

class Real
Expand All @@ -201,11 +207,11 @@ class Real
# ==== Returns
# * IAM object with connection to AWS.
def initialize(options={})
@use_iam_profile = options[:use_iam_profile]
@connection_options = options[:connection_options] || {}
@instrumentor = options[:instrumentor]
@instrumentor_name = options[:instrumentor_name] || 'fog.aws.iam'

@use_iam_profile = options[:use_iam_profile]
@connection_options = options[:connection_options] || {}
@instrumentor = options[:instrumentor]
@instrumentor_name = options[:instrumentor_name] || 'fog.aws.iam'
@host = options[:host] || 'iam.amazonaws.com'
@path = options[:path] || '/'
@persistent = options[:persistent] || false
Expand All @@ -215,7 +221,6 @@ def initialize(options={})
@connection = Fog::XML::Connection.new("#{@scheme}://#{@host}:#{@port}#{@path}", @persistent, @connection_options)

setup_credentials(options)

end

def reload
Expand All @@ -225,14 +230,14 @@ def reload
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_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]

#global services that have no region are signed with the us-east-1 region
#the only exception is GovCloud, which requires the region to be explicitly specified as us-gov-west-1
@signer = Fog::AWS::SignatureV4.new( @aws_access_key_id, @aws_secret_access_key, @region,'iam')
@signer = Fog::AWS::SignatureV4.new(@aws_access_key_id, @aws_secret_access_key, @region, 'iam')
end

def request(params)
Expand Down
20 changes: 9 additions & 11 deletions lib/fog/aws/models/iam/policies.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,30 @@ class IAM
class Policies < Fog::Collection
model Fog::AWS::IAM::Policy

def initialize(attributes = {})
@username = attributes[:username]
raise ArgumentError.new("Can't get a policy's user without a username") unless @username
super
end
attribute :username

def all
requires :username
# AWS method get_user_policy only returns an array of policy names, this is kind of useless,
# that's why it has to loop through the list to get the details of each element. I don't like it because it makes this method slow
policy_names = service.list_user_policies(@username).body['PolicyNames'] # it returns an array
policies = []
policy_names.each do |policy_name|
policies << service.get_user_policy(policy_name,@username).body['Policy']
policy_names = service.list_user_policies(self.username).body['PolicyNames'] # it returns an array
policies = policy_names.map do |policy_name|
service.get_user_policy(policy_name, self.username).body['Policy']
end
load(policies) # data is an array of attribute hashes
end

def get(identity)
data = service.get_user_policy(identity,@username).body['Policy']
requires :username

data = service.get_user_policy(identity, self.username).body['Policy']
new(data) # data is an attribute hash
rescue Fog::AWS::IAM::NotFound
nil
end

def new(attributes = {})
super({ :username => @username }.merge!(attributes))
super({ :username => self.username }.merge!(attributes))
end
end
end
Expand Down
4 changes: 4 additions & 0 deletions lib/fog/aws/models/iam/users.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ def all(options = {})
load(data['Users']) # data is an array of attribute hashes
end

def current
new(service.get_user.body['User'])
end

def get(identity)
data = service.get_user(identity).body['User']
new(data) # data is an attribute hash
Expand Down
30 changes: 15 additions & 15 deletions lib/fog/aws/requests/iam/create_user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,22 @@ def create_user(user_name, path = '/')

class Mock
def create_user(user_name, path='/')
if data[:users].key? user_name
if data[:users].key?(user_name)
raise Fog::AWS::IAM::EntityAlreadyExists.new "User with name #{user_name} already exists."
else
data[:users][user_name][:path] = path
Excon::Response.new.tap do |response|
response.status = 200
response.body = { 'User' => {
"UserId" => data[:users][user_name][:user_id],
"Path" => path,
"UserName" => user_name,
"Arn" => (data[:users][user_name][:arn]).strip,
"CreateDate" => data[:users][user_name][:created_at]
},
'RequestId' => Fog::AWS::Mock.request_id
}
end
end

data[:users][user_name][:path] = path

Excon::Response.new.tap do |response|
response.status = 200
response.body = { 'User' => {
"UserId" => data[:users][user_name][:user_id],
"Path" => path,
"UserName" => user_name,
"Arn" => (data[:users][user_name][:arn]).strip,
},
'RequestId' => Fog::AWS::Mock.request_id
}
end
end
end
Expand Down
64 changes: 44 additions & 20 deletions lib/fog/aws/requests/iam/get_user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,55 @@ class Real
# ==== See Also
# http://docs.amazonwebservices.com/IAM/latest/APIReference/API_Getuser.html
#
def get_user(username, options = {})
request({
'Action' => 'GetUser',
'UserName' => username,
:parser => Fog::Parsers::AWS::IAM::GetUser.new
}.merge!(options))
def get_user(username = nil, options = {})
params = {
'Action' => 'GetUser',
:parser => Fog::Parsers::AWS::IAM::GetUser.new
}

if username
params.merge!('UserName' => username)
end

request(params.merge(options))
end
end

class Mock
def get_user(user, options = {})
raise Fog::AWS::IAM::NotFound.new(
"The user with name #{user} cannot be found."
) unless self.data[:users].key?(user)
Excon::Response.new.tap do |response|
response.body = {'User' => {
'UserId' => data[:users][user][:user_id],
'Path' => data[:users][user][:path],
'UserName' => user,
'Arn' => (data[:users][user][:arn]).strip,
'CreateDate' => data[:users][user][:created_at]
},
'RequestId' => Fog::AWS::Mock.request_id }
response.status = 200
def get_user(username = nil, options = {})
response = Excon::Response.new
user_body = nil

if username.nil? # show current user
user = self.current_user

user_body = {
'UserId' => user[:user_id],
'Arn' => user[:arn].strip,
'CreateDate' => user[:created_at]
}

elsif !self.data[:users].key?(username)
raise Fog::AWS::IAM::NotFound.new("The user with name #{username} cannot be found.")
else
user = self.data[:users][username]

user_body = {
'UserId' => user[:user_id],
'Path' => user[:path],
'UserName' => username,
'Arn' => user[:arn].strip,
'CreateDate' => user[:created_at]
}
end

response.status = 200
response.body = {
'User' => user_body,
'RequestId' => Fog::AWS::Mock.request_id
}

response
end
end
end
Expand Down
4 changes: 4 additions & 0 deletions tests/models/iam/users_tests.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ def all_users
@iam.users.get(@user_one_name).id == @user_one_name
end

tests('#current').succeeds do
@iam.users.current
end

tests('#get',"returns nil if the user doesn't exists").succeeds do
@iam.users.get('non-exists') == nil
end
Expand Down
42 changes: 38 additions & 4 deletions tests/requests/iam/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ module IAM
DF3qnnPyArLFx0HLB7wQdm9xYVIqQuLO+V6GRuOd+uSX//aDLDZhwbERf35hoyto
Jfk4gX/qwuRFNy0vjQeTzdvhB1igG/w=
-----END CERTIFICATE-----
}
}
# The public key for SERVER_CERT. Generated using the command:
# openssl x509 -inform pem -in server-public.crt -pubkey -noout > server.pubkey
SERVER_CERT_PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC0CR76sovjdmpWRmEaf8XaG+nGe7czhpdLKkau2b16VtSjkPctxPL5U4vaMxQUboLPr+9oL+9fSYN31VzDD4hyaeGoeI5fhnGeqk71kq5uHONBOQUMbZbBQ8PVd9Sdk+y9JJ6E5fC+GhLL5I+y2DK7syBzyymq1Wi6rPp1XXF7AQIDAQAB"
Expand All @@ -43,7 +43,7 @@ module IAM
Yjs+QiLmOHcbPqX+GHcCQERsSn0RjzKmKirDntseMB59BB/cEN32+gMDVsZuCfb+
fOy2ZavFl13afnhbh2/AjKeDhnb19x/uXjF7JCUtwpA=
-----END RSA PRIVATE KEY-----
}
}

# openssl pkcs8 -nocrypt -topk8 -in SERVER_CERT_PRIVATE_KEY.key -outform pem
SERVER_CERT_PRIVATE_KEY_PKCS8 = %{-----BEGIN PRIVATE KEY-----
Expand All @@ -62,7 +62,7 @@ module IAM
MqYqKsOe2x4wHn0EH9wQ3fb6AwNWxm4J9v587LZlq8WXXdp+eFuHb8CMp4OGdvX3
H+5eMXskJS3CkA==
-----END PRIVATE KEY-----
}
}

SERVER_CERT_PRIVATE_KEY_MISMATCHED = %{-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAyITMqYJMzkPMcaC+x0W2hnZVW99RXzLR8RYyD3xo2AotdJKx
Expand Down Expand Up @@ -91,12 +91,46 @@ module IAM
7G6diyzGrvRX81Yw616ppKJUJVr/zRc13K+eRXXKtNpGkf35B+1NDDjjWZpIHqgx
Xb9WSr07saxZQbxBPQyTlb0Q9Tu2djAq2/o/nYD1/50/fXUTuWMB
-----END RSA PRIVATE KEY-----
}
}

module Formats
BASIC = {
'RequestId' => String
}

USER = {
'Arn' => String,
'Path' => String,
'UserId' => String,
'UserName' => String,
}

CREATE_USER = BASIC.merge('User' => USER)

GET_USER = BASIC.merge('User' => USER.merge('CreateDate' => Time))

GET_CURRENT_USER = BASIC.merge(
'User' => {
'Arn' => String,
'UserId' => String,
'CreateDate' => Time
}
)

LIST_USER = BASIC.merge(
'Users' => [USER.merge('CreateDate' => Time)],
'IsTruncated' => Fog::Boolean
)

GROUPS = BASIC.merge(
'GroupsForUser' => [{
'Arn' => String,
'GroupId' => String,
'GroupName' => String,
'Path' => String
}],
'IsTruncated' => Fog::Boolean
)
end
end
end
Loading