cloud-mu 3.2.0 → 3.5.0

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.
Files changed (156) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +1 -1
  3. data/ansible/roles/mu-nat/tasks/main.yml +3 -0
  4. data/bin/mu-adopt +12 -1
  5. data/bin/mu-aws-setup +41 -7
  6. data/bin/mu-azure-setup +34 -0
  7. data/bin/mu-configure +214 -119
  8. data/bin/mu-gcp-setup +37 -2
  9. data/bin/mu-load-config.rb +2 -1
  10. data/bin/mu-node-manage +3 -0
  11. data/bin/mu-refresh-ssl +67 -0
  12. data/bin/mu-run-tests +28 -6
  13. data/bin/mu-self-update +30 -10
  14. data/bin/mu-upload-chef-artifacts +30 -26
  15. data/cloud-mu.gemspec +10 -8
  16. data/cookbooks/mu-master/attributes/default.rb +5 -1
  17. data/cookbooks/mu-master/metadata.rb +2 -2
  18. data/cookbooks/mu-master/recipes/default.rb +81 -26
  19. data/cookbooks/mu-master/recipes/init.rb +197 -62
  20. data/cookbooks/mu-master/recipes/update_nagios_only.rb +1 -1
  21. data/cookbooks/mu-master/recipes/vault.rb +78 -77
  22. data/cookbooks/mu-master/templates/default/mods/rewrite.conf.erb +1 -0
  23. data/cookbooks/mu-master/templates/default/nagios.conf.erb +103 -0
  24. data/cookbooks/mu-master/templates/default/web_app.conf.erb +14 -30
  25. data/cookbooks/mu-tools/attributes/default.rb +12 -0
  26. data/cookbooks/mu-tools/files/centos-6/CentOS-Base.repo +47 -0
  27. data/cookbooks/mu-tools/libraries/helper.rb +98 -4
  28. data/cookbooks/mu-tools/libraries/monkey.rb +1 -1
  29. data/cookbooks/mu-tools/recipes/apply_security.rb +31 -9
  30. data/cookbooks/mu-tools/recipes/aws_api.rb +8 -2
  31. data/cookbooks/mu-tools/recipes/base_repositories.rb +1 -1
  32. data/cookbooks/mu-tools/recipes/gcloud.rb +2 -9
  33. data/cookbooks/mu-tools/recipes/google_api.rb +7 -0
  34. data/cookbooks/mu-tools/recipes/rsyslog.rb +8 -1
  35. data/cookbooks/mu-tools/resources/disk.rb +113 -42
  36. data/cookbooks/mu-tools/resources/mommacat_request.rb +1 -2
  37. data/cookbooks/mu-tools/templates/centos-8/sshd_config.erb +215 -0
  38. data/extras/Gemfile.lock.bootstrap +394 -0
  39. data/extras/bucketstubs/error.html +0 -0
  40. data/extras/bucketstubs/index.html +0 -0
  41. data/extras/clean-stock-amis +11 -3
  42. data/extras/generate-stock-images +6 -3
  43. data/extras/git_rpm/build.sh +20 -0
  44. data/extras/git_rpm/mugit.spec +53 -0
  45. data/extras/image-generators/AWS/centos7.yaml +19 -16
  46. data/extras/image-generators/AWS/{rhel7.yaml → rhel71.yaml} +0 -0
  47. data/extras/image-generators/AWS/{win2k12.yaml → win2k12r2.yaml} +0 -0
  48. data/extras/image-generators/VMWare/centos8.yaml +15 -0
  49. data/extras/openssl_rpm/build.sh +19 -0
  50. data/extras/openssl_rpm/mussl.spec +46 -0
  51. data/extras/python_rpm/muthon.spec +14 -4
  52. data/extras/ruby_rpm/muby.spec +9 -5
  53. data/extras/sqlite_rpm/build.sh +19 -0
  54. data/extras/sqlite_rpm/muqlite.spec +47 -0
  55. data/install/installer +7 -5
  56. data/modules/mommacat.ru +2 -2
  57. data/modules/mu.rb +14 -7
  58. data/modules/mu/adoption.rb +5 -5
  59. data/modules/mu/cleanup.rb +47 -25
  60. data/modules/mu/cloud.rb +29 -1
  61. data/modules/mu/cloud/dnszone.rb +0 -2
  62. data/modules/mu/cloud/machine_images.rb +1 -1
  63. data/modules/mu/cloud/providers.rb +6 -1
  64. data/modules/mu/cloud/resource_base.rb +16 -7
  65. data/modules/mu/cloud/ssh_sessions.rb +5 -1
  66. data/modules/mu/cloud/wrappers.rb +20 -7
  67. data/modules/mu/config.rb +28 -12
  68. data/modules/mu/config/bucket.rb +31 -2
  69. data/modules/mu/config/cache_cluster.rb +1 -1
  70. data/modules/mu/config/cdn.rb +100 -0
  71. data/modules/mu/config/container_cluster.rb +1 -1
  72. data/modules/mu/config/database.rb +3 -3
  73. data/modules/mu/config/dnszone.rb +4 -3
  74. data/modules/mu/config/endpoint.rb +1 -0
  75. data/modules/mu/config/firewall_rule.rb +1 -1
  76. data/modules/mu/config/function.rb +16 -7
  77. data/modules/mu/config/job.rb +89 -0
  78. data/modules/mu/config/notifier.rb +7 -18
  79. data/modules/mu/config/ref.rb +55 -9
  80. data/modules/mu/config/schema_helpers.rb +12 -3
  81. data/modules/mu/config/server.rb +11 -5
  82. data/modules/mu/config/server_pool.rb +2 -2
  83. data/modules/mu/config/vpc.rb +11 -10
  84. data/modules/mu/defaults/AWS.yaml +106 -106
  85. data/modules/mu/deploy.rb +40 -14
  86. data/modules/mu/groomers/chef.rb +2 -2
  87. data/modules/mu/master.rb +70 -3
  88. data/modules/mu/mommacat.rb +28 -9
  89. data/modules/mu/mommacat/daemon.rb +13 -7
  90. data/modules/mu/mommacat/naming.rb +2 -2
  91. data/modules/mu/mommacat/search.rb +16 -5
  92. data/modules/mu/mommacat/storage.rb +67 -32
  93. data/modules/mu/providers/aws.rb +298 -85
  94. data/modules/mu/providers/aws/alarm.rb +5 -5
  95. data/modules/mu/providers/aws/bucket.rb +284 -50
  96. data/modules/mu/providers/aws/cache_cluster.rb +26 -26
  97. data/modules/mu/providers/aws/cdn.rb +782 -0
  98. data/modules/mu/providers/aws/collection.rb +16 -16
  99. data/modules/mu/providers/aws/container_cluster.rb +84 -64
  100. data/modules/mu/providers/aws/database.rb +59 -55
  101. data/modules/mu/providers/aws/dnszone.rb +29 -12
  102. data/modules/mu/providers/aws/endpoint.rb +535 -50
  103. data/modules/mu/providers/aws/firewall_rule.rb +32 -26
  104. data/modules/mu/providers/aws/folder.rb +1 -1
  105. data/modules/mu/providers/aws/function.rb +300 -134
  106. data/modules/mu/providers/aws/group.rb +16 -14
  107. data/modules/mu/providers/aws/habitat.rb +4 -4
  108. data/modules/mu/providers/aws/job.rb +469 -0
  109. data/modules/mu/providers/aws/loadbalancer.rb +67 -45
  110. data/modules/mu/providers/aws/log.rb +17 -17
  111. data/modules/mu/providers/aws/msg_queue.rb +22 -13
  112. data/modules/mu/providers/aws/nosqldb.rb +99 -8
  113. data/modules/mu/providers/aws/notifier.rb +137 -65
  114. data/modules/mu/providers/aws/role.rb +119 -83
  115. data/modules/mu/providers/aws/search_domain.rb +166 -30
  116. data/modules/mu/providers/aws/server.rb +209 -118
  117. data/modules/mu/providers/aws/server_pool.rb +95 -130
  118. data/modules/mu/providers/aws/storage_pool.rb +19 -11
  119. data/modules/mu/providers/aws/user.rb +5 -5
  120. data/modules/mu/providers/aws/userdata/linux.erb +5 -4
  121. data/modules/mu/providers/aws/vpc.rb +109 -54
  122. data/modules/mu/providers/aws/vpc_subnet.rb +43 -39
  123. data/modules/mu/providers/azure.rb +78 -12
  124. data/modules/mu/providers/azure/server.rb +20 -4
  125. data/modules/mu/providers/cloudformation/server.rb +1 -1
  126. data/modules/mu/providers/google.rb +21 -5
  127. data/modules/mu/providers/google/bucket.rb +1 -1
  128. data/modules/mu/providers/google/container_cluster.rb +1 -1
  129. data/modules/mu/providers/google/database.rb +1 -1
  130. data/modules/mu/providers/google/firewall_rule.rb +1 -1
  131. data/modules/mu/providers/google/folder.rb +7 -3
  132. data/modules/mu/providers/google/function.rb +66 -31
  133. data/modules/mu/providers/google/group.rb +1 -1
  134. data/modules/mu/providers/google/habitat.rb +1 -1
  135. data/modules/mu/providers/google/loadbalancer.rb +1 -1
  136. data/modules/mu/providers/google/role.rb +6 -3
  137. data/modules/mu/providers/google/server.rb +1 -1
  138. data/modules/mu/providers/google/server_pool.rb +1 -1
  139. data/modules/mu/providers/google/user.rb +1 -1
  140. data/modules/mu/providers/google/vpc.rb +28 -3
  141. data/modules/tests/aws-jobs-functions.yaml +46 -0
  142. data/modules/tests/aws-servers-with-handrolled-iam.yaml +37 -0
  143. data/modules/tests/centos6.yaml +4 -0
  144. data/modules/tests/centos7.yaml +4 -0
  145. data/modules/tests/ecs.yaml +2 -2
  146. data/modules/tests/eks.yaml +1 -1
  147. data/modules/tests/functions/node-function/lambda_function.js +10 -0
  148. data/modules/tests/functions/python-function/lambda_function.py +12 -0
  149. data/modules/tests/k8s.yaml +1 -1
  150. data/modules/tests/microservice_app.yaml +288 -0
  151. data/modules/tests/rds.yaml +5 -5
  152. data/modules/tests/regrooms/rds.yaml +5 -5
  153. data/modules/tests/server-with-scrub-muisms.yaml +1 -1
  154. data/modules/tests/super_complex_bok.yml +2 -2
  155. data/modules/tests/super_simple_bok.yml +2 -2
  156. metadata +42 -17
