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
|
@@ -64,10 +64,9 @@ module MU
|
|
|
64
64
|
size = @config['basis']['launch_config']['size']
|
|
65
65
|
@config['image_id'] = @config['basis']['launch_config']['image_id']
|
|
66
66
|
end
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
end
|
|
67
|
+
# XXX this should create a non-regional instance group
|
|
68
|
+
# az = @config['availability_zone']
|
|
69
|
+
# az ||= MU::Cloud::Google.listAZs(@config['region']).sample
|
|
71
70
|
|
|
72
71
|
metadata = { # :items?
|
|
73
72
|
"startup-script" => @userdata
|
|
@@ -90,8 +89,8 @@ module MU
|
|
|
90
89
|
machine_type: size,
|
|
91
90
|
service_accounts: [@service_acct],
|
|
92
91
|
labels: labels,
|
|
93
|
-
disks: MU::Cloud
|
|
94
|
-
network_interfaces: MU::Cloud
|
|
92
|
+
disks: MU::Cloud.resourceClass("Google", "Server").diskConfig(@config, false, false, credentials: @config['credentials']),
|
|
93
|
+
network_interfaces: MU::Cloud.resourceClass("Google", "Server").interfaceConfig(@config, @vpc),
|
|
95
94
|
metadata: metadata,
|
|
96
95
|
tags: MU::Cloud::Google.compute(:Tags).new(items: [MU::Cloud::Google.nameStr(@mu_name)])
|
|
97
96
|
)
|
|
@@ -170,8 +169,7 @@ module MU
|
|
|
170
169
|
# Locate an existing ServerPool or ServerPools and return an array containing matching Google resource descriptors for those that match.
|
|
171
170
|
# @return [Hash<String,OpenStruct>]: The cloud provider's complete descriptions of matching ServerPools
|
|
172
171
|
def self.find(**args)
|
|
173
|
-
args
|
|
174
|
-
args[:project] ||= MU::Cloud::Google.defaultProject(args[:credentials])
|
|
172
|
+
args = MU::Cloud::Google.findLocationArgs(args)
|
|
175
173
|
|
|
176
174
|
regions = if args[:region]
|
|
177
175
|
[args[:region]]
|
|
@@ -213,7 +211,7 @@ module MU
|
|
|
213
211
|
# Reverse-map our cloud description into a runnable config hash.
|
|
214
212
|
# We assume that any values we have in +@config+ are placeholders, and
|
|
215
213
|
# calculate our own accordingly based on what's live in the cloud.
|
|
216
|
-
def toKitten(
|
|
214
|
+
def toKitten(**_args)
|
|
217
215
|
bok = {
|
|
218
216
|
"cloud" => "Google",
|
|
219
217
|
"credentials" => @credentials,
|
|
@@ -326,11 +324,11 @@ end
|
|
|
326
324
|
def self.schema(config)
|
|
327
325
|
toplevel_required = []
|
|
328
326
|
schema = {
|
|
329
|
-
"ssh_user" => MU::Cloud
|
|
330
|
-
"metadata" => MU::Cloud
|
|
331
|
-
"service_account" => MU::Cloud
|
|
332
|
-
"scopes" => MU::Cloud
|
|
333
|
-
"network_tags" => MU::Cloud
|
|
327
|
+
"ssh_user" => MU::Cloud.resourceClass("Google", "Server").schema(config)[1]["ssh_user"],
|
|
328
|
+
"metadata" => MU::Cloud.resourceClass("Google", "Server").schema(config)[1]["metadata"],
|
|
329
|
+
"service_account" => MU::Cloud.resourceClass("Google", "Server").schema(config)[1]["service_account"],
|
|
330
|
+
"scopes" => MU::Cloud.resourceClass("Google", "Server").schema(config)[1]["scopes"],
|
|
331
|
+
"network_tags" => MU::Cloud.resourceClass("Google", "Server").schema(config)[1]["network_tags"],
|
|
334
332
|
"availability_zone" => {
|
|
335
333
|
"type" => "string",
|
|
336
334
|
"description" => "Target a specific availability zone for this pool, which will create zonal instance managers and scalers instead of regional ones."
|
|
@@ -362,7 +360,7 @@ end
|
|
|
362
360
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
363
361
|
def self.validateConfig(pool, configurator)
|
|
364
362
|
ok = true
|
|
365
|
-
start = Time.now
|
|
363
|
+
#start = Time.now
|
|
366
364
|
pool['project'] ||= MU::Cloud::Google.defaultProject(pool['credentials'])
|
|
367
365
|
if pool['service_account']
|
|
368
366
|
pool['service_account']['cloud'] = "Google"
|
|
@@ -373,29 +371,7 @@ start = Time.now
|
|
|
373
371
|
ok = false
|
|
374
372
|
end
|
|
375
373
|
else
|
|
376
|
-
|
|
377
|
-
"name" => pool['name'],
|
|
378
|
-
"cloud" => "Google",
|
|
379
|
-
"project" => pool["project"],
|
|
380
|
-
"credentials" => pool["credentials"],
|
|
381
|
-
"type" => "service"
|
|
382
|
-
}
|
|
383
|
-
if user["name"].length < 6
|
|
384
|
-
user["name"] += Password.pronounceable(6)
|
|
385
|
-
end
|
|
386
|
-
configurator.insertKitten(user, "users", true)
|
|
387
|
-
pool['dependencies'] ||= []
|
|
388
|
-
pool['service_account'] = MU::Config::Ref.get(
|
|
389
|
-
type: "users",
|
|
390
|
-
cloud: "Google",
|
|
391
|
-
name: pool["name"],
|
|
392
|
-
project: pool["project"],
|
|
393
|
-
credentials: pool["credentials"]
|
|
394
|
-
)
|
|
395
|
-
pool['dependencies'] << {
|
|
396
|
-
"type" => "user",
|
|
397
|
-
"name" => pool["name"]
|
|
398
|
-
}
|
|
374
|
+
pool = MU::Cloud::Google::User.genericServiceAccount(pool, configurator)
|
|
399
375
|
end
|
|
400
376
|
|
|
401
377
|
pool['named_ports'] ||= []
|
|
@@ -406,7 +382,7 @@ start = Time.now
|
|
|
406
382
|
if pool['basis']['launch_config']
|
|
407
383
|
launch = pool["basis"]["launch_config"]
|
|
408
384
|
|
|
409
|
-
launch['size'] = MU::Cloud
|
|
385
|
+
launch['size'] = MU::Cloud.resourceClass("Google", "Server").validateInstanceType(launch["size"], pool["region"])
|
|
410
386
|
ok = false if launch['size'].nil?
|
|
411
387
|
|
|
412
388
|
if launch['image_id'].nil?
|
|
@@ -421,7 +397,7 @@ start = Time.now
|
|
|
421
397
|
|
|
422
398
|
real_image = nil
|
|
423
399
|
begin
|
|
424
|
-
real_image = MU::Cloud
|
|
400
|
+
real_image = MU::Cloud.resourceClass("Google", "Server").fetchImage(launch['image_id'].to_s, credentials: pool['credentials'])
|
|
425
401
|
rescue ::Google::Apis::ClientError => e
|
|
426
402
|
MU.log e.inspect, MU::WARN
|
|
427
403
|
end
|
|
@@ -456,14 +432,19 @@ start = Time.now
|
|
|
456
432
|
# @param region [String]: The cloud provider region
|
|
457
433
|
# @return [void]
|
|
458
434
|
def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
|
|
459
|
-
flags["
|
|
460
|
-
return if !MU::Cloud
|
|
435
|
+
flags["habitat"] ||= MU::Cloud::Google.defaultProject(credentials)
|
|
436
|
+
return if !MU::Cloud.resourceClass("Google", "Habitat").isLive?(flags["habitat"], credentials)
|
|
437
|
+
filter = %Q{(labels.mu-id = "#{MU.deploy_id.downcase}")}
|
|
438
|
+
if !ignoremaster and MU.mu_public_ip
|
|
439
|
+
filter += %Q{ AND (labels.mu-master-ip = "#{MU.mu_public_ip.gsub(/\./, "_")}")}
|
|
440
|
+
end
|
|
441
|
+
MU.log "Placeholder: Google ServerPool artifacts do not support labels, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: filter
|
|
461
442
|
|
|
462
443
|
if !flags["global"]
|
|
463
444
|
["region_autoscaler", "region_instance_group_manager"].each { |type|
|
|
464
445
|
MU::Cloud::Google.compute(credentials: credentials).delete(
|
|
465
446
|
type,
|
|
466
|
-
flags["
|
|
447
|
+
flags["habitat"],
|
|
467
448
|
region,
|
|
468
449
|
noop
|
|
469
450
|
)
|
|
@@ -471,7 +452,7 @@ start = Time.now
|
|
|
471
452
|
else
|
|
472
453
|
MU::Cloud::Google.compute(credentials: credentials).delete(
|
|
473
454
|
"instance_template",
|
|
474
|
-
flags["
|
|
455
|
+
flags["habitat"],
|
|
475
456
|
noop
|
|
476
457
|
)
|
|
477
458
|
end
|
|
@@ -26,10 +26,12 @@ module MU
|
|
|
26
26
|
# If we're being reverse-engineered from a cloud descriptor, use that
|
|
27
27
|
# to determine what sort of account we are.
|
|
28
28
|
if args[:from_cloud_desc]
|
|
29
|
+
@cloud_desc_cache = args[:from_cloud_desc]
|
|
29
30
|
MU::Cloud::Google.admin_directory
|
|
30
31
|
MU::Cloud::Google.iam
|
|
31
32
|
if args[:from_cloud_desc].class == ::Google::Apis::AdminDirectoryV1::User
|
|
32
33
|
@config['type'] = "interactive"
|
|
34
|
+
@cloud_id = args[:from_cloud_desc].primary_email
|
|
33
35
|
elsif args[:from_cloud_desc].class == ::Google::Apis::IamV1::ServiceAccount
|
|
34
36
|
@config['type'] = "service"
|
|
35
37
|
@config['name'] = args[:from_cloud_desc].display_name
|
|
@@ -48,6 +50,10 @@ module MU
|
|
|
48
50
|
@config['name']
|
|
49
51
|
end
|
|
50
52
|
|
|
53
|
+
if @config['type'] == "interactive" and @config['email']
|
|
54
|
+
@cloud_id ||= @config['email']
|
|
55
|
+
end
|
|
56
|
+
|
|
51
57
|
end
|
|
52
58
|
|
|
53
59
|
# Called automatically by {MU::Deploy#createResources}
|
|
@@ -58,7 +64,7 @@ module MU
|
|
|
58
64
|
account_id: acct_id,
|
|
59
65
|
service_account: MU::Cloud::Google.iam(:ServiceAccount).new(
|
|
60
66
|
display_name: @mu_name,
|
|
61
|
-
description: @config['scrub_mu_isms'] ?
|
|
67
|
+
description: @config['scrub_mu_isms'] ? @config['description'] : @deploy.deploy_id
|
|
62
68
|
)
|
|
63
69
|
)
|
|
64
70
|
if @config['use_if_exists']
|
|
@@ -90,7 +96,7 @@ module MU
|
|
|
90
96
|
end
|
|
91
97
|
elsif @config['external']
|
|
92
98
|
@cloud_id = @config['email']
|
|
93
|
-
MU::Cloud
|
|
99
|
+
MU::Cloud.resourceClass("Google", "Role").bindFromConfig("user", @cloud_id, @config['roles'], credentials: @config['credentials'])
|
|
94
100
|
else
|
|
95
101
|
if !@config['email']
|
|
96
102
|
domains = MU::Cloud::Google.admin_directory(credentials: @credentials).list_domains(@customer)
|
|
@@ -122,10 +128,10 @@ module MU
|
|
|
122
128
|
# Called automatically by {MU::Deploy#createResources}
|
|
123
129
|
def groom
|
|
124
130
|
if @config['external']
|
|
125
|
-
MU::Cloud
|
|
131
|
+
MU::Cloud.resourceClass("Google", "Role").bindFromConfig("user", @cloud_id, @config['roles'], credentials: @config['credentials'])
|
|
126
132
|
elsif @config['type'] == "interactive"
|
|
127
133
|
need_update = false
|
|
128
|
-
MU::Cloud
|
|
134
|
+
MU::Cloud.resourceClass("Google", "Role").bindFromConfig("user", @cloud_id, @config['roles'], credentials: @config['credentials'])
|
|
129
135
|
|
|
130
136
|
if @config['force_password_change'] and !cloud_desc.change_password_at_next_login
|
|
131
137
|
MU.log "Forcing #{@mu_name} to change their password at next login", MU::NOTICE
|
|
@@ -170,7 +176,7 @@ module MU
|
|
|
170
176
|
end
|
|
171
177
|
|
|
172
178
|
else
|
|
173
|
-
MU::Cloud
|
|
179
|
+
MU::Cloud.resourceClass("Google", "Role").bindFromConfig("serviceAccount", @cloud_id.gsub(/.*?\/([^\/]+)$/, '\1'), @config['roles'], credentials: @config['credentials'])
|
|
174
180
|
if @config['create_api_key']
|
|
175
181
|
resp = MU::Cloud::Google.iam(credentials: @config['credentials']).list_project_service_account_keys(
|
|
176
182
|
cloud_desc.name
|
|
@@ -187,21 +193,36 @@ module MU
|
|
|
187
193
|
end
|
|
188
194
|
end
|
|
189
195
|
|
|
196
|
+
@cloud_desc_cache = nil
|
|
190
197
|
# Retrieve the cloud descriptor for this resource.
|
|
191
198
|
# @return [Google::Apis::Core::Hashable]
|
|
192
|
-
def cloud_desc
|
|
199
|
+
def cloud_desc(use_cache: true)
|
|
200
|
+
return @cloud_desc_cache if @cloud_desc_cache and use_cache
|
|
193
201
|
if @config['type'] == "interactive" or !@config['type']
|
|
194
202
|
@config['type'] ||= "interactive"
|
|
195
203
|
if !@config['external']
|
|
196
|
-
|
|
204
|
+
@cloud_id ||= @config['email']
|
|
205
|
+
@cloud_desc_cache = MU::Cloud::Google.admin_directory(credentials: @config['credentials']).get_user(@cloud_id)
|
|
197
206
|
else
|
|
198
207
|
return nil
|
|
199
208
|
end
|
|
200
209
|
else
|
|
201
210
|
@config['type'] ||= "service"
|
|
202
|
-
|
|
211
|
+
# this often fails even when it succeeded earlier, so try to be
|
|
212
|
+
# resilient on GCP's behalf
|
|
213
|
+
retries = 0
|
|
214
|
+
begin
|
|
215
|
+
@cloud_desc_cache = MU::Cloud::Google.iam(credentials: @config['credentials']).get_project_service_account(@cloud_id)
|
|
216
|
+
rescue ::Google::Apis::ClientError => e
|
|
217
|
+
if e.message.match(/notFound:/) and retries < 10
|
|
218
|
+
sleep 3
|
|
219
|
+
retries += 1
|
|
220
|
+
retry
|
|
221
|
+
end
|
|
222
|
+
end
|
|
203
223
|
end
|
|
204
224
|
|
|
225
|
+
@cloud_desc_cache
|
|
205
226
|
end
|
|
206
227
|
|
|
207
228
|
# Return the metadata for this user configuration
|
|
@@ -212,7 +233,7 @@ module MU
|
|
|
212
233
|
else
|
|
213
234
|
{}
|
|
214
235
|
end
|
|
215
|
-
description.delete(:etag)
|
|
236
|
+
description.delete(:etag) if description
|
|
216
237
|
description
|
|
217
238
|
end
|
|
218
239
|
|
|
@@ -232,12 +253,17 @@ module MU
|
|
|
232
253
|
# Remove all users associated with the currently loaded deployment.
|
|
233
254
|
# @param noop [Boolean]: If true, will only print what would be done
|
|
234
255
|
# @param ignoremaster [Boolean]: If true, will remove resources not flagged as originating from this Mu server
|
|
235
|
-
# @param region [String]: The cloud provider region
|
|
236
256
|
# @return [void]
|
|
237
|
-
def self.cleanup(noop: false, ignoremaster: false,
|
|
238
|
-
|
|
257
|
+
def self.cleanup(noop: false, ignoremaster: false, credentials: nil, flags: {})
|
|
258
|
+
MU::Cloud::Google.getDomains(credentials)
|
|
239
259
|
my_org = MU::Cloud::Google.getOrg(credentials)
|
|
240
260
|
|
|
261
|
+
filter = %Q{(labels.mu-id = "#{MU.deploy_id.downcase}")}
|
|
262
|
+
if !ignoremaster and MU.mu_public_ip
|
|
263
|
+
filter += %Q{ AND (labels.mu-master-ip = "#{MU.mu_public_ip.gsub(/\./, "_")}")}
|
|
264
|
+
end
|
|
265
|
+
MU.log "Placeholder: Google User artifacts do not support labels, so ignoremaster cleanup flag has no effect", MU::DEBUG, details: filter
|
|
266
|
+
|
|
241
267
|
# We don't have a good way of tagging directory users, so we rely
|
|
242
268
|
# on the known parameter, which is pulled from deployment metadata
|
|
243
269
|
if flags['known'] and my_org
|
|
@@ -256,15 +282,15 @@ module MU
|
|
|
256
282
|
next if user_email.nil?
|
|
257
283
|
next if !user_email.match(/^[^\/]+@[^\/]+$/)
|
|
258
284
|
|
|
259
|
-
MU::Cloud
|
|
285
|
+
MU::Cloud.resourceClass("Google", "Role").removeBindings("user", user_email, credentials: credentials, noop: noop)
|
|
260
286
|
}
|
|
261
287
|
|
|
262
288
|
end
|
|
263
289
|
end
|
|
264
290
|
|
|
265
|
-
flags["
|
|
291
|
+
flags["habitat"] ||= MU::Cloud::Google.defaultProject(credentials)
|
|
266
292
|
resp = MU::Cloud::Google.iam(credentials: credentials).list_project_service_accounts(
|
|
267
|
-
"projects/"+flags["
|
|
293
|
+
"projects/"+flags["habitat"]
|
|
268
294
|
)
|
|
269
295
|
|
|
270
296
|
if resp and resp.accounts and MU.deploy_id
|
|
@@ -319,7 +345,7 @@ module MU
|
|
|
319
345
|
MU::Cloud::Google.iam(credentials: args[:credentials]).list_project_service_accounts(
|
|
320
346
|
"projects/"+args[:project]
|
|
321
347
|
)
|
|
322
|
-
rescue ::Google::Apis::ClientError
|
|
348
|
+
rescue ::Google::Apis::ClientError
|
|
323
349
|
MU.log "Do not have permissions to retrieve service accounts for project #{args[:project]}", MU::WARN
|
|
324
350
|
end
|
|
325
351
|
|
|
@@ -337,8 +363,10 @@ module MU
|
|
|
337
363
|
else
|
|
338
364
|
if cred_cfg['masquerade_as']
|
|
339
365
|
resp = MU::Cloud::Google.admin_directory(credentials: args[:credentials]).list_users(customer: MU::Cloud::Google.customerID(args[:credentials]), show_deleted: false)
|
|
366
|
+
# XXX this ain't exactly performant, do some caching or something
|
|
340
367
|
if resp and resp.users
|
|
341
368
|
resp.users.each { |u|
|
|
369
|
+
next if args[:cloud_id] and !args[:cloud_id] != u.primary_email
|
|
342
370
|
found[u.primary_email] = u
|
|
343
371
|
}
|
|
344
372
|
end
|
|
@@ -355,6 +383,7 @@ module MU
|
|
|
355
383
|
name.match(/\b\d+\-compute@developer\.gserviceaccount\.com$/) or
|
|
356
384
|
name.match(/\bproject-\d+@storage-transfer-service\.iam\.gserviceaccount\.com$/) or
|
|
357
385
|
name.match(/\b\d+@cloudbuild\.gserviceaccount\.com$/) or
|
|
386
|
+
name.match(/\b\d+@cloudservices\.gserviceaccount\.com$/) or
|
|
358
387
|
name.match(/\bservice-\d+@containerregistry\.iam\.gserviceaccount\.com$/) or
|
|
359
388
|
name.match(/\bservice-\d+@container-analysis\.iam\.gserviceaccount\.com$/) or
|
|
360
389
|
name.match(/\bservice-\d+@compute-system\.iam\.gserviceaccount\.com$/) or
|
|
@@ -382,7 +411,7 @@ module MU
|
|
|
382
411
|
# Reverse-map our cloud description into a runnable config hash.
|
|
383
412
|
# We assume that any values we have in +@config+ are placeholders, and
|
|
384
413
|
# calculate our own accordingly based on what's live in the cloud.
|
|
385
|
-
def toKitten(
|
|
414
|
+
def toKitten(**_args)
|
|
386
415
|
if MU::Cloud::Google::User.cannedServiceAcctName?(@cloud_id)
|
|
387
416
|
return nil
|
|
388
417
|
end
|
|
@@ -397,7 +426,7 @@ module MU
|
|
|
397
426
|
return nil
|
|
398
427
|
end
|
|
399
428
|
|
|
400
|
-
user_roles = MU::Cloud
|
|
429
|
+
user_roles = MU::Cloud.resourceClass("Google", "Role").getAllBindings(@config['credentials'])["by_entity"]
|
|
401
430
|
|
|
402
431
|
if cloud_desc.nil?
|
|
403
432
|
MU.log "FAILED TO FIND CLOUD DESCRIPTOR FOR #{self}", MU::ERR, details: @config
|
|
@@ -410,6 +439,10 @@ module MU
|
|
|
410
439
|
|
|
411
440
|
if bok['type'] == "service"
|
|
412
441
|
bok['name'].gsub!(/@.*/, '')
|
|
442
|
+
if cloud_desc.description and !cloud_desc.description.empty? and
|
|
443
|
+
!cloud_desc.description.match(/^[A-Z0-9_-]+-[A-Z0-9_-]+-\d{10}-[A-Z]{2}$/)
|
|
444
|
+
bok['description'] = cloud_desc.description
|
|
445
|
+
end
|
|
413
446
|
bok['project'] = @project_id
|
|
414
447
|
keys = MU::Cloud::Google.iam(credentials: @config['credentials']).list_project_service_account_keys(@cloud_id)
|
|
415
448
|
|
|
@@ -420,13 +453,13 @@ module MU
|
|
|
420
453
|
if user_roles["serviceAccount"] and
|
|
421
454
|
user_roles["serviceAccount"][bok['cloud_id']] and
|
|
422
455
|
user_roles["serviceAccount"][bok['cloud_id']].size > 0
|
|
423
|
-
bok['roles'] = MU::Cloud
|
|
456
|
+
bok['roles'] = MU::Cloud.resourceClass("Google", "Role").entityBindingsToSchema(user_roles["serviceAccount"][bok['cloud_id']])
|
|
424
457
|
end
|
|
425
458
|
else
|
|
426
459
|
if user_roles["user"] and
|
|
427
460
|
user_roles["user"][bok['cloud_id']] and
|
|
428
461
|
user_roles["user"][bok['cloud_id']].size > 0
|
|
429
|
-
bok['roles'] = MU::Cloud
|
|
462
|
+
bok['roles'] = MU::Cloud.resourceClass("Google", "Role").entityBindingsToSchema(user_roles["user"][bok['cloud_id']], credentials: @config['credentials'])
|
|
430
463
|
end
|
|
431
464
|
bok['given_name'] = cloud_desc.name.given_name if cloud_desc.name.given_name and !cloud_desc.name.given_name.empty?
|
|
432
465
|
bok['family_name'] = cloud_desc.name.family_name if cloud_desc.name.family_name and !cloud_desc.name.family_name.empty?
|
|
@@ -441,9 +474,9 @@ module MU
|
|
|
441
474
|
end
|
|
442
475
|
|
|
443
476
|
# Cloud-specific configuration properties.
|
|
444
|
-
# @param
|
|
477
|
+
# @param _config [MU::Config]: The calling MU::Config object
|
|
445
478
|
# @return [Array<Array,Hash>]: List of required fields, and json-schema Hash of cloud-specific configuration parameters for this resource
|
|
446
|
-
def self.schema(
|
|
479
|
+
def self.schema(_config)
|
|
447
480
|
toplevel_required = []
|
|
448
481
|
schema = {
|
|
449
482
|
"name" => {
|
|
@@ -482,6 +515,10 @@ If we are binding (rather than creating) a user and no roles are specified, we w
|
|
|
482
515
|
"type" => "string",
|
|
483
516
|
"description" => "Alias for +family_name+"
|
|
484
517
|
},
|
|
518
|
+
"description" => {
|
|
519
|
+
"type" => "string",
|
|
520
|
+
"description" => "Comment field for service accounts, which we normally use to store the originating deploy's deploy id, since GCP service accounts do not have labels. This field is only honored if +scrub_mu_isms+ is set."
|
|
521
|
+
},
|
|
485
522
|
"email" => {
|
|
486
523
|
"type" => "string",
|
|
487
524
|
"description" => "Canonical email address for a +directory+ user. If not specified, will be set to +name@domain+."
|
|
@@ -509,7 +546,7 @@ If we are binding (rather than creating) a user and no roles are specified, we w
|
|
|
509
546
|
"roles" => {
|
|
510
547
|
"type" => "array",
|
|
511
548
|
"description" => "One or more Google IAM roles to associate with this user.",
|
|
512
|
-
"items" => MU::Cloud
|
|
549
|
+
"items" => MU::Cloud.resourceClass("Google", "Role").ref_schema
|
|
513
550
|
}
|
|
514
551
|
}
|
|
515
552
|
[toplevel_required, schema]
|
|
@@ -517,9 +554,9 @@ If we are binding (rather than creating) a user and no roles are specified, we w
|
|
|
517
554
|
|
|
518
555
|
# Cloud-specific pre-processing of {MU::Config::BasketofKittens::users}, bare and unvalidated.
|
|
519
556
|
# @param user [Hash]: The resource to process and validate
|
|
520
|
-
# @param
|
|
557
|
+
# @param _configurator [MU::Config]: The overall deployment configurator of which this resource is a member
|
|
521
558
|
# @return [Boolean]: True if validation succeeded, False otherwise
|
|
522
|
-
def self.validateConfig(user,
|
|
559
|
+
def self.validateConfig(user, _configurator)
|
|
523
560
|
ok = true
|
|
524
561
|
|
|
525
562
|
my_domains = MU::Cloud::Google.getDomains(user['credentials'])
|
|
@@ -595,15 +632,11 @@ If we are binding (rather than creating) a user and no roles are specified, we w
|
|
|
595
632
|
ok = false
|
|
596
633
|
end
|
|
597
634
|
|
|
598
|
-
user['dependencies'] ||= []
|
|
599
635
|
if user['roles']
|
|
600
636
|
user['roles'].each { |r|
|
|
601
637
|
if r['role'] and r['role']['name'] and
|
|
602
638
|
(!r['role']['deploy_id'] and !r['role']['id'])
|
|
603
|
-
user['
|
|
604
|
-
"type" => "role",
|
|
605
|
-
"name" => r['role']['name']
|
|
606
|
-
}
|
|
639
|
+
MU::Config.addDependency(user, r['role']['name'], "role")
|
|
607
640
|
end
|
|
608
641
|
|
|
609
642
|
if !r["projects"] and !r["organizations"] and !r["folders"]
|
|
@@ -621,7 +654,38 @@ If we are binding (rather than creating) a user and no roles are specified, we w
|
|
|
621
654
|
ok
|
|
622
655
|
end
|
|
623
656
|
|
|
624
|
-
|
|
657
|
+
# Create and inject a service account on behalf of the parent resource.
|
|
658
|
+
# Return the modified parent configuration hash with references to the
|
|
659
|
+
# new addition.
|
|
660
|
+
# @param parent [Hash]
|
|
661
|
+
# @param configurator [MU::Config]
|
|
662
|
+
# @return [Hash]
|
|
663
|
+
def self.genericServiceAccount(parent, configurator)
|
|
664
|
+
user = {
|
|
665
|
+
"name" => parent['name'],
|
|
666
|
+
"cloud" => "Google",
|
|
667
|
+
"project" => parent["project"],
|
|
668
|
+
"credentials" => parent["credentials"],
|
|
669
|
+
"type" => "service"
|
|
670
|
+
}
|
|
671
|
+
if user["name"].length < 6
|
|
672
|
+
user["name"] += Password.pronounceable(6)
|
|
673
|
+
end
|
|
674
|
+
if parent['roles']
|
|
675
|
+
user['roles'] = parent['roles'].dup
|
|
676
|
+
end
|
|
677
|
+
configurator.insertKitten(user, "users", true)
|
|
678
|
+
parent['service_account'] = MU::Config::Ref.get(
|
|
679
|
+
type: "users",
|
|
680
|
+
cloud: "Google",
|
|
681
|
+
name: user["name"],
|
|
682
|
+
project: user["project"],
|
|
683
|
+
credentials: user["credentials"]
|
|
684
|
+
)
|
|
685
|
+
MU::Config.addDependency(parent, user['name'], "user")
|
|
686
|
+
|
|
687
|
+
parent
|
|
688
|
+
end
|
|
625
689
|
|
|
626
690
|
end
|
|
627
691
|
end
|