leap_cli 1.8.1 → 1.9

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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/bin/leap +6 -12
  3. data/lib/leap_cli.rb +3 -23
  4. data/lib/leap_cli/bootstrap.rb +36 -12
  5. data/lib/leap_cli/commands/common.rb +88 -46
  6. data/lib/leap_cli/commands/new.rb +24 -17
  7. data/lib/leap_cli/commands/pre.rb +3 -1
  8. data/lib/leap_cli/core_ext/hash.rb +19 -0
  9. data/lib/leap_cli/leapfile.rb +47 -32
  10. data/lib/leap_cli/log.rb +196 -88
  11. data/lib/leap_cli/path.rb +5 -5
  12. data/lib/leap_cli/util.rb +28 -18
  13. data/lib/leap_cli/version.rb +8 -3
  14. data/vendor/acme-client/lib/acme-client.rb +1 -0
  15. data/vendor/acme-client/lib/acme/client.rb +122 -0
  16. data/vendor/acme-client/lib/acme/client/certificate.rb +30 -0
  17. data/vendor/acme-client/lib/acme/client/certificate_request.rb +111 -0
  18. data/vendor/acme-client/lib/acme/client/crypto.rb +98 -0
  19. data/vendor/acme-client/lib/acme/client/error.rb +16 -0
  20. data/vendor/acme-client/lib/acme/client/faraday_middleware.rb +123 -0
  21. data/vendor/acme-client/lib/acme/client/resources.rb +5 -0
  22. data/vendor/acme-client/lib/acme/client/resources/authorization.rb +44 -0
  23. data/vendor/acme-client/lib/acme/client/resources/challenges.rb +6 -0
  24. data/vendor/acme-client/lib/acme/client/resources/challenges/base.rb +43 -0
  25. data/vendor/acme-client/lib/acme/client/resources/challenges/dns01.rb +19 -0
  26. data/vendor/acme-client/lib/acme/client/resources/challenges/http01.rb +18 -0
  27. data/vendor/acme-client/lib/acme/client/resources/challenges/tls_sni01.rb +24 -0
  28. data/vendor/acme-client/lib/acme/client/resources/registration.rb +37 -0
  29. data/vendor/acme-client/lib/acme/client/self_sign_certificate.rb +60 -0
  30. data/vendor/acme-client/lib/acme/client/version.rb +7 -0
  31. data/vendor/base32/lib/base32.rb +67 -0
  32. data/vendor/certificate_authority/lib/certificate_authority.rb +2 -1
  33. data/vendor/certificate_authority/lib/certificate_authority/certificate.rb +4 -4
  34. data/vendor/certificate_authority/lib/certificate_authority/certificate_revocation_list.rb +7 -5
  35. data/vendor/certificate_authority/lib/certificate_authority/core_extensions.rb +46 -0
  36. data/vendor/certificate_authority/lib/certificate_authority/distinguished_name.rb +6 -2
  37. data/vendor/certificate_authority/lib/certificate_authority/extensions.rb +10 -3
  38. data/vendor/certificate_authority/lib/certificate_authority/key_material.rb +11 -9
  39. data/vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb +3 -3
  40. data/vendor/certificate_authority/lib/certificate_authority/pkcs11_key_material.rb +0 -2
  41. data/vendor/certificate_authority/lib/certificate_authority/serial_number.rb +8 -2
  42. data/vendor/certificate_authority/lib/certificate_authority/validations.rb +31 -0
  43. data/vendor/rsync_command/lib/rsync_command.rb +49 -12
  44. metadata +50 -91
  45. data/lib/leap/platform.rb +0 -90
  46. data/lib/leap_cli/config/environment.rb +0 -180
  47. data/lib/leap_cli/config/filter.rb +0 -178
  48. data/lib/leap_cli/config/manager.rb +0 -419
  49. data/lib/leap_cli/config/node.rb +0 -77
  50. data/lib/leap_cli/config/object.rb +0 -428
  51. data/lib/leap_cli/config/object_list.rb +0 -209
  52. data/lib/leap_cli/config/provider.rb +0 -22
  53. data/lib/leap_cli/config/secrets.rb +0 -87
  54. data/lib/leap_cli/config/sources.rb +0 -11
  55. data/lib/leap_cli/config/tag.rb +0 -25
  56. data/lib/leap_cli/lib_ext/capistrano_connections.rb +0 -16
  57. data/lib/leap_cli/logger.rb +0 -237
  58. data/lib/leap_cli/remote/leap_plugin.rb +0 -192
  59. data/lib/leap_cli/remote/puppet_plugin.rb +0 -26
  60. data/lib/leap_cli/remote/rsync_plugin.rb +0 -35
  61. data/lib/leap_cli/remote/tasks.rb +0 -51
  62. data/lib/leap_cli/ssh_key.rb +0 -195
  63. data/lib/leap_cli/util/remote_command.rb +0 -158
  64. data/lib/leap_cli/util/secret.rb +0 -55
  65. data/lib/leap_cli/util/x509.rb +0 -33
