subiam 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,466 @@
1
+ class Subiam::Driver
2
+ include Subiam::Logger::Helper
3
+
4
+ MAX_POLICY_SIZE = 2048
5
+ MAX_POLICY_VERSIONS = 5
6
+
7
+ def initialize(iam, options = {})
8
+ @iam = iam
9
+ @options = options
10
+ end
11
+
12
+ def create_user(user_name, attrs)
13
+ log(:info, "Create User `#{user_name}`", :color => :cyan)
14
+
15
+ unless_dry_run do
16
+ params = {:user_name => user_name}
17
+ params[:path] = attrs[:path] if attrs[:path]
18
+ @iam.create_user(params)
19
+ end
20
+
21
+ new_user_attrs = {:groups => [], :policies => {}, :attached_managed_policies => []}
22
+ new_user_attrs[:path] = attrs[:path] if attrs[:path]
23
+ new_user_attrs
24
+ end
25
+
26
+ def create_access_key(user_name)
27
+ log(:info, "Create access key for User `#{user_name}`", :color => :cyan)
28
+ access_key = nil
29
+
30
+ unless_dry_run do
31
+ resp = @iam.create_access_key(:user_name => user_name)
32
+
33
+ access_key = {
34
+ :access_key_id => resp.access_key.access_key_id,
35
+ :secret_access_key => resp.access_key.secret_access_key,
36
+ }
37
+ end
38
+
39
+ access_key
40
+ end
41
+
42
+ def delete_user(user_name, attrs)
43
+ log(:info, "Delete User `#{user_name}`", :color => :red)
44
+
45
+ unless_dry_run do
46
+ if attrs[:login_profile]
47
+ @iam.delete_login_profile(:user_name => user_name)
48
+ end
49
+
50
+ attrs[:policies].keys.each do |policy_name|
51
+ @iam.delete_user_policy(:user_name => user_name, :policy_name => policy_name)
52
+ end
53
+
54
+ attrs[:groups].each do |group_name|
55
+ @iam.remove_user_from_group(:group_name => group_name, :user_name => user_name)
56
+ end
57
+
58
+ attrs[:attached_managed_policies].each do |policy_arn|
59
+ @iam.detach_user_policy(:user_name => user_name, :policy_arn => policy_arn)
60
+ end
61
+
62
+ list_access_key_ids(user_name).each do |access_key_id|
63
+ @iam.delete_access_key(:user_name => user_name, :access_key_id => access_key_id)
64
+ end
65
+
66
+ list_signing_certificate_ids(user_name).each do |certificate_id|
67
+ @iam.delete_signing_certificate(:user_name => user_name, :certificate_id => certificate_id)
68
+ end
69
+
70
+ @iam.delete_user(:user_name => user_name)
71
+ end
72
+ end
73
+
74
+ def create_login_profile(user_name, attrs)
75
+ log_attrs = attrs.dup
76
+ log_attrs.delete(:password)
77
+
78
+ log(:info, "Update User `#{user_name}`", :color => :green)
79
+ log(:info, " create login profile: #{log_attrs.inspect}", :color => :green)
80
+
81
+ unless_dry_run do
82
+ @iam.create_login_profile(attrs.merge(:user_name => user_name))
83
+ end
84
+ end
85
+
86
+ def delete_login_profile(user_name)
87
+ log(:info, "Update User `#{user_name}`", :color => :green)
88
+ log(:info, " delete login profile", :color => :green)
89
+
90
+ unless_dry_run do
91
+ @iam.delete_login_profile(:user_name => user_name)
92
+ end
93
+ end
94
+
95
+ def update_login_profile(user_name, attrs, old_attrs)
96
+ log_attrs = attrs.dup
97
+ log_attrs.delete(:password)
98
+
99
+ log(:info, "Update User `#{user_name}`", :color => :green)
100
+ log(:info, " login profile:\n".green + Subiam::Utils.diff(old_attrs, attrs, :color => @options[:color], :indent => ' '), :color => false)
101
+
102
+ unless_dry_run do
103
+ @iam.update_login_profile(attrs.merge(:user_name => user_name))
104
+ end
105
+ end
106
+
107
+ def add_user_to_groups(user_name, group_names)
108
+ log(:info, "Update User `#{user_name}`", :color => :green)
109
+ log(:info, " add groups=#{group_names.join(',')}", :color => :green)
110
+
111
+ unless_dry_run do
112
+ group_names.each do |group_name|
113
+ @iam.add_user_to_group(:group_name => group_name, :user_name => user_name)
114
+ end
115
+ end
116
+ end
117
+
118
+ def remove_user_from_groups(user_name, group_names)
119
+ log(:info, "Update User `#{user_name}`", :color => :green)
120
+ log(:info, " remove groups=#{group_names.join(',')}", :color => :green)
121
+
122
+ unless_dry_run do
123
+ group_names.each do |group_name|
124
+ @iam.remove_user_from_group(:group_name => group_name, :user_name => user_name)
125
+ end
126
+ end
127
+ end
128
+
129
+ def create_group(group_name, attrs)
130
+ log(:info, "Create Group `#{group_name}`", :color => :cyan)
131
+
132
+ unless_dry_run do
133
+ params = {:group_name => group_name}
134
+ params[:path] = attrs[:path] if attrs[:path]
135
+ @iam.create_group(params)
136
+ end
137
+
138
+ new_group_attrs = {:policies => {}, :attached_managed_policies => []}
139
+ new_group_attrs[:path] = attrs[:path] if attrs[:path]
140
+ new_group_attrs
141
+ end
142
+
143
+ def delete_group(group_name, attrs, users_in_group)
144
+ log(:info, "Delete Group `#{group_name}`", :color => :red)
145
+
146
+ unless_dry_run do
147
+ attrs[:policies].keys.each do |policy_name|
148
+ @iam.delete_group_policy(:group_name => group_name, :policy_name => policy_name)
149
+ end
150
+
151
+ users_in_group.each do |user_name|
152
+ @iam.remove_user_from_group(:group_name => group_name, :user_name => user_name)
153
+ end
154
+
155
+ attrs[:attached_managed_policies].each do |policy_arn|
156
+ @iam.detach_group_policy(:group_name => group_name, :policy_arn => policy_arn)
157
+ end
158
+
159
+ @iam.delete_group(:group_name => group_name)
160
+ end
161
+ end
162
+
163
+ def create_role(role_name, attrs)
164
+ log(:info, "Create Role `#{role_name}`", :color => :cyan)
165
+ assume_role_policy_document = attrs.fetch(:assume_role_policy_document)
166
+
167
+ unless_dry_run do
168
+ params = {
169
+ :role_name => role_name,
170
+ :assume_role_policy_document => encode_document(assume_role_policy_document),
171
+ }
172
+
173
+ params[:path] = attrs[:path] if attrs[:path]
174
+ @iam.create_role(params)
175
+ end
176
+
177
+ new_role_attrs = {
178
+ :instance_profiles => [],
179
+ :assume_role_policy_document => assume_role_policy_document,
180
+ :policies => {},
181
+ :attached_managed_policies => [],
182
+ }
183
+
184
+ new_role_attrs[:path] = attrs[:path] if attrs[:path]
185
+ new_role_attrs
186
+ end
187
+
188
+ def delete_role(role_name, instance_profile_names, attrs)
189
+ log(:info, "Delete Role `#{role_name}`", :color => :red)
190
+
191
+ unless_dry_run do
192
+ attrs[:policies].keys.each do |policy_name|
193
+ @iam.delete_role_policy(:role_name => role_name, :policy_name => policy_name)
194
+ end
195
+
196
+ instance_profile_names.each do |instance_profile_name|
197
+ @iam.remove_role_from_instance_profile(:instance_profile_name => instance_profile_name, :role_name => role_name)
198
+ end
199
+
200
+ attrs[:attached_managed_policies].each do |policy_arn|
201
+ @iam.detach_role_policy(:role_name => role_name, :policy_arn => policy_arn)
202
+ end
203
+
204
+ @iam.delete_role(:role_name => role_name)
205
+ end
206
+ end
207
+
208
+ def add_role_to_instance_profiles(role_name, instance_profile_names)
209
+ log(:info, "Update Role `#{role_name}`", :color => :green)
210
+ log(:info, " add instance_profiles=#{instance_profile_names.join(',')}", :color => :green)
211
+
212
+ unless_dry_run do
213
+ instance_profile_names.each do |instance_profile_name|
214
+ @iam.add_role_to_instance_profile(:instance_profile_name => instance_profile_name, :role_name => role_name)
215
+ end
216
+ end
217
+ end
218
+
219
+ def remove_role_from_instance_profiles(role_name, instance_profile_names)
220
+ log(:info, "Update Role `#{role_name}`", :color => :green)
221
+ log(:info, " remove instance_profiles=#{instance_profile_names.join(',')}", :color => :green)
222
+
223
+ unless_dry_run do
224
+ instance_profile_names.each do |instance_profile_name|
225
+ @iam.remove_role_from_instance_profile(:instance_profile_name => instance_profile_name, :role_name => role_name)
226
+ end
227
+ end
228
+ end
229
+
230
+ def update_assume_role_policy(role_name, policy_document, old_policy_document)
231
+ log(:info, "Update Role `#{role_name}` > AssumeRolePolicy", :color => :green)
232
+ log(:info, Subiam::Utils.diff(old_policy_document, policy_document, :color => @options[:color]), :color => false)
233
+
234
+ unless_dry_run do
235
+ @iam.update_assume_role_policy(
236
+ :role_name => role_name,
237
+ :policy_document => encode_document(policy_document),
238
+ )
239
+ end
240
+ end
241
+
242
+ def create_instance_profile(instance_profile_name, attrs)
243
+ log(:info, "Create InstanceProfile `#{instance_profile_name}`", :color => :cyan)
244
+
245
+ unless_dry_run do
246
+ params = {:instance_profile_name => instance_profile_name}
247
+ params[:path] = attrs[:path] if attrs[:path]
248
+ @iam.create_instance_profile(params)
249
+ end
250
+
251
+ new_instance_profile_attrs = {}
252
+ new_instance_profile_attrs[:path] = attrs[:path] if attrs[:path]
253
+ new_instance_profile_attrs
254
+ end
255
+
256
+ def delete_instance_profile(instance_profile_name, attrs, roles_in_instance_profile)
257
+ log(:info, "Delete InstanceProfile `#{instance_profile_name}`", :color => :red)
258
+
259
+ unless_dry_run do
260
+ roles_in_instance_profile.each do |role_name|
261
+ @iam.remove_role_from_instance_profile(:instance_profile_name => instance_profile_name, :role_name => role_name)
262
+ end
263
+
264
+ @iam.delete_instance_profile(:instance_profile_name => instance_profile_name)
265
+ end
266
+ end
267
+
268
+ def update_name(type, user_or_group_name, new_name)
269
+ log(:info, "Update #{Subiam::Utils.camelize(type.to_s)} `#{user_or_group_name}`", :color => :green)
270
+ log(:info, " name:\n".green + Subiam::Utils.diff(user_or_group_name, new_name, :color => @options[:color], :indent => ' '), :color => false)
271
+ update_user_or_group(type, user_or_group_name, "new_#{type}_name".to_sym => new_name)
272
+ end
273
+
274
+ def update_path(type, user_or_group_name, new_path, old_path)
275
+ log(:info, "Update #{Subiam::Utils.camelize(type.to_s)} `#{user_or_group_name}`", :color => :green)
276
+ log(:info, " path:\n".green + Subiam::Utils.diff(old_path, new_path, :color => @options[:color], :indent => ' '), :color => false)
277
+ update_user_or_group(type, user_or_group_name, :new_path => new_path)
278
+ end
279
+
280
+ def update_user_or_group(type, user_or_group_name, params)
281
+ unless_dry_run do
282
+ params["#{type}_name".to_sym] = user_or_group_name
283
+ @iam.send("update_#{type}", params)
284
+ end
285
+ end
286
+
287
+ def create_policy(type, user_or_group_name, policy_name, policy_document)
288
+ log(:info, "Create #{Subiam::Utils.camelize(type.to_s)} `#{user_or_group_name}` > Policy `#{policy_name}`", :color => :cyan)
289
+ log(:info, " #{policy_document.pretty_inspect.gsub("\n", "\n ").strip}", :color => :cyan)
290
+ put_policy(type, user_or_group_name, policy_name, policy_document)
291
+ end
292
+
293
+ def update_policy(type, user_or_group_name, policy_name, policy_document, old_policy_document)
294
+ log(:info, "Update #{Subiam::Utils.camelize(type.to_s)} `#{user_or_group_name}` > Policy `#{policy_name}`", :color => :green)
295
+ log(:info, Subiam::Utils.diff(old_policy_document, policy_document, :color => @options[:color]), :color => false)
296
+ put_policy(type, user_or_group_name, policy_name, policy_document)
297
+ end
298
+
299
+ def delete_policy(type, user_or_group_name, policy_name)
300
+ logmsg = "Delete #{Subiam::Utils.camelize(type.to_s)} `#{user_or_group_name}` > Policy `#{policy_name}`"
301
+ log(:info, logmsg, :color => :red)
302
+
303
+ unless_dry_run do
304
+ params = {:policy_name => policy_name}
305
+ params["#{type}_name".to_sym] = user_or_group_name
306
+ @iam.send("delete_#{type}_policy", params)
307
+ end
308
+ end
309
+
310
+ def put_policy(type, user_or_group_name, policy_name, policy_document)
311
+ unless_dry_run do
312
+ params = {
313
+ :policy_name => policy_name,
314
+ :policy_document => encode_document(policy_document),
315
+ }
316
+
317
+ params["#{type}_name".to_sym] = user_or_group_name
318
+ @iam.send("put_#{type}_policy", params)
319
+ end
320
+ end
321
+
322
+ def attach_policies(type, name, policies)
323
+ type = type.to_s
324
+ type_s = type.slice(0, 1).upcase + type.slice(1..-1)
325
+
326
+ log(:info, "Update #{type_s} `#{name}`", :color => :green)
327
+ log(:info, " attach policies=#{policies.join(',')}", :color => :green)
328
+
329
+ unless_dry_run do
330
+ policies.each do |arn|
331
+ @iam.send("attach_#{type}_policy", :"#{type}_name" => name, :policy_arn => arn)
332
+ end
333
+ end
334
+ end
335
+
336
+ def detach_policies(type, name, policies)
337
+ type = type.to_s
338
+ type_s = type.slice(0, 1).upcase + type.slice(1..-1)
339
+
340
+ log(:info, "Update #{type_s} `#{name}`", :color => :green)
341
+ log(:info, " detach policies=#{policies.join(',')}", :color => :green)
342
+
343
+ unless_dry_run do
344
+ policies.each do |arn|
345
+ @iam.send("detach_#{type}_policy", :"#{type}_name" => name, :policy_arn => arn)
346
+ end
347
+ end
348
+ end
349
+
350
+ def list_access_key_ids(user_name)
351
+ @iam.list_access_keys(:user_name => user_name).map {|resp|
352
+ resp.access_key_metadata.map do |metadata|
353
+ metadata.access_key_id
354
+ end
355
+ }.flatten
356
+ end
357
+
358
+ def list_signing_certificate_ids(user_name)
359
+ @iam.list_signing_certificates(:user_name => user_name).map {|resp|
360
+ resp.certificates.map do |cert|
361
+ cert.certificate_id
362
+ end
363
+ }.flatten
364
+ end
365
+
366
+ def create_managed_policy(policy_name, attrs)
367
+ log(:info, "Create ManagedPolicy `#{policy_name}`", :color => :cyan)
368
+
369
+ unless_dry_run do
370
+ params = {
371
+ :policy_name => policy_name,
372
+ :path => attrs[:path],
373
+ :policy_document => encode_document(attrs[:document]),
374
+ }
375
+
376
+ @iam.create_policy(params)
377
+ end
378
+ end
379
+
380
+ def delete_managed_policy(policy_name)
381
+ log(:info, "Delete ManagedPolicy `#{policy_name}`", :color => :red)
382
+
383
+ unless_dry_run do
384
+ policy_versions = @iam.list_policy_versions(
385
+ :policy_arn => policy_arn(policy_name),
386
+ :max_items => MAX_POLICY_VERSIONS
387
+ )
388
+
389
+ policy_versions.versions.reject {|pv|
390
+ pv.is_default_version
391
+ }.each {|pv|
392
+ @iam.delete_policy_version(
393
+ :policy_arn => policy_arn(policy_name),
394
+ :version_id => pv.version_id
395
+ )
396
+ }
397
+
398
+ @iam.delete_policy(
399
+ :policy_arn => policy_arn(policy_name)
400
+ )
401
+ end
402
+ end
403
+
404
+ def update_managed_policy(policy_name, policy_document, old_policy_document)
405
+ log(:info, "Update ManagedPolicy `#{policy_name}`", :color => :green)
406
+ log(:info, Subiam::Utils.diff(old_policy_document, policy_document, :color => @options[:color]), :color => false)
407
+
408
+ unless_dry_run do
409
+ policy_versions = @iam.list_policy_versions(
410
+ :policy_arn => policy_arn(policy_name),
411
+ :max_items => MAX_POLICY_VERSIONS
412
+ )
413
+
414
+ if policy_versions.versions.length >= MAX_POLICY_VERSIONS
415
+ delete_policy_version = policy_versions.versions.reject {|pv|
416
+ pv.is_default_version
417
+ }.sort_by {|pv| pv.version_id[1..-1].to_i }.first
418
+
419
+ @iam.delete_policy_version(
420
+ :policy_arn => policy_arn(policy_name),
421
+ :version_id => delete_policy_version.version_id
422
+ )
423
+ end
424
+
425
+ @iam.create_policy_version(
426
+ :policy_arn => policy_arn(policy_name),
427
+ :policy_document => encode_document(policy_document),
428
+ set_as_default: true
429
+ )
430
+ end
431
+ end
432
+
433
+ private
434
+
435
+ def encode_document(policy_document)
436
+ if @options[:disable_form_json]
437
+ JSON.dump(policy_document)
438
+ else
439
+ encoded = JSON.pretty_generate(policy_document)
440
+
441
+ if Subiam::Utils.bytesize(encoded) > MAX_POLICY_SIZE
442
+ encoded = JSON.pretty_generate(policy_document)
443
+ encoded = encoded.gsub(/^\s+/m, '').strip
444
+ end
445
+
446
+ if Subiam::Utils.bytesize(encoded) > MAX_POLICY_SIZE
447
+ encoded = JSON.dump(policy_document)
448
+ end
449
+
450
+ encoded
451
+ end
452
+ end
453
+
454
+ def unless_dry_run
455
+ yield unless @options[:dry_run]
456
+ end
457
+
458
+ def account_id
459
+ # https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html
460
+ @account_id ||= @iam.get_user.user.arn.split(':').fetch(4)
461
+ end
462
+
463
+ def policy_arn(policy_name)
464
+ "arn:aws:iam::#{account_id}:policy/#{policy_name}"
465
+ end
466
+ end
@@ -0,0 +1,35 @@
1
+ class Subiam::DSL::Context::Group
2
+ include Subiam::TemplateHelper
3
+ include Subiam::DSL::Helper::Arn
4
+
5
+ def initialize(context, name, &block)
6
+ @group_name = name
7
+ @context = context.merge(:group_name => name)
8
+ @result = {:policies => {}, :attached_managed_policies => []}
9
+ instance_eval(&block)
10
+ end
11
+
12
+ attr_reader :result
13
+
14
+ private
15
+
16
+ def policy(name)
17
+ name = name.to_s
18
+
19
+ if @result[:policies][name]
20
+ raise "Group `#{@group_name}` > Policy `#{name}`: already defined"
21
+ end
22
+
23
+ policy_document = yield
24
+
25
+ unless policy_document.kind_of?(Hash)
26
+ raise "Group `#{@group_name}` > Policy `#{name}`: wrong argument type #{policy_document.class} (expected Hash)"
27
+ end
28
+
29
+ @result[:policies][name] = policy_document.keys_to_s_recursive
30
+ end
31
+
32
+ def attached_managed_policies(*policies)
33
+ @result[:attached_managed_policies].concat(policies.map(&:to_s))
34
+ end
35
+ end
@@ -0,0 +1,23 @@
1
+ class Subiam::DSL::Context::ManagedPolicy
2
+ include Subiam::TemplateHelper
3
+
4
+ def initialize(context, name, &block)
5
+ @policy_name = name
6
+ @context = context.merge(:policy_name => name)
7
+ @result = {:document => get_document(block)}
8
+ end
9
+
10
+ attr_reader :result
11
+
12
+ private
13
+
14
+ def get_document(block)
15
+ document = instance_eval(&block)
16
+
17
+ unless document.kind_of?(Hash)
18
+ raise "ManagedPolicy `#{@policy_name}`: wrong argument type #{document.class} (expected Hash)"
19
+ end
20
+
21
+ document.keys_to_s_recursive
22
+ end
23
+ end
@@ -0,0 +1,59 @@
1
+ class Subiam::DSL::Context::Role
2
+ include Subiam::TemplateHelper
3
+ include Subiam::DSL::Helper::Arn
4
+
5
+ def initialize(context, name, &block)
6
+ @role_name = name
7
+ @context = context.merge(:role_name => name)
8
+ @result = {:instance_profiles => [], :policies => {}, :attached_managed_policies => []}
9
+ instance_eval(&block)
10
+ end
11
+
12
+ def result
13
+ unless @result[:assume_role_policy_document]
14
+ raise "Role `#{@role_name}`: AssumeRolePolicyDocument is not defined"
15
+ end
16
+
17
+ @result
18
+ end
19
+
20
+ private
21
+
22
+ def instance_profiles(*profiles)
23
+ @result[:instance_profiles].concat(profiles.map(&:to_s))
24
+ end
25
+
26
+ def assume_role_policy_document
27
+ if @result[:assume_role_policy_document]
28
+ raise "Role `#{@role_name}` > AssumeRolePolicyDocument: already defined"
29
+ end
30
+
31
+ assume_role_policy_document = yield
32
+
33
+ unless assume_role_policy_document.kind_of?(Hash)
34
+ raise "Role `#{@role_name}` > AssumeRolePolicyDocument: wrong argument type #{policy_document.class} (expected Hash)"
35
+ end
36
+
37
+ @result[:assume_role_policy_document] = assume_role_policy_document.keys_to_s_recursive
38
+ end
39
+
40
+ def policy(name)
41
+ name = name.to_s
42
+
43
+ if @result[:policies][name]
44
+ raise "Role `#{@role_name}` > Policy `#{name}`: already defined"
45
+ end
46
+
47
+ policy_document = yield
48
+
49
+ unless policy_document.kind_of?(Hash)
50
+ raise "Role `#{@role_name}` > Policy `#{name}`: wrong argument type #{policy_document.class} (expected Hash)"
51
+ end
52
+
53
+ @result[:policies][name] = policy_document.keys_to_s_recursive
54
+ end
55
+
56
+ def attached_managed_policies(*policies)
57
+ @result[:attached_managed_policies].concat(policies.map(&:to_s))
58
+ end
59
+ end
@@ -0,0 +1,43 @@
1
+ class Subiam::DSL::Context::User
2
+ include Subiam::TemplateHelper
3
+ include Subiam::DSL::Helper::Arn
4
+
5
+ def initialize(context, name, &block)
6
+ @user_name = name
7
+ @context = context.merge(:user_name => name)
8
+ @result = {:groups => [], :policies => {}, :attached_managed_policies => []}
9
+ instance_eval(&block)
10
+ end
11
+
12
+ attr_reader :result
13
+
14
+ private
15
+
16
+ def login_profile(value)
17
+ @result[:login_profile] = value
18
+ end
19
+
20
+ def groups(*grps)
21
+ @result[:groups].concat(grps.map(&:to_s))
22
+ end
23
+
24
+ def policy(name)
25
+ name = name.to_s
26
+
27
+ if @result[:policies][name]
28
+ raise "User `#{@user_name}` > Policy `#{name}`: already defined"
29
+ end
30
+
31
+ policy_document = yield
32
+
33
+ unless policy_document.kind_of?(Hash)
34
+ raise "User `#{@user_name}` > Policy `#{name}`: wrong argument type #{policy_document.class} (expected Hash)"
35
+ end
36
+
37
+ @result[:policies][name] = policy_document.keys_to_s_recursive
38
+ end
39
+
40
+ def attached_managed_policies(*policies)
41
+ @result[:attached_managed_policies].concat(policies.map(&:to_s))
42
+ end
43
+ end