cloud-mu 3.1.2 → 3.2.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.
- checksums.yaml +4 -4
- data/Dockerfile +15 -3
- data/ansible/roles/mu-windows/README.md +33 -0
- data/ansible/roles/mu-windows/defaults/main.yml +2 -0
- data/ansible/roles/mu-windows/files/LaunchConfig.json +9 -0
- data/ansible/roles/mu-windows/files/config.xml +76 -0
- data/ansible/roles/mu-windows/handlers/main.yml +2 -0
- data/ansible/roles/mu-windows/meta/main.yml +53 -0
- data/ansible/roles/mu-windows/tasks/main.yml +36 -0
- data/ansible/roles/mu-windows/tests/inventory +2 -0
- data/ansible/roles/mu-windows/tests/test.yml +5 -0
- data/ansible/roles/mu-windows/vars/main.yml +2 -0
- data/bin/mu-adopt +10 -13
- data/bin/mu-azure-tests +57 -0
- data/bin/mu-cleanup +2 -4
- data/bin/mu-configure +52 -0
- data/bin/mu-deploy +3 -3
- data/bin/mu-findstray-tests +25 -0
- data/bin/mu-gen-docs +2 -4
- data/bin/mu-load-config.rb +2 -3
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +135 -37
- data/cloud-mu.gemspec +22 -20
- data/cookbooks/mu-activedirectory/resources/domain.rb +4 -4
- data/cookbooks/mu-activedirectory/resources/domain_controller.rb +4 -4
- data/cookbooks/mu-tools/libraries/helper.rb +3 -2
- data/cookbooks/mu-tools/libraries/monkey.rb +35 -0
- data/cookbooks/mu-tools/recipes/apply_security.rb +14 -14
- data/cookbooks/mu-tools/recipes/aws_api.rb +9 -0
- data/cookbooks/mu-tools/recipes/eks.rb +2 -2
- data/cookbooks/mu-tools/recipes/google_api.rb +2 -2
- data/cookbooks/mu-tools/recipes/selinux.rb +2 -1
- data/cookbooks/mu-tools/recipes/windows-client.rb +163 -164
- data/cookbooks/mu-tools/resources/disk.rb +1 -1
- data/cookbooks/mu-tools/resources/windows_users.rb +44 -43
- data/extras/clean-stock-amis +25 -19
- data/extras/generate-stock-images +1 -0
- data/extras/image-generators/AWS/win2k12.yaml +18 -13
- data/extras/image-generators/AWS/win2k16.yaml +18 -13
- data/extras/image-generators/AWS/win2k19.yaml +21 -0
- data/extras/image-generators/Google/centos6.yaml +1 -0
- data/extras/image-generators/Google/centos7.yaml +1 -1
- data/modules/mommacat.ru +6 -16
- data/modules/mu.rb +165 -111
- data/modules/mu/adoption.rb +401 -68
- data/modules/mu/cleanup.rb +199 -306
- data/modules/mu/cloud.rb +100 -1632
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +46 -0
- data/modules/mu/cloud/machine_images.rb +212 -0
- data/modules/mu/cloud/providers.rb +81 -0
- data/modules/mu/cloud/resource_base.rb +920 -0
- data/modules/mu/cloud/server.rb +40 -0
- data/modules/mu/cloud/server_pool.rb +1 -0
- data/modules/mu/cloud/ssh_sessions.rb +228 -0
- data/modules/mu/cloud/winrm_sessions.rb +237 -0
- data/modules/mu/cloud/wrappers.rb +165 -0
- data/modules/mu/config.rb +171 -1767
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +4 -4
- data/modules/mu/config/cache_cluster.rb +1 -1
- data/modules/mu/config/collection.rb +4 -4
- data/modules/mu/config/container_cluster.rb +9 -4
- data/modules/mu/config/database.rb +83 -104
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +6 -6
- data/modules/mu/config/doc_helpers.rb +516 -0
- data/modules/mu/config/endpoint.rb +4 -4
- data/modules/mu/config/firewall_rule.rb +103 -4
- data/modules/mu/config/folder.rb +4 -4
- data/modules/mu/config/function.rb +3 -3
- data/modules/mu/config/group.rb +4 -4
- data/modules/mu/config/habitat.rb +4 -4
- data/modules/mu/config/loadbalancer.rb +60 -14
- data/modules/mu/config/log.rb +4 -4
- data/modules/mu/config/msg_queue.rb +4 -4
- data/modules/mu/config/nosqldb.rb +4 -4
- data/modules/mu/config/notifier.rb +3 -3
- data/modules/mu/config/ref.rb +365 -0
- data/modules/mu/config/role.rb +4 -4
- data/modules/mu/config/schema_helpers.rb +509 -0
- data/modules/mu/config/search_domain.rb +4 -4
- data/modules/mu/config/server.rb +97 -70
- data/modules/mu/config/server.yml +1 -0
- data/modules/mu/config/server_pool.rb +5 -9
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +200 -0
- data/modules/mu/config/user.rb +4 -4
- data/modules/mu/config/vpc.rb +70 -27
- data/modules/mu/config/vpc.yml +0 -1
- data/modules/mu/defaults/AWS.yaml +83 -60
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +3 -2
- data/modules/mu/deploy.rb +30 -26
- data/modules/mu/groomer.rb +17 -2
- data/modules/mu/groomers/ansible.rb +188 -41
- data/modules/mu/groomers/chef.rb +116 -55
- data/modules/mu/logger.rb +127 -148
- data/modules/mu/master.rb +389 -2
- data/modules/mu/master/chef.rb +3 -4
- data/modules/mu/master/ldap.rb +3 -3
- data/modules/mu/master/ssl.rb +12 -3
- data/modules/mu/mommacat.rb +217 -2612
- data/modules/mu/mommacat/daemon.rb +397 -0
- data/modules/mu/mommacat/naming.rb +473 -0
- data/modules/mu/mommacat/search.rb +495 -0
- data/modules/mu/mommacat/storage.rb +722 -0
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +271 -112
- data/modules/mu/{clouds → providers}/aws/alarm.rb +5 -3
- data/modules/mu/{clouds → providers}/aws/bucket.rb +26 -22
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +33 -67
- data/modules/mu/{clouds → providers}/aws/collection.rb +24 -23
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +681 -721
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +64 -63
- data/modules/mu/{clouds → providers}/aws/endpoint.rb +22 -27
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +214 -244
- data/modules/mu/{clouds → providers}/aws/folder.rb +7 -7
- data/modules/mu/{clouds → providers}/aws/function.rb +17 -22
- data/modules/mu/{clouds → providers}/aws/group.rb +23 -23
- data/modules/mu/{clouds → providers}/aws/habitat.rb +17 -14
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +57 -48
- data/modules/mu/{clouds → providers}/aws/log.rb +15 -12
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +17 -16
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +18 -11
- data/modules/mu/{clouds → providers}/aws/notifier.rb +11 -6
- data/modules/mu/{clouds → providers}/aws/role.rb +112 -86
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +39 -33
- data/modules/mu/{clouds → providers}/aws/server.rb +835 -1133
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +56 -60
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +24 -42
- data/modules/mu/{clouds → providers}/aws/user.rb +21 -22
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +2 -1
- data/modules/mu/{clouds → providers}/aws/vpc.rb +523 -929
- data/modules/mu/providers/aws/vpc_subnet.rb +286 -0
- data/modules/mu/{clouds → providers}/azure.rb +29 -9
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +3 -8
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +18 -11
- data/modules/mu/{clouds → providers}/azure/habitat.rb +8 -6
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +5 -5
- data/modules/mu/{clouds → providers}/azure/role.rb +8 -10
- data/modules/mu/{clouds → providers}/azure/server.rb +95 -48
- data/modules/mu/{clouds → providers}/azure/user.rb +6 -8
- data/modules/mu/{clouds → providers}/azure/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/azure/vpc.rb +16 -21
- data/modules/mu/{clouds → providers}/cloudformation.rb +18 -7
- data/modules/mu/{clouds → providers}/cloudformation/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/cache_cluster.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/collection.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/database.rb +6 -17
- data/modules/mu/{clouds → providers}/cloudformation/dnszone.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/firewall_rule.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/loadbalancer.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/log.rb +3 -3
- data/modules/mu/{clouds → providers}/cloudformation/server.rb +7 -7
- data/modules/mu/{clouds → providers}/cloudformation/server_pool.rb +5 -5
- data/modules/mu/{clouds → providers}/cloudformation/vpc.rb +5 -7
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +67 -30
- data/modules/mu/{clouds → providers}/google/bucket.rb +13 -15
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +84 -77
- data/modules/mu/{clouds → providers}/google/database.rb +10 -20
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +15 -14
- data/modules/mu/{clouds → providers}/google/folder.rb +20 -17
- data/modules/mu/{clouds → providers}/google/function.rb +139 -167
- data/modules/mu/{clouds → providers}/google/group.rb +29 -34
- data/modules/mu/{clouds → providers}/google/habitat.rb +21 -22
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +18 -20
- data/modules/mu/{clouds → providers}/google/role.rb +92 -58
- data/modules/mu/{clouds → providers}/google/server.rb +242 -155
- data/modules/mu/{clouds → providers}/google/server_pool.rb +25 -44
- data/modules/mu/{clouds → providers}/google/user.rb +95 -31
- data/modules/mu/{clouds → providers}/google/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/linux.erb +0 -0
- data/modules/mu/{clouds → providers}/google/userdata/windows.erb +0 -0
- data/modules/mu/{clouds → providers}/google/vpc.rb +103 -79
- data/modules/tests/bucket.yml +4 -0
- data/modules/tests/centos6.yaml +11 -0
- data/modules/tests/centos7.yaml +11 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +23 -0
- data/modules/tests/includes-and-params.yaml +2 -1
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/aws-iam.yaml +201 -0
- data/modules/tests/regrooms/bucket.yml +19 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +1 -0
- data/modules/tests/super_simple_bok.yml +1 -3
- data/modules/tests/win2k12.yaml +17 -5
- data/modules/tests/win2k16.yaml +25 -0
- data/modules/tests/win2k19.yaml +25 -0
- data/requirements.txt +1 -0
- data/spec/mu/clouds/azure_spec.rb +2 -2
- metadata +232 -154
- data/extras/image-generators/AWS/windows.yaml +0 -18
- data/modules/mu/clouds/aws/database.rb +0 -1985
|
@@ -344,8 +344,8 @@ module MU
|
|
|
344
344
|
)
|
|
345
345
|
rescue Aws::Route53::Errors::LastVPCAssociation => e
|
|
346
346
|
MU.log e.inspect, MU::WARN
|
|
347
|
-
rescue Aws::Route53::Errors::VPCAssociationNotFound
|
|
348
|
-
MU.log "VPC #{vpc_id} access to zone #{id} already revoked", MU::
|
|
347
|
+
rescue Aws::Route53::Errors::VPCAssociationNotFound
|
|
348
|
+
MU.log "VPC #{vpc_id} access to zone #{id} already revoked", MU::NOTICE
|
|
349
349
|
end
|
|
350
350
|
end
|
|
351
351
|
end
|
|
@@ -366,10 +366,10 @@ module MU
|
|
|
366
366
|
# @param location [Hash<String>]: A parsed Hash of {MU::Config::BasketofKittens::dnszones::records::geo_location}.
|
|
367
367
|
# @param set_identifier [String]: A unique string to differentiate otherwise-similar records. Normally auto-generated, should not need to specify.
|
|
368
368
|
# @param alias_zone [String]: Zone ID of the target's hosted zone, when creating an alias (type R53ALIAS)
|
|
369
|
-
def self.manageRecord(id, name, type, targets: nil,
|
|
369
|
+
def self.manageRecord(id, name, type, targets: nil,
|
|
370
370
|
ttl: 7200, delete: false, sync_wait: true, failover: nil,
|
|
371
371
|
healthcheck: nil, region: nil, weight: nil, overwrite: true,
|
|
372
|
-
location: nil, set_identifier: nil, alias_zone: nil)
|
|
372
|
+
location: nil, set_identifier: nil, alias_zone: nil, noop: false)
|
|
373
373
|
|
|
374
374
|
MU.setVar("curRegion", region) if !region.nil?
|
|
375
375
|
zone = MU::Cloud::DNSZone.find(cloud_id: id).values.first
|
|
@@ -380,6 +380,11 @@ module MU
|
|
|
380
380
|
action = "UPSERT" if overwrite
|
|
381
381
|
action = "DELETE" if delete
|
|
382
382
|
|
|
383
|
+
record_sets = MU::Cloud::AWS.route53.list_resource_record_sets(
|
|
384
|
+
hosted_zone_id: id,
|
|
385
|
+
start_record_name: name
|
|
386
|
+
).resource_record_sets if delete
|
|
387
|
+
|
|
383
388
|
if type == "R53ALIAS"
|
|
384
389
|
target_zone = id
|
|
385
390
|
target_name = targets[0].downcase
|
|
@@ -413,7 +418,15 @@ module MU
|
|
|
413
418
|
}
|
|
414
419
|
else
|
|
415
420
|
rrsets = []
|
|
416
|
-
if
|
|
421
|
+
if delete
|
|
422
|
+
record_sets.each { |r|
|
|
423
|
+
if r.name == name and r.type == type
|
|
424
|
+
rrsets = MU.structToHash(r.resource_records)
|
|
425
|
+
end
|
|
426
|
+
}
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
if !targets.nil? and (!delete or rrsets.empty?)
|
|
417
430
|
targets.each { |target|
|
|
418
431
|
rrsets << {value: target}
|
|
419
432
|
}
|
|
@@ -426,6 +439,7 @@ module MU
|
|
|
426
439
|
resource_records: rrsets
|
|
427
440
|
}
|
|
428
441
|
|
|
442
|
+
|
|
429
443
|
if !healthcheck.nil?
|
|
430
444
|
base_rrset[:health_check_id] = healthcheck
|
|
431
445
|
end
|
|
@@ -445,12 +459,13 @@ module MU
|
|
|
445
459
|
|
|
446
460
|
# Doing an UPSERT with a new set_identifier will fail with a record already exist error, so lets try and get it from an existing record.
|
|
447
461
|
# This can be an issue with multiple secondary failover records
|
|
448
|
-
if (location || failover || region || weight)
|
|
449
|
-
record_sets
|
|
462
|
+
if (location || failover || region || weight) and set_identifier.nil?
|
|
463
|
+
record_sets ||= MU::Cloud::AWS.route53.list_resource_record_sets(
|
|
450
464
|
hosted_zone_id: id,
|
|
451
465
|
start_record_name: name
|
|
452
466
|
).resource_record_sets
|
|
453
467
|
|
|
468
|
+
|
|
454
469
|
record_sets.each { |r|
|
|
455
470
|
if r.name == name
|
|
456
471
|
if location && location == r.location
|
|
@@ -497,18 +512,23 @@ module MU
|
|
|
497
512
|
MU.log "Adding DNS record #{name} => #{targets} (#{type}) to #{id}", details: params
|
|
498
513
|
end
|
|
499
514
|
|
|
500
|
-
|
|
515
|
+
return if noop
|
|
516
|
+
|
|
517
|
+
on_retry = Proc.new { |e|
|
|
518
|
+
if (delete and e.message.match(/but it was not found/)) or
|
|
519
|
+
(!delete and e.message.match(/(it|name) already exists/))
|
|
520
|
+
MU.log e.message, MU::DEBUG, details: params
|
|
521
|
+
return
|
|
522
|
+
elsif e.class == Aws::Route53::Errors::InvalidChangeBatch
|
|
523
|
+
MU.log "Problem managing entry for #{name}", MU::ERR, details: params
|
|
524
|
+
raise MuError, e.inspect
|
|
525
|
+
end
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
change_id = nil
|
|
529
|
+
MU.retrier([Aws::Route53::Errors::PriorRequestNotComplete, Aws::Route53::Errors::InvalidChangeBatch], wait: 15, max: 10, on_retry: on_retry) {
|
|
501
530
|
change_id = MU::Cloud::AWS.route53.change_resource_record_sets(params).change_info.id
|
|
502
|
-
|
|
503
|
-
sleep 10
|
|
504
|
-
retry
|
|
505
|
-
rescue Aws::Route53::Errors::InvalidChangeBatch, Aws::Route53::Errors::InvalidInput, Exception => e
|
|
506
|
-
return if e.message.match(/ but it already exists/) and !delete
|
|
507
|
-
MU.log "Failed to change DNS records, #{e.inspect}", MU::ERR, details: params
|
|
508
|
-
raise e if !delete
|
|
509
|
-
MU.log "Record #{name} (#{type}) in #{id} can't be deleted. Already removed? #{e.inspect}", MU::WARN, details: params if delete
|
|
510
|
-
return
|
|
511
|
-
end
|
|
531
|
+
}
|
|
512
532
|
|
|
513
533
|
if sync_wait
|
|
514
534
|
attempts = 0
|
|
@@ -535,23 +555,27 @@ module MU
|
|
|
535
555
|
# @param delete [Boolean]: Remove this entry instead of creating it.
|
|
536
556
|
# @param cloudclass [Object]: The resource's Mu class.
|
|
537
557
|
# @param sync_wait [Boolean]: Wait for DNS entry to propagate across zone.
|
|
538
|
-
def self.genericMuDNSEntry(name: nil, target: nil, cloudclass: nil, noop: false, delete: false, sync_wait: true)
|
|
539
|
-
return nil if name.nil? or
|
|
540
|
-
|
|
558
|
+
def self.genericMuDNSEntry(name: nil, target: nil, cloudclass: nil, noop: false, delete: false, sync_wait: true, credentials: nil)
|
|
559
|
+
return nil if name.nil? or cloudclass.nil?
|
|
560
|
+
return nil if target.nil? and !delete
|
|
561
|
+
mu_zone = MU::Cloud::DNSZone.find(cloud_id: "platform-mu", credentials: credentials).values.first
|
|
541
562
|
raise MuError, "Couldn't isolate platform-mu DNS zone" if mu_zone.nil?
|
|
542
563
|
|
|
543
564
|
if !mu_zone.nil? and !MU.myVPC.nil?
|
|
544
565
|
subdomain = cloudclass.cfg_name
|
|
545
566
|
dns_name = name.downcase+"."+subdomain
|
|
546
567
|
dns_name += "."+MU.myInstanceId if MU.myInstanceId
|
|
568
|
+
|
|
547
569
|
record_type = "CNAME"
|
|
548
570
|
record_type = "A" if target.match(/^\d+\.\d+\.\d+\.\d+/)
|
|
549
571
|
ip = nil
|
|
550
572
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
573
|
+
records = []
|
|
574
|
+
lookup = MU::Cloud::AWS.route53(credentials: credentials).list_resource_record_sets(
|
|
575
|
+
hosted_zone_id: mu_zone.id,
|
|
576
|
+
start_record_name: "#{dns_name}.platform-mu",
|
|
577
|
+
start_record_type: record_type,
|
|
578
|
+
max_items: 1
|
|
555
579
|
).resource_record_sets
|
|
556
580
|
|
|
557
581
|
lookup.each { |record|
|
|
@@ -572,34 +596,14 @@ module MU
|
|
|
572
596
|
# MU.log "'#{dns_name}.platform-mu' does not resolve.", MU::DEBUG, details: e.inspect
|
|
573
597
|
# end
|
|
574
598
|
|
|
575
|
-
if ip == target
|
|
576
|
-
return "#{dns_name}.platform-mu"
|
|
577
|
-
elsif noop
|
|
578
|
-
return nil
|
|
599
|
+
if ip == target and !delete
|
|
600
|
+
return "#{dns_name}.platform-mu"
|
|
579
601
|
end
|
|
580
602
|
|
|
581
603
|
sync_wait = false if delete
|
|
582
604
|
|
|
583
605
|
record_type = "R53ALIAS" if cloudclass == MU::Cloud::AWS::LoadBalancer
|
|
584
|
-
|
|
585
|
-
begin
|
|
586
|
-
MU::Cloud::AWS::DNSZone.manageRecord(mu_zone.id, dns_name, record_type, targets: [target], delete: delete, sync_wait: sync_wait)
|
|
587
|
-
rescue Aws::Route53::Errors::PriorRequestNotComplete => e
|
|
588
|
-
MU.log "Route53 was still processing a request, waiting", MU::WARN, details: e
|
|
589
|
-
sleep 15
|
|
590
|
-
retry
|
|
591
|
-
rescue Aws::Route53::Errors::InvalidChangeBatch => e
|
|
592
|
-
if e.inspect.match(/alias target name does not lie within the target zone/) and attempts < 5
|
|
593
|
-
MU.log e.inspect, MU::WARN
|
|
594
|
-
sleep 15
|
|
595
|
-
attempts = attempts + 1
|
|
596
|
-
retry
|
|
597
|
-
elsif !e.inspect.match(/(it|name) already exists/)
|
|
598
|
-
raise MuError, "Problem managing entry for #{dns_name} -> #{target}: #{e.inspect}"
|
|
599
|
-
else
|
|
600
|
-
MU.log "#{dns_name} already exists", MU::DEBUG, details: e.inspect
|
|
601
|
-
end
|
|
602
|
-
end
|
|
606
|
+
MU::Cloud::AWS::DNSZone.manageRecord(mu_zone.id, dns_name, record_type, targets: [target], delete: delete, sync_wait: sync_wait, noop: noop)
|
|
603
607
|
return "#{dns_name}.platform-mu"
|
|
604
608
|
else
|
|
605
609
|
return nil
|
|
@@ -663,7 +667,8 @@ module MU
|
|
|
663
667
|
# Called by {MU::Cleanup}. Locates resources that were created by the
|
|
664
668
|
# currently-loaded deployment, and purges them.
|
|
665
669
|
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
666
|
-
|
|
670
|
+
MU.log "AWS::DNSZone.cleanup: need to support flags['known']", MU::DEBUG, details: flags
|
|
671
|
+
|
|
667
672
|
threads = []
|
|
668
673
|
MU::Cloud::AWS.route53(credentials: credentials).list_health_checks.health_checks.each { |check|
|
|
669
674
|
begin
|
|
@@ -692,19 +697,19 @@ module MU
|
|
|
692
697
|
threads << Thread.new(check) { |mycheck|
|
|
693
698
|
MU.dupGlobals(parent_thread_id)
|
|
694
699
|
Thread.abort_on_exception = true
|
|
695
|
-
MU.log "Removing health check #{
|
|
700
|
+
MU.log "Removing health check #{mycheck.id}"
|
|
696
701
|
retries = 5
|
|
697
702
|
begin
|
|
698
|
-
MU::Cloud::AWS.route53(credentials: credentials).delete_health_check(
|
|
703
|
+
MU::Cloud::AWS.route53(credentials: credentials).delete_health_check(health_mycheck_id: mycheck.id) if !noop
|
|
699
704
|
rescue Aws::Route53::Errors::NoSuchHealthCheck => e
|
|
700
|
-
MU.log "Health Check '#{
|
|
705
|
+
MU.log "Health Check '#{mycheck.id}' disappeared before I could remove it", MU::WARN, details: e.inspect
|
|
701
706
|
rescue Aws::Route53::Errors::InvalidInput => e
|
|
702
707
|
if e.message.match(/is still referenced from parent health check/) && retries <= 5
|
|
703
708
|
sleep 5
|
|
704
709
|
retries += 1
|
|
705
710
|
retry
|
|
706
711
|
else
|
|
707
|
-
MU.log "Health Check #{
|
|
712
|
+
MU.log "Health Check #{mycheck.id} still has a parent health check associated with it, skipping", MU::WARN, details: e.inspect
|
|
708
713
|
end
|
|
709
714
|
end
|
|
710
715
|
}
|
|
@@ -719,7 +724,7 @@ module MU
|
|
|
719
724
|
}
|
|
720
725
|
|
|
721
726
|
zones = MU::Cloud::DNSZone.find(deploy_id: MU.deploy_id, region: region)
|
|
722
|
-
zones.
|
|
727
|
+
zones.values.each { |zone|
|
|
723
728
|
MU.log "Purging DNS Zone '#{zone.name}' (#{zone.id})"
|
|
724
729
|
if !noop
|
|
725
730
|
begin
|
|
@@ -727,7 +732,6 @@ module MU
|
|
|
727
732
|
rrsets = MU::Cloud::AWS.route53(credentials: credentials).list_resource_record_sets(hosted_zone_id: zone.id)
|
|
728
733
|
rrsets.resource_record_sets.each { |rrset|
|
|
729
734
|
next if zone.name == rrset.name and (rrset.type == "NS" or rrset.type == "SOA")
|
|
730
|
-
records = []
|
|
731
735
|
MU::Cloud::AWS.route53(credentials: credentials).change_resource_record_sets(
|
|
732
736
|
hosted_zone_id: zone.id,
|
|
733
737
|
change_batch: {
|
|
@@ -791,9 +795,9 @@ module MU
|
|
|
791
795
|
end
|
|
792
796
|
|
|
793
797
|
# Cloud-specific configuration properties.
|
|
794
|
-
# @param
|
|
798
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
795
799
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
796
|
-
def self.schema(
|
|
800
|
+
def self.schema(_config)
|
|
797
801
|
toplevel_required = []
|
|
798
802
|
schema = {}
|
|
799
803
|
[toplevel_required, schema]
|
|
@@ -801,9 +805,9 @@ module MU
|
|
|
801
805
|
|
|
802
806
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::dnszones}, bare and unvalidated.
|
|
803
807
|
# @param zone [Hash]: The resource to process and validate
|
|
804
|
-
# @param
|
|
808
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
805
809
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
806
|
-
def self.validateConfig(zone,
|
|
810
|
+
def self.validateConfig(zone, _configurator)
|
|
807
811
|
ok = true
|
|
808
812
|
|
|
809
813
|
if !zone["records"].nil?
|
|
@@ -821,10 +825,7 @@ module MU
|
|
|
821
825
|
end
|
|
822
826
|
|
|
823
827
|
if !record['mu_type'].nil?
|
|
824
|
-
zone[
|
|
825
|
-
"type" => record['mu_type'],
|
|
826
|
-
"name" => record['target']
|
|
827
|
-
}
|
|
828
|
+
MU::Config.addDependency(zone, record['target'], record['mu_type'])
|
|
828
829
|
end
|
|
829
830
|
|
|
830
831
|
if record.has_key?('healthchecks') && !record['healthchecks'].empty?
|
|
@@ -116,15 +116,15 @@ MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials
|
|
|
116
116
|
end
|
|
117
117
|
|
|
118
118
|
if m['integrate_with']
|
|
119
|
-
role_arn = if m['iam_role']
|
|
120
|
-
if m['iam_role'].match(/^arn:/)
|
|
121
|
-
m['iam_role']
|
|
122
|
-
else
|
|
123
|
-
sib_role = @deploy.findLitterMate(name: m['iam_role'], type: "roles")
|
|
124
|
-
sib_role.cloudobj.arn
|
|
119
|
+
# role_arn = if m['iam_role']
|
|
120
|
+
# if m['iam_role'].match(/^arn:/)
|
|
121
|
+
# m['iam_role']
|
|
122
|
+
# else
|
|
123
|
+
# sib_role = @deploy.findLitterMate(name: m['iam_role'], type: "roles")
|
|
124
|
+
# sib_role.cloudobj.arn
|
|
125
125
|
# XXX make this more like get_role_arn in Function, or just use Role.find?
|
|
126
|
-
end
|
|
127
|
-
end
|
|
126
|
+
# end
|
|
127
|
+
# end
|
|
128
128
|
|
|
129
129
|
function_obj = nil
|
|
130
130
|
|
|
@@ -198,13 +198,12 @@ MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials
|
|
|
198
198
|
generate_methods
|
|
199
199
|
|
|
200
200
|
MU.log "Deploying API Gateway #{@config['name']} to #{@config['deploy_to']}"
|
|
201
|
-
|
|
201
|
+
MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).create_deployment(
|
|
202
202
|
rest_api_id: @cloud_id,
|
|
203
203
|
stage_name: @config['deploy_to']
|
|
204
204
|
# cache_cluster_enabled: false,
|
|
205
205
|
# cache_cluster_size: 0.5,
|
|
206
206
|
)
|
|
207
|
-
deployment_id = resp.id
|
|
208
207
|
# this automatically creates a stage with the same name, so we don't
|
|
209
208
|
# have to deal with that
|
|
210
209
|
|
|
@@ -220,11 +219,14 @@ MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials
|
|
|
220
219
|
|
|
221
220
|
end
|
|
222
221
|
|
|
222
|
+
@cloud_desc_cache = nil
|
|
223
223
|
# @return [Struct]
|
|
224
|
-
def cloud_desc
|
|
225
|
-
|
|
224
|
+
def cloud_desc(use_cache: true)
|
|
225
|
+
return @cloud_desc_cache if @cloud_desc_cache and use_cache
|
|
226
|
+
@cloud_desc_cache = MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials']).get_rest_api(
|
|
226
227
|
rest_api_id: @cloud_id
|
|
227
228
|
)
|
|
229
|
+
@cloud_desc_cache
|
|
228
230
|
end
|
|
229
231
|
|
|
230
232
|
# Return the metadata for this API
|
|
@@ -241,6 +243,9 @@ MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials
|
|
|
241
243
|
# @param region [String]: The cloud provider region
|
|
242
244
|
# @return [void]
|
|
243
245
|
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
246
|
+
MU.log "AWS::Endpoint.cleanup: need to support flags['known']", MU::DEBUG, details: flags
|
|
247
|
+
MU.log "Placeholder: AWS Endpoint artifacts do not support tags, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: ignoremaster
|
|
248
|
+
|
|
244
249
|
resp = MU::Cloud::AWS.apig(region: region, credentials: credentials).get_rest_apis
|
|
245
250
|
if resp and resp.items
|
|
246
251
|
resp.items.each { |api|
|
|
@@ -279,9 +284,9 @@ MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials
|
|
|
279
284
|
end
|
|
280
285
|
|
|
281
286
|
# Cloud-specific configuration properties.
|
|
282
|
-
# @param
|
|
287
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
283
288
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
284
|
-
def self.schema(
|
|
289
|
+
def self.schema(_config)
|
|
285
290
|
toplevel_required = []
|
|
286
291
|
schema = {
|
|
287
292
|
"deploy_to" => {
|
|
@@ -467,11 +472,7 @@ MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials
|
|
|
467
472
|
endpoint['methods'].each { |m|
|
|
468
473
|
if m['integrate_with'] and m['integrate_with']['name']
|
|
469
474
|
if m['integrate_with']['type'] != "aws_generic"
|
|
470
|
-
endpoint['
|
|
471
|
-
endpoint['dependencies'] << {
|
|
472
|
-
"type" => m['integrate_with']['type'],
|
|
473
|
-
"name" => m['integrate_with']['name']
|
|
474
|
-
}
|
|
475
|
+
MU::Config.addDependency(endpoint, m['integrate_with']['name'], m['integrate_with']['type'])
|
|
475
476
|
end
|
|
476
477
|
|
|
477
478
|
m['integrate_with']['backend_http_method'] ||= m['type']
|
|
@@ -520,13 +521,8 @@ MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials
|
|
|
520
521
|
end
|
|
521
522
|
configurator.insertKitten(roledesc, "roles")
|
|
522
523
|
|
|
523
|
-
endpoint['dependencies'] ||= []
|
|
524
524
|
m['iam_role'] = endpoint['name']+"-"+m['integrate_with']['name']
|
|
525
|
-
|
|
526
|
-
endpoint['dependencies'] << {
|
|
527
|
-
"type" => "role",
|
|
528
|
-
"name" => endpoint['name']+"-"+m['integrate_with']['name']
|
|
529
|
-
}
|
|
525
|
+
MU::Config.addDependency(endpoint, m['iam_role'], "role")
|
|
530
526
|
end
|
|
531
527
|
end
|
|
532
528
|
}
|
|
@@ -538,8 +534,6 @@ MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials
|
|
|
538
534
|
ok
|
|
539
535
|
end
|
|
540
536
|
|
|
541
|
-
private
|
|
542
|
-
|
|
543
537
|
def self.cors_option_integrations(path)
|
|
544
538
|
{
|
|
545
539
|
"type" => "OPTIONS",
|
|
@@ -585,6 +579,7 @@ MU::Cloud::AWS.apig(region: @config['region'], credentials: @config['credentials
|
|
|
585
579
|
}
|
|
586
580
|
}
|
|
587
581
|
end
|
|
582
|
+
private_class_method :cors_option_integrations
|
|
588
583
|
|
|
589
584
|
end
|
|
590
585
|
end
|
|
@@ -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/
|
|
21
|
+
require "mu/providers/aws/vpc"
|
|
22
22
|
|
|
23
23
|
@admin_sgs = Hash.new
|
|
24
24
|
@admin_sg_semaphore = Mutex.new
|
|
@@ -54,13 +54,12 @@ module MU
|
|
|
54
54
|
|
|
55
55
|
secgroup = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).create_security_group(sg_struct)
|
|
56
56
|
@cloud_id = secgroup.group_id
|
|
57
|
-
rescue Aws::EC2::Errors::InvalidGroupDuplicate
|
|
57
|
+
rescue Aws::EC2::Errors::InvalidGroupDuplicate
|
|
58
58
|
MU.log "EC2 Security Group #{groupname} already exists, using it", MU::NOTICE
|
|
59
59
|
filters = [{name: "group-name", values: [groupname]}]
|
|
60
60
|
filters << {name: "vpc-id", values: [vpc_id]} if !vpc_id.nil?
|
|
61
61
|
|
|
62
62
|
secgroup = MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_security_groups(filters: filters).security_groups.first
|
|
63
|
-
deploy_id = @deploy.deploy_id if !@deploy_id.nil?
|
|
64
63
|
if secgroup.nil?
|
|
65
64
|
raise MuError, "Failed to locate security group named #{groupname}, even though EC2 says it already exists", caller
|
|
66
65
|
end
|
|
@@ -69,24 +68,24 @@ module MU
|
|
|
69
68
|
|
|
70
69
|
begin
|
|
71
70
|
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).describe_security_groups(group_ids: [secgroup.group_id])
|
|
72
|
-
rescue Aws::EC2::Errors::InvalidGroupNotFound
|
|
71
|
+
rescue Aws::EC2::Errors::InvalidGroupNotFound
|
|
73
72
|
MU.log "#{secgroup.group_id} not yet ready, waiting...", MU::NOTICE
|
|
74
73
|
sleep 10
|
|
75
74
|
retry
|
|
76
75
|
end
|
|
77
76
|
|
|
78
77
|
MU::Cloud::AWS.createStandardTags(secgroup.group_id, region: @config['region'], credentials: @config['credentials'])
|
|
79
|
-
MU::
|
|
78
|
+
MU::Cloud::AWS.createTag(secgroup.group_id, "Name", groupname, region: @config['region'], credentials: @config['credentials'])
|
|
80
79
|
|
|
81
80
|
if @config['optional_tags']
|
|
82
81
|
MU::MommaCat.listOptionalTags.each { |key, value|
|
|
83
|
-
MU::
|
|
82
|
+
MU::Cloud::AWS.createTag(secgroup.group_id, key, value, region: @config['region'], credentials: @config['credentials'])
|
|
84
83
|
}
|
|
85
84
|
end
|
|
86
85
|
|
|
87
86
|
if @config['tags']
|
|
88
87
|
@config['tags'].each { |tag|
|
|
89
|
-
MU::
|
|
88
|
+
MU::Cloud::AWS.createTag(secgroup.group_id, tag['key'], tag['value'], region: @config['region'], credentials: @config['credentials'])
|
|
90
89
|
}
|
|
91
90
|
end
|
|
92
91
|
|
|
@@ -180,7 +179,7 @@ module MU
|
|
|
180
179
|
ip_permissions: ec2_rule
|
|
181
180
|
)
|
|
182
181
|
end
|
|
183
|
-
rescue Aws::EC2::Errors::InvalidPermissionDuplicate
|
|
182
|
+
rescue Aws::EC2::Errors::InvalidPermissionDuplicate
|
|
184
183
|
MU.log "Attempt to add duplicate rule to #{@cloud_id}", MU::DEBUG, details: ec2_rule
|
|
185
184
|
# Ensure that, at least, the description field gets updated on
|
|
186
185
|
# existing rules
|
|
@@ -246,7 +245,7 @@ module MU
|
|
|
246
245
|
# Reverse-map our cloud description into a runnable config hash.
|
|
247
246
|
# We assume that any values we have in +@config+ are placeholders, and
|
|
248
247
|
# calculate our own accordingly based on what's live in the cloud.
|
|
249
|
-
def toKitten(
|
|
248
|
+
def toKitten(**_args)
|
|
250
249
|
bok = {
|
|
251
250
|
"cloud" => "AWS",
|
|
252
251
|
"credentials" => @config['credentials'],
|
|
@@ -383,9 +382,8 @@ module MU
|
|
|
383
382
|
# @param region [String]: The cloud provider region
|
|
384
383
|
# @return [void]
|
|
385
384
|
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
386
|
-
filters =
|
|
387
|
-
|
|
388
|
-
filters = [
|
|
385
|
+
filters = if flags and flags["vpc_id"]
|
|
386
|
+
[
|
|
389
387
|
{name: "vpc-id", values: [flags["vpc_id"]]}
|
|
390
388
|
]
|
|
391
389
|
else
|
|
@@ -395,11 +393,12 @@ module MU
|
|
|
395
393
|
if !ignoremaster
|
|
396
394
|
filters << {name: "tag:MU-MASTER-IP", values: [MU.mu_public_ip]}
|
|
397
395
|
end
|
|
396
|
+
filters
|
|
398
397
|
end
|
|
399
398
|
|
|
400
399
|
# Some services create sneaky rogue ENIs which then block removal of
|
|
401
400
|
# associated security groups. Find them and fry them.
|
|
402
|
-
MU::Cloud
|
|
401
|
+
MU::Cloud.resourceClass("AWS", "VPC").purge_interfaces(noop, filters, region: region, credentials: credentials)
|
|
403
402
|
|
|
404
403
|
resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_security_groups(
|
|
405
404
|
filters: filters
|
|
@@ -409,75 +408,8 @@ module MU
|
|
|
409
408
|
MU.log "Revoking rules in EC2 Security Group #{sg.group_name} (#{sg.group_id})"
|
|
410
409
|
|
|
411
410
|
if !noop
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
sg.ip_permissions.each { |hole|
|
|
415
|
-
ingress_to_revoke << MU.structToHash(hole)
|
|
416
|
-
ingress_to_revoke.each { |rule|
|
|
417
|
-
if !rule[:user_id_group_pairs].nil? and rule[:user_id_group_pairs] .size == 0
|
|
418
|
-
rule.delete(:user_id_group_pairs)
|
|
419
|
-
elsif !rule[:user_id_group_pairs].nil?
|
|
420
|
-
rule[:user_id_group_pairs].each { |group_ref|
|
|
421
|
-
group_ref = MU.structToHash(group_ref)
|
|
422
|
-
group_ref.delete(:group_name) if group_ref[:group_id]
|
|
423
|
-
}
|
|
424
|
-
end
|
|
425
|
-
|
|
426
|
-
if !rule[:ip_ranges].nil? and rule[:ip_ranges].size == 0
|
|
427
|
-
rule.delete(:ip_ranges)
|
|
428
|
-
end
|
|
429
|
-
|
|
430
|
-
if !rule[:prefix_list_ids].nil? and rule[:prefix_list_ids].size == 0
|
|
431
|
-
rule.delete(:prefix_list_ids)
|
|
432
|
-
end
|
|
433
|
-
|
|
434
|
-
if !rule[:ipv_6_ranges].nil? and rule[:ipv_6_ranges].size == 0
|
|
435
|
-
rule.delete(:ipv_6_ranges)
|
|
436
|
-
end
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
sg.ip_permissions_egress.each { |hole|
|
|
440
|
-
egress_to_revoke << MU.structToHash(hole)
|
|
441
|
-
egress_to_revoke.each { |rule|
|
|
442
|
-
if !rule[:user_id_group_pairs].nil? and rule[:user_id_group_pairs].size == 0
|
|
443
|
-
rule.delete(:user_id_group_pairs)
|
|
444
|
-
elsif !rule[:user_id_group_pairs].nil?
|
|
445
|
-
rule[:user_id_group_pairs].each { |group_ref|
|
|
446
|
-
group_ref = MU.structToHash(group_ref)
|
|
447
|
-
group_ref.delete(:group_name) if group_ref[:group_id]
|
|
448
|
-
}
|
|
449
|
-
end
|
|
450
|
-
|
|
451
|
-
if !rule[:ip_ranges].nil? and rule[:ip_ranges].size == 0
|
|
452
|
-
rule.delete(:ip_ranges)
|
|
453
|
-
end
|
|
454
|
-
|
|
455
|
-
if !rule[:prefix_list_ids].nil? and rule[:prefix_list_ids].size == 0
|
|
456
|
-
rule.delete(:prefix_list_ids)
|
|
457
|
-
end
|
|
458
|
-
|
|
459
|
-
if !rule[:ipv_6_ranges].nil? and rule[:ipv_6_ranges].size == 0
|
|
460
|
-
rule.delete(:ipv_6_ranges)
|
|
461
|
-
end
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
begin
|
|
465
|
-
|
|
466
|
-
if ingress_to_revoke.size > 0
|
|
467
|
-
MU::Cloud::AWS.ec2(credentials: credentials, region: region).revoke_security_group_ingress(
|
|
468
|
-
group_id: sg.group_id,
|
|
469
|
-
ip_permissions: ingress_to_revoke
|
|
470
|
-
)
|
|
471
|
-
end
|
|
472
|
-
if egress_to_revoke.size > 0
|
|
473
|
-
MU::Cloud::AWS.ec2(credentials: credentials, region: region).revoke_security_group_egress(
|
|
474
|
-
group_id: sg.group_id,
|
|
475
|
-
ip_permissions: egress_to_revoke
|
|
476
|
-
)
|
|
477
|
-
end
|
|
478
|
-
rescue Aws::EC2::Errors::InvalidPermissionNotFound
|
|
479
|
-
MU.log "Rule in #{sg.group_id} disappeared before I could remove it", MU::WARN
|
|
480
|
-
end
|
|
411
|
+
revoke_rules(sg, region: region, credentials: credentials)
|
|
412
|
+
revoke_rules(sg, egress: true, region: region, credentials: credentials)
|
|
481
413
|
end
|
|
482
414
|
}
|
|
483
415
|
|
|
@@ -485,61 +417,132 @@ module MU
|
|
|
485
417
|
next if sg.group_name == "default"
|
|
486
418
|
MU.log "Removing EC2 Security Group #{sg.group_name}"
|
|
487
419
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
{ name: "vpc-id", values: [sg.vpc_id] }
|
|
506
|
-
]
|
|
507
|
-
).security_groups
|
|
508
|
-
if default_resp and default_resp.size == 1
|
|
509
|
-
default_sg = default_resp.first.group_id
|
|
510
|
-
eni_resp = MU::Cloud::AWS.ec2(credentials: credentials, region: region).describe_network_interfaces(
|
|
511
|
-
filters: [ {name: "group-id", values: [sg.group_id]} ]
|
|
512
|
-
)
|
|
513
|
-
if eni_resp and eni_resp.data and
|
|
514
|
-
eni_resp.data.network_interfaces
|
|
515
|
-
eni_resp.data.network_interfaces.each { |iface|
|
|
516
|
-
iface_groups = iface.groups.map { |sg| sg.group_id }
|
|
517
|
-
iface_groups.delete(sg.group_id)
|
|
518
|
-
iface_groups << default_sg if iface_groups.empty?
|
|
519
|
-
MU.log "Attempting to remove #{sg.group_id} from ENI #{iface.network_interface_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
|
|
520
437
|
MU::Cloud::AWS.ec2(credentials: credentials, region: region).modify_network_interface_attribute(
|
|
521
438
|
network_interface_id: iface.network_interface_id,
|
|
522
439
|
groups: iface_groups
|
|
523
440
|
)
|
|
524
|
-
|
|
525
|
-
|
|
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
|
|
446
|
+
}
|
|
526
447
|
end
|
|
527
448
|
end
|
|
449
|
+
end
|
|
450
|
+
}
|
|
528
451
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
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
|
|
461
|
+
|
|
462
|
+
}
|
|
463
|
+
end
|
|
464
|
+
|
|
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]
|
|
479
|
+
}
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
if !rule[:ip_ranges].nil? and rule[:ip_ranges].size == 0
|
|
483
|
+
rule.delete(:ip_ranges)
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
if !rule[:prefix_list_ids].nil? and rule[:prefix_list_ids].size == 0
|
|
487
|
+
rule.delete(:prefix_list_ids)
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
if !rule[:ipv_6_ranges].nil? and rule[:ipv_6_ranges].size == 0
|
|
491
|
+
rule.delete(:ipv_6_ranges)
|
|
492
|
+
end
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
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
|
+
)
|
|
532
503
|
else
|
|
533
|
-
MU.
|
|
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
|
+
)
|
|
534
508
|
end
|
|
509
|
+
rescue Aws::EC2::Errors::InvalidPermissionNotFound
|
|
510
|
+
MU.log "Rule in #{sg.group_id} disappeared before I could remove it", MU::WARN
|
|
535
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
|
+
}
|
|
536
539
|
}
|
|
537
540
|
end
|
|
538
541
|
|
|
539
542
|
# Cloud-specific configuration properties.
|
|
540
|
-
# @param
|
|
543
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
541
544
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
542
|
-
def self.schema(
|
|
545
|
+
def self.schema(_config)
|
|
543
546
|
toplevel_required = []
|
|
544
547
|
schema = {
|
|
545
548
|
"rules" => {
|
|
@@ -645,36 +648,16 @@ module MU
|
|
|
645
648
|
|
|
646
649
|
if rule['firewall_rules']
|
|
647
650
|
rule['firewall_rules'].each { |sg|
|
|
648
|
-
if sg
|
|
649
|
-
|
|
650
|
-
"type" => "firewall_rule",
|
|
651
|
-
"name" => sg.name,
|
|
652
|
-
"no_create_wait" => true
|
|
653
|
-
}
|
|
654
|
-
elsif sg['name'] and !sg['deploy_id']
|
|
655
|
-
acl["dependencies"] << {
|
|
656
|
-
"type" => "firewall_rule",
|
|
657
|
-
"name" => sg['name'],
|
|
658
|
-
"no_create_wait" => true
|
|
659
|
-
}
|
|
651
|
+
if sg['name'] and !sg['deploy_id']
|
|
652
|
+
MU::Config.addDependency(acl, sg['name'], "firewall_rule", no_create_wait: true)
|
|
660
653
|
end
|
|
661
654
|
}
|
|
662
655
|
end
|
|
663
656
|
|
|
664
657
|
if rule['loadbalancers']
|
|
665
658
|
rule['loadbalancers'].each { |lb|
|
|
666
|
-
if lb
|
|
667
|
-
|
|
668
|
-
"type" => "loadbalancer",
|
|
669
|
-
"name" => lb.name,
|
|
670
|
-
"phase" => "groom"
|
|
671
|
-
}
|
|
672
|
-
elsif lb['name'] and !lb['deploy_id']
|
|
673
|
-
acl["dependencies"] << {
|
|
674
|
-
"type" => "loadbalancer",
|
|
675
|
-
"name" => lb['name'],
|
|
676
|
-
"phase" => "groom"
|
|
677
|
-
}
|
|
659
|
+
if lb['name'] and !lb['deploy_id']
|
|
660
|
+
MU::Config.addDependency(acl, lb['name'], "loadbalancer", phase: "groom")
|
|
678
661
|
end
|
|
679
662
|
}
|
|
680
663
|
end
|
|
@@ -716,32 +699,7 @@ module MU
|
|
|
716
699
|
|
|
717
700
|
private
|
|
718
701
|
|
|
719
|
-
|
|
720
|
-
# Manufacture an EC2 security group. The second parameter, rules, is an
|
|
721
|
-
# "ingress_rules" structure parsed and validated by MU::Config.
|
|
722
|
-
#########################################################################
|
|
723
|
-
def setRules(rules, add_to_self: false, ingress: true, egress: false)
|
|
724
|
-
describe
|
|
725
|
-
# XXX warn about attempt to set rules before we exist
|
|
726
|
-
return if rules.nil? or rules.size == 0 or !@cloud_id
|
|
727
|
-
|
|
728
|
-
# add_to_self means that this security is a "member" of its own rules
|
|
729
|
-
# (which is to say, objects that have this SG are allowed in my these
|
|
730
|
-
# rules)
|
|
731
|
-
if add_to_self
|
|
732
|
-
rules.each { |rule|
|
|
733
|
-
if rule['sgs'].nil? or !rule['sgs'].include?(@cloud_id)
|
|
734
|
-
new_rule = rule.clone
|
|
735
|
-
new_rule.delete('hosts')
|
|
736
|
-
rule['sgs'] = Array.new if rule['sgs'].nil?
|
|
737
|
-
rule['sgs'] << @cloud_id
|
|
738
|
-
end
|
|
739
|
-
}
|
|
740
|
-
end
|
|
741
|
-
|
|
742
|
-
ec2_rules = convertToEc2(rules)
|
|
743
|
-
ext_permissions = MU.structToHash(cloud_desc.ip_permissions)
|
|
744
|
-
|
|
702
|
+
def purge_extraneous_rules(ec2_rules, ext_permissions)
|
|
745
703
|
# Purge any old rules that we're sure we created (check the comment)
|
|
746
704
|
# but which are no longer configured.
|
|
747
705
|
ext_permissions.each { |ext_rule|
|
|
@@ -778,97 +736,109 @@ module MU
|
|
|
778
736
|
ip_permissions: [ext_rule]
|
|
779
737
|
)
|
|
780
738
|
end
|
|
781
|
-
|
|
782
739
|
}
|
|
740
|
+
end
|
|
783
741
|
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
}
|
|
803
|
-
break
|
|
804
|
-
end
|
|
805
|
-
}
|
|
806
|
-
if haverule and !different
|
|
807
|
-
MU.log "Security Group rule already up-to-date in #{@mu_name}", MU::DEBUG, details: rule
|
|
808
|
-
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
|
|
809
760
|
end
|
|
761
|
+
}
|
|
762
|
+
end
|
|
810
763
|
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
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)
|
|
823
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
|
|
824
799
|
begin
|
|
825
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).
|
|
800
|
+
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).revoke_security_group_ingress(
|
|
826
801
|
group_id: @cloud_id,
|
|
827
|
-
ip_permissions: [
|
|
802
|
+
ip_permissions: [haverule]
|
|
828
803
|
)
|
|
829
|
-
rescue Aws::EC2::Errors::
|
|
830
|
-
MU.log "FirewallRule #{@mu_name} had a bogus rule: #{e.message}", MU::ERR, details: rule
|
|
831
|
-
raise e
|
|
804
|
+
rescue Aws::EC2::Errors::InvalidPermissionNotFound
|
|
832
805
|
end
|
|
833
806
|
end
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
if haverule
|
|
837
|
-
begin
|
|
838
|
-
MU::Cloud::AWS.ec2(region: @config['region'], credentials: @config['credentials']).revoke_security_group_egress(
|
|
839
|
-
group_id: @cloud_id,
|
|
840
|
-
ip_permissions: [haverule]
|
|
841
|
-
)
|
|
842
|
-
rescue Aws::EC2::Errors::InvalidPermissionNotFound => e
|
|
843
|
-
end
|
|
844
|
-
end
|
|
845
|
-
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(
|
|
846
809
|
group_id: @cloud_id,
|
|
847
810
|
ip_permissions: [rule]
|
|
848
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
|
|
849
815
|
end
|
|
816
|
+
end
|
|
850
817
|
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
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
|
|
859
827
|
end
|
|
860
|
-
|
|
861
|
-
|
|
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
|
+
)
|
|
862
832
|
end
|
|
863
833
|
}
|
|
864
|
-
|
|
834
|
+
}
|
|
865
835
|
|
|
866
836
|
end
|
|
867
837
|
|
|
868
|
-
|
|
869
|
-
# Convert our config languages description of firewall rules into
|
|
870
|
-
#
|
|
871
|
-
|
|
838
|
+
#######################################################################
|
|
839
|
+
# Convert our config languages description of firewall rules into
|
|
840
|
+
# Amazon's. Our rule structure is as defined in MU::Config.
|
|
841
|
+
#######################################################################
|
|
872
842
|
def convertToEc2(rules)
|
|
873
843
|
ec2_rules = []
|
|
874
844
|
if rules != nil
|
|
@@ -992,8 +962,8 @@ module MU
|
|
|
992
962
|
ec2_rules << ec2_rule
|
|
993
963
|
}
|
|
994
964
|
end
|
|
995
|
-
|
|
996
|
-
|
|
965
|
+
|
|
966
|
+
ec2_rules.uniq
|
|
997
967
|
end
|
|
998
968
|
|
|
999
969
|
end #class
|