cloud-mu 2.0.0.pre.alpha → 2.0.0.pre.alpha2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f1059c013e5f5e7c2ece20c2aa9ffcb60facab001cc864c0c26f60baf384d7c4
4
- data.tar.gz: ebca2309c37e8a8038df432be18bb2b4f54e44b52da42029a79461515603f899
3
+ metadata.gz: ea07140b34d57b4dea2bc06b6a9184896585db834782e6b2b4c40184b6cdee71
4
+ data.tar.gz: 5382c8d82180c39d6797ccbfabb4903877f29f914f2c968aa4550033c6607db8
5
5
  SHA512:
6
- metadata.gz: d73ffd1304213dc06b04f0f350ef9d70cf99e48a3dd1c0ea7db0424606437b83e710bd87c0b9df471ca0ed0998991cf4e0e7a7e482d859ce647d0e0e09f84f6e
7
- data.tar.gz: ad2503195884645217ee178aa1a9d94fb12520c83132f355cc1042535059d3b8d89cd8ce0066f1eae3d4e665aa6b678599ba2d174acbd7f9701430a1c242b464
6
+ metadata.gz: b4f27d9340d4146cadcd2eeb0a9a2abe650a0822158b136560ff3c8f409975f1a83e8106372c0e8c1f51e35a5868de3764492026f50e6aed9faa410fc133199a
7
+ data.tar.gz: 411b9b7d3e8db61459dfc480a1d2d874603580d87e3597956d882a0e9e9e41fc0eff61d3af3d01924a4ddd8c6f10916bcb6df8a18576bd3fd5f3a187a2d460b7
data/bin/mu-configure CHANGED
@@ -28,6 +28,11 @@ require 'fileutils'
28
28
  require 'erb'
29
29
  require 'tmpdir'
30
30
 
