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
|
request :upload_signing_certificate
|
||||||
|
|
||||||
model_path 'fog/aws/models/iam'
|
model_path 'fog/aws/models/iam'
|
||||||
model :user
|
|
||||||
collection :users
|
|
||||||
model :policy
|
|
||||||
collection :policies
|
|
||||||
model :access_key
|
model :access_key
|
||||||
collection :access_keys
|
collection :access_keys
|
||||||
|
model :group
|
||||||
|
collection :groups
|
||||||
|
model :policy
|
||||||
|
collection :policies
|
||||||
model :role
|
model :role
|
||||||
collection :roles
|
collection :roles
|
||||||
|
model :user
|
||||||
|
collection :users
|
||||||
|
|
||||||
class Mock
|
class Mock
|
||||||
def self.data
|
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
|
model Fog::AWS::IAM::Policy
|
||||||
|
|
||||||
attribute :username
|
attribute :username
|
||||||
|
attribute :group_name
|
||||||
|
|
||||||
def all
|
def all
|
||||||
requires :username
|
requires_one :username, :group_name
|
||||||
# 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
|
policies = if self.username
|
||||||
policy_names = service.list_user_policies(self.username).body['PolicyNames'] # it returns an array
|
all_by_user(self.username)
|
||||||
policies = policy_names.map do |policy_name|
|
else
|
||||||
service.get_user_policy(policy_name, self.username).body['Policy']
|
all_by_group(self.group_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
load(policies) # data is an array of attribute hashes
|
load(policies) # data is an array of attribute hashes
|
||||||
end
|
end
|
||||||
|
|
||||||
def get(identity)
|
def get(identity)
|
||||||
requires :username
|
requires_one :username, :group_name
|
||||||
|
|
||||||
data = service.get_user_policy(identity, self.username).body['Policy']
|
data = if self.username
|
||||||
new(data) # data is an attribute hash
|
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
|
rescue Fog::AWS::IAM::NotFound
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def new(attributes = {})
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,12 +6,19 @@ module Fog
|
||||||
attribute :username, :aliases => 'UserName'
|
attribute :username, :aliases => 'UserName'
|
||||||
attribute :document, :aliases => 'PolicyDocument'
|
attribute :document, :aliases => 'PolicyDocument'
|
||||||
|
|
||||||
|
attr_accessor :group_name
|
||||||
|
|
||||||
def save
|
def save
|
||||||
requires :id
|
requires :id
|
||||||
requires :username
|
requires_one :username, :group_name
|
||||||
requires :document
|
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)
|
merge_attributes(data)
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,33 +3,41 @@ module Fog
|
||||||
class IAM
|
class IAM
|
||||||
class User < Fog::Model
|
class User < Fog::Model
|
||||||
identity :id, :aliases => 'UserName'
|
identity :id, :aliases => 'UserName'
|
||||||
|
|
||||||
attribute :path, :aliases => 'Path'
|
attribute :path, :aliases => 'Path'
|
||||||
attribute :arn, :aliases => 'Arn'
|
attribute :arn, :aliases => 'Arn'
|
||||||
attribute :user_id, :aliases => 'UserId'
|
attribute :user_id, :aliases => 'UserId'
|
||||||
attribute :created_at, :aliases => 'CreateDate', :type => :time
|
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
|
def save
|
||||||
requires :id
|
requires :id
|
||||||
data = service.create_user(id, path || '/').body['User']
|
data = service.create_user(id, path || '/').body['User']
|
||||||
merge_attributes(data)
|
merge_attributes(data)
|
||||||
true
|
true
|
||||||
end
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
require 'fog/aws/parsers/iam/policy_parser'
|
||||||
|
|
||||||
module Fog
|
module Fog
|
||||||
module Parsers
|
module Parsers
|
||||||
module AWS
|
module AWS
|
||||||
module IAM
|
module IAM
|
||||||
require 'fog/aws/parsers/iam/policy_parser'
|
|
||||||
class ListManagedPolicies < Fog::Parsers::AWS::IAM::PolicyParser
|
class ListManagedPolicies < Fog::Parsers::AWS::IAM::PolicyParser
|
||||||
def reset
|
def reset
|
||||||
super
|
super
|
||||||
|
|
|
@ -13,10 +13,10 @@ module Fog
|
||||||
when 'Policies'
|
when 'Policies'
|
||||||
@stack << name
|
@stack << name
|
||||||
when 'Policy'
|
when 'Policy'
|
||||||
@role =fresh_policy
|
@policy = fresh_policy
|
||||||
when 'member'
|
when 'member'
|
||||||
if @stack.last == 'Policies'
|
if @stack.last == 'Policies'
|
||||||
@role = fresh_policy
|
@policy = fresh_policy
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
super
|
super
|
||||||
|
|
|
@ -30,8 +30,13 @@ module Fog
|
||||||
|
|
||||||
class Mock
|
class Mock
|
||||||
def add_user_to_group(group_name, user_name)
|
def add_user_to_group(group_name, user_name)
|
||||||
if data[:groups].key? group_name
|
unless data[:groups].key?(group_name)
|
||||||
if data[:users].key? user_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)
|
unless data[:groups][group_name][:members].include?(user_name)
|
||||||
data[:groups][group_name][:members] << user_name
|
data[:groups][group_name][:members] << user_name
|
||||||
|
@ -41,12 +46,6 @@ module Fog
|
||||||
response.status = 200
|
response.status = 200
|
||||||
response.body = { 'RequestId' => Fog::AWS::Mock.request_id }
|
response.body = { 'RequestId' => Fog::AWS::Mock.request_id }
|
||||||
end
|
end
|
||||||
else
|
|
||||||
raise Fog::AWS::IAM::NotFound.new("The user with name #{user_name} cannot be found.")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
raise Fog::AWS::IAM::NotFound.new("The group with name #{group_name} cannot be found.")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -32,6 +32,22 @@ module Fog
|
||||||
}.merge!(options))
|
}.merge!(options))
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -32,6 +32,43 @@ module Fog
|
||||||
}.merge!(options))
|
}.merge!(options))
|
||||||
end
|
end
|
||||||
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
|
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