vagrant-lxd 0.3.4 → 0.4.0

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
  SHA1:
3
- metadata.gz: 19b57c015f383c61855e133fbcca178eec5c389b
4
- data.tar.gz: ebe1a99f880fa00afdf740e7c1c9f3163b53f22d
3
+ metadata.gz: 37988b3901f0e99417203fbab0b8c532e631f0c4
4
+ data.tar.gz: c39bdfa2e6e7912cd5dc3cad36600bc6d98ff51d
5
5
  SHA512:
6
- metadata.gz: b7f17bca98f8490e9c773d3848b5348a521e97d6352fae665007fb16b579e3fa74605fd73eccdbeb217cba0c8fa6f889b606e4b06925667d7632cb88a51c9096
7
- data.tar.gz: 89218b6793e3ce419c4c9b486d81c8e88e4d35c5b00d22857247558d889f9d2a6faee55adfdecf1d03b38fb201217843507234ef71a5371526c2c9f6eae27dab
6
+ metadata.gz: 1c14feb0f9522935357fe750329e288697bb8dc226218aeeebec74baa8e78afc36689a3972db637db9fa0e507e594dcfc9ae8df0c68a25550ee6359e536f6d35
7
+ data.tar.gz: 68cb1f0440026627051a5754e64857b25a78dc5d7a0d155c798304af8676efff555a5e226e01be3daa6d4d258e0d64856fa6195070c8a8366004df987bade911
data/Gemfile.lock CHANGED
@@ -27,7 +27,7 @@ GIT
27
27
  PATH
28
28
  remote: .
29
29
  specs:
30
- vagrant-lxd (0.3.4)
30
+ vagrant-lxd (0.4.0)
31
31
  hyperkit (~> 1.2.0)
32
32
 
33
33
  GEM
data/README.md CHANGED
@@ -67,7 +67,7 @@ VM images from [Vagrant Cloud][cloud] should work without modification:
67
67
 
68
68
  #### Configuration
69
69
 
70
- Below is an example Vagrantfile showing all of the provider's
70
+ Below is an example Vagrantfile showing most of the provider's
71
71
  configurable values, along with their defaults. The `debian/stretch64`
72
72
  box is available on the Vagrant Cloud, so you should be able to copy
73
73
  this file and adjust it as you see fit.
@@ -90,6 +90,27 @@ Vagrant.configure('2') do |config|
90
90
  end
91
91
  ```
92
92
 
93
+ ### Client Authentication
94
+
95
+ The LXD API uses client certificates to authenticate requests.
96
+
97
+ By default, the plugin will first try to use files from
98
+ `~/.config/lxc/client.crt` and `client.key`, if they exist. Otherwise,
99
+ it will generate a new 4096-bit RSA certificate (and accompanying
100
+ private key) in Vagrant's data directory. When using the plugin for the
101
+ first time, you will need to add this certificate to LXD's trust store
102
+ by running:
103
+
104
+ $ lxc config trust add ~/.vagrant.d/data/lxd/client.crt
105
+
106
+ If you would rather use an existing certificate, you can specify the
107
+ files for the plugin to use with the following settings:
108
+
109
+ config.vm.provider 'lxd' do |lxd|
110
+ lxd.client_certificate = '/path/to/client.crt'
111
+ lxd.client_key = '/path/to/client.key'
112
+ end
113
+
93
114
  ### Synced Folders
94
115
 
95
116
  In order to use shared folders, you must first add your user ID to the
@@ -177,6 +198,10 @@ configuration documentation][docs] for details.
177
198
  lxd.privileged = true
178
199
  end
179
200
 
201
+ Note that enabling these options will invalidate any user and group ID
202
+ mappings you may have configured for synced folders, since privileged
203
+ containers use the same UID and GID space as the host machine.
204
+
180
205
  [docs]: https://lxd.readthedocs.io/en/latest/containers/
181
206
 
182
207
  ## Hacking
@@ -18,6 +18,7 @@
18
18
  #
19
19
 
20
20
  require 'uri'
21
+ require 'openssl'
21
22
 
22
23
  module VagrantLXD
23
24
  class Config < Vagrant.plugin('2', :config)
@@ -32,6 +33,8 @@ module VagrantLXD
32
33
  attr_accessor :profiles
33
34
  attr_accessor :vagrant_uid
34
35
  attr_accessor :vagrant_gid
36
+ attr_accessor :client_certificate
37
+ attr_accessor :client_key
35
38
 
36
39
  def initialize
37
40
  @name = UNSET_VALUE
@@ -45,6 +48,8 @@ module VagrantLXD
45
48
  @api_endpoint = UNSET_VALUE
46
49
  @vagrant_uid = UNSET_VALUE
47
50
  @vagrant_gid = UNSET_VALUE
51
+ @client_certificate = UNSET_VALUE
52
+ @client_key = UNSET_VALUE
48
53
  end
49
54
 
50
55
  def validate(machine)
@@ -110,6 +115,30 @@ module VagrantLXD
110
115
  errors << "Invalid `vagrant_gid' (value must be a non-negative integer): #{vagrant_gid.inspect}"