@@ -1,77 +0,0 @@
1
- #
2
- # Configuration for a 'node' (a server in the provider's infrastructure)
3
- #
4
-
5
- require 'ipaddr'
6
-
7
- module LeapCli; module Config
8
-
9
- class Node < Object
10
- attr_accessor :file_paths
11
-
12
- def initialize(environment=nil)
13
- super(environment)
14
- @node = self
15
- @file_paths = []
16
- end
17
-
18
- #
19
- # returns true if this node has an ip address in the range of the vagrant network
20
- #
21
- def vagrant?
22
- begin
23
- vagrant_range = IPAddr.new LeapCli.leapfile.vagrant_network
24
- rescue ArgumentError => exc
25
- Util::bail! { Util::log :invalid, "ip address '#{@node.ip_address}' vagrant.network" }
26
- end
27
-
28
- begin
29
- ip_address = IPAddr.new @node.get('ip_address')
30
- rescue ArgumentError => exc
31
- Util::log :warning, "invalid ip address '#{@node.get('ip_address')}' for node '#{@node.name}'"
32
- end
33
- return vagrant_range.include?(ip_address)
34
- end
35
-
36
- #
37
- # Return a hash table representation of ourselves, with the key equal to the @node.name,
38
- # and the value equal to the fields specified in *keys.
39
- #
40
- # Also, the result is flattened to a single hash, so a key of 'a.b' becomes 'a_b'
41
- #
42
- # compare to Object#pick(*keys). This method is the sames as Config::ObjectList#pick_fields,
43
- # but works on a single node.
44
- #
45
- # Example:
46
- #
47
- # node.pick('domain.internal') =>
48
- #
49
- # {
50
- # 'node1': {
51
- # 'domain_internal': 'node1.example.i'
52
- # }
53
- # }
54
- #
55
- def pick_fields(*keys)
56
- {@node.name => self.pick(*keys)}
57
- end
58
-
59
- #
60
- # can be overridden by the platform.
61
- # returns a list of node names that should be tested before this node
62
- #
63
- def test_dependencies
64
- []
65
- end
66
-
67
- # returns a string list of supported ssh host key algorithms for this node.
68
- # or an empty string if it could not be determined
69
- def supported_ssh_host_key_algorithms
70
- @host_key_algo ||= SshKey.supported_host_key_algorithms(
71
- Util.read_file([:node_ssh_pub_key, @node.name])
72
- )
73
- end
74
-
75
- end
76
-
77
- end; end
@@ -1,428 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'erb'
4
- require 'json/pure' # pure ruby implementation is required for our sorted trick to work.
5
-
6
- if $ruby_version < [1,9]
7
- $KCODE = 'UTF8'
8
- end
9
- require 'ya2yaml' # pure ruby yaml
10
-
11
- module LeapCli
12
- module Config
13
-
14
- #
15
- # This class represents the configuration for a single node, service, or tag.
16
- # Also, all the nested hashes are also of this type.
17
- #
18
- # It is called 'object' because it corresponds to an Object in JSON.
19
- #
20
- class Object < Hash
21
-
22
- attr_reader :env
23
- attr_reader :node
24
-
25
- def initialize(environment=nil, node=nil)
26
- raise ArgumentError unless environment.nil? || environment.is_a?(Config::Environment)
27
- @env = environment
28
- # an object that is a node as @node equal to self, otherwise all the
29
- # child objects point back to the top level node.
30
- @node = node || self
31
- end
32
-
33
- def manager
34
- @env.manager
35
- end
36
-
37
- #
38
- # TODO: deprecate node.global()
39
- #
40
- def global
41
- @env
42
- end
43
-
44
- def environment=(e)
45
- self.store('environment', e)
46
- end
47
-
48
- def environment
49
- self['environment']
50
- end
51
-
52
- def duplicate(env)
53
- new_object = self.deep_dup
54
- new_object.set_environment(env, new_object)
55
- end
56
-
57
- #
58
- # export YAML
59
- #
60
- # We use pure ruby yaml exporter ya2yaml instead of SYCK or PSYCH because it
61
- # allows us greater compatibility regardless of installed ruby version and
62
- # greater control over how the yaml is exported (sorted keys, in particular).
63
- #
64
- def dump_yaml
65
- evaluate(@node)
66
- sorted_ya2yaml(:syck_compatible => true)
67
- end
68
-
69
- #
70
- # export JSON
71
- #
72
- def dump_json(options={})
73
- evaluate(@node)
74
- if options[:format] == :compact
75
- return self.to_json
76
- else
77
- excluded = {}
78
- if options[:exclude]
79
- options[:exclude].each do |key|
80
- excluded[key] = self[key]
81
- self.delete(key)
82
- end
83
- end
84
- json_str = JSON.sorted_generate(self)
85
- if excluded.any?
86
- self.merge!(excluded)
87
- end
88
- return json_str
89
- end
90
- end
91
-
92
- def evaluate(context=@node)
93
- evaluate_everything(context)
94
- late_evaluate_everything(context)
95
- end
96
-
97
- ##
98
- ## FETCHING VALUES
99
- ##
100
-
101
- def [](key)
102
- get(key)
103
- end
104
-
105
- # Overrride some default methods in Hash that are likely to
106
- # be used as attributes.
107
- alias_method :hkey, :key
108
- def key; get('key'); end
109
-
110
- #
111
- # make hash addressable like an object (e.g. obj['name'] available as obj.name)
112
- #
113
- def method_missing(method, *args, &block)
114
- get!(method)
115
- end
116
-
117
- def get(key)
118
- begin
119
- get!(key)
120
- rescue NoMethodError
121
- nil
122
- end
123
- end
124
-
125
- # override behavior of #default() from Hash
126
- def default
127
- get!('default')
128
- end
129
-
130
- #
131
- # Like a normal Hash#[], except:
132
- #
133
- # (1) lazily eval dynamic values when we encounter them. (i.e. strings that start with "= ")
134
- #
135
- # (2) support for nested references in a single string (e.g. ['a.b'] is the same as ['a']['b'])
136
- # the dot path is always absolute, starting at the top-most object.
137
- #
138
- def get!(key)
139
- key = key.to_s
140
- if self.has_key?(key)
141
- fetch_value(key)
142
- elsif key =~ /\./
143
- # for keys with with '.' in them, we start from the root object (@node).
144
- keys = key.split('.')
145
- value = self.get!(keys.first)
146
- if value.is_a? Config::Object
147
- value.get!(keys[1..-1].join('.'))
148
- else
149
- value
150
- end
151
- else
152
- raise NoMethodError.new(key, "No method '#{key}' for #{self.class}")
153
- end
154
- end
155
-
156
- ##
157
- ## COPYING
158
- ##
159
-
160
- #
161
- # A deep (recursive) merge with another Config::Object.
162
- #
163
- # If prefer_self is set to true, the value from self will be picked when there is a conflict
164
- # that cannot be merged.
165
- #
166
- # Merging rules:
167
- #
168
- # - If a value is a hash, we recursively merge it.
169
- # - If the value is simple, like a string, the new one overwrites the value.
170
- # - If the value is an array:
171
- # - If both old and new values are arrays, the new one replaces the old.
172
- # - If one of the values is simple but the other is an array, the simple is added to the array.
173
- #
174
- def deep_merge!(object, prefer_self=false)
175
- object.each do |key,new_value|
176
- if self.has_key?('+'+key)
177
- mode = :add
178
- old_value = self.fetch '+'+key, nil
179
- self.delete('+'+key)
180
- elsif self.has_key?('-'+key)
181
- mode = :subtract
182
- old_value = self.fetch '-'+key, nil
183
- self.delete('-'+key)
184
- elsif self.has_key?('!'+key)
185
- mode = :replace
186
- old_value = self.fetch '!'+key, nil
187
- self.delete('!'+key)
188
- else
189
- mode = :normal
190
- old_value = self.fetch key, nil
191
- end
192
-
193
- # clean up boolean
194
- new_value = true if new_value == "true"
195
- new_value = false if new_value == "false"
196
- old_value = true if old_value == "true"
197
- old_value = false if old_value == "false"
198
-
199
- # force replace?
200
- if mode == :replace && prefer_self
201
- value = old_value
202
-
203
- # merge hashes
204
- elsif old_value.is_a?(Hash) || new_value.is_a?(Hash)
205
- value = Config::Object.new(@env, @node)
206
- old_value.is_a?(Hash) ? value.deep_merge!(old_value) : (value[key] = old_value if !old_value.nil?)
207
- new_value.is_a?(Hash) ? value.deep_merge!(new_value, prefer_self) : (value[key] = new_value if !new_value.nil?)
208
-
209
- # merge nil
210
- elsif new_value.nil?
211
- value = old_value
212
- elsif old_value.nil?
213
- value = new_value
214
-
215
- # merge arrays when one value is not an array
216
- elsif old_value.is_a?(Array) && !new_value.is_a?(Array)
217
- (value = (old_value.dup << new_value).compact.uniq).delete('REQUIRED')
218
- elsif new_value.is_a?(Array) && !old_value.is_a?(Array)
219
- (value = (new_value.dup << old_value).compact.uniq).delete('REQUIRED')
220
-
221
- # merge two arrays
222
- elsif old_value.is_a?(Array) && new_value.is_a?(Array)
223
- if mode == :add
224
- value = (old_value + new_value).sort.uniq
225
- elsif mode == :subtract
226
- value = new_value - old_value
227
- elsif prefer_self
228
- value = old_value
229
- else
230
- value = new_value
231
- end
232
-
233
- # catch errors
234
- elsif type_mismatch?(old_value, new_value)
235
- raise 'Type mismatch. Cannot merge %s (%s) with %s (%s). Key is "%s", name is "%s".' % [
236
- old_value.inspect, old_value.class,
237
- new_value.inspect, new_value.class,
238
- key, self.class
239
- ]
240
-
241
- # merge simple strings & numbers
242
- else
243
- if prefer_self
244
- value = old_value
245
- else
246
- value = new_value
247
- end
248
- end
249
-
250
- # save value
251
- self[key] = value
252
- end
253
- self
254
- end
255
-
256
- def set_environment(env, node)
257
- @env = env
258
- @node = node
259
- self.each do |key, value|
260
- if value.is_a?(Config::Object)
261
- value.set_environment(env, node)
262
- end
263
- end
264
- end
265
-
266
- #
267
- # like a reverse deep merge
268
- # (self takes precedence)
269
- #
270
- def inherit_from!(object)
271
- self.deep_merge!(object, true)
272
- end
273
-
274
- #
275
- # Make a copy of ourselves, except only including the specified keys.
276
- #
277
- # Also, the result is flattened to a single hash, so a key of 'a.b' becomes 'a_b'
278
- #
279
- def pick(*keys)
280
- keys.map(&:to_s).inject(self.class.new(@manager)) do |hsh, key|
281
- value = self.get(key)
282
- if !value.nil?
283
- hsh[key.gsub('.','_')] = value
284
- end
285
- hsh
286
- end
287
- end
288
-
289
- def eval_file(filename)
290
- evaluate_ruby(filename, File.read(filename))
291
- end
292
-
293
- protected
294
-
295
- #
296
- # walks the object tree, eval'ing all the attributes that are dynamic ruby (e.g. value starts with '= ')
297
- #
298
- def evaluate_everything(context)
299
- keys.each do |key|
300
- obj = fetch_value(key, context)
301
- if is_required_value_not_set?(obj)
302
- Util::log 0, :warning, "required property \"#{key}\" is not set in node \"#{node.name}\"."
303
- elsif obj.is_a? Config::Object
304
- obj.evaluate_everything(context)
305
- end
306
- end
307
- end
308
-
309
- #
310
- # some keys need to be evaluated 'late', after all the other keys have been evaluated.
311
- #
312
- def late_evaluate_everything(context)
313
- if @late_eval_list
314
- @late_eval_list.each do |key, value|
315
- self[key] = context.evaluate_ruby(key, value)
316
- if is_required_value_not_set?(self[key])
317
- Util::log 0, :warning, "required property \"#{key}\" is not set in node \"#{node.name}\"."
318
- end
319
- end
320
- end
321
- values.each do |obj|
322
- if obj.is_a? Config::Object
323
- obj.late_evaluate_everything(context)
324
- end
325
- end
326
- end
327
-
328
- #
329
- # evaluates the string `value` as ruby in the context of self.
330
- # (`key` is just passed for debugging purposes)
331
- #
332
- def evaluate_ruby(key, value)
333
- self.instance_eval(value, key, 1)
334
- rescue ConfigError => exc
335
- raise exc # pass through
336
- rescue SystemStackError => exc
337
- Util::log 0, :error, "while evaluating node '#{self.name}'"
338
- Util::log 0, "offending key: #{key}", :indent => 1
339
- Util::log 0, "offending string: #{value}", :indent => 1
340
- Util::log 0, "STACK OVERFLOW, BAILING OUT. There must be an eval loop of death (variables with circular dependencies).", :indent => 1
341
- raise SystemExit.new(1)
342
- rescue FileMissing => exc
343
- Util::bail! do
344
- if exc.options[:missing]
345
- Util::log :missing, exc.options[:missing].gsub('$node', self.name).gsub('$file', exc.path)
346
- else
347
- Util::log :error, "while evaluating node '#{self.name}'"
348
- Util::log "offending key: #{key}", :indent => 1
349
- Util::log "offending string: #{value}", :indent => 1
350
- Util::log "error message: no file '#{exc}'", :indent => 1
351
- end
352
- raise exc if DEBUG
353
- end
354
- rescue AssertionFailed => exc
355
- Util.bail! do
356
- Util::log :failed, "assertion while evaluating node '#{self.name}'"
357
- Util::log 'assertion: %s' % exc.assertion, :indent => 1
358
- Util::log "offending key: #{key}", :indent => 1
359
- raise exc if DEBUG
360
- end
361
- rescue SyntaxError, StandardError => exc
362
- Util::bail! do
363
- Util::log :error, "while evaluating node '#{self.name}'"
364
- Util::log "offending key: #{key}", :indent => 1
365
- Util::log "offending string: #{value}", :indent => 1
366
- Util::log "error message: #{exc.inspect}", :indent => 1
367
- raise exc if DEBUG
368
- end
369
- end
370
-
371
- private
372
-
373
- #
374
- # fetches the value for the key, evaluating the value as ruby if it begins with '='
375
- #
376
- def fetch_value(key, context=@node)
377
- value = fetch(key, nil)
378
- if value.is_a?(String) && value =~ /^=/
379
- if value =~ /^=> (.*)$/
380
- value = evaluate_later(key, $1)
381
- elsif value =~ /^= (.*)$/
382
- value = context.evaluate_ruby(key, $1)
383
- end
384
- self[key] = value
385
- end
386
- return value
387
- end
388
-
389
- def evaluate_later(key, value)
390
- @late_eval_list ||= []
391
- @late_eval_list << [key, value]
392
- '<evaluate later>'
393
- end
394
-
395
- #
396
- # when merging, we raise an error if this method returns true for the two values.
397
- #
398
- def type_mismatch?(old_value, new_value)
399
- if old_value.is_a?(Boolean) && new_value.is_a?(Boolean)
400
- # note: FalseClass and TrueClass are different classes
401
- # so we can't do old_value.class == new_value.class
402
- return false
403
- elsif old_value.is_a?(String) && old_value =~ /^=/
404
- # pass through macros, since we don't know what the type will eventually be.
405
- return false
406
- elsif new_value.is_a?(String) && new_value =~ /^=/
407
- return false
408
- elsif old_value.class == new_value.class
409
- return false
410
- else
411
- return true
412
- end
413
- end
414
-
415
- #
416
- # returns true if the value has not been changed and the default is "REQUIRED"
417
- #
418
- def is_required_value_not_set?(value)
419
- if value.is_a? Array
420
- value == ["REQUIRED"]
421
- else
422
- value == "REQUIRED"
423
- end
424
- end
425
-
426
- end # class
427
- end # module
428
- end # module