31
+ $IN_GEM = false
32
+ if Gem.paths and Gem.paths.home and File.dirname(__FILE__).match(/^#{Gem.paths.home}/)
33
+ $IN_GEM = true
34
+ end
35
+
31
36
  GIT_PATTERN = /(((git|ssh|http(s)?)|(git@[\w\.]+))(:(\/\/)?))?([\w\.@\:\/\-~]+)(\.git)?(\/)?/
32
37
 
33
38
  # Top-level keys in $MU_CFG for which we'll provide interactive, menu-driven
@@ -197,6 +202,11 @@ $CONFIGURABLES = {
197
202
  "required" => true,
198
203
  "changes" => ["chefrun"]
199
204
  },
205
+ "masequerade_as" => {
206
+ "title" => "GSuite Masquerade User",
207
+ "required" => false,
208
+ "desc" => "For Google Cloud projects which are attached to a GSuite domain. GCP service accounts cannot view or manage GSuite resources (groups, users, etc) directly, but must instead masquerade as a GSuite user which has delegated authority to the service account. See also: https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority"
209
+ },
200
210
  "default" => {
201
211
  "title" => "Is Default Account",
202
212
  "default" => false,
@@ -281,10 +291,11 @@ end
281
291
 
282
292
  $INITIALIZE = (!File.size?("#{MU_BASE}/etc/mu.yaml") or $opts[:force])
283
293
  $HAVE_GLOBAL_CONFIG = File.size?("#{MU_BASE}/etc/mu.yaml")
284
- if !AMROOT and ($INITIALIZE or !$HAVE_GLOBAL_CONFIG)
294
+ if !AMROOT and ($INITIALIZE or !$HAVE_GLOBAL_CONFIG) and !$IN_GEM
285
295
  puts "Global configuration has not been initialized or is missing. Must run as root to correct."
286
296
  exit 1
287
297
  end
298
+
288
299
  if !$HAVE_GLOBAL_CONFIG and $opts[:noninteractive] and (!$opts[:public_address] or !$opts[:mu_admin_email])
289
300
  puts "Specify --public-address and --mu-admin-email on new non-interactive configs"
290
301
  exit 1
@@ -315,7 +326,7 @@ begin
315
326
  instance_id = open("http://169.254.169.254/metadata/instance/compute").read
316
327
  $IN_AWS = true if !instance_id.nil? and instance_id.size > 0
317
328
  end
318
- rescue OpenURI::HTTPError, Timeout::Error, SocketError, Errno::ENETUNREACH
329
+ rescue OpenURI::HTTPError, Timeout::Error, SocketError, Errno::ENETUNREACH, Errno::EHOSTUNREACH
319
330
  end
320
331
 
321
332
 
@@ -385,6 +396,7 @@ def assignMenuEntries(tree = $CONFIGURABLES, map = $MENU_MAP)
385
396
  "required" => true
386
397
  }
387
398
  map[count.to_s]["#addnew"] = true
399
+ map[count.to_s]["#title"] = data['title']
388
400
  map[count.to_s]["#key"] = key
389
401
 
390
402
  # Now the menu entries for the existing ones
@@ -480,7 +492,7 @@ def cloneGitRepo(repo)
480
492
  puts "Testing ability to check out Git repository #{repo.bold}"
481
493
  fullrepo = repo
482
494
  if !repo.match(/@|:\/\//) # we try ssh first
483
- fullrepo = "git@github.com:"+repo
495
+ fullrepo = "git@github.com:"+repo
484
496
  puts "Doesn't look like a full URL, trying SSH to #{fullrepo}"
485
497
  end
486
498
  cwd = Dir.pwd
@@ -511,7 +523,7 @@ def cloneGitRepo(repo)
511
523
  end
512
524
  end
513
525
  if !repo.match(/@|:\/\//)
514
- fullrepo = "git://github.com/"+repo
526
+ fullrepo = "git://github.com/"+repo
515
527
  puts ""
516
528
  puts "No luck there, trying #{fullrepo}".bold
517
529
  puts "/usr/bin/git clone #{fullrepo}"
@@ -522,7 +534,7 @@ def cloneGitRepo(repo)
522
534
  return fullrepo
523
535
  else
524
536
  puts output.red.on_black
525
- fullrepo = "https://github.com/"+repo
537
+ fullrepo = "https://github.com/"+repo
526
538
  puts "Final attempt, trying #{fullrepo}"
527
539
  puts "/usr/bin/git clone #{fullrepo}"
528
540
  output = %x{/usr/bin/git clone #{fullrepo} 2>&1}
@@ -745,8 +757,8 @@ def displayCurrentOpts(tree = $CONFIGURABLES)
745
757
  count = 1
746
758
  optlist = []
747
759
  tree.each_pair { |key, data|
748
- next if !AMROOT and data['rootonly']
749
760
  next if !data.is_a?(Hash)
761
+ next if !AMROOT and data['rootonly']
750
762
  if data["title"].nil? or data["#menu"].nil?
751
763
  next
752
764
  end
@@ -780,7 +792,7 @@ end
780
792
  ###############################################################################
781
793
 
782
794
  trap("INT"){ puts "" ; exit }
783
- importCurrentValues if !$INITIALIZE or $HAVE_GLOBAL_CONFIG
795
+ importCurrentValues if !$INITIALIZE or $HAVE_GLOBAL_CONFIG or $IN_GEM
784
796
  importCLIValues
785
797
  setDefaults
786
798
  assignMenuEntries # populates $MENU_MAP
@@ -821,7 +833,7 @@ def validate(newval, reqs, addnewline = true, in_use: [])
821
833
  puts "\nInvalid value '#{newval.bold}' for #{reqs['title'].bold} (must be true or false)".light_red.on_black
822
834
  puts "\n\n" if addnewline
823
835
  ok = false
824
- elsif in_use.size > 0 and in_use.include?(newval)
836
+ elsif in_use and in_use.size > 0 and in_use.include?(newval)
825
837
  puts "\n##{reqs['title'].bold} #{newval} not available".light_red.on_black
826
838
  puts "\n\n" if addnewline
827
839
  ok = false
@@ -830,7 +842,7 @@ def validate(newval, reqs, addnewline = true, in_use: [])
830
842
  puts "\nSupplied value for #{reqs['title'].bold} did not pass validation".light_red.on_black
831
843
  puts "\n\n" if addnewline
832
844
  ok = false
833
- elsif reqs['negate_pattern']
845
+ elsif reqs['negate_pattern']
834
846
  if newval.to_s.match(reqs['pattern'])
835
847
  puts "\nInvalid value '#{newval.bold}' for #{reqs['title'].bold} (must NOT match #{reqs['pattern']})".light_red.on_black
836
848
  puts "\n\n" if addnewline
@@ -915,7 +927,9 @@ def menu(tree = $CONFIGURABLES, map = $MENU_MAP, submenu_name = nil, in_use_name
915
927
  map[answer],
916
928
  minimap,
917
929
  map[answer]['#title']+" (NEW)",
918
- map[answer]['#entries'].keys.reject { |k| k.match(/^#/) }
930
+ if map[answer]['#entries']
931
+ map[answer]['#entries'].keys.reject { |k| k.match(/^#/) }
932
+ end
919
933
  )
920
934
  if newtree
921
935
  newname = newtree["name"]["value"]
@@ -945,7 +959,7 @@ def menu(tree = $CONFIGURABLES, map = $MENU_MAP, submenu_name = nil, in_use_name
945
959
  newtree, newmap = menu(
946
960
  map[answer],
947
961
  minimap,
948
- map[answer]["#title"],
962
+ map[answer]["#title"],
949
963
  (map[answer]['#entries'].keys - [map[answer]['#title']])
950
964
  )
951
965
  map[answer] = newtree if newtree
@@ -1070,7 +1084,9 @@ if AMROOT
1070
1084
  end
1071
1085
 
1072
1086
  if $INITIALIZE
1073
- %x{/sbin/service iptables stop} # Chef run will set up correct rules later
1087
+ if AMROOT
1088
+ %x{/sbin/service iptables stop} # Chef run will set up correct rules later
1089
+ end
1074
1090
  $MU_SET_DEFAULTS = setConfigTree
1075
1091
  require File.realpath(File.expand_path(File.dirname(__FILE__)+"/mu-load-config.rb"))
1076
1092
  else
@@ -1093,6 +1109,12 @@ rescue LoadError
1093
1109
  require 'mu'
1094
1110
  end
1095
1111
 
1112
+ if $IN_GEM
1113
+ puts $MU_CFG.to_yaml
1114
+ saveMuConfig($MU_CFG)
1115
+ exit
1116
+ end
1117
+
1096
1118
  if AMROOT and ($INITIALIZE or $CHANGES.include?("hostname"))
1097
1119
  system("/bin/hostname #{$MU_CFG['hostname']}")
1098
1120
  end
@@ -1130,6 +1152,7 @@ def updateChefRbs
1130
1152
  user = AMROOT ? "mu" : Etc.getpwuid(Process.uid).name
1131
1153
  chefuser = user.gsub(/\./, "")
1132
1154
  templates = { HOMEDIR+"/.chef/knife.rb" => KNIFE_TEMPLATE }
1155
+ Dir.mkdir(HOMEDIR+"/.chef") if !Dir.exists?(HOMEDIR+"/.chef")
1133
1156
  if AMROOT
1134
1157
  templates["/etc/chef/client.rb"] = CLIENT_TEMPLATE
1135
1158
  templates["/etc/opscode/pivotal.rb"] = PIVOTAL_TEMPLATE
@@ -1252,7 +1275,7 @@ if $INITIALIZE or $CHANGES.include?("vault")
1252
1275
  system("chef-client -o 'recipe[mu-master::vault]'")
1253
1276
  end
1254
1277
 
1255
- if $MU_CFG['ldap']['type'] == "389 Directory Services"
1278
+ if $MU_CFG['ldap']['type'] == "389 Directory Services"
1256
1279
  begin
1257
1280
  MU::Master::LDAP.listUsers
1258
1281
  rescue Exception => e # XXX lazy exception handling is lazy
data/cloud-mu.gemspec CHANGED
@@ -17,7 +17,7 @@ end
17
17
 
18
18
  Gem::Specification.new do |s|
19
19
  s.name = 'cloud-mu'
20
- s.version = '2.0.0-alpha'
20
+ s.version = '2.0.0-alpha2'
21
21
  s.date = '2018-12-11'
22
22
  s.require_paths = ['modules']
23
23
  s.required_ruby_version = '>= 2.4'
@@ -61,8 +61,7 @@ module MU
61
61
  end
62
62
 
63
63
 
64
- # XXX AWS needs to check MU::Cloud::AWS.isGovCloud? on some things, or gracefully handle the API not existing
65
- types_in_order = ["Collection", "Function", "ServerPool", "ContainerCluster", "SearchDomain", "Server", "MsgQueue", "Database", "CacheCluster", "StoragePool", "LoadBalancer", "FirewallRule", "Alarm", "Notifier", "Log", "VPC", "DNSZone", "Collection"]
64
+ types_in_order = ["Collection", "Function", "ServerPool", "ContainerCluster", "SearchDomain", "Server", "MsgQueue", "Database", "CacheCluster", "StoragePool", "LoadBalancer", "FirewallRule", "Alarm", "Notifier", "Log", "VPC", "DNSZone", "Collection", "Habitat"]
66
65
 
67
66
  # Load up our deployment metadata
68
67
  if !mommacat.nil?
@@ -161,6 +160,7 @@ module MU
161
160
 
162
161
  if @mommacat.nil? or @mommacat.numKittens(types: [t]) > 0
163
162
  begin
163
+ puts t if t == "Habitat"
164
164
  resclass = Object.const_get("MU").const_get("Cloud").const_get(t)
165
165
  resclass.cleanup(
166
166
  noop: @noop,
@@ -184,7 +184,7 @@ module MU
184
184
  # XXX move to MU::AWS
185
185
  if provider == "AWS"
186
186
  resp = MU::Cloud::AWS.ec2(region: r, credentials: credset).describe_key_pairs(
187
- filters: [{name: "key-name", values: [keyname]}]
187
+ filters: [{name: "key-name", values: [keyname]}]
188
188
  )
189
189
  resp.data.key_pairs.each { |keypair|
190
190
  MU.log "Deleting key pair #{keypair.key_name} from #{r}"
data/modules/mu/cloud.rb CHANGED
@@ -1424,6 +1424,7 @@ MU.log "in dependencies() and findLitterMate gave me "+sib_by_name.to_s+" on beh
1424
1424
  # Wrapper for the cleanup class method of underlying cloud object implementations.
1425
1425
  def self.cleanup(*flags)
1426
1426
  params = flags.first
1427
+
1427
1428
  clouds = MU::Cloud.supportedClouds
1428
1429
  if params[:cloud]
1429
1430
  clouds = [params[:cloud]]
@@ -1433,10 +1434,12 @@ MU.log "in dependencies() and findLitterMate gave me "+sib_by_name.to_s+" on beh
1433
1434
  begin
1434
1435
  cloudclass = MU::Cloud.loadCloudType(cloud, shortname)
1435
1436
  raise MuCloudResourceNotImplemented if !cloudclass.respond_to?(:cleanup) or cloudclass.method(:cleanup).owner.to_s != "#<Class:#{cloudclass}>"
1436
- MU.log "Invoking #{cloudclass}.cleanup from #{shortname}", MU::DEBUG, details: flags
1437
+ if cfg_name == "habitat"
1438
+ MU.log "Invoking #{cloudclass}.cleanup from #{shortname}", MU::WARN, details: flags
1439
+ end
1437
1440
  cloudclass.cleanup(params)
1438
1441
  rescue MuCloudResourceNotImplemented
1439
- MU.log "No #{cloud} implementation of #{shortname}.cleanup, skipping", MU::DEBUG, details: flags
1442
+ MU.log "No #{cloud} implementation of #{shortname}.cleanup, skipping", MU::WARN, details: flags
1440
1443
  end
1441
1444
  }
1442
1445
  MU::MommaCat.unlockAll
@@ -96,6 +96,16 @@ module MU
96
96
  # @param region [String]: The cloud provider region
97
97
  # @return [void]
98
98
  def self.cleanup(noop: false, ignoremaster: false, region: MU.curRegion, credentials: nil, flags: {})
99
+ puts "IN HABITAT CLEANUP"
100
+ return if !orgMasterCreds?(credentials)
101
+
102
+ resp = MU::Cloud::AWS.orgs(credentials: credentials).list_accounts
103
+
104
+ if resp and resp.accounts
105
+ resp.accounts.each { |acct|
106
+ pp acct
107
+ }
108
+ end
99
109
  end
100
110
 
101
111
  # Locate an existing account
@@ -121,6 +131,19 @@ module MU
121
131
  [toplevel_required, schema]
122
132
  end
123
133
 
134
+ # Figure out what account we're calling from, and then figure out if
135
+ # it's the organization's master account- the only place from which
136
+ # we can create accounts, amongst other things.
137
+ # @param credentials [String]
138
+ # @return [Boolean]
139
+ def self.orgMasterCreds?(credentials = nil)
140
+ user_list = MU::Cloud::AWS.iam(credentials: credentials).list_users.users
141
+ acct_num = MU::Cloud::AWS.iam(credentials: credentials).list_users.users.first.arn.split(/:/)[4]
142
+
143
+ parentorg = MU::Cloud::AWS::Folder.find(credentials: credentials).values.first
144
+ acct_num == parentorg.master_account_id
145
+ end
146
+
124
147
  # Cloud-specific pre-processing of {MU::Config::BasketofKittens::habitats}, bare and unvalidated.
125
148
  # @param habitat [Hash]: The resource to process and validate
126
149
  # @param configurator [MU::Config]: The overall deployment configurator of which this resource is a member
@@ -132,14 +155,7 @@ module MU
132
155
  MU.log "No email address specified in habitat #{habitat['name']}, and AWS requires a unique contact email. Will generate an alias to #{$MU_CFG['mu_admin_email']} at run time.", MU::NOTICE
133
156
  end
134
157
 
135
- # Figure out what account we're calling from, and then figure out if
136
- # it's the organization's master account- the only place from which
137
- # we can create accounts.
138
- user_list = MU::Cloud::AWS.iam(credentials: habitat['credentials']).list_users.users
139
- acct_num = MU::Cloud::AWS.iam(credentials: habitat['credentials']).list_users.users.first.arn.split(/:/)[4]
140
-
141
- parentorg = MU::Cloud::AWS::Folder.find(credentials: habitat['credentials']).values.first
142
- if acct_num != parentorg.master_account_id
158
+ if !orgMasterCreds?(habitat['credentials'])
143
159
  MU.log "The Organization master account for habitat #{habitat["name"]} is #{parentorg.master_account_id}, but my credentials (#{ habitat['credentials'] ? habitat['credentials'] : "default"}) are for a non-master account (#{acct_num}). AWS accounts can only be created and managed with credentials from an Organization's master account.", MU::ERR
144
160
  ok = false
145
161
  end
@@ -487,7 +487,10 @@ module MU
487
487
  # MU.log "Got #{e.inspect} while trying to figure out our account number", MU::WARN, details: caller
488
488
  # end
489
489
  # if user_list.nil? or user_list.size == 0
490
- mac = MU::Cloud::AWS.getAWSMetaData("network/interfaces/macs/").split(/\n/)[0]
490
+ resp = MU::Cloud::AWS.getAWSMetaData("network/interfaces/macs/")
491
+ return nil if !resp
492
+
493
+ mac = resp.split(/\n/)[0]
491
494
  acct_num = MU::Cloud::AWS.getAWSMetaData("network/interfaces/macs/#{mac}owner-id")
492
495
  acct_num.chomp!
493
496
  # else
@@ -25,6 +25,7 @@ module MU
25
25
  @@authtoken = nil
26
26
  @@default_project = nil
27
27
  @@myRegion_var = nil
28
+ @@my_hosted_cfg = nil
28
29
  @@authorizers = {}
29
30
  @@acct_to_profile_map = {}
30
31
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloud-mu
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre.alpha
4
+ version: 2.0.0.pre.alpha2
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Stange