111
116
  end
112
117
 
118
+ if client_certificate.is_a? String
119
+ begin
120
+ OpenSSL::X509::Certificate.new(File.read(client_certificate))
121
+ rescue Exception => e
122
+ errors << "Invalid `client_certificate' (unable to read certificate): #{e.message}"
123
+ end
124
+ elsif not client_certificate.nil?
125
+ errors << "Invalid `client_certificate' (value must be a string): #{client_certificate.inspect}"
126
+ elsif not client_key.nil?
127
+ errors << "You must provide both `client_certificate' and `client_key'"
128
+ end
129
+
130
+ if client_key.is_a? String
131
+ begin
132
+ OpenSSL::PKey.read(File.read(client_key))
133
+ rescue Exception => e
134
+ errors << "Invalid `client_key' (unable to read key): #{e.message}"
135
+ end
136
+ elsif not client_key.nil?
137
+ errors << "Invalid `client_key' (value must be a string): #{client_key.inspect}"
138
+ elsif not client_certificate.nil?
139
+ errors << "You must provide both `client_certificate' and `client_key'"
140
+ end
141
+
113
142
  { Version::NAME => errors }
114
143
  end
115
144
 
@@ -148,7 +177,7 @@ module VagrantLXD
148
177
 
149
178
  if api_endpoint == UNSET_VALUE
150
179
  @api_endpoint = URI('https://127.0.0.1:8443')
151
- else
180
+ elsif String === api_endpoint
152
181
  @api_endpoint = URI(api_endpoint)
153
182
  end
154
183
 
@@ -159,6 +188,18 @@ module VagrantLXD
159
188
  if vagrant_gid == UNSET_VALUE
160
189
  @vagrant_gid = vagrant_uid
161
190
  end
191
+
192
+ if client_certificate == UNSET_VALUE
193
+ @client_certificate = nil
194
+ elsif String === client_certificate
195
+ @client_certificate = File.expand_path(client_certificate)
196
+ end
197
+
198
+ if client_key == UNSET_VALUE
199
+ @client_key = nil
200
+ elsif String === client_key
201
+ @client_key = File.expand_path(client_key)
202
+ end
162
203
  end
163
204
  end
164
205
  end
@@ -24,7 +24,7 @@ require 'tempfile'
24
24
  require 'timeout'
25
25
  require 'monitor'
26
26
  require 'vagrant/machine_state'
27
- require 'vagrant-lxd/config'
27
+ require 'vagrant-lxd/driver/certificate'
28
28
 
29
29
  module VagrantLXD
30
30
  class Driver
@@ -88,6 +88,10 @@ module VagrantLXD
88
88
  error_key 'lxd_disk_unmount_failure'
89
89
  end
90
90
 
91
+ class CertificateGenerationFailure < Vagrant::Errors::VagrantError
92
+ error_key 'lxd_certificate_generation_failure'
93
+ end
94
+
91
95
  class SnapshotNotFound < Vagrant::Errors::VagrantError
92
96
  error_key 'snapshot_not_found'
93
97
  end
@@ -118,6 +122,8 @@ module VagrantLXD
118
122
  attr_reader :nesting
119
123
  attr_reader :privileged
