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.
- checksums.yaml +4 -4
- data/Dockerfile +5 -1
- 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 +16 -12
- 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 -1
- data/bin/mu-node-manage +15 -16
- data/bin/mu-run-tests +37 -12
- data/cloud-mu.gemspec +5 -3
- 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 +1 -1
- 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/selinux.rb +2 -1
- data/cookbooks/mu-tools/recipes/windows-client.rb +163 -164
- 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/modules/mommacat.ru +1 -1
- data/modules/mu.rb +158 -107
- data/modules/mu/adoption.rb +386 -59
- data/modules/mu/cleanup.rb +214 -303
- data/modules/mu/cloud.rb +128 -1632
- data/modules/mu/cloud/database.rb +49 -0
- data/modules/mu/cloud/dnszone.rb +44 -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 +926 -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 +169 -0
- data/modules/mu/config.rb +135 -82
- data/modules/mu/config/alarm.rb +2 -6
- data/modules/mu/config/bucket.rb +32 -3
- data/modules/mu/config/cache_cluster.rb +2 -2
- data/modules/mu/config/cdn.rb +100 -0
- data/modules/mu/config/collection.rb +1 -1
- data/modules/mu/config/container_cluster.rb +7 -2
- data/modules/mu/config/database.rb +84 -105
- data/modules/mu/config/database.yml +1 -2
- data/modules/mu/config/dnszone.rb +5 -4
- data/modules/mu/config/doc_helpers.rb +5 -6
- data/modules/mu/config/endpoint.rb +2 -1
- data/modules/mu/config/firewall_rule.rb +3 -19
- data/modules/mu/config/folder.rb +1 -1
- data/modules/mu/config/function.rb +17 -8
- data/modules/mu/config/group.rb +1 -1
- data/modules/mu/config/habitat.rb +1 -1
- data/modules/mu/config/job.rb +89 -0
- data/modules/mu/config/loadbalancer.rb +57 -11
- data/modules/mu/config/log.rb +1 -1
- data/modules/mu/config/msg_queue.rb +1 -1
- data/modules/mu/config/nosqldb.rb +1 -1
- data/modules/mu/config/notifier.rb +8 -19
- data/modules/mu/config/ref.rb +92 -14
- data/modules/mu/config/role.rb +1 -1
- data/modules/mu/config/schema_helpers.rb +38 -37
- data/modules/mu/config/search_domain.rb +1 -1
- data/modules/mu/config/server.rb +12 -13
- data/modules/mu/config/server.yml +1 -0
- data/modules/mu/config/server_pool.rb +3 -7
- data/modules/mu/config/storage_pool.rb +1 -1
- data/modules/mu/config/tail.rb +11 -0
- data/modules/mu/config/user.rb +1 -1
- data/modules/mu/config/vpc.rb +27 -23
- data/modules/mu/config/vpc.yml +0 -1
- data/modules/mu/defaults/AWS.yaml +91 -68
- data/modules/mu/defaults/Azure.yaml +1 -0
- data/modules/mu/defaults/Google.yaml +1 -0
- data/modules/mu/deploy.rb +33 -19
- data/modules/mu/groomer.rb +16 -1
- data/modules/mu/groomers/ansible.rb +123 -21
- data/modules/mu/groomers/chef.rb +64 -11
- data/modules/mu/logger.rb +120 -144
- data/modules/mu/master.rb +97 -4
- data/modules/mu/master/ssl.rb +0 -1
- data/modules/mu/mommacat.rb +154 -867
- data/modules/mu/mommacat/daemon.rb +23 -14
- data/modules/mu/mommacat/naming.rb +110 -3
- data/modules/mu/mommacat/search.rb +495 -0
- data/modules/mu/mommacat/storage.rb +225 -192
- data/modules/mu/{clouds → providers}/README.md +1 -1
- data/modules/mu/{clouds → providers}/aws.rb +281 -64
- data/modules/mu/{clouds → providers}/aws/alarm.rb +3 -3
- data/modules/mu/{clouds → providers}/aws/bucket.rb +275 -41
- data/modules/mu/{clouds → providers}/aws/cache_cluster.rb +14 -50
- data/modules/mu/providers/aws/cdn.rb +782 -0
- data/modules/mu/{clouds → providers}/aws/collection.rb +5 -5
- data/modules/mu/{clouds → providers}/aws/container_cluster.rb +708 -749
- data/modules/mu/providers/aws/database.rb +1744 -0
- data/modules/mu/{clouds → providers}/aws/dnszone.rb +75 -57
- data/modules/mu/providers/aws/endpoint.rb +1072 -0
- data/modules/mu/{clouds → providers}/aws/firewall_rule.rb +212 -242
- data/modules/mu/{clouds → providers}/aws/folder.rb +1 -1
- data/modules/mu/{clouds → providers}/aws/function.rb +289 -134
- data/modules/mu/{clouds → providers}/aws/group.rb +18 -20
- data/modules/mu/{clouds → providers}/aws/habitat.rb +3 -3
- data/modules/mu/providers/aws/job.rb +466 -0
- data/modules/mu/{clouds → providers}/aws/loadbalancer.rb +50 -41
- data/modules/mu/{clouds → providers}/aws/log.rb +5 -5
- data/modules/mu/{clouds → providers}/aws/msg_queue.rb +14 -11
- data/modules/mu/{clouds → providers}/aws/nosqldb.rb +96 -5
- data/modules/mu/{clouds → providers}/aws/notifier.rb +135 -63
- data/modules/mu/{clouds → providers}/aws/role.rb +94 -57
- data/modules/mu/{clouds → providers}/aws/search_domain.rb +173 -42
- data/modules/mu/{clouds → providers}/aws/server.rb +782 -1107
- data/modules/mu/{clouds → providers}/aws/server_pool.rb +36 -46
- data/modules/mu/{clouds → providers}/aws/storage_pool.rb +21 -38
- data/modules/mu/{clouds → providers}/aws/user.rb +12 -16
- data/modules/mu/{clouds → providers}/aws/userdata/README.md +0 -0
- data/modules/mu/{clouds → providers}/aws/userdata/linux.erb +5 -4
- data/modules/mu/{clouds → providers}/aws/userdata/windows.erb +2 -1
- data/modules/mu/{clouds → providers}/aws/vpc.rb +429 -849
- data/modules/mu/providers/aws/vpc_subnet.rb +286 -0
- data/modules/mu/{clouds → providers}/azure.rb +13 -0
- data/modules/mu/{clouds → providers}/azure/container_cluster.rb +1 -5
- data/modules/mu/{clouds → providers}/azure/firewall_rule.rb +8 -1
- data/modules/mu/{clouds → providers}/azure/habitat.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/loadbalancer.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/role.rb +0 -0
- data/modules/mu/{clouds → providers}/azure/server.rb +32 -24
- data/modules/mu/{clouds → providers}/azure/user.rb +1 -1
- 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 +4 -6
- data/modules/mu/{clouds → providers}/cloudformation.rb +10 -0
- 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 +3 -3
- data/modules/mu/{clouds → providers}/docker.rb +0 -0
- data/modules/mu/{clouds → providers}/google.rb +29 -6
- data/modules/mu/{clouds → providers}/google/bucket.rb +5 -5
- data/modules/mu/{clouds → providers}/google/container_cluster.rb +59 -37
- data/modules/mu/{clouds → providers}/google/database.rb +5 -12
- data/modules/mu/{clouds → providers}/google/firewall_rule.rb +5 -5
- data/modules/mu/{clouds → providers}/google/folder.rb +5 -9
- data/modules/mu/{clouds → providers}/google/function.rb +14 -8
- data/modules/mu/{clouds → providers}/google/group.rb +9 -17
- data/modules/mu/{clouds → providers}/google/habitat.rb +4 -8
- data/modules/mu/{clouds → providers}/google/loadbalancer.rb +5 -5
- data/modules/mu/{clouds → providers}/google/role.rb +50 -31
- data/modules/mu/{clouds → providers}/google/server.rb +142 -55
- data/modules/mu/{clouds → providers}/google/server_pool.rb +14 -14
- data/modules/mu/{clouds → providers}/google/user.rb +34 -24
- 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 +46 -15
- data/modules/tests/aws-jobs-functions.yaml +46 -0
- data/modules/tests/centos6.yaml +15 -0
- data/modules/tests/centos7.yaml +15 -0
- data/modules/tests/centos8.yaml +12 -0
- data/modules/tests/ecs.yaml +23 -0
- data/modules/tests/eks.yaml +1 -1
- data/modules/tests/functions/node-function/lambda_function.js +10 -0
- data/modules/tests/functions/python-function/lambda_function.py +12 -0
- data/modules/tests/includes-and-params.yaml +2 -1
- data/modules/tests/microservice_app.yaml +288 -0
- data/modules/tests/rds.yaml +108 -0
- data/modules/tests/regrooms/rds.yaml +123 -0
- data/modules/tests/server-with-scrub-muisms.yaml +2 -1
- data/modules/tests/super_complex_bok.yml +2 -2
- data/modules/tests/super_simple_bok.yml +3 -5
- data/modules/tests/win2k12.yaml +25 -0
- 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 +169 -93
- data/extras/image-generators/AWS/windows.yaml +0 -18
- data/modules/mu/clouds/aws/database.rb +0 -1974
- data/modules/mu/clouds/aws/endpoint.rb +0 -596
- data/modules/tests/needwork/win2k12.yaml +0 -13
|
@@ -89,7 +89,7 @@ Looking elsewhere in `cloud.rb` let's see what all we have to do:
|
|
|
89
89
|
generic_instance_methods = [:create, :notify, :mu_name, :cloud_id, :config]
|
|
90
90
|
```
|
|
91
91
|
|
|
92
|
-
Just the basics, for now. Here's what that will look like in the AWS layer, in the file `modules/mu/
|
|
92
|
+
Just the basics, for now. Here's what that will look like in the AWS layer, in the file `modules/mu/providers/aws/function.rb`:
|
|
93
93
|
|
|
94
94
|
```
|
|
95
95
|
module MU
|
|
@@ -33,6 +33,18 @@ module MU
|
|
|
33
33
|
module AdditionalResourceMethods
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
# Is this a "real" cloud provider, or a stub like CloudFormation?
|
|
37
|
+
def self.virtual?
|
|
38
|
+
false
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# List all AWS projects available to our credentials
|
|
42
|
+
def self.listHabitats(credentials = nil, use_cache: true)
|
|
43
|
+
cfg = credConfig(credentials)
|
|
44
|
+
return [] if !cfg or !cfg['account_number']
|
|
45
|
+
[cfg['account_number']]
|
|
46
|
+
end
|
|
47
|
+
|
|
36
48
|
# A hook that is always called just before any of the instance method of
|
|
37
49
|
# our resource implementations gets invoked, so that we can ensure that
|
|
38
50
|
# repetitive setup tasks (like resolving +:resource_group+ for Azure
|
|
@@ -182,18 +194,34 @@ end
|
|
|
182
194
|
end
|
|
183
195
|
end
|
|
184
196
|
|
|
185
|
-
# Tag
|
|
197
|
+
# Tag an EC2 resource
|
|
186
198
|
#
|
|
187
199
|
# @param resource [String]: The cloud provider identifier of the resource to tag
|
|
188
200
|
# @param region [String]: The cloud provider region
|
|
201
|
+
# @param credentials [String]: Credentials to authorize API requests
|
|
202
|
+
# @param optional [Boolean]: Whether to apply our optional generic tags
|
|
203
|
+
# @param nametag [String]: A +Name+ tag to apply
|
|
204
|
+
# @param othertags [Array<Hash>]: Miscellaneous custom tags, in Basket of Kittens style
|
|
189
205
|
# @return [void]
|
|
190
|
-
def self.createStandardTags(resource = nil, region: MU.curRegion, credentials: nil)
|
|
206
|
+
def self.createStandardTags(resource = nil, region: MU.curRegion, credentials: nil, optional: true, nametag: nil, othertags: nil)
|
|
191
207
|
tags = []
|
|
192
208
|
MU::MommaCat.listStandardTags.each_pair { |name, value|
|
|
193
|
-
if !value.nil?
|
|
194
|
-
tags << {key: name, value: value}
|
|
195
|
-
end
|
|
209
|
+
tags << {key: name, value: value} if !value.nil?
|
|
196
210
|
}
|
|
211
|
+
if optional
|
|
212
|
+
MU::MommaCat.listOptionalTags.each { |key, value|
|
|
213
|
+
tags << {key: name, value: value} if !value.nil?
|
|
214
|
+
}
|
|
215
|
+
end
|
|
216
|
+
if nametag
|
|
217
|
+
tags << { key: "Name", value: nametag }
|
|
218
|
+
end
|
|
219
|
+
if othertags
|
|
220
|
+
othertags.each { |tag|
|
|
221
|
+
tags << { key: tag['key'], value: tag['value'] }
|
|
222
|
+
}
|
|
223
|
+
end
|
|
224
|
+
|
|
197
225
|
if MU::Cloud::CloudFormation.emitCloudFormation
|
|
198
226
|
return tags
|
|
199
227
|
end
|
|
@@ -215,6 +243,7 @@ end
|
|
|
215
243
|
end
|
|
216
244
|
end
|
|
217
245
|
MU.log "Created standard tags for resource #{resource}", MU::DEBUG, details: caller
|
|
246
|
+
|
|
218
247
|
end
|
|
219
248
|
|
|
220
249
|
@@myVPCObj = nil
|
|
@@ -327,6 +356,27 @@ end
|
|
|
327
356
|
# etc)
|
|
328
357
|
# @param deploy_id [MU::MommaCat]
|
|
329
358
|
def self.cleanDeploy(deploy_id, credentials: nil, noop: false)
|
|
359
|
+
|
|
360
|
+
if !noop
|
|
361
|
+
MU.log "Deleting s3://#{adminBucketName(credentials)}/#{deploy_id}-secret"
|
|
362
|
+
MU::Cloud::AWS.s3(credentials: credentials).delete_object(
|
|
363
|
+
bucket: adminBucketName(credentials),
|
|
364
|
+
key: "#{deploy_id}-secret"
|
|
365
|
+
)
|
|
366
|
+
listRegions(credentials: credentials).each { |r|
|
|
367
|
+
resp = MU::Cloud::AWS.ec2(region: r, credentials: credentials).describe_key_pairs(
|
|
368
|
+
filters: [{name: "key-name", values: ["deploy-#{MU.deploy_id}"]}]
|
|
369
|
+
)
|
|
370
|
+
resp.data.key_pairs.each { |keypair|
|
|
371
|
+
MU.log "Deleting key pair #{keypair.key_name} from #{r}"
|
|
372
|
+
MU::Cloud::AWS.ec2(region: r, credentials: credentials).delete_key_pair(key_name: keypair.key_name) if !noop
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
end
|
|
377
|
+
if hosted?
|
|
378
|
+
MU::Cloud::AWS.openFirewallForClients
|
|
379
|
+
end
|
|
330
380
|
end
|
|
331
381
|
|
|
332
382
|
# Plant a Mu deploy secret into a storage bucket somewhere for so our kittens can consume it
|
|
@@ -406,7 +456,7 @@ end
|
|
|
406
456
|
end
|
|
407
457
|
|
|
408
458
|
begin
|
|
409
|
-
Timeout.timeout(
|
|
459
|
+
Timeout.timeout(4) do
|
|
410
460
|
instance_id = open("http://169.254.169.254/latest/meta-data/instance-id").read
|
|
411
461
|
if !instance_id.nil? and instance_id.size > 0
|
|
412
462
|
@@is_in_aws = true
|
|
@@ -755,50 +805,47 @@ end
|
|
|
755
805
|
|
|
756
806
|
@@instance_types ||= {}
|
|
757
807
|
@@instance_types[region] ||= {}
|
|
758
|
-
next_token = nil
|
|
759
808
|
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
type: "TERM_MATCH"
|
|
780
|
-
}
|
|
781
|
-
],
|
|
782
|
-
next_token: next_token
|
|
783
|
-
)
|
|
784
|
-
resp.price_list.each { |pricing|
|
|
785
|
-
data = JSON.parse(pricing)
|
|
786
|
-
type = data["product"]["attributes"]["instanceType"]
|
|
787
|
-
next if @@instance_types[region].has_key?(type)
|
|
788
|
-
@@instance_types[region][type] = {}
|
|
789
|
-
["ecu", "vcpu", "memory", "storage"].each { |a|
|
|
790
|
-
@@instance_types[region][type][a] = data["product"]["attributes"][a]
|
|
809
|
+
# Pricing API isn't widely available, so ask a region we know supports
|
|
810
|
+
# it
|
|
811
|
+
resp = MU::Cloud::AWS.pricing(region: "us-east-1").get_products(
|
|
812
|
+
service_code: "AmazonEC2",
|
|
813
|
+
filters: [
|
|
814
|
+
{
|
|
815
|
+
field: "productFamily",
|
|
816
|
+
value: "Compute Instance",
|
|
817
|
+
type: "TERM_MATCH"
|
|
818
|
+
},
|
|
819
|
+
{
|
|
820
|
+
field: "tenancy",
|
|
821
|
+
value: "Shared",
|
|
822
|
+
type: "TERM_MATCH"
|
|
823
|
+
},
|
|
824
|
+
{
|
|
825
|
+
field: "location",
|
|
826
|
+
value: human_region,
|
|
827
|
+
type: "TERM_MATCH"
|
|
791
828
|
}
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
829
|
+
]
|
|
830
|
+
)
|
|
831
|
+
resp.price_list.each { |pricing|
|
|
832
|
+
data = JSON.parse(pricing)
|
|
833
|
+
type = data["product"]["attributes"]["instanceType"]
|
|
834
|
+
next if @@instance_types[region].has_key?(type)
|
|
835
|
+
@@instance_types[region][type] = {}
|
|
836
|
+
["ecu", "vcpu", "memory", "storage"].each { |a|
|
|
837
|
+
@@instance_types[region][type][a] = data["product"]["attributes"][a]
|
|
795
838
|
}
|
|
796
|
-
|
|
797
|
-
|
|
839
|
+
@@instance_types[region][type]["memory"].sub!(/ GiB/, "")
|
|
840
|
+
@@instance_types[region][type]["memory"] = @@instance_types[region][type]["memory"].to_f
|
|
841
|
+
@@instance_types[region][type]["vcpu"] = @@instance_types[region][type]["vcpu"].to_f
|
|
842
|
+
}
|
|
798
843
|
|
|
799
844
|
@@instance_types
|
|
800
845
|
end
|
|
801
846
|
|
|
847
|
+
@@certificates = {}
|
|
848
|
+
|
|
802
849
|
# AWS can stash API-available certificates in Amazon Certificate Manager
|
|
803
850
|
# or in IAM. Rather than make people crazy trying to get the syntax
|
|
804
851
|
# correct in our Baskets of Kittens, let's have a helper that tries to do
|
|
@@ -807,21 +854,24 @@ end
|
|
|
807
854
|
# @param name [String]: The name of the cert. For IAM certs this can be any IAM name; for ACM, it's usually the domain name. If multiple matches are found, or no matches, an exception is raised.
|
|
808
855
|
# @param id [String]: The ARN of a known certificate. We just validate that it exists. This is ignored if a name parameter is supplied.
|
|
809
856
|
# @return [String]: The ARN of a matching certificate that is known to exist. If it is an ACM certificate, we also know that it is not expired.
|
|
810
|
-
def self.findSSLCertificate(name: nil, id: nil, region: myRegion)
|
|
811
|
-
if name.nil?
|
|
857
|
+
def self.findSSLCertificate(name: nil, id: nil, region: myRegion, credentials: nil, raise_on_missing: true)
|
|
858
|
+
if (name.nil? or name.empty?) and (id.nil? or id.empty?)
|
|
812
859
|
raise MuError, "Can't call findSSLCertificate without specifying either a name or an id"
|
|
813
860
|
end
|
|
861
|
+
if id and @@certificates[id]
|
|
862
|
+
return [id, @@certificates[id]]
|
|
863
|
+
end
|
|
814
864
|
|
|
815
865
|
if !name.nil? and !name.empty?
|
|
816
866
|
matches = []
|
|
817
|
-
acmcerts = MU::Cloud::AWS.acm(region: region).list_certificates(
|
|
867
|
+
acmcerts = MU::Cloud::AWS.acm(region: region, credentials: credentials).list_certificates(
|
|
818
868
|
certificate_statuses: ["ISSUED"]
|
|
819
869
|
)
|
|
820
870
|
acmcerts.certificate_summary_list.each { |cert|
|
|
821
871
|
matches << cert.certificate_arn if cert.domain_name == name
|
|
822
872
|
}
|
|
823
873
|
begin
|
|
824
|
-
iamcert = MU::Cloud::AWS.iam.get_server_certificate(
|
|
874
|
+
iamcert = MU::Cloud::AWS.iam(credentials: credentials).get_server_certificate(
|
|
825
875
|
server_certificate_name: name
|
|
826
876
|
)
|
|
827
877
|
rescue Aws::IAM::Errors::ValidationError, Aws::IAM::Errors::NoSuchEntity
|
|
@@ -831,32 +881,45 @@ end
|
|
|
831
881
|
matches << iamcert.server_certificate.server_certificate_metadata.arn
|
|
832
882
|
end
|
|
833
883
|
if matches.size == 1
|
|
834
|
-
|
|
884
|
+
id = matches.first
|
|
835
885
|
elsif matches.size == 0
|
|
836
|
-
|
|
886
|
+
if raise_on_missing
|
|
887
|
+
raise MuError, "No IAM or ACM certificate named #{name} was found in #{region}"
|
|
888
|
+
else
|
|
889
|
+
return nil
|
|
890
|
+
end
|
|
837
891
|
elsif matches.size > 1
|
|
838
892
|
raise MuError, "Multiple certificates named #{name} were found in #{region}. Remove extras or use ssl_certificate_id to supply the exact ARN of the one you want to use."
|
|
839
893
|
end
|
|
840
894
|
end
|
|
841
895
|
|
|
896
|
+
domains = []
|
|
897
|
+
|
|
842
898
|
if id.match(/^arn:aws(?:-us-gov)?:acm/)
|
|
843
|
-
resp = MU::Cloud::AWS.acm(region: region).
|
|
899
|
+
resp = MU::Cloud::AWS.acm(region: region).describe_certificate(
|
|
844
900
|
certificate_arn: id
|
|
845
901
|
)
|
|
846
|
-
|
|
902
|
+
|
|
903
|
+
if resp.nil? or resp.certificate.nil?
|
|
847
904
|
raise MuError, "No such ACM certificate '#{id}'"
|
|
848
905
|
end
|
|
906
|
+
domains << resp.certificate.domain_name
|
|
907
|
+
if resp.certificate.subject_alternative_names
|
|
908
|
+
domains.concat(resp.certificate.subject_alternative_names)
|
|
909
|
+
end
|
|
849
910
|
elsif id.match(/^arn:aws(?:-us-gov)?:iam/)
|
|
850
911
|
resp = MU::Cloud::AWS.iam.list_server_certificates
|
|
851
912
|
if resp.nil?
|
|
852
913
|
raise MuError, "No such IAM certificate '#{id}'"
|
|
853
914
|
end
|
|
854
915
|
resp.server_certificate_metadata_list.each { |cert|
|
|
916
|
+
|
|
855
917
|
if cert.arn == id
|
|
856
918
|
if cert.expiration < Time.now
|
|
857
919
|
MU.log "IAM SSL certificate #{cert.server_certificate_name} (#{id}) is EXPIRED", MU::WARN
|
|
858
920
|
end
|
|
859
|
-
|
|
921
|
+
@@certificates[id] = [cert.server_certificate_name]
|
|
922
|
+
return [id, [cert.server_certificate_name]]
|
|
860
923
|
end
|
|
861
924
|
}
|
|
862
925
|
raise MuError, "No such IAM certificate '#{id}'"
|
|
@@ -864,7 +927,56 @@ end
|
|
|
864
927
|
raise MuError, "The format of '#{id}' doesn't look like an ARN for either Amazon Certificate Manager or IAM"
|
|
865
928
|
end
|
|
866
929
|
|
|
867
|
-
id
|
|
930
|
+
@@certificates[id] = domains.uniq
|
|
931
|
+
[id, domains.uniq]
|
|
932
|
+
end
|
|
933
|
+
|
|
934
|
+
# Given a domain name and an ACM or IAM certificate identifier, sort out
|
|
935
|
+
# whether the domain name is "covered" by the certificate
|
|
936
|
+
# @param name [String]
|
|
937
|
+
# @param cert_id [String]
|
|
938
|
+
# @return [Boolean]
|
|
939
|
+
def self.nameMatchesCertificate(name, cert_id)
|
|
940
|
+
_id, domains = findSSLCertificate(id: cert_id)
|
|
941
|
+
return false if !domains
|
|
942
|
+
domains.each { |dom|
|
|
943
|
+
if dom == name or
|
|
944
|
+
(dom =~ /^\*/ and name =~ /.*#{Regexp.quote(dom[1..-1])}/)
|
|
945
|
+
return true
|
|
946
|
+
end
|
|
947
|
+
}
|
|
948
|
+
false
|
|
949
|
+
end
|
|
950
|
+
|
|
951
|
+
# Given a {MU::Config::Ref} block for an IAM or ACM SSL certificate,
|
|
952
|
+
# look up and validate the specified certificate. This is intended to be
|
|
953
|
+
# invoked from resource implementations' +validateConfig+ methods.
|
|
954
|
+
# @param certblock [Hash,MU::Config::Ref]:
|
|
955
|
+
# @param region [String]: Default region to use when looking up the certificate, if its configuration block does not specify any
|
|
956
|
+
# @param credentials [String]: Default credentials to use when looking up the certificate, if its configuration block does not specify any
|
|
957
|
+
# @return [Boolean]
|
|
958
|
+
def self.resolveSSLCertificate(certblock, region: nil, credentials: nil)
|
|
959
|
+
return false if !certblock
|
|
960
|
+
ok = true
|
|
961
|
+
|
|
962
|
+
certblock['region'] ||= region if !certblock['id']
|
|
963
|
+
certblock['credentials'] ||= credentials
|
|
964
|
+
cert_arn, cert_domains = MU::Cloud::AWS.findSSLCertificate(
|
|
965
|
+
name: certblock["name"],
|
|
966
|
+
id: certblock["id"],
|
|
967
|
+
region: certblock['region'],
|
|
968
|
+
credentials: certblock['credentials']
|
|
969
|
+
)
|
|
970
|
+
|
|
971
|
+
if cert_arn
|
|
972
|
+
certblock['id'] ||= cert_arn
|
|
973
|
+
end
|
|
974
|
+
|
|
975
|
+
['region', 'credentials'].each { |field|
|
|
976
|
+
certblock.delete(field) if certblock[field].nil?
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
[cert_arn, cert_domains]
|
|
868
980
|
end
|
|
869
981
|
|
|
870
982
|
# Amazon Certificate Manager API
|
|
@@ -984,6 +1096,14 @@ end
|
|
|
984
1096
|
@@cloudwatchlogs_api[credentials][region]
|
|
985
1097
|
end
|
|
986
1098
|
|
|
1099
|
+
# Amazon's CloudWatchEvents API
|
|
1100
|
+
def self.cloudwatchevents(region: MU.curRegion, credentials: nil)
|
|
1101
|
+
region ||= myRegion
|
|
1102
|
+
@@cloudwatchevents_api[credentials] ||= {}
|
|
1103
|
+
@@cloudwatchevents_api[credentials][region] ||= MU::Cloud::AWS::AmazonEndpoint.new(api: "CloudWatchEvents", region: region, credentials: credentials)
|
|
1104
|
+
@@cloudwatchevents_api[credentials][region]
|
|
1105
|
+
end
|
|
1106
|
+
|
|
987
1107
|
# Amazon's CloudFront API
|
|
988
1108
|
def self.cloudfront(region: MU.curRegion, credentials: nil)
|
|
989
1109
|
region ||= myRegion
|
|
@@ -1072,6 +1192,14 @@ end
|
|
|
1072
1192
|
@@dynamo_api[credentials][region]
|
|
1073
1193
|
end
|
|
1074
1194
|
|
|
1195
|
+
# Amazon's DynamoStream API
|
|
1196
|
+
def self.dynamostream(region: MU.curRegion, credentials: nil)
|
|
1197
|
+
region ||= myRegion
|
|
1198
|
+
@@dynamostream_api[credentials] ||= {}
|
|
1199
|
+
@@dynamostream_api[credentials][region] ||= MU::Cloud::AWS::AmazonEndpoint.new(api: "DynamoDBStreams", region: region, credentials: credentials)
|
|
1200
|
+
@@dynamostream_api[credentials][region]
|
|
1201
|
+
end
|
|
1202
|
+
|
|
1075
1203
|
# Amazon's Pricing API
|
|
1076
1204
|
def self.pricing(region: MU.curRegion, credentials: nil)
|
|
1077
1205
|
region ||= myRegion
|
|
@@ -1120,6 +1248,14 @@ end
|
|
|
1120
1248
|
@@kms_api[credentials][region]
|
|
1121
1249
|
end
|
|
1122
1250
|
|
|
1251
|
+
# Amazon's CloudFront API
|
|
1252
|
+
def self.cloudfront(region: MU.curRegion, credentials: nil)
|
|
1253
|
+
region ||= myRegion
|
|
1254
|
+
@@cloudfront_api[credentials] ||= {}
|
|
1255
|
+
@@cloudfront_api[credentials][region] ||= MU::Cloud::AWS::AmazonEndpoint.new(api: "CloudFront", region: region, credentials: credentials)
|
|
1256
|
+
@@cloudfront_api[credentials][region]
|
|
1257
|
+
end
|
|
1258
|
+
|
|
1123
1259
|
# Amazon's Organizations API
|
|
1124
1260
|
def self.orgs(credentials: nil)
|
|
1125
1261
|
@@organizations_api ||= {}
|
|
@@ -1150,7 +1286,6 @@ end
|
|
|
1150
1286
|
|
|
1151
1287
|
# Tag a resource. Defaults to applying our MU deployment identifier, if no
|
|
1152
1288
|
# arguments other than the resource identifier are given.
|
|
1153
|
-
# XXX this belongs in the cloud layer(s)
|
|
1154
1289
|
#
|
|
1155
1290
|
# @param resource [String]: The cloud provider identifier of the resource to tag
|
|
1156
1291
|
# @param tag_name [String]: The name of the tag to create
|
|
@@ -1202,7 +1337,7 @@ end
|
|
|
1202
1337
|
# Mu Master, if we're in AWS.
|
|
1203
1338
|
# @return [void]
|
|
1204
1339
|
def self.openFirewallForClients
|
|
1205
|
-
MU::Cloud.
|
|
1340
|
+
MU::Cloud.resourceClass("AWS", :FirewallRule)
|
|
1206
1341
|
begin
|
|
1207
1342
|
if File.exist?(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
|
|
1208
1343
|
::Chef::Config.from_file(Etc.getpwuid(Process.uid).dir+"/.chef/knife.rb")
|
|
@@ -1378,7 +1513,7 @@ end
|
|
|
1378
1513
|
# Create an AWS API client
|
|
1379
1514
|
# @param region [String]: Amazon region so we know what endpoint to use
|
|
1380
1515
|
# @param api [String]: Which API are we wrapping?
|
|
1381
|
-
def initialize(region:
|
|
1516
|
+
def initialize(region: nil, api: "EC2", credentials: nil)
|
|
1382
1517
|
@cred_obj = MU::Cloud::AWS.loadCredentials(credentials)
|
|
1383
1518
|
@credentials = MU::Cloud::AWS.credConfig(credentials, name_only: true)
|
|
1384
1519
|
|
|
@@ -1387,6 +1522,8 @@ end
|
|
|
1387
1522
|
end
|
|
1388
1523
|
|
|
1389
1524
|
params = {}
|
|
1525
|
+
region ||= MU::Cloud::AWS.credConfig(credentials)['region']
|
|
1526
|
+
region ||= MU.myRegion
|
|
1390
1527
|
|
|
1391
1528
|
if region
|
|
1392
1529
|
@region = region
|
|
@@ -1403,21 +1540,98 @@ end
|
|
|
1403
1540
|
# Catch-all for AWS client methods. Essentially a pass-through with some
|
|
1404
1541
|
# rescues for known silly endpoint behavior.
|
|
1405
1542
|
def method_missing(method_sym, *arguments)
|
|
1543
|
+
# make sure error symbols are loaded for our exception handling later
|
|
1406
1544
|
require "aws-sdk-core"
|
|
1545
|
+
require "aws-sdk-core/rds"
|
|
1546
|
+
require "aws-sdk-core/ec2"
|
|
1547
|
+
require "aws-sdk-core/route53"
|
|
1548
|
+
require "aws-sdk-core/iam"
|
|
1549
|
+
require "aws-sdk-core/efs"
|
|
1550
|
+
require "aws-sdk-core/pricing"
|
|
1551
|
+
require "aws-sdk-core/apigateway"
|
|
1552
|
+
require "aws-sdk-core/ecs"
|
|
1553
|
+
require "aws-sdk-core/eks"
|
|
1554
|
+
require "aws-sdk-core/cloudwatchlogs"
|
|
1555
|
+
require "aws-sdk-core/cloudwatchevents"
|
|
1556
|
+
require "aws-sdk-core/elasticloadbalancing"
|
|
1557
|
+
require "aws-sdk-core/elasticloadbalancingv2"
|
|
1558
|
+
require "aws-sdk-core/autoscaling"
|
|
1559
|
+
require "aws-sdk-core/client_waiters"
|
|
1560
|
+
require "aws-sdk-core/waiters/errors"
|
|
1407
1561
|
|
|
1408
1562
|
retries = 0
|
|
1409
1563
|
begin
|
|
1410
1564
|
MU.log "Calling #{method_sym} in #{@region}", MU::DEBUG, details: arguments
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1565
|
+
|
|
1566
|
+
retval = if !arguments.nil? and arguments.size == 1
|
|
1567
|
+
@api.method(method_sym).call(arguments[0])
|
|
1568
|
+
elsif !arguments.nil? and arguments.size > 0
|
|
1569
|
+
@api.method(method_sym).call(*arguments)
|
|
1570
|
+
else
|
|
1571
|
+
@api.method(method_sym).call
|
|
1572
|
+
end
|
|
1573
|
+
|
|
1574
|
+
if !retval.nil?
|
|
1575
|
+
begin
|
|
1576
|
+
page_markers = {
|
|
1577
|
+
:marker => :marker,
|
|
1578
|
+
:next_token => :next_token,
|
|
1579
|
+
:next_marker => :marker
|
|
1580
|
+
}
|
|
1581
|
+
paginator = nil
|
|
1582
|
+
new_page = nil
|
|
1583
|
+
page_markers.each_key { |m|
|
|
1584
|
+
if !retval.nil? and retval.respond_to?(m)
|
|
1585
|
+
paginator = m
|
|
1586
|
+
new_page = retval.send(m)
|
|
1587
|
+
break
|
|
1588
|
+
end
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
if paginator and new_page and !new_page.empty?
|
|
1592
|
+
resp = retval.respond_to?(:__getobj__) ? retval.__getobj__ : retval
|
|
1593
|
+
concat_to = resp.class.instance_methods(false).reject { |m|
|
|
1594
|
+
m.to_s.match(/=$/) or m == paginator or resp.send(m).nil? or !resp.send(m).is_a?(Array)
|
|
1595
|
+
}
|
|
1596
|
+
if concat_to.size != 1
|
|
1597
|
+
MU.log "Tried to figure out where I might append paginated results for a #{resp.class.name}, but failed", MU::DEBUG, details: concat_to
|
|
1598
|
+
else
|
|
1599
|
+
concat_to = concat_to.first
|
|
1600
|
+
new_args = arguments ? arguments.dup : [{}]
|
|
1601
|
+
begin
|
|
1602
|
+
if new_args.is_a?(Array)
|
|
1603
|
+
new_args << {} if new_args.empty?
|
|
1604
|
+
if new_args.size == 1 and new_args.first.is_a?(Hash)
|
|
1605
|
+
new_args[0][page_markers[paginator]] = new_page
|
|
1606
|
+
else
|
|
1607
|
+
MU.log "I don't know how to insert a #{paginator} into these arguments for #{method_sym}", MU::WARN, details: new_args
|
|
1608
|
+
end
|
|
1609
|
+
elsif new_args.is_a?(Hash)
|
|
1610
|
+
new_args[page_markers[paginator]] = new_page
|
|
1611
|
+
end
|
|
1612
|
+
|
|
1613
|
+
MU.log "Attempting magic pagination for #{method_sym}", MU::DEBUG, details: new_args
|
|
1614
|
+
|
|
1615
|
+
# resp = if !arguments.nil? and arguments.size == 1
|
|
1616
|
+
# @api.method(method_sym).call(new_args[0])
|
|
1617
|
+
# elsif !arguments.nil? and arguments.size > 0
|
|
1618
|
+
resp = @api.method(method_sym).call(*new_args)
|
|
1619
|
+
# end
|
|
1620
|
+
break if resp.nil?
|
|
1621
|
+
resp = resp.__getobj__ if resp.respond_to?(:__getobj__)
|
|
1622
|
+
retval.send(concat_to).concat(resp.send(concat_to))
|
|
1623
|
+
new_page = resp.send(paginator) if !resp.nil?
|
|
1624
|
+
end while !resp.nil? and !new_page.nil? and !new_page.empty?
|
|
1625
|
+
end
|
|
1626
|
+
end
|
|
1627
|
+
rescue StandardError => e
|
|
1628
|
+
MU.log "Made a good-faith effort to auto-paginate API call to #{method_sym} and failed with #{e.message}", MU::DEBUG, details: arguments
|
|
1629
|
+
raise e
|
|
1630
|
+
end
|
|
1418
1631
|
end
|
|
1632
|
+
|
|
1419
1633
|
return retval
|
|
1420
|
-
rescue Aws::EC2::Errors::InternalError, Aws::EC2::Errors::RequestLimitExceeded, Aws::EC2::Errors::Unavailable, Aws::Route53::Errors::Throttling, Aws::ElasticLoadBalancing::Errors::HttpFailureException, Aws::EC2::Errors::Http503Error, Aws::AutoScaling::Errors::Http503Error, Aws::AutoScaling::Errors::InternalFailure, Aws::AutoScaling::Errors::ServiceUnavailable, Aws::Route53::Errors::ServiceUnavailable, Aws::ElasticLoadBalancing::Errors::Throttling, Aws::RDS::Errors::ClientUnavailable, Aws::Waiters::Errors::UnexpectedError, Aws::ElasticLoadBalancing::Errors::ServiceUnavailable, Aws::ElasticLoadBalancingV2::Errors::Throttling, Seahorse::Client::NetworkingError, Aws::IAM::Errors::Throttling, Aws::EFS::Errors::ThrottlingException, Aws::Pricing::Errors::ThrottlingException, Aws::APIGateway::Errors::TooManyRequestsException, Aws::ECS::Errors::ThrottlingException, Net::ReadTimeout, Faraday::TimeoutError, Aws::CloudWatchLogs::Errors::ThrottlingException => e
|
|
1634
|
+
rescue Aws::Lambda::Errors::TooManyRequestsException, Aws::RDS::Errors::Throttling, Aws::EC2::Errors::InternalError, Aws::EC2::Errors::RequestLimitExceeded, Aws::EC2::Errors::Unavailable, Aws::Route53::Errors::Throttling, Aws::ElasticLoadBalancing::Errors::HttpFailureException, Aws::EC2::Errors::Http503Error, Aws::AutoScaling::Errors::Http503Error, Aws::AutoScaling::Errors::InternalFailure, Aws::AutoScaling::Errors::ServiceUnavailable, Aws::Route53::Errors::ServiceUnavailable, Aws::ElasticLoadBalancing::Errors::Throttling, Aws::RDS::Errors::ClientUnavailable, Aws::Waiters::Errors::UnexpectedError, Aws::ElasticLoadBalancing::Errors::ServiceUnavailable, Aws::ElasticLoadBalancingV2::Errors::Throttling, Seahorse::Client::NetworkingError, Aws::IAM::Errors::Throttling, Aws::EFS::Errors::ThrottlingException, Aws::Pricing::Errors::ThrottlingException, Aws::APIGateway::Errors::TooManyRequestsException, Aws::ECS::Errors::ThrottlingException, Net::ReadTimeout, Faraday::TimeoutError, Aws::CloudWatchLogs::Errors::ThrottlingException => e
|
|
1421
1635
|
if e.class.name == "Seahorse::Client::NetworkingError" and e.message.match(/Name or service not known/)
|
|
1422
1636
|
MU.log e.inspect, MU::ERR
|
|
1423
1637
|
raise e
|
|
@@ -1459,6 +1673,7 @@ end
|
|
|
1459
1673
|
@@wafglobal = {}
|
|
1460
1674
|
@@waf = {}
|
|
1461
1675
|
@@cloudwatchlogs_api = {}
|
|
1676
|
+
@@cloudwatchevents_api = {}
|
|
1462
1677
|
@@cloudfront_api = {}
|
|
1463
1678
|
@@elasticache_api = {}
|
|
1464
1679
|
@@sns_api = {}
|
|
@@ -1477,6 +1692,8 @@ end
|
|
|
1477
1692
|
@@kms_api ={}
|
|
1478
1693
|
@@organization_api ={}
|
|
1479
1694
|
@@dynamo_api ={}
|
|
1695
|
+
@@dynamostream_api ={}
|
|
1696
|
+
@@cloudfront_api ={}
|
|
1480
1697
|
end
|
|
1481
1698
|
end
|
|
1482
1699
|
end
|