cloud-mu 3.1.4 → 3.3.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.
Files changed (203) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +5 -1
  3. data/ansible/roles/mu-windows/README.md +33 -0
  4. data/ansible/roles/mu-windows/defaults/main.yml +2 -0
  5. data/ansible/roles/mu-windows/files/LaunchConfig.json +9 -0
  6. data/ansible/roles/mu-windows/files/config.xml +76 -0
  7. data/ansible/roles/mu-windows/handlers/main.yml +2 -0
  8. data/ansible/roles/mu-windows/meta/main.yml +53 -0
  9. data/ansible/roles/mu-windows/tasks/main.yml +36 -0
  10. data/ansible/roles/mu-windows/tests/inventory +2 -0
  11. data/ansible/roles/mu-windows/tests/test.yml +5 -0
  12. data/ansible/roles/mu-windows/vars/main.yml +2 -0
  13. data/bin/mu-adopt +16 -12
  14. data/bin/mu-azure-tests +57 -0
  15. data/bin/mu-cleanup +2 -4
  16. data/bin/mu-configure +52 -0
  17. data/bin/mu-deploy +3 -3
  18. data/bin/mu-findstray-tests +25 -0
  19. data/bin/mu-gen-docs +2 -4
  20. data/bin/mu-load-config.rb +2 -1
  21. data/bin/mu-node-manage +15 -16
  22. data/bin/mu-run-tests +37 -12
  23. data/cloud-mu.gemspec +5 -3
  24. data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
  25. data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
  26. data/cookbooks/mu-tools/libraries/helper.rb +1 -1
  27. data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
  28. data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
  29. data/cookbooks/mu-tools/recipes/eks.rb +2 -2
  30. data/cookbooks/mu-tools/recipes/selinux.rb +2 -1
  31. data/cookbooks/mu-tools/recipes/windows-client.rb +163 -164
  32. data/cookbooks/mu-tools/resources/windows_users.rb +44 -43
  33. data/extras/clean-stock-amis +25 -19
  34. data/extras/generate-stock-images +1 -0
  35. data/extras/image-generators/AWS/win2k12.yaml +18 -13
  36. data/extras/image-generators/AWS/win2k16.yaml +18 -13
  37. data/extras/image-generators/AWS/win2k19.yaml +21 -0
  38. data/modules/mommacat.ru +1 -1
  39. data/modules/mu.rb +158 -107
  40. data/modules/mu/adoption.rb +386 -59
  41. data/modules/mu/cleanup.rb +214 -303
  42. data/modules/mu/cloud.rb +128 -1632
  43. data/modules/mu/cloud/database.rb +49 -0
  44. data/modules/mu/cloud/dnszone.rb +44 -0
  45. data/modules/mu/cloud/machine_images.rb +212 -0
  46. data/modules/mu/cloud/providers.rb +81 -0
  47. data/modules/mu/cloud/resource_base.rb +926 -0
  48. data/modules/mu/cloud/server.rb +40 -0
  49. data/modules/mu/cloud/server_pool.rb +1 -0
  50. data/modules/mu/cloud/ssh_sessions.rb +228 -0
  51. data/modules/mu/cloud/winrm_sessions.rb +237 -0
  52. data/modules/mu/cloud/wrappers.rb +169 -0
  53. data/modules/mu/config.rb +135 -82
  54. data/modules/mu/config/alarm.rb +2 -6
  55. data/modules/mu/config/bucket.rb +32 -3
  56. data/modules/mu/config/cache_cluster.rb +2 -2
  57. data/modules/mu/config/cdn.rb +100 -0
  58. data/modules/mu/config/collection.rb +1 -1
  59. data/modules/mu/config/container_cluster.rb +7 -2
  60. data/modules/mu/config/database.rb +84 -105
  61. data/modules/mu/config/database.yml +1 -2
  62. data/modules/mu/config/dnszone.rb +5 -4
  63. data/modules/mu/config/doc_helpers.rb +5 -6
  64. data/modules/mu/config/endpoint.rb +2 -1
  65. data/modules/mu/config/firewall_rule.rb +3 -19
  66. data/modules/mu/config/folder.rb +1 -1
  67. data/modules/mu/config/function.rb +17 -8
  68. data/modules/mu/config/group.rb +1 -1
  69. data/modules/mu/config/habitat.rb +1 -1
  70. data/modules/mu/config/job.rb +89 -0
  71. data/modules/mu/config/loadbalancer.rb +57 -11
  72. data/modules/mu/config/log.rb +1 -1
  73. data/modules/mu/config/msg_queue.rb +1 -1
  74. data/modules/mu/config/nosqldb.rb +1 -1
  75. data/modules/mu/config/notifier.rb +8 -19
  76. data/modules/mu/config/ref.rb +92 -14
  77. data/modules/mu/config/role.rb +1 -1
  78. data/modules/mu/config/schema_helpers.rb +38 -37
  79. data/modules/mu/config/search_domain.rb +1 -1
  80. data/modules/mu/config/server.rb +12 -13
  81. data/modules/mu/config/server.yml +1 -0
  82. data/modules/mu/config/server_pool.rb +3 -7
  83. data/modules/mu/config/storage_pool.rb +1 -1
  84. data/modules/mu/config/tail.rb +11 -0
  85. data/modules/mu/config/user.rb +1 -1
  86. data/modules/mu/config/vpc.rb +27 -23
  87. data/modules/mu/config/vpc.yml +0 -1
  88. data/modules/mu/defaults/AWS.yaml +91 -68
  89. data/modules/mu/defaults/Azure.yaml +1 -0
  90. data/modules/mu/defaults/Google.yaml +1 -0
  91. data/modules/mu/deploy.rb +33 -19
  92. data/modules/mu/groomer.rb +16 -1
  93. data/modules/mu/groomers/ansible.rb +123 -21
  94. data/modules/mu/groomers/chef.rb +64 -11
  95. data/modules/mu/logger.rb +120 -144
  96. data/modules/mu/master.rb +97 -4
  97. data/modules/mu/master/ssl.rb +0 -1
  98. data/modules/mu/mommacat.rb +154 -867
  99. data/modules/mu/mommacat/daemon.rb +23 -14
  100. data/modules/mu/mommacat/naming.rb +110 -3
  101. data/modules/mu/mommacat/search.rb +495 -0
  102. data/modules/mu/mommacat/storage.rb +225 -192
  103. data/modules/mu/{clouds → providers}/README.md +1 -1
  104. data/modules/mu/{clouds → providers}/aws.rb +281 -64
  105. data/modules/mu/{clouds → providers}/aws/alarm.rb +3 -3
  106. data/modules/mu/{clouds → providers}/aws/bucket.rb +275 -41
  107. data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +14 -50
  108. data/modules/mu/providers/aws/cdn.rb +782 -0
  109. data/modules/mu/{clouds → providers}/aws/collection.rb +5 -5
  110. data/modules/mu/{clouds → providers}/aws/container_cluster.rb +708 -749
  111. data/modules/mu/providers/aws/database.rb +1744 -0
  112. data/modules/mu/{clouds → providers}/aws/dnszone.rb +75 -57
  113. data/modules/mu/providers/aws/endpoint.rb +1072 -0
  114. data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +212 -242
  115. data/modules/mu/{clouds → providers}/aws/folder.rb +1 -1
  116. data/modules/mu/{clouds → providers}/aws/function.rb +289 -134
  117. data/modules/mu/{clouds → providers}/aws/group.rb +18 -20
  118. data/modules/mu/{clouds → providers}/aws/habitat.rb +3 -3
  119. data/modules/mu/providers/aws/job.rb +466 -0
  120. data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +50 -41
  121. data/modules/mu/{clouds → providers}/aws/log.rb +5 -5
  122. data/modules/mu/{clouds → providers}/aws/msg_queue.rb +14 -11
  123. data/modules/mu/{clouds → providers}/aws/nosqldb.rb +96 -5
  124. data/modules/mu/{clouds → providers}/aws/notifier.rb +135 -63
  125. data/modules/mu/{clouds → providers}/aws/role.rb +94 -57
  126. data/modules/mu/{clouds → providers}/aws/search_domain.rb +173 -42
  127. data/modules/mu/{clouds → providers}/aws/server.rb +782 -1107
  128. data/modules/mu/{clouds → providers}/aws/server_pool.rb +36 -46
  129. data/modules/mu/{clouds → providers}/aws/storage_pool.rb +21 -38
  130. data/modules/mu/{clouds → providers}/aws/user.rb +12 -16
  131. data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
  132. data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +5 -4
  133. data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +2 -1
  134. data/modules/mu/{clouds → providers}/aws/vpc.rb +429 -849
  135. data/modules/mu/providers/aws/vpc_subnet.rb +286 -0
  136. data/modules/mu/{clouds → providers}/azure.rb +13 -0
  137. data/modules/mu/{clouds → providers}/azure/container_cluster.rb +1 -5
  138. data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +8 -1
  139. data/modules/mu/{clouds → providers}/azure/habitat.rb +0 -0
  140. data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +0 -0
  141. data/modules/mu/{clouds → providers}/azure/role.rb +0 -0
  142. data/modules/mu/{clouds → providers}/azure/server.rb +32 -24
  143. data/modules/mu/{clouds → providers}/azure/user.rb +1 -1
  144. data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
  145. data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
  146. data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
  147. data/modules/mu/{clouds → providers}/azure/vpc.rb +4 -6
  148. data/modules/mu/{clouds → providers}/cloudformation.rb +10 -0
  149. data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
  150. data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
  151. data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
  152. data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
  153. data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
  154. data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
  155. data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
  156. data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
  157. data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
  158. data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
  159. data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +3 -3
  160. data/modules/mu/{clouds → providers}/docker.rb +0 -0
  161. data/modules/mu/{clouds → providers}/google.rb +29 -6
  162. data/modules/mu/{clouds → providers}/google/bucket.rb +5 -5
  163. data/modules/mu/{clouds → providers}/google/container_cluster.rb +59 -37
  164. data/modules/mu/{clouds → providers}/google/database.rb +5 -12
  165. data/modules/mu/{clouds → providers}/google/firewall_rule.rb +5 -5
  166. data/modules/mu/{clouds → providers}/google/folder.rb +5 -9
  167. data/modules/mu/{clouds → providers}/google/function.rb +14 -8
  168. data/modules/mu/{clouds → providers}/google/group.rb +9 -17
  169. data/modules/mu/{clouds → providers}/google/habitat.rb +4 -8
  170. data/modules/mu/{clouds → providers}/google/loadbalancer.rb +5 -5
  171. data/modules/mu/{clouds → providers}/google/role.rb +50 -31
  172. data/modules/mu/{clouds → providers}/google/server.rb +142 -55
  173. data/modules/mu/{clouds → providers}/google/server_pool.rb +14 -14
  174. data/modules/mu/{clouds → providers}/google/user.rb +34 -24
  175. data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
  176. data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
  177. data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
  178. data/modules/mu/{clouds → providers}/google/vpc.rb +46 -15
  179. data/modules/tests/aws-jobs-functions.yaml +46 -0
  180. data/modules/tests/centos6.yaml +15 -0
  181. data/modules/tests/centos7.yaml +15 -0
  182. data/modules/tests/centos8.yaml +12 -0
  183. data/modules/tests/ecs.yaml +23 -0
  184. data/modules/tests/eks.yaml +1 -1
  185. data/modules/tests/functions/node-function/lambda_function.js +10 -0
  186. data/modules/tests/functions/python-function/lambda_function.py +12 -0
  187. data/modules/tests/includes-and-params.yaml +2 -1
  188. data/modules/tests/microservice_app.yaml +288 -0
  189. data/modules/tests/rds.yaml +108 -0
  190. data/modules/tests/regrooms/rds.yaml +123 -0
  191. data/modules/tests/server-with-scrub-muisms.yaml +2 -1
  192. data/modules/tests/super_complex_bok.yml +2 -2
  193. data/modules/tests/super_simple_bok.yml +3 -5
  194. data/modules/tests/win2k12.yaml +25 -0
  195. data/modules/tests/win2k16.yaml +25 -0
  196. data/modules/tests/win2k19.yaml +25 -0
  197. data/requirements.txt +1 -0
  198. data/spec/mu/clouds/azure_spec.rb +2 -2
  199. metadata +169 -93
  200. data/extras/image-generators/AWS/windows.yaml +0 -18
  201. data/modules/mu/clouds/aws/database.rb +0 -1974
  202. data/modules/mu/clouds/aws/endpoint.rb +0 -596
  203. data/modules/tests/needwork/win2k12.yaml +0 -13