120
124
  attr_reader :profiles
125
+ attr_reader :client_certificate
126
+ attr_reader :client_key
121
127
  attr_reader :vagrant_uid
122
128
  attr_reader :vagrant_gid
123
129
 
@@ -132,10 +138,11 @@ module VagrantLXD
132
138
  @ephemeral = machine.provider_config.ephemeral
133
139
  @profiles = machine.provider_config.profiles
134
140
  @name = machine.provider_config.name
141
+ @client_certificate = machine.provider_config.client_certificate
142
+ @client_key = machine.provider_config.client_key
135
143
  @vagrant_uid = machine.provider_config.vagrant_uid
136
144
  @vagrant_gid = machine.provider_config.vagrant_gid
137
145
  @logger = Log4r::Logger.new('vagrant::lxd::driver')
138
- @lxd = Hyperkit::Client.new(api_endpoint: api_endpoint.to_s, verify_ssl: false, user_agent: USER_AGENT)
139
146
  end
140
147
 
141
148
  def validate!
@@ -156,18 +163,18 @@ module VagrantLXD
156
163
  end
157
164
 
158
165
  def mount(name, options)
159
- container = @lxd.container(machine_id)
166
+ container = lxd.container(machine_id)
160
167
  devices = container[:devices].to_hash
161
168
  devices[name] = { type: 'disk', path: options[:guestpath], source: options[:hostpath] }.merge(options[:config])
162
169
  container[:devices] = devices
163
- @lxd.update_container(machine_id, container)
170
+ lxd.update_container(machine_id, container)
164
171
  rescue Hyperkit::BadRequest => e
165
172
  @machine.ui.error 'Failed to mount synced folder'
166
173
  fail DiskMountFailure, machine_name: @machine.name, guestpath: options[:guestpath], reason: e.reason
167
174
  end
168
175
 
169
176
  def mounted?(name, options)
170
- container = @lxd.container(machine_id)
177
+ container = lxd.container(machine_id)
171
178
  devices = container[:devices].to_hash
172
179
  name = name.to_sym
173
180
  begin
@@ -179,18 +186,18 @@ module VagrantLXD
179
186
  end
180
187
 
181
188
  def unmount(name, options)
182
- container = @lxd.container(machine_id)
189
+ container = lxd.container(machine_id)
183
190
  devices = container[:devices].to_hash
184
191
  devices.delete(name.to_sym)
185
192
  container[:devices] = devices
186
- @lxd.update_container(machine_id, container)
193
+ lxd.update_container(machine_id, container)
187
194
  rescue Hyperkit::BadRequest => e
188
195
  @machine.ui.error 'Failed to unmount synced folder'
189
196
  fail DiskUnmountFailure, machine_name: @machine.name, guestpath: options[:guestpath], reason: e.reason
190
197
  end
191
198
 
192
199
  def attach(container)
193
- @lxd.container(container) # Query LXD to make sure the container exists.
200
+ lxd.container(container) # Query LXD to make sure the container exists.
194
201
 
195
202
  if in_state? NOT_CREATED
196
203
  @machine.id = container
@@ -211,17 +218,17 @@ module VagrantLXD
211
218
  #
212
219
 
213
220
  def snapshot_list
214
- @lxd.snapshots(machine_id)
221
+ lxd.snapshots(machine_id)
215
222
  end
216
223
 
217
224
  def snapshot_save(name)
218
225
  snapshot_delete(name) # noops if the snapshot doesn't exist
219
- operation = @lxd.create_snapshot(machine_id, name, sync: false)
226
+ operation = lxd.create_snapshot(machine_id, name, sync: false)
220
227
  wait_for_operation(operation)
221
228
  end
222
229
 
223
230
  def snapshot_restore(name)
224
- operation = @lxd.restore_snapshot(machine_id, name, sync: false)
231
+ operation = lxd.restore_snapshot(machine_id, name, sync: false)
225
232
  wait_for_operation(operation)
226
233
  rescue Hyperkit::BadRequest
227
234
  @logger.warn 'Snapshot restoration failed: ' << name
@@ -229,14 +236,14 @@ module VagrantLXD
229
236
  end
230
237
 
