mirror of
https://github.com/fog/fog-aws.git
synced 2022-11-09 13:50:52 -05:00
model IAM groups
This commit is contained in:
parent
8908b6f6e7
commit
e131f1266e
15 changed files with 361 additions and 67 deletions
|
@ -85,14 +85,16 @@ module Fog
|
|||
request :upload_signing_certificate
|
||||
|
||||
model_path 'fog/aws/models/iam'
|
||||
model :user
|
||||
collection :users
|
||||
model :policy
|
||||
collection :policies
|
||||
model :access_key
|
||||
collection :access_keys
|
||||
model :group
|
||||
collection :groups
|
||||
model :policy
|
||||
collection :policies
|
||||
model :role
|
||||
collection :roles
|
||||
model :user
|
||||
collection :users
|
||||
|
||||
class Mock
|
||||
def self.data
|
||||
|
|
78
lib/fog/aws/models/iam/group.rb
Normal file
78
lib/fog/aws/models/iam/group.rb
Normal file
|
@ -0,0 +1,78 @@
|
|||
module Fog
|
||||
module AWS
|
||||
class IAM
|
||||
class Group < Fog::Model
|
||||
|
||||
identity :id, :aliases => 'GroupId'
|
||||
|
||||
attribute :arn, :aliases => 'Arn'
|
||||
attribute :name, :aliases => 'GroupName'
|
||||
attribute :path, :aliases => 'Path'
|
||||
attribute :users, :aliases => 'Users', :type => :array
|
||||
|
||||
def add_user(user_or_name)
|
||||
requires :name
|
||||
|
||||
user = if user_or_name.is_a?(Fog::AWS::IAM::User)
|
||||
user_or_name
|
||||
else
|
||||
service.users.new(:id => user_or_name)
|
||||
end
|
||||
|
||||
service.add_user_to_group(self.name, user.identity)
|
||||
merge_attributes(:users => self.users + [user])
|
||||
end
|
||||
|
||||
def attach(policy_arn)
|
||||
requires :name
|
||||
|
||||
service.attach_group_policy(self.name, policy_arn)
|
||||
end
|
||||
|
||||
def save
|
||||
if !persisted?
|
||||
requires :name
|
||||
|
||||
merge_attributes(
|
||||
service.create_group(self.name, self.path).body["Group"]
|
||||
)
|
||||
else
|
||||
params = {}
|
||||
|
||||
if self.name
|
||||
params['NewGroupName'] = self.name
|
||||
end
|
||||
|
||||
if self.path
|
||||
params['NewPath'] = self.path
|
||||
end
|
||||
|
||||
service.update_group(self.name, params)
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def policies
|
||||
requires :name
|
||||
|
||||
service.policies(:group_name => self.name)
|
||||
end
|
||||
|
||||
def reload
|
||||
requires :name
|
||||
|
||||
data = begin
|
||||
collection.get(self.name)
|
||||
rescue Excon::Errors::SocketError
|
||||
nil
|
||||
end
|
||||
|
||||
return unless data
|
||||
|
||||
merge_attributes(data.attributes)
|
||||
self
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
59
lib/fog/aws/models/iam/groups.rb
Normal file
59
lib/fog/aws/models/iam/groups.rb
Normal file
|
@ -0,0 +1,59 @@
|
|||
require 'fog/aws/models/iam/group'
|
||||
|
||||
module Fog
|
||||
module AWS
|
||||
class IAM
|
||||
class Groups < Fog::Collection
|
||||
|
||||
attribute :truncated, :aliases => 'IsTruncated', :type => :boolean
|
||||
attribute :marker, :aliases => 'Marker'
|
||||
attribute :username
|
||||
|
||||
model Fog::AWS::IAM::Group
|
||||
|
||||
def all(options = {})
|
||||
merge_attributes(options)
|
||||
|
||||
data, records = if self.username
|
||||
response = service.list_groups_for_user(self.username, options)
|
||||
[response.body, response.body['GroupsForUser']]
|
||||
else
|
||||
response = service.list_groups(options)
|
||||
[response.body, response.body['Groups']]
|
||||
end
|
||||
|
||||
merge_attributes(data)
|
||||
load(records)
|
||||
end
|
||||
|
||||
def get(identity)
|
||||
data = service.get_group(identity)
|
||||
|
||||
group = data.body['Group']
|
||||
users = data.body['Users'].map { |u| service.users.new(u) }
|
||||
|
||||
new(group.merge(:users => users))
|
||||
rescue Fog::AWS::IAM::NotFound
|
||||
nil
|
||||
end
|
||||
|
||||
def each
|
||||
if !block_given?
|
||||
self
|
||||
else
|
||||
subset = dup.all
|
||||
|
||||
subset.each { |f| yield f }
|
||||
|
||||
while subset.truncated
|
||||
subset = subset.all('Marker' => subset.marker, 'MaxItems' => 1000)
|
||||
subset.each { |f| yield f }
|
||||
end
|
||||
|
||||
self
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -7,29 +7,57 @@ module Fog
|
|||
model Fog::AWS::IAM::Policy
|
||||
|
||||
attribute :username
|
||||
attribute :group_name
|
||||
|
||||
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(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
|
||||
requires_one :username, :group_name
|
||||
|
||||
policies = if self.username
|
||||
all_by_user(self.username)
|
||||
else
|
||||
all_by_group(self.group_name)
|
||||
end
|
||||
|
||||
load(policies) # data is an array of attribute hashes
|
||||
end
|
||||
|
||||
def get(identity)
|
||||
requires :username
|
||||
requires_one :username, :group_name
|
||||
|
||||
data = service.get_user_policy(identity, self.username).body['Policy']
|
||||
new(data) # data is an attribute hash
|
||||
data = if self.username
|
||||
service.get_user_policy(identity, self.username)
|
||||
else
|
||||
service.get_group_policy(identity, self.group_name)
|
||||
end.body['Policy']
|
||||
|
||||
new(data)
|
||||
rescue Fog::AWS::IAM::NotFound
|
||||
nil
|
||||
end
|
||||
|
||||
def new(attributes = {})
|
||||
super({ :username => self.username }.merge!(attributes))
|
||||
super(self.attributes.merge(attributes))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# AWS method get_user_policy and list_group_policies 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
|
||||
|
||||
def all_by_group(group_name)
|
||||
response = service.list_group_policies(group_name)
|
||||
|
||||
response.body['PolicyNames'].map do |policy_name|
|
||||
service.get_group_policy(policy_name, group_name).body['Policy']
|
||||
end
|
||||
end
|
||||
|
||||
def all_by_user(username)
|
||||
response = service.list_user_policies(username)
|
||||
|
||||
response.body['PolicyNames'].map do |policy_name|
|
||||
service.get_user_policy(policy_name, username).body['Policy']
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,12 +6,19 @@ module Fog
|
|||
attribute :username, :aliases => 'UserName'
|
||||
attribute :document, :aliases => 'PolicyDocument'
|
||||
|
||||
attr_accessor :group_name
|
||||
|
||||
def save
|
||||
requires :id
|
||||
requires :username
|
||||
requires_one :username, :group_name
|
||||
requires :document
|
||||
|
||||
data = service.put_user_policy(username, id, document).body
|
||||
data = if username
|
||||
service.put_user_policy(username, id, document).body
|
||||
else
|
||||
service.put_group_policy(group_name, id, document).body
|
||||
end
|
||||
|
||||
merge_attributes(data)
|
||||
true
|
||||
end
|
||||
|
|
|
@ -3,33 +3,41 @@ module Fog
|
|||
class IAM
|
||||
class User < Fog::Model
|
||||
identity :id, :aliases => 'UserName'
|
||||
attribute :path, :aliases => 'Path'
|
||||
attribute :arn, :aliases => 'Arn'
|
||||
attribute :user_id, :aliases => 'UserId'
|
||||
|
||||
attribute :path, :aliases => 'Path'
|
||||
attribute :arn, :aliases => 'Arn'
|
||||
attribute :user_id, :aliases => 'UserId'
|
||||
attribute :created_at, :aliases => 'CreateDate', :type => :time
|
||||
|
||||
def access_keys
|
||||
requires :id
|
||||
|
||||
service.access_keys(:username => id)
|
||||
end
|
||||
|
||||
def destroy
|
||||
requires :id
|
||||
|
||||
service.delete_user(id)
|
||||
true
|
||||
end
|
||||
|
||||
def groups
|
||||
service.groups(:username => self.identity)
|
||||
end
|
||||
|
||||
def policies
|
||||
requires :id
|
||||
|
||||
service.policies(:username => id)
|
||||
end
|
||||
|
||||
def save
|
||||
requires :id
|
||||
data = service.create_user(id, path || '/').body['User']
|
||||
merge_attributes(data)
|
||||
true
|
||||
end
|
||||
|
||||
def destroy
|
||||
requires :id
|
||||
service.delete_user(id)
|
||||
true
|
||||
end
|
||||
|
||||
def policies
|
||||
requires :id
|
||||
service.policies(:username => id)
|
||||
end
|
||||
|
||||
def access_keys
|
||||
requires :id
|
||||
service.access_keys(:username => id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
require 'fog/aws/parsers/iam/policy_parser'
|
||||
|
||||
module Fog
|
||||
module Parsers
|
||||
module AWS
|
||||
module IAM
|
||||
require 'fog/aws/parsers/iam/policy_parser'
|
||||
class ListManagedPolicies < Fog::Parsers::AWS::IAM::PolicyParser
|
||||
def reset
|
||||
super
|
||||
|
|
|
@ -13,10 +13,10 @@ module Fog
|
|||
when 'Policies'
|
||||
@stack << name
|
||||
when 'Policy'
|
||||
@role =fresh_policy
|
||||
@policy = fresh_policy
|
||||
when 'member'
|
||||
if @stack.last == 'Policies'
|
||||
@role = fresh_policy
|
||||
@policy = fresh_policy
|
||||
end
|
||||
end
|
||||
super
|
||||
|
|
|
@ -30,23 +30,22 @@ module Fog
|
|||
|
||||
class Mock
|
||||
def add_user_to_group(group_name, user_name)
|
||||
if data[:groups].key? group_name
|
||||
if data[:users].key? user_name
|
||||
|
||||
unless data[:groups][group_name][:members].include?(user_name)
|
||||
data[:groups][group_name][:members] << user_name
|
||||
end
|
||||
|
||||
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 user with name #{user_name} cannot be found.")
|
||||
end
|
||||
else
|
||||
unless data[:groups].key?(group_name)
|
||||
raise Fog::AWS::IAM::NotFound.new("The group with name #{group_name} cannot be found.")
|
||||
end
|
||||
|
||||
unless data[:users].key?(user_name)
|
||||
raise Fog::AWS::IAM::NotFound.new("The user with name #{user_name} cannot be found.")
|
||||
end
|
||||
|
||||
unless data[:groups][group_name][:members].include?(user_name)
|
||||
data[:groups][group_name][:members] << user_name
|
||||
end
|
||||
|
||||
Excon::Response.new.tap do |response|
|
||||
response.status = 200
|
||||
response.body = { 'RequestId' => Fog::AWS::Mock.request_id }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,10 +20,10 @@ module Fog
|
|||
#
|
||||
def attach_group_policy(group_name, policy_arn)
|
||||
request(
|
||||
'Action' => 'AttachGroupPolicy',
|
||||
'GroupName' => group_name,
|
||||
'PolicyArn' => policy_arn,
|
||||
:parser => Fog::Parsers::AWS::IAM::Basic.new
|
||||
'Action' => 'AttachGroupPolicy',
|
||||
'GroupName' => group_name,
|
||||
'PolicyArn' => policy_arn,
|
||||
:parser => Fog::Parsers::AWS::IAM::Basic.new
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -45,9 +45,9 @@ module Fog
|
|||
Excon::Response.new.tap do |response|
|
||||
response.body = { 'Group' => {
|
||||
'GroupId' => data[:groups][group_name][:group_id],
|
||||
'Path' => data[:groups][group_name][:path],
|
||||
'Path' => data[:groups][group_name][:path],
|
||||
'GroupName' => group_name,
|
||||
'Arn' => (data[:groups][group_name][:arn]).strip
|
||||
'Arn' => (data[:groups][group_name][:arn]).strip
|
||||
},
|
||||
'Users' => data[:groups][group_name][:members].map { |user| get_user(user).body['User'] },
|
||||
'RequestId' => Fog::AWS::Mock.request_id }
|
||||
|
|
|
@ -22,10 +22,10 @@ module Fog
|
|||
#
|
||||
def get_group_policy(policy_name, group_name)
|
||||
request({
|
||||
'Action' => 'GetGroupPolicy',
|
||||
'PolicyName' => policy_name,
|
||||
'GroupName' => group_name,
|
||||
:parser => Fog::Parsers::AWS::IAM::GetGroupPolicy.new
|
||||
'Action' => 'GetGroupPolicy',
|
||||
'PolicyName' => policy_name,
|
||||
'GroupName' => group_name,
|
||||
:parser => Fog::Parsers::AWS::IAM::GetGroupPolicy.new
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,6 +32,22 @@ module Fog
|
|||
}.merge!(options))
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def list_group_policies(group_name, options = {})
|
||||
#FIXME: doesn't use options atm
|
||||
if data[:groups].key? group_name
|
||||
Excon::Response.new.tap do |response|
|
||||
response.body = { 'PolicyNames' => data[:groups][group_name][:policies].keys,
|
||||
'IsTruncated' => false,
|
||||
'RequestId' => Fog::AWS::Mock.request_id }
|
||||
response.status = 200
|
||||
end
|
||||
else
|
||||
raise Fog::AWS::IAM::NotFound.new("The user with name #{user_name} cannot be found.")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -26,12 +26,49 @@ module Fog
|
|||
#
|
||||
def update_group(group_name, options = {})
|
||||
request({
|
||||
'Action' => 'UpdateGroup',
|
||||
'GroupName' => group_name,
|
||||
:parser => Fog::Parsers::AWS::IAM::UpdateGroup.new
|
||||
'Action' => 'UpdateGroup',
|
||||
'GroupName' => group_name,
|
||||
:parser => Fog::Parsers::AWS::IAM::UpdateGroup.new
|
||||
}.merge!(options))
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def update_group(group_name, options = {})
|
||||
raise Fog::AWS::IAM::NotFound.new(
|
||||
"The user with name #{group_name} cannot be found."
|
||||
) unless self.data[:groups].key?(group_name)
|
||||
|
||||
response = Excon::Response.new
|
||||
|
||||
group = self.data[:groups][group_name]
|
||||
|
||||
new_path = options['NewPath']
|
||||
new_group_name = options['NewGroupName']
|
||||
|
||||
if new_path
|
||||
unless new_path.match(/\A\/[a-zA-Z0-9]+\/\Z/)
|
||||
raise Fog::AWS::IAM::ValidationError,
|
||||
"The specified value for path is invalid. It must begin and end with / and contain only alphanumeric characters and/or / characters."
|
||||
end
|
||||
|
||||
group[:path] = new_path
|
||||
end
|
||||
|
||||
if new_group_name
|
||||
self.data[:groups].delete(group_name)
|
||||
self.data[:groups][new_group_name] = group
|
||||
end
|
||||
|
||||
response.status = 200
|
||||
response.body = {
|
||||
'Group' => {},
|
||||
'RequestId' => Fog::AWS::Mock.request_id
|
||||
}
|
||||
|
||||
response
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
59
tests/models/iam/groups_tests.rb
Normal file
59
tests/models/iam/groups_tests.rb
Normal file
|
@ -0,0 +1,59 @@
|
|||
Shindo.tests("Fog::Compute[:iam] | groups", ['aws','iam']) do
|
||||
|
||||
service = Fog::AWS[:iam]
|
||||
group_name = uniq_id('fog-test-group')
|
||||
policy_name = uniq_id('fog-test-policy')
|
||||
group = nil
|
||||
document = {"Statement" => [{"Effect" => "Allow", "Action" => "*", "Resource" => "*"}]}
|
||||
|
||||
tests('#create').succeeds do
|
||||
group = service.groups.create(:name => group_name)
|
||||
|
||||
group.name == group_name
|
||||
end
|
||||
|
||||
tests('#all').succeeds do
|
||||
service.groups.all.map(&:name).include?(group_name)
|
||||
end
|
||||
|
||||
tests('update').succeeds do
|
||||
new_path = group.path = "/newpath/"
|
||||
group.save
|
||||
|
||||
group.reload.path == new_path
|
||||
end
|
||||
|
||||
tests('group') do
|
||||
policy = nil
|
||||
|
||||
tests('#policies', '#create') do
|
||||
policy = group.policies.create(:id => policy_name, :document => document)
|
||||
end
|
||||
|
||||
tests('#policies', '#get').succeeds do
|
||||
group.policies.get(policy_name) != nil
|
||||
end
|
||||
|
||||
tests('#policies', '#all').succeeds do
|
||||
group.policies.all.map(&:id).include?(policy.id)
|
||||
end
|
||||
|
||||
tests('#users', 'when none').succeeds do
|
||||
group.users.empty?
|
||||
end
|
||||
|
||||
user = nil
|
||||
|
||||
tests('#add_user').succeeds do
|
||||
user = service.users.create(:id => 'fog-test')
|
||||
|
||||
group.add_user(user)
|
||||
|
||||
group.users.include?(user)
|
||||
end
|
||||
|
||||
tests('#users').succeeds do
|
||||
group.reload.users.map(&:identity).include?(user.identity)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue