rs_user_policy 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +40 -2
- data/bin/rs_user_policy +50 -30
- data/lib/rs_user_policy/right_api/multi_client.rb +91 -0
- data/lib/rs_user_policy/user.rb +9 -3
- data/lib/rs_user_policy/user_assignments/json_user_assignments.rb +32 -3
- data/lib/rs_user_policy/user_assignments/user_assignments.rb +30 -0
- data/lib/rs_user_policy/user_collection.rb +10 -7
- data/lib/rs_user_policy/utilities.rb +10 -0
- metadata +5 -4
data/README.rdoc
CHANGED
@@ -1,12 +1,32 @@
|
|
1
1
|
= rs_user_policy
|
2
2
|
|
3
|
-
A useful tool for managing many users across many
|
3
|
+
A useful tool for managing many users across many RightScale accounts.
|
4
4
|
|
5
5
|
While the tests are not exhaustive, the current build status is..
|
6
6
|
{<img src="https://travis-ci.org/rgeyer/rs_user_policy.png" />}[https://travis-ci.org/rgeyer/rs_user_policy]
|
7
7
|
|
8
8
|
== Usage
|
9
9
|
|
10
|
+
You must pass in your RightScale authentication information, and a policy file. You can also specify one or many RightScale accounts using the --rs-acct-num or -a parameters. If an account that you specify is an Enterprise Master account, all Enterprise Children accounts will automatically be included.
|
11
|
+
|
12
|
+
Options:
|
13
|
+
--rs-email, -r <s>: You RightScale User Email Address
|
14
|
+
--rs-pass, -s <s>: Your RightScale User Password
|
15
|
+
--rs-acct-num, -a <s>: A RightScale Enterprise Master Account ID
|
16
|
+
--policy, -p <s>: The path to a JSON file containing the role to permissions policy to enforce
|
17
|
+
--user-assignments, -u <s>: The path to a JSON file containing email address => role pairs for user assignments
|
18
|
+
--dry-run, -d: A flag indicating that no changes should be made, only the user_assignments.json should be evaluated (or created) and
|
19
|
+
the audit_log.json produced
|
20
|
+
--help, -h: Show this message
|
21
|
+
|
22
|
+
Example (One account)
|
23
|
+
rs_user_policy -r "foo@bar.baz" -s "password" -p policy.json -u user_assignments.json -a 12345
|
24
|
+
|
25
|
+
Example (Multiple accounts)
|
26
|
+
rs_user_policy -r "foo@bar.baz" -s "password" -p policy.json -u user_assignments.json -a 12345 -a 67891 -a 11121
|
27
|
+
|
28
|
+
=== Managing existing user permissions
|
29
|
+
|
10
30
|
The binary contained in this gem accepts two files as inputs to determine it's behavior. The first, is a policy JSON file which specifies the permissions to be applied to users.
|
11
31
|
|
12
32
|
Policy JSON should be in the following format
|
@@ -73,6 +93,24 @@ user2 will be assigned observer and lite_user rights on account 12345, and obser
|
|
73
93
|
|
74
94
|
Got that? Cool!
|
75
95
|
|
96
|
+
=== Creating new users
|
97
|
+
|
98
|
+
This tool can also be used to create net-new users who have either never used RightScale, or who have never been associated with one of the accounts targetted by the tool. For those type of users some additional parameters are necessary in the user_assignments source file. The minimum set of properties is ["roles", "company", "first_name", "last_name", "phone"]
|
99
|
+
|
100
|
+
{
|
101
|
+
"net@new.user": {
|
102
|
+
"roles": ["team1"],
|
103
|
+
"company": "RightScale",
|
104
|
+
"first_name": "Net",
|
105
|
+
"last_name": "New",
|
106
|
+
"phone": "9999999999"
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
The order of the additional parameters does not matter. The properties list can also include "identity_provider_href" and "principal_uid" or "password" to specify the users authentication details. If no authentication details are supplied a random secure password will be generated, and written to the output user_assignments.json file.
|
111
|
+
|
112
|
+
If a user with the specified email already exists, but that user does not have any permissions in the account(s) targetted by the tool, these additional properties are still required, but will be ignored.
|
113
|
+
|
76
114
|
== Output
|
77
115
|
|
78
116
|
When the script is run, it will produce two JSON files as output.
|
@@ -83,11 +121,11 @@ Second is the user_assignments-<timestamp>.json file. This will be a combinatio
|
|
83
121
|
|
84
122
|
== TODO
|
85
123
|
|
86
|
-
* Allow users to be added who are not already invited to any RS parent or child account
|
87
124
|
* In absence of a policy.json, create a new policy.json with base roles for each account discovered (I.E. Admin, Observer, Designer, etc)
|
88
125
|
* Perhaps allow a role to inherit from another, or be a concatenation of several?
|
89
126
|
* Handle the race condition where permissions have been deleted in the correct order, but API still throws 422 removing "observer" because the changes have not become consistent server side
|
90
127
|
* HTTP Code: 422, Response body: A user must have the observer role. (RightApi::Exceptions::ApiException)
|
128
|
+
* 2012/12/18 - This does not appear to be an issue any longer. Or at least I am not encountering it anymore. Perhaps this was a transient issue?
|
91
129
|
|
92
130
|
== Copyright
|
93
131
|
|
data/bin/rs_user_policy
CHANGED
@@ -24,6 +24,7 @@
|
|
24
24
|
require 'trollop'
|
25
25
|
require 'right_api_client'
|
26
26
|
require 'logger'
|
27
|
+
require 'digest/md5'
|
27
28
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'rs_user_policy'))
|
28
29
|
|
29
30
|
opts = Trollop::options do
|
@@ -31,7 +32,7 @@ opts = Trollop::options do
|
|
31
32
|
|
32
33
|
opt :rs_email, "You RightScale User Email Address", :type => :string, :required => true
|
33
34
|
opt :rs_pass, "Your RightScale User Password", :type => :string, :required => true
|
34
|
-
opt :rs_acct_num, "A RightScale Enterprise Master Account ID", :type => :string, :required => true
|
35
|
+
opt :rs_acct_num, "A RightScale Enterprise Master Account ID", :type => :string, :multi => true, :required => true
|
35
36
|
opt :policy, "The path to a JSON file containing the role to permissions policy to enforce", :type => :string, :required => true
|
36
37
|
opt :user_assignments, "The path to a JSON file containing email address => role pairs for user assignments", :type => :string
|
37
38
|
opt :dry_run, "A flag indicating that no changes should be made, only the user_assignments.json should be evaluated (or created) and the audit_log.json produced"
|
@@ -39,8 +40,6 @@ end
|
|
39
40
|
|
40
41
|
log = Logger.new(STDOUT)
|
41
42
|
timestamp = Time::now.to_i
|
42
|
-
deleted_users = []
|
43
|
-
accounts = []
|
44
43
|
|
45
44
|
if opts[:dry_run]
|
46
45
|
log.info("The dry_run option was selected, no action will be taken, but the user_assignments output and audit_log files will be written reflecting the actions which would have been taken")
|
@@ -66,40 +65,56 @@ end
|
|
66
65
|
|
67
66
|
user_collection = RsUserPolicy::UserCollection.new
|
68
67
|
|
69
|
-
|
70
|
-
master_account = client.accounts(:id => opts[:rs_acct_num]).show()
|
71
|
-
user_collection.add_users(client.users.index)
|
72
|
-
user_collection.add_permissions(master_account.href, client.permissions.index)
|
68
|
+
multi_client = RsUserPolicy::RightApi::MultiClient.new(opts[:rs_email], opts[:rs_pass], opts[:rs_acct_num])
|
73
69
|
|
74
|
-
|
70
|
+
# Iterate over all accounts once to discover users and their permissions
|
71
|
+
multi_client.each do |account_id, account|
|
72
|
+
child_client = account[:client]
|
73
|
+
child_account = child_client.accounts(:id => account_id).show()
|
74
|
+
account_href = child_account.href
|
75
|
+
users_hash = Hash[child_client.users.index.map{|user| [user.href, user.email] }]
|
76
|
+
user_collection.add_users(users_hash)
|
77
|
+
user_collection.add_permissions(account_href, child_client.permissions.index)
|
78
|
+
end
|
75
79
|
|
76
|
-
|
80
|
+
# Populate the user_assignments with hrefs
|
81
|
+
user_collection.users.each do |user|
|
82
|
+
user_assignments[user.email]["href"] = user.href
|
83
|
+
end
|
77
84
|
|
78
|
-
|
79
|
-
client.child_accounts.index.each do |child|
|
80
|
-
child_client = RightApi::Client.new(:email => opts[:rs_email], :password => opts[:rs_pass], :account_id => RsUserPolicy::Utilities.id_from_href(child.href))
|
81
|
-
accounts << {:client => child_client, :href => child.href, :name => child.name}
|
85
|
+
net_new_users = user_assignments.list - user_collection.users.map{|u| u.email }
|
82
86
|
|
83
|
-
|
84
|
-
|
87
|
+
net_new_users.each do |net_new_user_email|
|
88
|
+
client = multi_client[opts[:rs_acct_num].first()][:client]
|
89
|
+
user_create_params = user_assignments[net_new_user_email]
|
90
|
+
user_create_params = {:email => net_new_user_email}.merge(user_create_params)
|
91
|
+
unless user_create_params.key?("password") || (user_create_params.key?("identity_provider_href") && user_create_params.key?("principal_uid"))
|
92
|
+
pass = RsUserPolicy::Utilities.generate_compliant_password
|
93
|
+
user_create_params["password"] = pass
|
94
|
+
user_assignments[net_new_user_email]["password"] = pass
|
85
95
|
end
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
raise e
|
96
|
+
net_new_user_href = Digest::MD5.hexdigest((Time.now.to_i + rand(256)).to_s)
|
97
|
+
unless opts[:dry_run]
|
98
|
+
net_new_user = client.users.create(:user => user_create_params)
|
99
|
+
net_new_user_href = net_new_user.href
|
91
100
|
end
|
101
|
+
user_collection.add_users({net_new_user_href => net_new_user_email})
|
102
|
+
user_assignments[net_new_user_email]["href"] = net_new_user_href
|
92
103
|
end
|
93
104
|
|
105
|
+
# Now iterate over all accounts to do actual permission assignments.
|
94
106
|
begin
|
95
|
-
|
107
|
+
multi_client.each do |account_id,account|
|
96
108
|
child_client = account[:client]
|
109
|
+
child_account = child_client.accounts(:id => account_id).show()
|
110
|
+
account_name = child_account.name
|
111
|
+
account_href = child_account.href
|
97
112
|
|
98
|
-
log.info("#{
|
113
|
+
log.info("#{account_name} - #{account_href}")
|
99
114
|
user_collection.users.each do |user|
|
100
115
|
email = user.email
|
101
116
|
user_role = user_assignments.get_roles(email)
|
102
|
-
existing_permissions = user.get_api_permissions(
|
117
|
+
existing_permissions = user.get_api_permissions(account_href)
|
103
118
|
|
104
119
|
# Allow some different options about possibly prompting the user etc
|
105
120
|
if user_role.include?('delete')
|
@@ -107,16 +122,15 @@ begin
|
|
107
122
|
# a user can also be effectively deleted if they have an empty list of
|
108
123
|
# permissions for a particular account
|
109
124
|
unless opts[:dry_run]
|
110
|
-
log.debug("Deleting #{user.email} from #{
|
111
|
-
user.clear_permissions(
|
112
|
-
user_assignments.delete(user.email)
|
125
|
+
log.debug("Deleting #{user.email} from #{account_name} by removing these permissions #{JSON.pretty_generate(existing_permissions)}")
|
126
|
+
user.clear_permissions(account_href, child_client)
|
113
127
|
end
|
114
|
-
audit_log.add_entry(email,
|
128
|
+
audit_log.add_entry(email, account_name, 'deleted', 'deleted')
|
115
129
|
elsif !user_role.include?("immutable")
|
116
|
-
user_policy = policy.get_permissions(user_role,
|
117
|
-
removed,added = user.set_api_permissions(user_policy,
|
130
|
+
user_policy = policy.get_permissions(user_role, account_href)
|
131
|
+
removed,added = user.set_api_permissions(user_policy, account_href, child_client, :dry_run => opts[:dry_run])
|
118
132
|
changes = "-#{removed.values} +#{added.values}"
|
119
|
-
audit_log.add_entry(email,
|
133
|
+
audit_log.add_entry(email, account_name, 'update_permissions', changes) unless removed.length + added.length == 0
|
120
134
|
end
|
121
135
|
end
|
122
136
|
end
|
@@ -124,5 +138,11 @@ rescue RightApi::Exceptions::ApiException => e
|
|
124
138
|
log.fatal("A RightScale API exception occurred - #{e}")
|
125
139
|
end
|
126
140
|
|
141
|
+
user_collection.users.each do |user|
|
142
|
+
if user_assignments.get_roles(user.email).include?("delete") && user.permissions == {}
|
143
|
+
user_assignments.delete(user.email)
|
144
|
+
end
|
145
|
+
end unless opts[:dry_run]
|
146
|
+
|
127
147
|
user_assignments.serialize(:filename => user_assignments_output)
|
128
148
|
audit_log.write_file
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# Copyright (c) 2012 Ryan J. Geyer
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
module RsUserPolicy
|
23
|
+
module RightApi
|
24
|
+
class MultiClient
|
25
|
+
|
26
|
+
attr_accessor :accounts
|
27
|
+
|
28
|
+
# Creates RightApi::Client instances for each account ID supplied.
|
29
|
+
# If any supplied account ID is an enterprise master account, the
|
30
|
+
# child accounts are found and added to this MultiClient as well.
|
31
|
+
#
|
32
|
+
# @param [String] email Email address of a RightScale user with permissions to access the API
|
33
|
+
# @param [String] password Password of a RightScale user with permissions to access the API
|
34
|
+
# @param [Array<Integer>] accounts List of accounts for which to create RightApi::Client objects
|
35
|
+
def initialize(email, password, accounts)
|
36
|
+
@accounts ||= {}
|
37
|
+
accounts.each do |account_id|
|
38
|
+
client = ::RightApi::Client.new(
|
39
|
+
:email => email,
|
40
|
+
:password => password,
|
41
|
+
:account_id => account_id
|
42
|
+
)
|
43
|
+
this_account = {
|
44
|
+
:client => client,
|
45
|
+
:has_children => false
|
46
|
+
}
|
47
|
+
begin
|
48
|
+
child_accounts = client.child_accounts.index
|
49
|
+
this_account[:has_children] = true
|
50
|
+
# NOTE: Assuming that children can not have grand children
|
51
|
+
child_accounts.each do |child_account_res|
|
52
|
+
# TODO: Looser coupling to the Utilities class here?
|
53
|
+
child_account_id = RsUserPolicy::Utilities.id_from_href(child_account_res.href).to_i
|
54
|
+
child_account = ::RightApi::Client.new(
|
55
|
+
:email => email,
|
56
|
+
:password => password,
|
57
|
+
:account_id => child_account_id
|
58
|
+
)
|
59
|
+
@accounts[child_account_id] = {
|
60
|
+
:client => child_account,
|
61
|
+
:has_children => false,
|
62
|
+
:parent => account_id
|
63
|
+
}
|
64
|
+
end
|
65
|
+
rescue ::RightApi::Exceptions::ApiException => e
|
66
|
+
raise e unless e.message =~ /Permission denied/
|
67
|
+
end
|
68
|
+
@accounts[account_id] = this_account
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def length
|
73
|
+
@accounts.length
|
74
|
+
end
|
75
|
+
|
76
|
+
def size
|
77
|
+
length
|
78
|
+
end
|
79
|
+
|
80
|
+
def [](account_id)
|
81
|
+
@accounts[account_id]
|
82
|
+
end
|
83
|
+
|
84
|
+
def each(&block)
|
85
|
+
@accounts.each do |account_id,account|
|
86
|
+
yield account_id, account
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/rs_user_policy/user.rb
CHANGED
@@ -21,7 +21,7 @@
|
|
21
21
|
|
22
22
|
module RsUserPolicy
|
23
23
|
class User
|
24
|
-
attr_reader :email, :href
|
24
|
+
attr_reader :email, :href, :permissions
|
25
25
|
|
26
26
|
# Initializes read only attributes for an RsUserPolicy::User
|
27
27
|
#
|
@@ -67,10 +67,12 @@ module RsUserPolicy
|
|
67
67
|
if options[:dry_run]
|
68
68
|
Hash[current_permissions.map{|p| [p.href, p.role_title]}]
|
69
69
|
else
|
70
|
-
RsUserPolicy::RightApi::PermissionUtilities.destroy_permissions(
|
70
|
+
retval = RsUserPolicy::RightApi::PermissionUtilities.destroy_permissions(
|
71
71
|
current_permissions,
|
72
72
|
client
|
73
73
|
)
|
74
|
+
@permissions.delete(account_href)
|
75
|
+
retval
|
74
76
|
end
|
75
77
|
end
|
76
78
|
|
@@ -91,7 +93,9 @@ module RsUserPolicy
|
|
91
93
|
existing_api_permissions_response = get_api_permissions(account_href)
|
92
94
|
existing_api_permissions = Hash[existing_api_permissions_response.map{|p| [p.role_title, p] }]
|
93
95
|
if permissions.length == 0
|
94
|
-
|
96
|
+
removed = clear_permissions(account_href, client, options)
|
97
|
+
@permissions.delete(account_href)
|
98
|
+
return removed, {}
|
95
99
|
else
|
96
100
|
permissions_to_remove = (existing_api_permissions.keys - permissions).map{|p| existing_api_permissions[p]}
|
97
101
|
remove_response = Hash[permissions_to_remove.map{|p| [p.href, p.role_title]}]
|
@@ -112,6 +116,8 @@ module RsUserPolicy
|
|
112
116
|
add_response = RsUserPolicy::RightApi::PermissionUtilities.create_permissions(permissions_to_add, client)
|
113
117
|
end
|
114
118
|
|
119
|
+
@permissions[account_href] = client.permissions.index(:filter => ["user_href==#{@href}"]) unless options[:dry_run]
|
120
|
+
|
115
121
|
return remove_response, Hash[add_response[@href].keys.map{|p| [add_response[@href][p],p]}]
|
116
122
|
end
|
117
123
|
end
|
@@ -75,9 +75,7 @@ module RsUserPolicy
|
|
75
75
|
# @return [Array<String>] The roles assigned to the user
|
76
76
|
def get_roles(email)
|
77
77
|
# TODO: This seems expensive to do in an accessor?
|
78
|
-
|
79
|
-
@user_assignments[email] = {'roles' => ['immutable']}
|
80
|
-
end
|
78
|
+
add_user(email)
|
81
79
|
@user_assignments[email]['roles']
|
82
80
|
end
|
83
81
|
|
@@ -101,6 +99,37 @@ module RsUserPolicy
|
|
101
99
|
File.open(options[:filename], 'w') {|f| f.write(JSON.pretty_generate(@user_assignments))}
|
102
100
|
end
|
103
101
|
|
102
|
+
# Returns a list of all user emails which have a user assignment in the source
|
103
|
+
#
|
104
|
+
# @return [Array<String>] An array of email addresses for users with a user assignment
|
105
|
+
def list
|
106
|
+
@user_assignments.keys
|
107
|
+
end
|
108
|
+
|
109
|
+
# Returns a hash which represents the user specified by the email address specified
|
110
|
+
# If the user does not exist the (see #add_user) method will be called and the
|
111
|
+
# user will be created.
|
112
|
+
#
|
113
|
+
# @param [String] email The email address of the user to fetch
|
114
|
+
#
|
115
|
+
# @return [Hash] A hash of key/value pairs to be passed to the RightScale API for Users#create. This will also include a "roles" key, and may also include any other keys returned by the source
|
116
|
+
def [](email)
|
117
|
+
add_user(email)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Adds a user to user_assignments. If the user already exists the existing record
|
121
|
+
# will be returned. Otherwise the user will be created with a single role of "immutable"
|
122
|
+
#
|
123
|
+
# @param [String] email The email address of the user to create or return
|
124
|
+
# @param [Hash] options Hash of property key/value pairs for the user. The following options are known, but there can be any key in thi hash
|
125
|
+
# @option options [Array<String>] "roles" An array of role names for the user
|
126
|
+
#
|
127
|
+
# @return [Hash] The added or existing user where they key is the users email, and the value is a hash of key/value pairs of user properties.
|
128
|
+
def add_user(email, options={})
|
129
|
+
options = {"roles" => ["immutable"]}.merge(options)
|
130
|
+
@user_assignments[email] || @user_assignments[email] = options
|
131
|
+
end
|
132
|
+
|
104
133
|
private
|
105
134
|
|
106
135
|
def validate()
|
@@ -22,6 +22,13 @@
|
|
22
22
|
module RsUserPolicy
|
23
23
|
module UserAssignments
|
24
24
|
module UserAssignments
|
25
|
+
# Returns a list of all user emails which have a user assignment in the source
|
26
|
+
#
|
27
|
+
# @return [Array<String>] An array of email addresses for users with a user assignment
|
28
|
+
def list
|
29
|
+
raise NotImplementedError, "Please implement this in your concrete class"
|
30
|
+
end
|
31
|
+
|
25
32
|
# @return [Int] The number of users in the user assignments object
|
26
33
|
def length
|
27
34
|
raise NotImplementedError, "Please implement this in your concrete class"
|
@@ -57,6 +64,29 @@ module RsUserPolicy
|
|
57
64
|
def serialize(options={})
|
58
65
|
raise NotImplementedError, "Please implement this in your concrete class"
|
59
66
|
end
|
67
|
+
|
68
|
+
# Returns a hash which represents the user specified by the email address specified
|
69
|
+
# If the user does not exist the (see #add_user) method will be called and the
|
70
|
+
# user will be created.
|
71
|
+
#
|
72
|
+
# @param [String] email The email address of the user to fetch
|
73
|
+
#
|
74
|
+
# @return [Hash] A hash of key/value pairs to be passed to the RightScale API for Users#create. This will also include a "roles" key, and may also include any other keys returned by the source
|
75
|
+
def [](email)
|
76
|
+
raise NotImplementedError, "Please implement this in your concrete class"
|
77
|
+
end
|
78
|
+
|
79
|
+
# Adds a user to user_assignments. If the user already exists the existing record
|
80
|
+
# will be returned. Otherwise the user will be created with a single role of "immutable"
|
81
|
+
#
|
82
|
+
# @param [String] email The email address of the user to create or return
|
83
|
+
# @param [Hash] options Hash of property key/value pairs for the user. The following options are known, but there can be any key in thi hash
|
84
|
+
# @option options [Array<String>] "roles" An array of role names for the user
|
85
|
+
#
|
86
|
+
# @return [Hash] The added or existing user where they key is the users email, and the value is a hash of key/value pairs of user properties.
|
87
|
+
def add_user(email, options={})
|
88
|
+
raise NotImplementedError, "Please implement this in your concrete class"
|
89
|
+
end
|
60
90
|
end
|
61
91
|
end
|
62
92
|
end
|
@@ -37,23 +37,26 @@ module RsUserPolicy
|
|
37
37
|
# include the specified users. The users RightScale API href is used
|
38
38
|
# as the unique identifier for deduplication
|
39
39
|
#
|
40
|
-
# @param [
|
40
|
+
# @param [Hash] users A hash where the key is a users href, and the value is the users email
|
41
41
|
def add_users(users)
|
42
|
-
users.each do |
|
43
|
-
unless @users_by_href.has_key?(
|
44
|
-
@users_by_href[
|
42
|
+
users.each do |href, email|
|
43
|
+
unless @users_by_href.has_key?(href)
|
44
|
+
@users_by_href[href] = RsUserPolicy::User.new(email, href)
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
def [](
|
50
|
-
@users_by_href[
|
49
|
+
def [](href)
|
50
|
+
@users_by_href[href]
|
51
51
|
end
|
52
52
|
|
53
53
|
def add_permissions(account_href, permissions)
|
54
54
|
permissions.each do |permission|
|
55
55
|
user_href = permission.user.href
|
56
|
-
|
56
|
+
unless @users_by_href.has_key?(user_href)
|
57
|
+
user = permission.user.show()
|
58
|
+
@users_by_href[user.href] = RsUserPolicy::User.new(user.email, user.href)
|
59
|
+
end
|
57
60
|
@users_by_href[user_href].add_permission(account_href, permission)
|
58
61
|
end
|
59
62
|
end
|
@@ -56,5 +56,15 @@ module RsUserPolicy
|
|
56
56
|
hash.select{|k,v| !order.include?(v) }.each{|k,v| yield k,v }
|
57
57
|
end
|
58
58
|
|
59
|
+
def self.generate_compliant_password(size=12)
|
60
|
+
chars = (
|
61
|
+
('a'..'z').to_a +
|
62
|
+
('A'..'Z').to_a +
|
63
|
+
('0'..'9').to_a +
|
64
|
+
["!","@","#","$","%","^","&","*","(",")","-","_","=","+"]
|
65
|
+
) - %w(i o 0 1 l 0)
|
66
|
+
(1..size).collect{|a| chars[rand(chars.size)] }.join
|
67
|
+
end
|
68
|
+
|
59
69
|
end
|
60
70
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rs_user_policy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: right_api_client
|
@@ -54,6 +54,7 @@ files:
|
|
54
54
|
- lib/rs_user_policy/audit_log.rb
|
55
55
|
- lib/rs_user_policy/policy/json_policy.rb
|
56
56
|
- lib/rs_user_policy/policy/policy.rb
|
57
|
+
- lib/rs_user_policy/right_api/multi_client.rb
|
57
58
|
- lib/rs_user_policy/right_api/permission_utilities.rb
|
58
59
|
- lib/rs_user_policy/user.rb
|
59
60
|
- lib/rs_user_policy/user_assignments/json_user_assignments.rb
|
@@ -79,7 +80,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
79
80
|
version: '0'
|
80
81
|
segments:
|
81
82
|
- 0
|
82
|
-
hash:
|
83
|
+
hash: 3250796022551410117
|
83
84
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
84
85
|
none: false
|
85
86
|
requirements:
|
@@ -88,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
89
|
version: '0'
|
89
90
|
segments:
|
90
91
|
- 0
|
91
|
-
hash:
|
92
|
+
hash: 3250796022551410117
|
92
93
|
requirements: []
|
93
94
|
rubyforge_project:
|
94
95
|
rubygems_version: 1.8.24
|