231
238
  def snapshot_delete(name)
232
- @lxd.delete_snapshot(machine_id, name)
239
+ lxd.delete_snapshot(machine_id, name)
233
240
  rescue Hyperkit::NotFound
234
241
  @logger.warn 'No such snapshot: ' << name
235
242
  end
236
243
 
237
244
  def state
238
245
  return NOT_CREATED if machine_id.nil?
239
- container_state = @lxd.container_state(machine_id)
246
+ container_state = lxd.container_state(machine_id)
240
247
  container_state[:status].downcase.to_sym
241
248
  rescue Hyperkit::NotFound
242
249
  NOT_CREATED
@@ -250,28 +257,28 @@ module VagrantLXD
250
257
 
251
258
  Driver.synchronize do
252
259
  begin
253
- image = @lxd.image(fingerprint)
260
+ image = lxd.image(fingerprint)
254
261
  @logger.debug 'Using image: ' << image.inspect
255
262
  rescue Hyperkit::NotFound
256
- image = @lxd.create_image_from_file(file)
263
+ image = lxd.create_image_from_file(file)
257
264
  @logger.debug 'Created image: ' << image.inspect
258
265
  begin
259
- @lxd.update_image(fingerprint, properties: IMAGE_PROPERTIES)
260
- @lxd.create_image_alias(fingerprint, machine_id, IMAGE_PROPERTIES)
266
+ lxd.update_image(fingerprint, properties: IMAGE_PROPERTIES)
267
+ lxd.create_image_alias(fingerprint, machine_id, IMAGE_PROPERTIES)
261
268
  rescue Hyperkit::Error
262
269
  @logger.error 'Failed to set description for image: ' << e.reason
263
270
  end
264
271
  end
265
272
  end
266
273
 
267
- container = @lxd.create_container(machine_id, ephemeral: ephemeral, fingerprint: fingerprint, config: config, profiles: profiles)
274
+ container = lxd.create_container(machine_id, ephemeral: ephemeral, fingerprint: fingerprint, config: config, profiles: profiles)
268
275
  @logger.debug 'Created container: ' << container.inspect
269
276
 
270
277
  @machine.id = machine_id
271
278
  end
272
279
  rescue Hyperkit::Error => e
273
- @lxd.delete_container(machine_id) rescue nil unless container.nil?
274
- @lxd.delete_image(image[:metadata][:fingerprint]) rescue nil unless image.nil?
280
+ lxd.delete_container(machine_id) rescue nil unless container.nil?
281
+ lxd.delete_image(image[:metadata][:fingerprint]) rescue nil unless image.nil?
275
282
  if e.reason =~ /Container '([^']+)' already exists/
276
283
  @machine.ui.error e.reason
277
284
  fail ContainerAlreadyExists, machine_name: @machine.name, container: $1
@@ -284,9 +291,9 @@ module VagrantLXD
284
291
  def resume
285
292
  case state
286
293
  when :stopped
287
- @lxd.start_container(machine_id)
294
+ lxd.start_container(machine_id)
288
295
  when :frozen
289
- @lxd.unfreeze_container(machine_id, timeout: timeout)
296
+ lxd.unfreeze_container(machine_id, timeout: timeout)
290
297
  end
291
298
  rescue Hyperkit::BadRequest
292
299
  @machine.ui.warn "Container failed to start within #{timeout} seconds"
@@ -295,7 +302,7 @@ module VagrantLXD
295
302
 
296
303
  def halt(force = false)
297
304
  if in_state? :running, :frozen
298
- @lxd.stop_container(machine_id, timeout: timeout, force: force)
305
+ lxd.stop_container(machine_id, timeout: timeout, force: force)
299
306
  end
300
307
  rescue Hyperkit::BadRequest
301
308
  if force
@@ -308,7 +315,7 @@ module VagrantLXD
308
315
 
309
316
  def suspend
310
317
  if in_state? :running
311
- @lxd.freeze_container(machine_id, timeout: timeout)
318
+ lxd.freeze_container(machine_id, timeout: timeout)
312
319
  end
313
320
  rescue Hyperkit::BadRequest
314
321
  @machine.ui.warn "Container failed to suspend within #{timeout} seconds"