@@ -18,7 +18,7 @@ module MU
18
18
  class AWS
19
19
  # A firewall ruleset as configured in {MU::Config::BasketofKittens::firewall_rules}
20
20
  class FirewallRule < MU::Cloud::FirewallRule
21
- require "mu/clouds/aws/vpc"
21
+ require "mu/providers/aws/vpc"
22
22
 
23
23
  @admin_sgs = Hash.new
24
24
  @admin_sg_semaphore = Mutex.new
@@ -381,24 +381,24 @@ module MU
381
381
  # @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
382
382
  # @param region [String]: The cloud provider region
383
383
  # @return [void]
384
- def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
385
- filters = nil
386
- if flags and flags["vpc_id"]
387
- filters = [
384
+ def self.cleanup(noop: false, deploy_id: MU.deploy_id, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
385
+ filters = if flags and flags["vpc_id"]
386
+ [
388
387
  {name: "vpc-id", values: [flags["vpc_id"]]}
389
388
  ]
390
389
  else
391
390
  filters = [
392
- {name: "tag:MU-ID", values: [MU.deploy_id]}
391
+ {name: "tag:MU-ID", values: [deploy_id]}
393
392
  ]
394
393
  if !ignoremaster
395
394
  filters << {name: "tag:MU-MASTER-IP", values: [MU.mu_public_ip]}
396
395
  end
396
+ filters
397
397
  end
398
398
 
399
399
  # Some services create sneaky rogue ENIs which then block removal of
400
400
  # associated security groups. Find them and fry them.
401
- MU::Cloud::AWS::VPC.purge_interfaces(noop, filters, region: region, credentials: credentials)
401
+ MU::Cloud.resourceClass("AWS", "VPC").purge_interfaces(noop, filters, region: region, credentials: credentials)
402
402
 
403
403
  resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_security_groups(
404
404
  filters: filters
@@ -408,134 +408,134 @@ module MU
408
408
  MU.log "Revoking rules in EC2 Security Group #{sg.group_name} (#{sg.group_id})"
409
409
 
410
410
  if !noop
411
- ingress_to_revoke = Array.new
412
- egress_to_revoke = Array.new
413
- sg.ip_permissions.each { |hole|
414
- ingress_to_revoke << MU.structToHash(hole)
415
- ingress_to_revoke.each { |rule|
416
- if !rule[:user_id_group_pairs].nil? and rule[:user_id_group_pairs] .size == 0
417
- rule.delete(:user_id_group_pairs)
418
- elsif !rule[:user_id_group_pairs].nil?
419
- rule[:user_id_group_pairs].each { |group_ref|
420
- group_ref = MU.structToHash(group_ref)
421
- group_ref.delete(:group_name) if group_ref[:group_id]
422
- }
423
- end
411
+ revoke_rules(sg, region: region, credentials: credentials)
412
+ revoke_rules(sg, egress: true, region: region, credentials: credentials)
413
+ end
414
+ }
424
415
 
425
- if !rule[:ip_ranges].nil? and rule[:ip_ranges].size == 0
426
- rule.delete(:ip_ranges)
427
- end
416
+ resp.data.security_groups.each { |sg|
417
+ next if sg.group_name == "default"
418
+ MU.log "Removing EC2 Security Group #{sg.group_name}"
428
419
 
429
- if !rule[:prefix_list_ids].nil? and rule[:prefix_list_ids].size == 0
430
- rule.delete(:prefix_list_ids)
431
- end
432
-
433
- if !rule[:ipv_6_ranges].nil? and rule[:ipv_6_ranges].size == 0
434
- rule.delete(:ipv_6_ranges)
435
- end
436
- }
437
- }
438
- sg.ip_permissions_egress.each { |hole|
439
- egress_to_revoke << MU.structToHash(hole)
440
- egress_to_revoke.each { |rule|
441
- if !rule[:user_id_group_pairs].nil? and rule[:user_id_group_pairs].size == 0
442
- rule.delete(:user_id_group_pairs)
443
- elsif !rule[:user_id_group_pairs].nil?
444
- rule[:user_id_group_pairs].each { |group_ref|
445
- group_ref = MU.structToHash(group_ref)
446
- group_ref.delete(:group_name) if group_ref[:group_id]
420
+ on_retry = Proc.new {
421
+ # try to get out from under loose network interfaces with which
422
+ # we're associated
423
+ if sg.vpc_id
424
+ default_sg = MU::Cloud.resourceClass("AWS", "VPC").getDefaultSg(sg.vpc_id, region: region, credentials: credentials)
425
+ if default_sg
426
+ eni_resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_network_interfaces(
427
+ filters: [ {name: "group-id", values: [sg.group_id]} ]
428
+ )
429
+ if eni_resp and eni_resp.data and
430
+ eni_resp.data.network_interfaces
431
+ eni_resp.data.network_interfaces.each { |iface|
432
+ iface_groups = iface.groups.map { |if_sg| if_sg.group_id }
433
+ iface_groups.delete(sg.group_id)
434
+ iface_groups << default_sg if iface_groups.empty?
435
+ MU.log "Attempting to remove #{sg.group_id} (#{sg.group_name}) from ENI #{iface.network_interface_id}"
436
+ begin
437
+ MU::Cloud::AWS.ec2(credentials: credentials, region: region).modify_network_interface_attribute(
438
+ network_interface_id: iface.network_interface_id,
439
+ groups: iface_groups
440
+ )
441
+ rescue ::Aws::EC2::Errors::InvalidNetworkInterfaceIDNotFound
442
+ # fine by me
443
+ rescue ::Aws::EC2::Errors::AuthFailure
444
+ MU.log "Permission denied attempting to trim Security Group list for #{iface.network_interface_id}", MU::WARN, details: iface.groups.map { |g| g.group_name }.join(",")+" => default"
445
+ end
447
446
  }
448
447
  end
448
+ end
449
+ end
450
+ }
449
451
 
450
- if !rule[:ip_ranges].nil? and rule[:ip_ranges].size == 0
451
- rule.delete(:ip_ranges)
452
- end
452
+ if !noop
453
+ MU.retrier([Aws::EC2::Errors::DependencyViolation, Aws::EC2::Errors::InvalidGroupInUse], ignoreme: [Aws::EC2::Errors::InvalidGroupNotFound], max: 10, wait: 10, on_retry: on_retry) {
454
+ begin
455
+ MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_security_group(group_id: sg.group_id)
456
+ rescue Aws::EC2::Errors::CannotDelete => e
457
+ MU.log e.message, MU::WARN
458
+ end
459
+ }
460
+ end
453
461
 
454
- if !rule[:prefix_list_ids].nil? and rule[:prefix_list_ids].size == 0
455
- rule.delete(:prefix_list_ids)
456
- end
462
+ }
463
+ end
457
464
 
458
- if !rule[:ipv_6_ranges].nil? and rule[:ipv_6_ranges].size == 0
459
- rule.delete(:ipv_6_ranges)
460
- end
465
+ def self.revoke_rules(sg, egress: false, region: MU.myregion, credentials: nil)
466
+ holes = sg.send(egress ? :ip_permissions_egress : :ip_permissions)
467
+
468
+ to_revoke = []
469
+
470
+ holes.each { |hole|
471
+ to_revoke << MU.structToHash(hole)
472
+ to_revoke.each { |rule|
473
+ if !rule[:user_id_group_pairs].nil? and rule[:user_id_group_pairs].size == 0
474
+ rule.delete(:user_id_group_pairs)
475
+ elsif !rule[:user_id_group_pairs].nil?
476
+ rule[:user_id_group_pairs].each { |group_ref|
477
+ group_ref = MU.structToHash(group_ref)
478
+ group_ref.delete(:group_name) if group_ref[:group_id]
461
479
  }
462
- }
463
- begin
480
+ end
464
481
 
465
- if ingress_to_revoke.size > 0
466
- MU::Cloud::AWS.ec2(credentials: credentials, region: region).revoke_security_group_ingress(
467
- group_id: sg.group_id,
468
- ip_permissions: ingress_to_revoke
469
- )
470
- end
471
- if egress_to_revoke.size > 0
472
- MU::Cloud::AWS.ec2(credentials: credentials, region: region).revoke_security_group_egress(
473
- group_id: sg.group_id,
474
- ip_permissions: egress_to_revoke
475
- )
476
- end
477
- rescue Aws::EC2::Errors::InvalidPermissionNotFound
478
- MU.log "Rule in #{sg.group_id} disappeared before I could remove it", MU::WARN
482
+ if !rule[:ip_ranges].nil? and rule[:ip_ranges].size == 0
483
+ rule.delete(:ip_ranges)
479
484
  end
480
- end
481
- }
482
485
 
483
- resp.data.security_groups.each { |sg|
484
- next if sg.group_name == "default"
485
- MU.log "Removing EC2 Security Group #{sg.group_name}"
486
+ if !rule[:prefix_list_ids].nil? and rule[:prefix_list_ids].size == 0
487
+ rule.delete(:prefix_list_ids)
488
+ end
486
489
 
487
- retries = 0
488
- begin
489
- MU::Cloud::AWS.ec2(credentials: credentials, region: region).delete_security_group(group_id: sg.group_id) if !noop
490
- rescue Aws::EC2::Errors::CannotDelete => e
491
- MU.log e.message, MU::WARN
492
- rescue Aws::EC2::Errors::InvalidGroupNotFound
493
- MU.log "EC2 Security Group #{sg.group_name} disappeared before I could delete it!", MU::WARN
494
- rescue Aws::EC2::Errors::DependencyViolation, Aws::EC2::Errors::InvalidGroupInUse
495
- if retries < 10
496
- MU.log "EC2 Security Group #{sg.group_name} is still in use, waiting...", MU::NOTICE
497
- # try to get out from under loose network interfaces with which
498
- # we're associated
499
- if sg.vpc_id
500
- # get the default SG for this VPC
501
- default_resp = MU::Cloud::AWS.ec2(region: region, credentials: credentials).describe_security_groups(
502
- filters: [
503
- { name: "group-name", values: ["default"] },
504
- { name: "vpc-id", values: [sg.vpc_id] }
505
- ]
506
- ).security_groups
507
- if default_resp and default_resp.size == 1
508
- default_sg = default_resp.first.group_id
509
- eni_resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_network_interfaces(
510
- filters: [ {name: "group-id", values: [sg.group_id]} ]
511
- )
512
- if eni_resp and eni_resp.data and
513
- eni_resp.data.network_interfaces
514
- eni_resp.data.network_interfaces.each { |iface|
515
- iface_groups = iface.groups.map { |if_sg| if_sg.group_id }
516
- iface_groups.delete(sg.group_id)
517
- iface_groups << default_sg if iface_groups.empty?
518
- MU.log "Attempting to remove #{sg.group_id} (#{sg.group_name}) from ENI #{iface.network_interface_id}"
519
- begin
520
- MU::Cloud::AWS.ec2(credentials: credentials, region: region).modify_network_interface_attribute(
521
- network_interface_id: iface.network_interface_id,
522
- groups: iface_groups
523
- )
524
- rescue ::Aws::EC2::Errors::AuthFailure
525
- MU.log "Permission denied attempting to trim Security Group list for #{iface.network_interface_id}", MU::WARN, details: iface.groups.map { |g| g.group_name }.join(",")+" => default"
526
- end
527
- }
528
- end
529
- end
530
- end
490
+ if !rule[:ipv_6_ranges].nil? and rule[:ipv_6_ranges].size == 0
491
+ rule.delete(:ipv_6_ranges)
492
+ end
493
+ }
494
+ }
531
495
 
532
- sleep 10
533
- retries = retries + 1
534
- retry
496
+ if to_revoke.size > 0
497
+ begin
498
+ if egress
499
+ MU::Cloud::AWS.ec2(credentials: credentials, region: region).revoke_security_group_egress(
500
+ group_id: sg.group_id,
501
+ ip_permissions: to_revoke
502
+ )
535
503
  else
536
- MU.log "Failed to delete #{sg.group_name}", MU::ERR
504
+ MU::Cloud::AWS.ec2(credentials: credentials, region: region).revoke_security_group_ingress(
505
+ group_id: sg.group_id,
506
+ ip_permissions: to_revoke
507
+ )
537
508
  end
509
+ rescue Aws::EC2::Errors::InvalidPermissionNotFound
510
+ MU.log "Rule in #{sg.group_id} disappeared before I could remove it", MU::WARN
538
511
  end
512
+ end
513
+
514
+ end
515
+ private_class_method :revoke_rules
516
+
517
+ # Return an AWS-specific chunk of schema commonly used in the +ingress_rules+ parameter of other resource types.
518
+ # @return [Hash]
519
+ def self.ingressRuleAddtlSchema
520
+ {
521
+ "items" => {
522
+ "properties" => {
523
+ "sgs" => {
524
+ "type" => "array",
525
+ "items" => {
526
+ "description" => "Other AWS Security Groups; resources that are associated with this group will have this rule applied to their traffic",
527
+ "type" => "string"
528
+ }
529
+ },
530
+ "lbs" => {
531
+ "type" => "array",
532
+ "items" => {
533
+ "description" => "AWS Load Balancers which will have this rule applied to their traffic",
534
+ "type" => "string"
535
+ }
536
+ }
537
+ }
538
+ }
539
539
  }
540
540
  end
541
541
 
@@ -648,36 +648,16 @@ module MU
648
648
 
649
649
  if rule['firewall_rules']
650
650
  rule['firewall_rules'].each { |sg|
651
- if sg.is_a?(MU::Config::Ref) and sg.name
652
- acl["dependencies"] << {
653
- "type" => "firewall_rule",
654
- "name" => sg.name,
655
- "no_create_wait" => true
656
- }
657
- elsif sg['name'] and !sg['deploy_id']
658
- acl["dependencies"] << {
659
- "type" => "firewall_rule",
660
- "name" => sg['name'],
661
- "no_create_wait" => true
662
- }
651
+ if sg['name'] and !sg['deploy_id']
652
+ MU::Config.addDependency(acl, sg['name'], "firewall_rule", no_create_wait: true)
663
653
  end
664
654
  }
665
655
  end
666
656
 
667
657
  if rule['loadbalancers']
668
658
  rule['loadbalancers'].each { |lb|
669
- if lb.is_a?(MU::Config::Ref) and lb.name
670
- acl["dependencies"] << {
671
- "type" => "loadbalancer",
672
- "name" => lb.name,
673
- "phase" => "groom"
674
- }
675
- elsif lb['name'] and !lb['deploy_id']
676
- acl["dependencies"] << {
677
- "type" => "loadbalancer",
678
- "name" => lb['name'],
679
- "phase" => "groom"
680
- }
659
+ if lb['name'] and !lb['deploy_id']
660
+ MU::Config.addDependency(acl, lb['name'], "loadbalancer", phase: "groom")
681
661
  end
682
662
  }
683
663
  end
@@ -719,32 +699,7 @@ module MU
719
699
 
720
700
  private
721
701
 
722
- #########################################################################
723
- # Manufacture an EC2 security group. The second parameter, rules, is an
724
- # "ingress_rules" structure parsed and validated by MU::Config.
725
- #########################################################################
726
- def setRules(rules, add_to_self: false, ingress: true, egress: false)
727
- describe
728
- # XXX warn about attempt to set rules before we exist
729
- return if rules.nil? or rules.size == 0 or !@cloud_id
730
-
731
- # add_to_self means that this security is a "member" of its own rules
732
- # (which is to say, objects that have this SG are allowed in my these
733
- # rules)
734
- if add_to_self
735
- rules.each { |rule|
736
- if rule['sgs'].nil? or !rule['sgs'].include?(@cloud_id)
737
- new_rule = rule.clone
738
- new_rule.delete('hosts')
739
- rule['sgs'] = Array.new if rule['sgs'].nil?
740
- rule['sgs'] << @cloud_id
741
- end
742
- }
743
- end
744
-
745
- ec2_rules = convertToEc2(rules)
746
- ext_permissions = MU.structToHash(cloud_desc.ip_permissions)
747
-
702
+ def purge_extraneous_rules(ec2_rules, ext_permissions)
748
703
  # Purge any old rules that we're sure we created (check the comment)
749
704
  # but which are no longer configured.
750
705
  ext_permissions.each { |ext_rule|
@@ -781,97 +736,109 @@ module MU
781
736
  ip_permissions: [ext_rule]
782
737
  )
783
738
  end
784
-
785
739
  }
740
+ end
786
741
 
787
- # Creating an empty security group is ok, so don't freak out if we get
788
- # a null rule list.
789
- if !ec2_rules.nil?
790
- ec2_rules.uniq!
791
- retries = 0
792
- ec2_rules.each { |rule|
793
- haverule = nil
794
- different = false
795
- ext_permissions.each { |ext_rule|
796
- if rule[:from_port] == ext_rule[:from_port] and
797
- rule[:to_port] == ext_rule[:to_port] and
798
- rule[:ip_protocol] == ext_rule[:ip_protocol]
799
- haverule = ext_rule
800
- ext_rule.keys.each { |k|
801
- if ext_rule[k].nil? or ext_rule[k] == []
802
- haverule.delete(k)
803
- end
804
- different = true if rule[k] != ext_rule[k]
805
- }
806
- break
807
- end
808
- }
809
- if haverule and !different
810
- MU.log "Security Group rule already up-to-date in #{@mu_name}", MU::DEBUG, details: rule
811
- next
742
+ #########################################################################
743
+ # Manufacture an EC2 security group. The second parameter, rules, is an
744
+ # "ingress_rules" structure parsed and validated by MU::Config.
745
+ #########################################################################
746
+ def setRules(rules, add_to_self: false, ingress: true, egress: false)
747
+ # XXX warn about attempt to set rules before we exist
748
+ return if rules.nil? or rules.size == 0 or !@cloud_id
749
+
750
+ # add_to_self means that this security is a "member" of its own rules
751
+ # (which is to say, objects that have this SG are allowed in my these
752
+ # rules)
753
+ if add_to_self
754
+ rules.each { |rule|
755
+ if rule['sgs'].nil? or !rule['sgs'].include?(@cloud_id)
756
+ new_rule = rule.clone
757
+ new_rule.delete('hosts')
758
+ rule['sgs'] = Array.new if rule['sgs'].nil?
759
+ rule['sgs'] << @cloud_id
812
760
  end
761
+ }
762
+ end
813
763
 
814
- MU.log "Setting #{ingress ? "ingress" : "egress"} rule in Security Group #{@mu_name} (#{@cloud_id})", MU::NOTICE, details: rule
815
- begin
816
-
817
- if ingress
818
- if haverule
819
- begin
820
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).revoke_security_group_ingress(
821
- group_id: @cloud_id,
822
- ip_permissions: [haverule]
823
- )
824
- rescue Aws::EC2::Errors::InvalidPermissionNotFound => e
825
- end
764
+ ec2_rules = convertToEc2(rules)
765
+ return if ec2_rules.nil?
766
+
767
+ ext_permissions = MU.structToHash(cloud_desc(use_cache: false).ip_permissions)
768
+
769
+ purge_extraneous_rules(ec2_rules, ext_permissions)
770
+
771
+ ec2_rules.uniq!
772
+ ec2_rules.each { |rule|
773
+ haverule = nil
774
+ different = false
775
+ ext_permissions.each { |ext_rule|
776
+ if rule[:from_port] == ext_rule[:from_port] and
777
+ rule[:to_port] == ext_rule[:to_port] and
778
+ rule[:ip_protocol] == ext_rule[:ip_protocol]
779
+ haverule = ext_rule
780
+ ext_rule.keys.each { |k|
781
+ if ext_rule[k].nil? or ext_rule[k] == []
782
+ haverule.delete(k)
826
783
  end
784
+ different = true if rule[k] != ext_rule[k]
785
+ }
786
+ break
787
+ end
788
+ }
789
+ if haverule and !different
790
+ MU.log "Security Group rule already up-to-date in #{@mu_name}", MU::DEBUG, details: rule
791
+ next
792
+ end
793
+
794
+ MU.log "Setting #{ingress ? "ingress" : "egress"} rule in Security Group #{@mu_name} (#{@cloud_id})", MU::NOTICE, details: rule
795
+
796
+ MU.retrier([Aws::EC2::Errors::InvalidGroupNotFound], max: 10, wait: 10, ignoreme: [Aws::EC2::Errors::InvalidPermissionDuplicate]) {
797
+ if ingress
798
+ if haverule
827
799
  begin
828
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).authorize_security_group_ingress(
800
+ MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).revoke_security_group_ingress(
829
801
  group_id: @cloud_id,
830
- ip_permissions: [rule]
802
+ ip_permissions: [haverule]
831
803
  )
832
- rescue Aws::EC2::Errors::InvalidParameterCombination => e
833
- MU.log "FirewallRule #{@mu_name} had a bogus rule: #{e.message}", MU::ERR, details: rule
834
- raise e
804
+ rescue Aws::EC2::Errors::InvalidPermissionNotFound
835
805
  end
836
806
  end
837
-
838
- if egress
839
- if haverule
840
- begin
841
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).revoke_security_group_egress(
842
- group_id: @cloud_id,
843
- ip_permissions: [haverule]
844
- )
845
- rescue Aws::EC2::Errors::InvalidPermissionNotFound => e
846
- end
847
- end
848
- MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).authorize_security_group_egress(
807
+ begin
808
+ MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).authorize_security_group_ingress(
849
809
  group_id: @cloud_id,
850
810
  ip_permissions: [rule]
851
811
  )
812
+ rescue Aws::EC2::Errors::InvalidParameterCombination => e
813
+ MU.log "FirewallRule #{@mu_name} had a bogus rule: #{e.message}", MU::ERR, details: rule
814
+ raise e
852
815
  end
816
+ end
853
817
 
854
- rescue Aws::EC2::Errors::InvalidGroupNotFound => e
855
- MU.log "#{@mu_name} (#{@cloud_id}) does not yet exist", MU::WARN
856
- retries = retries + 1
857
- if retries < 10
858
- sleep 10
859
- retry
860
- else
861
- raise MuError, "#{@mu_name} does not exist", e.backtrace
818
+ if egress
819
+ if haverule
820
+ begin
821
+ MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).revoke_security_group_egress(
822
+ group_id: @cloud_id,
823
+ ip_permissions: [haverule]
824
+ )
825
+ rescue Aws::EC2::Errors::InvalidPermissionNotFound
826
+ end
862
827
  end
863
- rescue Aws::EC2::Errors::InvalidPermissionDuplicate => e
864
- MU.log "Attempt to add duplicate rule to #{@mu_name}", MU::DEBUG, details: rule
828
+ MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).authorize_security_group_egress(
829
+ group_id: @cloud_id,
830
+ ip_permissions: [rule]
831
+ )
865
832
  end
