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

Sign up to get free protection for your applications and to get access to all the features.
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