@@ -325,9 +332,9 @@ module VagrantLXD
325
332
  end
326
333
 
327
334
  def configure
328
- container = @lxd.container(machine_id)
335
+ container = lxd.container(machine_id)
329
336
  container[:config] = container[:config].to_hash.merge(config)
330
- @lxd.update_container(machine_id, container)
337
+ lxd.update_container(machine_id, container)
331
338
  rescue Hyperkit::Error => e
332
339
  @machine.ui.error 'Failed to configure container'
333
340
  fail ContainerConfigurationFailure, machine_name: @machine.name, reason: e.reason
@@ -349,12 +356,22 @@ module VagrantLXD
349
356
  # used by the rest of the plugin.
350
357
  #
351
358
 
359
+ def lxd
360
+ @lxd ||= Hyperkit::Client.new(
361
+ api_endpoint: api_endpoint.to_s,
362
+ client_cert: cert.certificate,
363
+ client_key: cert.key,
364
+ verify_ssl: false,
365
+ user_agent: USER_AGENT,
366
+ )
367
+ end
368
+
352
369
  def machine_id
353
370
  @machine.id
354
371
  end
355
372
 
356
373
  def delete_container
357
- @lxd.delete_container(machine_id)
374
+ lxd.delete_container(machine_id)
358
375
  rescue Hyperkit::NotFound
359
376
  @logger.warn "Container '#{machine_id}' not found, unable to destroy"
360
377
  rescue Hyperkit::Error => e
@@ -369,7 +386,7 @@ module VagrantLXD
369
386
  end
370
387
 
371
388
  def delete_image
372
- @lxd.delete_image(container[:config][:'volatile.base_image'])
389
+ lxd.delete_image(container[:config][:'volatile.base_image'])
373
390
  rescue Hyperkit::NotFound
374
391
  @logger.warn "Image for '#{machine_id}' not found, unable to destroy"
375
392
  rescue Hyperkit::BadRequest
@@ -380,17 +397,17 @@ module VagrantLXD
380
397
  # is enabled or setting sync: true. TODO Upstream a better fix than
381
398
  # this, so that `wait_for_operation` really does.
382
399
  def wait_for_operation(operation)
383
- @lxd.wait_for_operation(operation.id)
400
+ lxd.wait_for_operation(operation.id)
384
401
  rescue Faraday::TimeoutError
385
402
  retry
386
403
  end
387
404
 
388
405
  def container
389
- @lxd.container(machine_id)
406
+ lxd.container(machine_id)
390
407
  end
391
408
 
392
409
  def connection_usable?
393
- @lxd.images
410
+ lxd.images
394
411
  rescue Faraday::ConnectionFailed
395
412
  false
396
413
  else
@@ -398,7 +415,7 @@ module VagrantLXD
398
415
  end
399
416
 
400
417
  def authentication_usable?
401
- connection_usable? and @lxd.containers
418
+ connection_usable? and lxd.containers
402
419
  rescue Hyperkit::Forbidden
403
420
  false
404
421
  else
@@ -425,7 +442,7 @@ module VagrantLXD
425
442
  @logger.debug "Looking up ipv4 address for #{machine_id}..."
426
443
  Timeout.timeout(timeout) do
427
444
  loop do
428
- container_state = @lxd.container_state(machine_id)
445
+ container_state = lxd.container_state(machine_id)
429
446
  if address = container_state[:network][:eth0][:addresses].find { |a| a[:family] == 'inet' }
430
447
  return address[:address]
431
448
  else
@@ -439,6 +456,16 @@ module VagrantLXD
439
456
  fail NetworkAddressAcquisitionTimeout, time_limit: timeout, lxd_bridge: 'lxdbr0' # FIXME Hardcoded bridge name
440
457
  end
441
458
 
459
+ def cert
460
+ @cert ||= if client_certificate
461
+ Certificate.new(client_certificate, client_key)
462
+ else
463
+ Driver.synchronize do
464
+ locate_or_generate_client_certificate
465
+ end
466
+ end
467
+ end
468
+
442
469
  def config
443
470
  # NOTE We reuse ActiveSupport for `#deep_dup` here, but if the Hyperkit
