Merge pull request #2565 from mitchellh/f-box-checksum
Implement box checksumming
This commit is contained in:
commit
2e199d0889
|
@ -2,6 +2,7 @@ require "digest/sha1"
|
|||
require "log4r"
|
||||
|
||||
require "vagrant/util/downloader"
|
||||
require "vagrant/util/file_checksum"
|
||||
require "vagrant/util/platform"
|
||||
|
||||
module Vagrant
|
||||
|
@ -18,6 +19,22 @@ module Vagrant
|
|||
def call(env)
|
||||
@download_interrupted = false
|
||||
|
||||
# Determine the checksum type to use
|
||||
checksum = (env[:box_checksum] || "").to_s
|
||||
checksum_klass = case env[:box_checksum_type].to_sym
|
||||
when nil
|
||||
nil
|
||||
when :md5
|
||||
Digest::MD5
|
||||
when :sha1
|
||||
Digest::SHA1
|
||||
when :sha256
|
||||
Digest::SHA2
|
||||
else
|
||||
raise Errors::BoxChecksumInvalidType,
|
||||
type: env[:box_checksum_type].to_s
|
||||
end
|
||||
|
||||
# Go through each URL and attempt to download it
|
||||
download_error = nil
|
||||
download_url = nil
|
||||
|
@ -45,6 +62,20 @@ module Vagrant
|
|||
# If all the URLs failed, then raise an exception
|
||||
raise download_error if download_error
|
||||
|
||||
if checksum_klass
|
||||
@logger.info("Validating checksum with #{checksum_klass}")
|
||||
@logger.info("Expected checksum: #{checksum}")
|
||||
|
||||
env[:ui].info(I18n.t("vagrant.actions.box.add.checksumming",
|
||||
name: env[:box_name]))
|
||||
actual = FileChecksum.new(@temp_path, checksum_klass).checksum
|
||||
if actual != checksum
|
||||
raise Errors::BoxChecksumMismatch,
|
||||
actual: actual,
|
||||
expected: checksum
|
||||
end
|
||||
end
|
||||
|
||||
box_formats = env[:box_provider]
|
||||
if box_formats
|
||||
# Determine the formats a box can support and allow the box to
|
||||
|
|
|
@ -41,6 +41,8 @@ module Vagrant
|
|||
box_name = env[:machine].config.vm.box
|
||||
box_url = env[:machine].config.vm.box_url
|
||||
box_download_ca_cert = env[:machine].config.vm.box_download_ca_cert
|
||||
box_download_checksum = env[:machine].config.vm.box_download_checksum
|
||||
box_download_checksum_type = env[:machine].config.vm.box_download_checksum_type
|
||||
box_download_client_cert = env[:machine].config.vm.box_download_client_cert
|
||||
box_download_insecure = env[:machine].config.vm.box_download_insecure
|
||||
|
||||
|
@ -69,8 +71,10 @@ module Vagrant
|
|||
|
||||
begin
|
||||
env[:action_runner].run(Vagrant::Action.action_box_add, {
|
||||
:box_download_ca_cert => box_download_ca_cert,
|
||||
:box_checksum => box_download_checksum,
|
||||
:box_checksum_type => box_download_checksum_type,
|
||||
:box_client_cert => box_download_client_cert,
|
||||
:box_download_ca_cert => box_download_ca_cert,
|
||||
:box_download_insecure => box_download_insecure,
|
||||
:box_name => box_name,
|
||||
:box_provider => box_formats,
|
||||
|
|
|
@ -120,6 +120,14 @@ module Vagrant
|
|||
error_key(:already_exists, "vagrant.actions.box.unpackage")
|
||||
end
|
||||
|
||||
class BoxChecksumInvalidType < VagrantError
|
||||
error_key(:box_checksum_invalid_type)
|
||||
end
|
||||
|
||||
class BoxChecksumMismatch < VagrantError
|
||||
error_key(:box_checksum_mismatch)
|
||||
end
|
||||
|
||||
class BoxConfigChangingBox < VagrantError
|
||||
error_key(:box_config_changing_box)
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ class DigestClass
|
|||
end
|
||||
|
||||
class FileChecksum
|
||||
BUFFER_SIZE = 1024
|
||||
BUFFER_SIZE = 16328
|
||||
|
||||
# Initializes an object to calculate the checksum of a file. The given
|
||||
# ``digest_klass`` should implement the ``DigestClass`` interface. Note
|
||||
|
@ -16,7 +16,7 @@ class FileChecksum
|
|||
# Digest::MD5, Digest::SHA1, etc.
|
||||
def initialize(path, digest_klass)
|
||||
@digest_klass = digest_klass
|
||||
@path = path
|
||||
@path = path
|
||||
end
|
||||
|
||||
# This calculates the checksum of the file and returns it as a
|
||||
|
@ -24,7 +24,7 @@ class FileChecksum
|
|||
#
|
||||
# @return [String]
|
||||
def checksum
|
||||
digest= @digest_klass.new
|
||||
digest = @digest_klass.new
|
||||
|
||||
File.open(@path, "r") do |f|
|
||||
while !f.eof
|
||||
|
|
|
@ -11,6 +11,14 @@ module VagrantPlugins
|
|||
o.banner = "Usage: vagrant box add <name> <url> [--provider provider] [-h]"
|
||||
o.separator ""
|
||||
|
||||
o.on("--checksum VALUE", String, "Checksum") do |c|
|
||||
options[:checksum] = c
|
||||
end
|
||||
|
||||
o.on("--checksum-type VALUE", String, "Checksum type") do |c|
|
||||
options[:checksum_type] = c.to_sym
|
||||
end
|
||||
|
||||
o.on("-c", "--clean", "Remove old temporary download if it exists.") do |c|
|
||||
options[:clean] = c
|
||||
end
|
||||
|
@ -51,6 +59,8 @@ module VagrantPlugins
|
|||
:box_name => argv[0],
|
||||
:box_provider => provider,
|
||||
:box_url => argv[1],
|
||||
:box_checksum_type => options[:checksum_type],
|
||||
:box_checksum => options[:checksum],
|
||||
:box_clean => options[:clean],
|
||||
:box_force => options[:force],
|
||||
:box_download_ca_cert => options[:ca_cert],
|
||||
|
|
|
@ -19,6 +19,8 @@ module VagrantPlugins
|
|||
attr_accessor :box
|
||||
attr_accessor :box_url
|
||||
attr_accessor :box_download_ca_cert
|
||||
attr_accessor :box_download_checksum
|
||||
attr_accessor :box_download_checksum_type
|
||||
attr_accessor :box_download_client_cert
|
||||
attr_accessor :box_download_insecure
|
||||
attr_accessor :graceful_halt_timeout
|
||||
|
@ -30,6 +32,8 @@ module VagrantPlugins
|
|||
def initialize
|
||||
@boot_timeout = UNSET_VALUE
|
||||
@box_download_ca_cert = UNSET_VALUE
|
||||
@box_download_checksum = UNSET_VALUE
|
||||
@box_download_checksum_type = UNSET_VALUE
|
||||
@box_download_client_cert = UNSET_VALUE
|
||||
@box_download_insecure = UNSET_VALUE
|
||||
@box_url = UNSET_VALUE
|
||||
|
@ -256,6 +260,8 @@ module VagrantPlugins
|
|||
# Defaults
|
||||
@boot_timeout = 300 if @boot_timeout == UNSET_VALUE
|
||||
@box_download_ca_cert = nil if @box_download_ca_cert == UNSET_VALUE
|
||||
@box_download_checksum = nil if @box_download_checksum == UNSET_VALUE
|
||||
@box_download_checksum_type = nil if @box_download_checksum_type == UNSET_VALUE
|
||||
@box_download_client_cert = nil if @box_download_client_cert == UNSET_VALUE
|
||||
@box_download_insecure = false if @box_download_insecure == UNSET_VALUE
|
||||
@box_url = nil if @box_url == UNSET_VALUE
|
||||
|
@ -264,6 +270,10 @@ module VagrantPlugins
|
|||
@hostname = nil if @hostname == UNSET_VALUE
|
||||
@hostname = @hostname.to_s if @hostname
|
||||
|
||||
if @box_download_checksum_type
|
||||
@box_download_checksum_type = @box_download_checksum_type.to_sym
|
||||
end
|
||||
|
||||
# Make sure the box URL is an array if it is set
|
||||
if @box_url && !@box_url.is_a?(Array)
|
||||
@box_url = [@box_url]
|
||||
|
@ -385,6 +395,16 @@ module VagrantPlugins
|
|||
end
|
||||
end
|
||||
|
||||
if box_download_checksum_type
|
||||
if box_download_checksum == ""
|
||||
errors << I18n.t("vagrant.config.vm.box_download_checksum_blank")
|
||||
end
|
||||
else
|
||||
if box_download_checksum != ""
|
||||
errors << I18n.t("vagrant.config.vm.box_download_checksum_notblank")
|
||||
end
|
||||
end
|
||||
|
||||
has_nfs = false
|
||||
used_guest_paths = Set.new
|
||||
@__synced_folders.each do |id, options|
|
||||
|
|
|
@ -177,6 +177,18 @@ en:
|
|||
|
||||
If the box appears to be booting properly, you may want to increase
|
||||
the timeout ("config.vm.boot_timeout") value.
|
||||
box_checksum_invalid_type: |-
|
||||
The specified checksum type is not supported by Vagrant: %{type}.
|
||||
Vagrant supports the following checksum types:
|
||||
|
||||
md5, sha1, sha256
|
||||
box_checksum_mismatch: |-
|
||||
The checksum of the dowloaded box did not match the expected
|
||||
value. Please verify that you have the proper URL setup and that
|
||||
you're downloading the proper file.
|
||||
|
||||
Expected: %{expected}
|
||||
Received: %{actual}
|
||||
box_config_changing_box: |-
|
||||
While loading the Vagrantfile, the provider override specified
|
||||
a new box. This box, in turn, specified a different box. This isn't
|
||||
|
@ -722,6 +734,10 @@ en:
|
|||
base_mac_invalid: "Base MAC address for eth0/NAT must be set. Contact box maintainer for more information."
|
||||
box_download_ca_cert_not_found: |-
|
||||
"box_download_ca_cert" file not found: %{path}
|
||||
box_download_checksum_blank: |-
|
||||
Checksum type specified but "box_download_checksum" is blank
|
||||
box_download_checksum_notblank: |-
|
||||
Checksum specified but must also specify "box_download_checksum_type"
|
||||
box_missing: "A box must be specified."
|
||||
box_not_found: "The box '%{name}' could not be found."
|
||||
hostname_invalid_characters: |-
|
||||
|
@ -1121,6 +1137,8 @@ en:
|
|||
Extracting box...
|
||||
added: |-
|
||||
Successfully added box '%{name}' with provider '%{provider}'!
|
||||
checksumming: |-
|
||||
Calculating and comparing box checksum...
|
||||
destroy:
|
||||
destroying: "Deleting box '%{name}'..."
|
||||
download:
|
||||
|
|
|
@ -44,6 +44,15 @@ after the initial download.
|
|||
* `--cert CERTFILE` - A client certificate to use when downloading the box, if
|
||||
necessary.
|
||||
|
||||
* `--checksum VALUE` - A checksum for the box that is downloaded. If specified,
|
||||
Vagrant will compare this checksum to what is actually downloaded and will
|
||||
error if the checksums do not match. This is highly recommended since
|
||||
box files are so large. If this is specified, `--checksum-type` must
|
||||
also be specified.
|
||||
|
||||
* `--checksum-type TYPE` - The type of checksum that `--checksum` is if it
|
||||
is specified. Supported values are currently "md5", "sha1", and "sha256".
|
||||
|
||||
* `--clean` - If given, Vagrant will remove any old temporary files from
|
||||
prior downloads of the same URL. This is useful if you don't want Vagrant
|
||||
to resume a download from a previous point, perhaps because the contents
|
||||
|
|
|
@ -23,6 +23,23 @@ the installed boxes on the system.
|
|||
|
||||
<hr>
|
||||
|
||||
`config.vm.box_download_checksum` - The checksum of the box specified by
|
||||
`config.vm.box_url`. If not specified, no checksum comparison will be done.
|
||||
If specified, Vagrant will compare the checksum of the downloaded box to
|
||||
this value and error if they do not match. Checksum checking is only done
|
||||
when Vagrant must download the box.
|
||||
|
||||
If this is specified, then `config.vm.box_download_checksum_type` must
|
||||
also be specified.
|
||||
|
||||
<hr>
|
||||
|
||||
`config.vm.box_download_checksum_type` - The type of checksum specified
|
||||
by `config.vm.box_download_checksum` (if any). Supported values are
|
||||
currently "md5", "sha1", and "sha256".
|
||||
|
||||
<hr>
|
||||
|
||||
`config.vm.box_download_client_cert` - Path to a client certificate to
|
||||
use when downloading the box, if it is necessary. By default, no client
|
||||
certificate is used to download the box.
|
||||
|
|
Loading…
Reference in New Issue