866
833
  }
867
- end
834
+ }
868
835
 
869
836
  end
870
837
 
871
- #########################################################################
872
- # Convert our config languages description of firewall rules into Amazon's.
873
- # This rule structure is as defined in MU::Config.
874
- #########################################################################
838
+ #######################################################################
839
+ # Convert our config languages description of firewall rules into
840
+ # Amazon's. Our rule structure is as defined in MU::Config.
841
+ #######################################################################
875
842
  def convertToEc2(rules)
876
843
  ec2_rules = []
877
844
  if rules != nil
@@ -893,8 +860,11 @@ module MU
893
860
  p_start = rule['port'].to_i
894
861
  p_end = rule['port'].to_i
895
862
  elsif rule['proto'] != "icmp"
896
- raise MuError, "Can't create a TCP or UDP security group rule without specifying ports: #{rule}"
863
+ MU.log "Can't create a TCP or UDP security group rule without specifying ports, assuming 'all'", MU::WARN, details: rule
864
+ p_start = "0"
865
+ p_end = "65535"
897
866
  end
867
+
898
868
  if rule['proto'] != "icmp"
899
869
  if p_start.nil? or p_end.nil?
900
870
  raise MuError, "Got nil ports out of rule #{rule}"
@@ -995,8 +965,8 @@ module MU
995
965
  ec2_rules << ec2_rule
996
966
  }
997
967
  end
998
- ec2_rules.uniq!
999
- return ec2_rules
968
+
969
+ ec2_rules.uniq
1000
970
  end
1001
971
 
1002
972
  end #class