444
471
  # dependency ever goes away, drop ActiveSupport and use some other
@@ -469,6 +496,18 @@ module VagrantLXD
469
496
  config
470
497
  end
471
498
 
499
+ def locate_or_generate_client_certificate
500
+ vagrant_path = @machine.env.data_dir / 'lxd'
501
+ default_path = Certificate.default_path / 'lxc'
502
+
503
+ search_paths = [vagrant_path, default_path]
504
+
505
+ Certificate.locate(search_paths) or
506
+ Certificate.generate(vagrant_path)
507
+ rescue Certificate::GenerationFailure => e
508
+ fail CertificateGenerationFailure, reason: e.message, api_endpoint: @api_endpoint.to_s, default_path: default_path, vagrant_path: vagrant_path
509
+ end
510
+
472
511
  # TODO Image handling should be moved into its own class.
473
512
  def prepare_image_file
474
513
  tmpdir = Dir.mktmpdir
@@ -520,7 +559,7 @@ module VagrantLXD
520
559
  machine: @machine.name,
521
560
  api_endpoint: @api_endpoint.to_s,
522
561
  https_address: @api_endpoint.host,
523
- client_cert: File.expand_path('.config/lxc/client.crt', ENV['HOME']),
562
+ client_cert: cert.certificate.to_s,
524
563
  )
525
564
  end
526
565
  end
@@ -0,0 +1,88 @@
1
+ #
2
+ # Copyright (c) 2019 Catalyst.net Ltd
3
+ #
4
+ # This file is part of vagrant-lxd.
5
+ #
6
+ # vagrant-lxd is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or (at
9
+ # your option) any later version.
10
+ #
11
+ # vagrant-lxd is distributed in the hope that it will be useful, but
12
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ # General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with vagrant-lxd. If not, see <http://www.gnu.org/licenses/>.
18
+ #
19
+
20
+ require 'etc'
21
+ require 'openssl'
22
+ require 'pathname'
23
+ require 'socket'
24
+ require 'vagrant-lxd/version'
25
+
26
+ module VagrantLXD
27
+ class Driver
28
+ class Certificate < Struct.new(:certificate, :key)
29
+ PKEY_BITS = 4096
30
+ CERT_EXPIRY_YEARS = 10
31
+
32
+ GenerationFailure = Class.new(Exception)
33
+
34
+ @logger = Log4r::Logger.new('vagrant::lxd::driver::certificate')
35
+
36
+ def Certificate.default_path
37
+ Pathname.new('~/.config').expand_path
38
+ end
39
+
40
+ def Certificate.issuer_name
41
+ version = "#{Version::DESCRIPTION} #{Version::VERSION}"
42
+ username = Etc.getpwuid(Process.uid).name
43
+ hostname = Socket.gethostname
44
+ "/O=linuxcontainers.org/OU=#{version}/CN=#{username}@#{hostname}"
45
+ end
46
+
47
+ def Certificate.locate(paths)
48
+ if path = paths.find { |x| usable?(x) }
49
+ @logger.debug "Found usable certificate under #{path}"
50
+ Certificate.new(path / 'client.crt', path / 'client.key')
51
+ end
52
+ end
53
+
54
+ def Certificate.generate(path)
55
+ @logger.debug 'Generating new client certificate...'
56
+ name = OpenSSL::X509::Name.parse(issuer_name)
57
+ pkey = OpenSSL::PKey::RSA.new(PKEY_BITS)
58
+ cert = OpenSSL::X509::Certificate.new
59
+ cert.serial = 0
60
+ cert.version = 3
61
+ cert.issuer = name
62
+ cert.subject = name
63
+ cert.public_key = pkey.public_key
64
+ cert.not_before = Time.now
65
+ cert.not_after = Time.now + (365 * 24 * 60 * 60 * CERT_EXPIRY_YEARS)
66
+ cert.sign(pkey, OpenSSL::Digest::SHA1.new)
67
+ @logger.debug "Saving new certificate to disk under #{path}..."
68
+ FileUtils.mkdir_p(path, mode: 0o700)
69
+ File.write(path / 'client.crt', cert.to_s, 0, perm: 0o600)
70
+ File.write(path / 'client.key', pkey.to_s, 0, perm: 0o600)
71
+ Certificate.new(path / 'client.crt', path / 'client.key')
72
+ rescue Exception => e
73
+ @logger.error 'Certificate creation failed: ' << e.message
74
+ fail GenerationFailure, e.message
75
+ end
76
+
77
+ def Certificate.usable?(path)
78
+ @logger.debug "Checking for existing client certificate in #{path}..."
79
+ OpenSSL::PKey.read(File.read(path / 'client.key'))
80
+ OpenSSL::X509::Certificate.new(File.read(path / 'client.crt'))
81
+ rescue Exception
82
+ false
83
+ else
84
+ true
85
+ end
86
+ end
87
+ end
88
+ end
@@ -20,7 +20,7 @@
20
20
  module VagrantLXD