@@ -30,7 +30,7 @@ module MU
30
30
  end
31
31
  end
32
32
 
33
- @mu_name ||= @deploy.getResourceName(@config["name"])
33
+ @mu_name ||= @config['scrub_mu_isms'] ? @config['name'] : @deploy.getResourceName(@config["name"], max_length: 64)
34
34
  end
35
35
 
36
36
  # Called automatically by {MU::Deploy#createResources}
@@ -43,7 +43,7 @@ module MU
43
43
 
44
44
  policy_name = @mu_name+"-"+policy.keys.first.upcase
45
45
  MU.log "Creating IAM policy #{policy_name}"
46
- MU::Cloud::AWS.iam(credentials: @config['credentials']).create_policy(
46
+ MU::Cloud::AWS.iam(credentials: @credentials).create_policy(
47
47
  policy_name: policy_name,
48
48
  path: "/"+@deploy.deploy_id+"/",
49
49
  policy_document: JSON.generate(policy.values.first),
@@ -53,16 +53,18 @@ module MU
53
53
  end
54
54
 
55
55
  if !@config['bare_policies']
56
- MU.log "Creating IAM role #{@mu_name}"
57
56
  @cloud_id = @mu_name
58
57
  path = @config['strip_path'] ? nil : "/"+@deploy.deploy_id+"/"
59
- MU::Cloud::AWS.iam(credentials: @config['credentials']).create_role(
60
- path: path,
61
- role_name: @mu_name,
62
- description: "Generated by Mu",
63
- assume_role_policy_document: gen_assume_role_policy_doc,
64
- tags: get_tag_params
65
- )
58
+ params = {
59
+ :path => path,
60
+ :role_name => @mu_name,
61
+ :description => "Generated by Mu",
62
+ :assume_role_policy_document => gen_assume_role_policy_doc,
63
+ :tags => get_tag_params(@config['scrub_mu_isms'])
64
+ }
65
+
66
+ MU.log "Creating IAM role #{@mu_name} (#{@credentials})", details: params
67
+ MU::Cloud::AWS.iam(credentials: @credentials).create_role(params)
66
68
  end
67
69
  end
68
70
 
@@ -75,7 +77,7 @@ module MU
75
77
  end
76
78
 
77
79
  if !@config['bare_policies']
78
- resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).get_role(
80
+ resp = MU::Cloud::AWS.iam(credentials: @credentials).get_role(
79
81
  role_name: @mu_name
80
82
  ).role
81
83
  ext_tags = resp.tags.map { |t| t.to_h }
@@ -84,7 +86,7 @@ module MU
84
86
 
85
87
  if tag_param.size > 0
86
88
  MU.log "Updating tags on IAM role #{@mu_name}", MU::NOTICE, details: tag_param
87
- MU::Cloud::AWS.iam(credentials: @config['credentials']).tag_role(role_name: @mu_name, tags: tag_param)
89
+ MU::Cloud::AWS.iam(credentials: @credentials).tag_role(role_name: @mu_name, tags: tag_param)
88
90
  end
89
91
  end
90
92
 
@@ -92,13 +94,14 @@ module MU
92
94
  configured_policies = []
93
95
 
94
96
  if @config['raw_policies']
97
+ MU.log "Attaching #{@config['raw_policies'].size.to_s} raw #{@config['raw_policies'].size > 1 ? "policies" : "policy"} to role #{@mu_name}", MU::NOTICE
95
98
  configured_policies = @config['raw_policies'].map { |p|
96
99
  @mu_name+"-"+p.keys.first.upcase
97
100
  }
98
101
  end
99
102
 
100
103
  if @config['attachable_policies']
101
- MU.log "Attaching #{@config['attachable_policies'].size.to_s} #{@config['attachable_policies'].size > 1 ? "policies" : "policy"} to role #{@mu_name}", MU::NOTICE
104
+ MU.log "Attaching #{@config['attachable_policies'].size.to_s} external #{@config['attachable_policies'].size > 1 ? "policies" : "policy"} to role #{@mu_name}", MU::NOTICE
102
105
  configured_policies.concat(@config['attachable_policies'].map { |p|
103
106
  id = if p.is_a?(MU::Config::Ref)
104
107
  p.cloud_id
@@ -109,18 +112,17 @@ module MU
109
112
  end
110
113
  id.gsub(/.*?\/([^:\/]+)$/, '\1')
111
114
  })
112
- configured_policies.each { |pol|
113
- }
114
115
  end
115
116
 
117
+ # Purge anything that doesn't belong
116
118
  if !@config['bare_policies']
117
- attached_policies = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_attached_role_policies(
119
+ attached_policies = MU::Cloud::AWS.iam(credentials: @credentials).list_attached_role_policies(
118
120
  role_name: @mu_name
119
121
  ).attached_policies
120
122
  attached_policies.each { |a|
121
123
  if !configured_policies.include?(a.policy_name)
122
- MU.log "Removing IAM policy #{a.policy_name} from role #{@mu_name}", MU::NOTICE
123
- MU::Cloud::AWS::Role.purgePolicy(a.policy_arn, @config['credentials'])
124
+ MU.log "Removing IAM policy #{a.policy_name} from role #{@mu_name}", MU::NOTICE, details: configured_policies
125
+ MU::Cloud::AWS::Role.purgePolicy(a.policy_arn, @credentials)
124
126
  end
125
127
  }
126
128
  end
@@ -153,8 +155,8 @@ module MU
153
155
  policy.values.each { |p|
154
156
  p["Version"] ||= "2012-10-17"
155
157
  }
156
- policy_name = basename+"-"+policy.keys.first.upcase
157
158
 
159
+ policy_name = basename+"-"+policy.keys.first.upcase
158
160
  arn = "arn:"+(MU::Cloud::AWS.isGovCloud? ? "aws-us-gov" : "aws")+":iam::"+MU::Cloud::AWS.credToAcct(credentials)+":policy#{path}/#{policy_name}"
159
161
  resp = begin
160
162
  desc = MU::Cloud::AWS.iam(credentials: credentials).get_policy(policy_arn: arn)
@@ -164,7 +166,7 @@ module MU
164
166
  version_id: desc.policy.default_version_id
165
167
  )
166
168
 
167
- ext = JSON.parse(URI.decode(version.policy_version.document))
169
+ ext = JSON.parse(CGI.unescape(version.policy_version.document))
168
170
  if ext != policy.values.first
169
171
  # Special exception- we don't want to overwrite extra rules
170
172
  # in MuSecrets policies, because our siblings might have
@@ -184,12 +186,16 @@ module MU
184
186
 
185
187
  rescue Aws::IAM::Errors::NoSuchEntity
186
188
  MU.log "Creating IAM policy #{policy_name}", details: policy.values.first
187
- MU::Cloud::AWS.iam(credentials: credentials).create_policy(
189
+ desc = MU::Cloud::AWS.iam(credentials: credentials).create_policy(
188
190
  policy_name: policy_name,
189
191
  path: path+"/",
190
192
  policy_document: JSON.generate(policy.values.first),
191
193
  description: "Raw policy from #{basename}"
192
194
  )
195
+ MU.retrier([Aws::IAM::Errors::NoSuchEntity], loop_if: Proc.new { desc.nil? }) {
196
+ desc = MU::Cloud::AWS.iam(credentials: credentials).get_policy(policy_arn: arn)
197
+ }
198
+ desc
193
199
  end
194
200
  arns << resp.policy.arn
195
201
  }
@@ -216,7 +222,23 @@ module MU
216
222
  # populated with one or both depending on what this resource has
217
223
  # defined.
218
224
  def cloud_desc(use_cache: true)
219
- return @cloud_desc_cache if @cloud_desc_cache and use_cache
225
+ require 'aws-sdk-iam'
226
+
227
+ # we might inherit a naive cached description from the base cloud
228
+ # layer; rearrange it to our tastes
229
+ if @cloud_desc_cache.is_a?(::Aws::IAM::Types::Role)
230
+ new_desc = {
231
+ "role" => @cloud_desc_cache
232
+ }
233
+ @cloud_desc_cache = new_desc
234
+ elsif @cloud_desc_cache.is_a?(::Aws::IAM::Types::Policy)
235
+ new_desc = {
236
+ "policies" => [@cloud_desc_cache]
237
+ }
238
+ @cloud_desc_cache = new_desc
239
+ end
240
+
241
+ return @cloud_desc_cache if @cloud_desc_cache and !@cloud_desc_cache.empty? and use_cache
220
242
 
221
243
  @cloud_desc_cache = {}
222
244
  if @config['bare_policies']
@@ -290,8 +312,8 @@ end
290
312
  # Insert a new target entity into an existing policy.
291
313
  # @param policy [String]: The name of the policy to which we're appending, which must already exist as part of this role resource
292
314
  # @param targets [Array<String>]: The target resource. If +target_type+ isn't specified, this should be a fully-resolved ARN.
293
- def injectPolicyTargets(policy, targets)
294
- if !policy.match(/^#{@deploy.deploy_id}/)
315
+ def injectPolicyTargets(policy, targets, attach: false)
316
+ if @deploy and !policy.match(/^#{@deploy.deploy_id}/)
295
317
  policy = @mu_name+"-"+policy.upcase
296
318
  end
297
319
  my_policies = cloud_desc(use_cache: false)["policies"]
@@ -301,19 +323,19 @@ end
301
323
  my_policies.each { |p|
302
324
  if p.policy_name == policy
303
325
  seen_policy = true
304
- old = MU::Cloud::AWS.iam(credentials: @config['credentials']).get_policy_version(
326
+ old = MU::Cloud::AWS.iam(credentials: @credentials).get_policy_version(
305
327
  policy_arn: p.arn,
306
328
  version_id: p.default_version_id
307
329
  ).policy_version
308
330
 
309
- doc = JSON.parse URI.decode_www_form_component old.document
331
+ doc = JSON.parse CGI.unescape_www_form_component old.document
310
332
  need_update = false
311
333
 
312
334
  doc["Statement"].each { |s|
313
335
  targets.each { |target|
314
336
  target_string = target
315
337
 
316
- if target['type']
338
+ if target['type'] and @deploy
317
339
  sibling = @deploy.findLitterMate(
318
340
  name: target["identifier"],
319
341
  type: target["type"]
@@ -419,14 +441,14 @@ end
419
441
  # @param noop [Boolean]: If true, will only print what would be done
420
442
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
421
443
  # @return [void]
422
- def self.cleanup(noop: false, ignoremaster: false, credentials: nil, flags: {})
444
+ def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, credentials: nil, flags: {})
423
445
 
424
446
  resp = MU::Cloud::AWS.iam(credentials: credentials).list_policies(
425
- path_prefix: "/"+MU.deploy_id+"/"
447
+ path_prefix: "/"+deploy_id+"/"
426
448
  )
427
449
  if resp and resp.policies
428
450
  resp.policies.each { |policy|
429
- MU.log "Deleting IAM policy /#{MU.deploy_id}/#{policy.policy_name}"
451
+ MU.log "Deleting IAM policy /#{deploy_id}/#{policy.policy_name}"
430
452
  if !noop
431
453
  purgePolicy(policy.arn, credentials)
432
454
  end
@@ -437,19 +459,23 @@ end
437
459
  roles = MU::Cloud::AWS::Role.find(credentials: credentials).values
438
460
  roles.each { |r|
439
461
  next if !r.respond_to?(:role_name)
440
- if r.path.match(/^\/#{Regexp.quote(MU.deploy_id)}/)
462
+ if r.path.match(/^\/#{Regexp.quote(deploy_id)}/)
441
463
  deleteme << r
442
464
  next
443
465
  end
444
466
  # For some dumb reason, the list output that .find gets doesn't
445
467
  # include the tags, so we need to fetch each role individually to
446
468
  # check tags. Hardly seems efficient.
447
- desc = MU::Cloud::AWS.iam(credentials: credentials).get_role(role_name: r.role_name)
469
+ desc = begin
470
+ MU::Cloud::AWS.iam(credentials: credentials).get_role(role_name: r.role_name)
471
+ rescue Aws::IAM::Errors::NoSuchEntity
472
+ next
473
+ end
448
474
  if desc.role and desc.role.tags and desc.role.tags
449
475
  master_match = false
450
476
  deploy_match = false
451
477
  desc.role.tags.each { |t|
452
- if t.key == "MU-ID" and t.value == MU.deploy_id
478
+ if t.key == "MU-ID" and t.value == deploy_id
453
479
  deploy_match = true
454
480
  elsif t.key == "MU-MASTER-IP" and t.value == MU.mu_public_ip
455
481
  master_match = true
@@ -516,7 +542,7 @@ end
516
542
 
517
543
  begin
518
544
  # managed policies get fetched by ARN, roles by plain name. Ok!
519
- if args[:cloud_id].match(/^arn:/)
545
+ if args[:cloud_id].match(/^arn:.*?:policy\//)
520
546
  resp = MU::Cloud::AWS.iam(credentials: args[:credentials]).get_policy(
521
547
  policy_arn: args[:cloud_id]
522
548
  )
@@ -525,39 +551,26 @@ end
525
551
  end
526
552
  else
527
553
  resp = MU::Cloud::AWS.iam(credentials: args[:credentials]).get_role(
528
- role_name: args[:cloud_id]
554
+ role_name: args[:cloud_id].sub(/^arn:.*?\/([^:\/]+)$/, '\1') # XXX if it's an ARN, actually parse it and look in the correct account when applicable
529
555
  )
556
+
530
557
  if resp and resp.role
531
- found[args[:cloud_id]] = resp.role
558
+ found[resp.role.role_name] = resp.role
532
559
  end
533
560
  end
534
561
  rescue ::Aws::IAM::Errors::NoSuchEntity
535
562
  end
536
563
 
537
564
  else
538
- marker = nil
539
- begin
540
- resp = MU::Cloud::AWS.iam(credentials: args[:credentials]).list_roles(
541
- marker: marker
542
- )
543
- break if !resp or !resp.roles
544
- resp.roles.each { |role|
545
- found[role.role_name] = role
546
- }
547
- marker = resp.marker
548
- end while marker
565
+ resp = MU::Cloud::AWS.iam(credentials: args[:credentials]).list_roles
566
+ resp.roles.each { |role|
567
+ found[role.role_name] = role
568
+ }
549
569
 
550
- begin
551
- resp = MU::Cloud::AWS.iam(credentials: args[:credentials]).list_policies(
552
- scope: "Local",
553
- marker: marker
554
- )
555
- break if !resp or !resp.policies
556
- resp.policies.each { |pol|
557
- found[pol.arn] = pol
558
- }
559
- marker = resp.marker
560
- end while marker
570
+ resp = MU::Cloud::AWS.iam(credentials: args[:credentials]).list_policies(scope: "Local")
571
+ resp.policies.each { |pol|
572
+ found[pol.arn] = pol
573
+ }
561
574
  end
562
575
 
563
576
  found
@@ -569,7 +582,7 @@ end
569
582
  def toKitten(**_args)
570
583
  bok = {
571
584
  "cloud" => "AWS",
572
- "credentials" => @config['credentials'],
585
+ "credentials" => @credentials,
573
586
  "cloud_id" => @cloud_id
574
587
  }
575
588
 
@@ -603,7 +616,7 @@ end
603
616
  policy_name: pol.policy_name
604
617
  )
605
618
  if resp and resp.policy_document
606
- JSON.parse(URI.decode(resp.policy_document))
619
+ JSON.parse(CGI.unescape(resp.policy_document))
607
620
  end
608
621
  rescue ::Aws::IAM::Errors::NoSuchEntity, ::Aws::IAM::Errors::ValidationError
609
622
  resp = MU::Cloud::AWS.iam(credentials: @credentials).get_policy(
@@ -613,7 +626,7 @@ end
613
626
  policy_arn: pol.arn,
614
627
  version_id: resp.policy.default_version_id
615
628
  )
616
- JSON.parse(URI.decode(version.policy_version.document))
629
+ JSON.parse(CGI.unescape(version.policy_version.document))
617
630
  end
618
631
  bok["policies"] = MU::Cloud::AWS::Role.doc2MuPolicies(pol.policy_name, doc, bok["policies"])
619
632
  end
@@ -629,7 +642,7 @@ end
629
642
  bok["strip_path"] = true if desc.path == "/"
630
643
 
631
644
  if desc.assume_role_policy_document
632
- assume_doc = JSON.parse(URI.decode(desc.assume_role_policy_document))
645
+ assume_doc = JSON.parse(CGI.unescape(desc.assume_role_policy_document))
633
646
  assume_doc["Statement"].each { |s|
634
647
  bok["can_assume"] ||= []
635
648
  method = if s["Action"] == "sts:AssumeRoleWithWebIdentity"
@@ -762,12 +775,12 @@ end
762
775
  def bindTo(entitytype, entityname)
763
776
  if entitytype == "instance_profile"
764
777
  begin
765
- resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).get_instance_profile(
778
+ resp = MU::Cloud::AWS.iam(credentials: @credentials).get_instance_profile(
766
779
  instance_profile_name: entityname
767
780
  ).instance_profile
768
781
 
769
782
  if !resp.roles.map { |r| r.role_name}.include?(@mu_name)
770
- MU::Cloud::AWS.iam(credentials: @config['credentials']).add_role_to_instance_profile(
783
+ MU::Cloud::AWS.iam(credentials: @credentials).add_role_to_instance_profile(
771
784
  instance_profile_name: entityname,
772
785
  role_name: @mu_name
773
786
  )
@@ -777,30 +790,30 @@ end
777
790
  raise e
778
791
  end
779
792
  elsif ["user", "group", "role"].include?(entitytype)
780
- mypolicies = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_policies(
793
+ mypolicies = MU::Cloud::AWS.iam(credentials: @credentials).list_policies(
781
794
  path_prefix: "/"+@deploy.deploy_id+"/"
782
795
  ).policies
783
796
  mypolicies.reject! { |p|
784
- !p.policy_name.match(/^#{Regexp.quote(@mu_name)}-/)
797
+ !p.policy_name.match(/^#{Regexp.quote(@mu_name)}(-|$)/)
785
798
  }
786
799
 
787
800
  if @config['attachable_policies']
788
801
  @config['attachable_policies'].each { |policy_hash|
789
802
  policy = policy_hash["id"]
790
803
  p_arn = if !policy.match(/^arn:/i)
791
- "arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":iam::aws:policy/"+policy
804
+ "arn:"+(MU::Cloud::AWS.isGovCloud?(@region) ? "aws-us-gov" : "aws")+":iam::aws:policy/"+policy
792
805
  else
793
806
  policy
794
807
  end
795
808
 
796
809
  subpaths = ["service-role", "aws-service-role", "job-function"]
797
810
  begin
798
- mypolicies << MU::Cloud::AWS.iam(credentials: @config['credentials']).get_policy(
811
+ mypolicies << MU::Cloud::AWS.iam(credentials: @credentials).get_policy(
799
812
  policy_arn: p_arn
800
813
  ).policy
801
814
  rescue Aws::IAM::Errors::NoSuchEntity => e
802
815
  if subpaths.size > 0
803
- p_arn = "arn:"+(MU::Cloud::AWS.isGovCloud?(@config["region"]) ? "aws-us-gov" : "aws")+":iam::aws:policy/#{subpaths.shift}/"+policy
816
+ p_arn = "arn:"+(MU::Cloud::AWS.isGovCloud?(@region) ? "aws-us-gov" : "aws")+":iam::aws:policy/#{subpaths.shift}/"+policy
804
817
  retry
805
818
  end
806
819
  raise e
@@ -808,39 +821,52 @@ end
808
821
  }
809
822
  end
810
823
 
824
+ if @config['raw_policies']
825
+ raw_arns = MU::Cloud::AWS::Role.manageRawPolicies(
826
+ @config['raw_policies'],
827
+ basename: @deploy.getResourceName(@config['name']),
828
+ credentials: @credentials
829
+ )
830
+ raw_arns.each { |p_arn|
831
+ mypolicies << MU::Cloud::AWS.iam(credentials: @credentials).get_policy(
832
+ policy_arn: p_arn
833
+ ).policy
834
+ }
835
+ end
836
+
811
837
  mypolicies.each { |p|
812
838
  if entitytype == "user"
813
- resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_attached_user_policies(
839
+ resp = MU::Cloud::AWS.iam(credentials: @credentials).list_attached_user_policies(
814
840
  path_prefix: "/"+@deploy.deploy_id+"/",
815
841
  user_name: entityname
816
842
  )
817
843
  if !resp or !resp.attached_policies.map { |a_p| a_p.policy_name }.include?(p.policy_name)
818
844
  MU.log "Attaching IAM policy #{p.policy_name} to user #{entityname}", MU::NOTICE
819
- MU::Cloud::AWS.iam(credentials: @config['credentials']).attach_user_policy(
845
+ MU::Cloud::AWS.iam(credentials: @credentials).attach_user_policy(
820
846
  policy_arn: p.arn,
821
847
  user_name: entityname
822
848
  )
823
849
  end
824
850
  elsif entitytype == "group"
825
- resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_attached_group_policies(
851
+ resp = MU::Cloud::AWS.iam(credentials: @credentials).list_attached_group_policies(
826
852
  path_prefix: "/"+@deploy.deploy_id+"/",
827
853
  group_name: entityname
828
854
  )
829
855
  if !resp or !resp.attached_policies.map { |a_p| a_p.policy_name }.include?(p.policy_name)
830
856
  MU.log "Attaching policy #{p.policy_name} to group #{entityname}", MU::NOTICE
831
- MU::Cloud::AWS.iam(credentials: @config['credentials']).attach_group_policy(
857
+ MU::Cloud::AWS.iam(credentials: @credentials).attach_group_policy(
832
858
  policy_arn: p.arn,
833
859
  group_name: entityname
834
860
  )
835
861
  end
836
862
  elsif entitytype == "role"
837
- resp = MU::Cloud::AWS.iam(credentials: @config['credentials']).list_attached_role_policies(
863
+ resp = MU::Cloud::AWS.iam(credentials: @credentials).list_attached_role_policies(
838
864
  role_name: entityname
839
865
  )
840
866
 
841
867
  if !resp or !resp.attached_policies.map { |a_p| a_p.policy_name }.include?(p.policy_name)
842
868
  MU.log "Attaching policy #{p.policy_name} to role #{entityname}", MU::NOTICE
843
- MU::Cloud::AWS.iam(credentials: @config['credentials']).attach_role_policy(
869
+ MU::Cloud::AWS.iam(credentials: @credentials).attach_role_policy(
844
870
  policy_arn: p.arn,
845
871
  role_name: entityname
846
872
  )
@@ -861,19 +887,19 @@ end
861
887
  end
862
888
 
863
889
  resp = begin
864
- MU.log "Creating instance profile #{@mu_name} #{@config['credentials']}"
865
- MU::Cloud::AWS.iam(credentials: @config['credentials']).create_instance_profile(
890
+ MU.log "Creating instance profile #{@mu_name} #{@credentials}"
891
+ MU::Cloud::AWS.iam(credentials: @credentials).create_instance_profile(
866
892
  instance_profile_name: @mu_name
867
893
  )
868
894
  rescue Aws::IAM::Errors::EntityAlreadyExists
869
- MU::Cloud::AWS.iam(credentials: @config['credentials']).get_instance_profile(
895
+ MU::Cloud::AWS.iam(credentials: @credentials).get_instance_profile(
870
896
  instance_profile_name: @mu_name
871
897
  )
872
898
  end
873
899
 
874
900
  # make sure it's really there before moving on
875
901
  begin
876
- MU::Cloud::AWS.iam(credentials: @config['credentials']).get_instance_profile(instance_profile_name: @mu_name)
902
+ MU::Cloud::AWS.iam(credentials: @credentials).get_instance_profile(instance_profile_name: @mu_name)
877
903
  rescue Aws::IAM::Errors::NoSuchEntity => e
878
904
  MU.log e.inspect, MU::WARN
879
905
  sleep 10
@@ -1061,6 +1087,8 @@ end
1061
1087
  role.delete("import")
1062
1088
  end
1063
1089
 
1090
+ role['strip_path'] = true if role['scrub_mu_isms']
1091
+
1064
1092
  # If we're attaching some managed policies, make sure all of the ones
1065
1093
  # that should already exist do indeed exist
1066
1094
  if role['attachable_policies']
@@ -1091,7 +1119,7 @@ end
1091
1119
  role['policies'].each { |policy|
1092
1120
  policy['targets'].each { |target|
1093
1121
  if target['type']
1094
- MU::Config.addDependency(role, target['identifier'], target['type'])
1122
+ MU::Config.addDependency(role, target['identifier'], target['type'], my_phase: "groom")
1095
1123
  end
1096
1124
  }
1097
1125
  }
@@ -1107,13 +1135,14 @@ end
1107
1135
  # @param policies [Array<Hash>]: One or more policy chunks
1108
1136
  # @param deploy_obj [MU::MommaCat]: Deployment object to use when looking up sibling Mu resources
1109
1137
  # @return [Array<Hash>]
1110
- def self.genPolicyDocument(policies, deploy_obj: nil, bucket_style: false)
1138
+ def self.genPolicyDocument(policies, deploy_obj: nil, bucket_style: false, version: "2012-10-17", doc_id: nil)
1111
1139
  if policies
1112
1140
  name = nil
1113
1141
  doc = {
1114
- "Version" => "2012-10-17",
1142
+ "Version" => version,
1115
1143
  "Statement" => []
1116
1144
  }
1145
+ doc["Id"] = doc_id if doc_id
1117
1146
  policies.each { |policy|
1118
1147
  policy["flag"] ||= "Allow"
1119
1148
  statement = {
@@ -1154,7 +1183,14 @@ end
1154
1183
  raise MuError, "Couldn't find a #{grantee["type"]} named #{grantee["identifier"]} when generating IAM policy"
1155
1184
  end
1156
1185
  else
1157
- bucket_prefix = grantee["identifier"].match(/^[^\.]+\.amazonaws\.com$/) ? "Service" : "AWS"
1186
+ bucket_prefix = if grantee["identifier"].match(/^[^\.]+\.amazonaws\.com$/)
1187
+ "Service"
1188
+ elsif grantee["identifier"] =~ /^[a-f0-9]+$/
1189
+ "CanonicalUser"
1190
+ else
1191
+ "AWS"
1192
+ end
1193
+
1158
1194
  if bucket_style
1159
1195
  statement["Principal"] << { bucket_prefix => grantee["identifier"] }
1160
1196
  else