21
21
  module Version
22
22
  NAME = 'vagrant-lxd'
23
- VERSION = '0.3.4'
23
+ VERSION = '0.4.0'
24
24
  DESCRIPTION = 'Vagrant LXD provider'
25
25
  end
26
26
  end
@@ -32,13 +32,13 @@ en:
32
32
 
33
33
  errors:
34
34
  lxd_connection_failure: |-
35
- The provider was unable to contact the LXD daemon at %{api_endpoint}.
35
+ The LXD provider was unable to contact the daemon at %{api_endpoint}.
36
36
 
37
37
  It's possible that LXD isn't installed, or that it isn't configured to
38
38
  accept HTTPS connections from your machine. You can check whether HTTPS
39
39
  access is enabled with the following command:
40
40
 
41
- $ lxc config show core.https_address
41
+ $ lxc config get core.https_address
42
42
 
43
43
  If the result is empty or an error is shown, you will need to correct
44
44
  the way LXD is configured before Vagrant can use it. This can be done
@@ -51,7 +51,7 @@ en:
51
51
  https://linuxcontainers.org/lxd/getting-started-cli/#initial-configuration
52
52
 
53
53
  lxd_authentication_failure: |-
54
- The provider could not authenticate to the LXD daemon at %{api_endpoint}.
54
+ The LXD provider could not authenticate to the daemon at %{api_endpoint}.
55
55
 
56
56
  You may need configure LXD to allow requests from this machine. The
57
57
  easiest way to do this is to add your LXC client certificate to LXD's
@@ -156,6 +156,18 @@ en:
156
156
  You will either need to delete this container and try again, or attach
157
157
  the VM to it with `vagrant lxd attach %{machine_name} %{container}`.
158
158
 
159
+ lxd_certificate_generation_failure: |-
160
+ The LXD provider was unable to generate a client certificate for
161
+ authenticating to the daemon at %{api_endpoint}.
162
+
163
+ It tried to place the files in %{vagrant_path}.
164
+
165
+ The underlying error message was: %{reason}
166
+
167
+ You can use an existing certificate by setting the `client_certificate`
168
+ and `client_key` options in the LXD provider's configuration, or by
169
+ placing 'client.crt' and 'client.key' files in %{default_path}.
170
+
159
171
  snapshot_not_found: |-
160
172
  The snapshot name `%{snapshot_name}` was not found for the
161
173
  virtual machine `%{machine}`.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-lxd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Hanson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-18 00:00:00.000000000 Z
11
+ date: 2019-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hyperkit
@@ -45,6 +45,7 @@ files:
45
45
  - lib/vagrant-lxd/command.rb
46
46
  - lib/vagrant-lxd/config.rb
47
47
  - lib/vagrant-lxd/driver.rb
48
+ - lib/vagrant-lxd/driver/certificate.rb
48
49
  - lib/vagrant-lxd/plugin.rb
49
50
  - lib/vagrant-lxd/provider.rb
50
51
  - lib/vagrant-lxd/synced_folder.rb
@@ -71,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
72
  version: '0'
72
73
  requirements: []
73
74
  rubyforge_project:
74
- rubygems_version: 2.6.12
75
+ rubygems_version: 2.6.8
75
76
  signing_key:
76
77
  specification_version: 4
77
78
  summary: Vagrant LXD provider