diff --git a/lib/vagrant/action/builtin/box_add.rb b/lib/vagrant/action/builtin/box_add.rb index b951a805d..60ac6d597 100644 --- a/lib/vagrant/action/builtin/box_add.rb +++ b/lib/vagrant/action/builtin/box_add.rb @@ -527,22 +527,11 @@ module Vagrant end def validate_checksum(checksum_type, checksum, path) - checksum_klass = case checksum_type.to_sym - when :md5 - Digest::MD5 - when :sha1 - Digest::SHA1 - when :sha256 - Digest::SHA2 - else - raise Errors::BoxChecksumInvalidType, - type: checksum_type.to_s - end - - @logger.info("Validating checksum with #{checksum_klass}") + @logger.info("Validating checksum with #{checksum_type}") @logger.info("Expected checksum: #{checksum}") - actual = FileChecksum.new(path, checksum_klass).checksum + actual = FileChecksum.new(path, checksum_type).checksum + @logger.info("Actual checksum: #{actual}") if actual.casecmp(checksum) != 0 raise Errors::BoxChecksumMismatch, actual: actual, diff --git a/lib/vagrant/util/downloader.rb b/lib/vagrant/util/downloader.rb index dee2cbaca..71c06769c 100644 --- a/lib/vagrant/util/downloader.rb +++ b/lib/vagrant/util/downloader.rb @@ -1,12 +1,14 @@ require "uri" require "log4r" +require "digest" require "digest/md5" require "digest/sha1" require "vagrant/util/busy" require "vagrant/util/platform" require "vagrant/util/subprocess" require "vagrant/util/curl_helper" +require "vagrant/util/file_checksum" module Vagrant module Util @@ -20,12 +22,6 @@ module Vagrant # Vagrant/1.7.4 (+https://www.vagrantup.com; ruby2.1.0) USER_AGENT = "Vagrant/#{VERSION} (+https://www.vagrantup.com; #{RUBY_ENGINE}#{RUBY_VERSION}) #{ENV['VAGRANT_USER_AGENT_PROVISIONAL_STRING']}".freeze - # Supported file checksum - CHECKSUM_MAP = { - :md5 => Digest::MD5, - :sha1 => Digest::SHA1 - }.freeze - # Hosts that do not require notification on redirect SILENCED_HOSTS = [ "vagrantcloud.com".freeze, @@ -68,8 +64,11 @@ module Vagrant @location_trusted = options[:location_trusted] @checksums = { :md5 => options[:md5], - :sha1 => options[:sha1] - } + :sha1 => options[:sha1], + :sha256 => options[:sha256], + :sha384 => options[:sha384], + :sha512 => options[:sha512] + }.compact end # This executes the actual download, downloading the source file @@ -165,36 +164,23 @@ module Vagrant # @option checksums [String] :sha1 Compare SHA1 checksum # @return [Boolean] def validate_download!(source, path, checksums) - CHECKSUM_MAP.each do |type, klass| - if checksums[type] - result = checksum_file(klass, path) - @logger.debug("Validating checksum (#{type}) for #{source}. " \ - "expected: #{checksums[type]} actual: #{result}") - if checksums[type] != result - raise Errors::DownloaderChecksumError.new( - source: source, - path: path, - type: type, - expected_checksum: checksums[type], - actual_checksum: result - ) - end + checksums.each do |type, expected| + actual = FileChecksum.new(path, type).checksum + @logger.debug("Validating checksum (#{type}) for #{source}. " \ + "expected: #{expected} actual: #{actual}") + if actual.casecmp(expected) != 0 + raise Errors::DownloaderChecksumError.new( + source: source, + path: path, + type: type, + expected_checksum: expected, + actual_checksum: actual + ) end end true end - # Generate checksum on given file - # - # @param digest_class [Class] Digest class to use for generating checksum - # @param path [String, Pathname] Path to file - # @return [String] hexdigest result - def checksum_file(digest_class, path) - digester = digest_class.new - digester.file(path) - digester.hexdigest - end - def execute_curl(options, subprocess_options, &data_proc) options = options.dup options << subprocess_options diff --git a/lib/vagrant/util/file_checksum.rb b/lib/vagrant/util/file_checksum.rb index 0591603e7..e5e7cf715 100644 --- a/lib/vagrant/util/file_checksum.rb +++ b/lib/vagrant/util/file_checksum.rb @@ -10,13 +10,27 @@ end class FileChecksum BUFFER_SIZE = 1024 * 8 + # Supported file checksum + CHECKSUM_MAP = { + :md5 => Digest::MD5, + :sha1 => Digest::SHA1, + :sha256 => Digest::SHA256, + :sha384 => Digest::SHA384, + :sha512 => Digest::SHA512 + }.freeze + # Initializes an object to calculate the checksum of a file. The given # ``digest_klass`` should implement the ``DigestClass`` interface. Note # that the built-in Ruby digest classes duck type this properly: # Digest::MD5, Digest::SHA1, etc. def initialize(path, digest_klass) - @digest_klass = digest_klass - @path = path + if digest_klass.is_a?(Class) + @digest_klass = digest_klass + else + @digest_klass = load_digest(digest_klass) + end + + @path = path end # This calculates the checksum of the file and returns it as a @@ -40,6 +54,17 @@ class FileChecksum end end - return digest.hexdigest + digest.hexdigest + end + + private + + def load_digest(type) + digest = CHECKSUM_MAP[type.to_s.to_sym] + if digest.nil? + raise Errors::BoxChecksumInvalidType, + type: type.to_s + end + digest end end diff --git a/plugins/commands/cloud/provider/create.rb b/plugins/commands/cloud/provider/create.rb index 2adb6a42a..5659d3836 100644 --- a/plugins/commands/cloud/provider/create.rb +++ b/plugins/commands/cloud/provider/create.rb @@ -19,6 +19,12 @@ module VagrantPlugins o.on("-u", "--username USERNAME_OR_EMAIL", String, "Vagrant Cloud username or email address") do |u| options[:username] = u end + o.on("-c", "--checksum CHECKSUM_VALUE", String, "Checksum of the box for this provider. --checksum-type option is required.") do |c| + options[:checksum] = c + end + o.on("-C", "--checksum-type TYPE", String, "Type of checksum used (md5, sha1, sha256, sha384, sha512). --checksum option is required.") do |c| + options[:checksum_type] = c + end end # Parse the options @@ -52,16 +58,17 @@ module VagrantPlugins account = VagrantPlugins::CloudCommand::Util.account(org, access_token, server_url) box = VagrantCloud::Box.new(account, box_name, nil, nil, nil, access_token) cloud_version = VagrantCloud::Version.new(box, version, nil, nil, access_token) - provider = VagrantCloud::Provider.new(cloud_version, provider_name, nil, url, org, box_name, access_token) + provider = VagrantCloud::Provider.new(cloud_version, provider_name, nil, url, org, box_name, + access_token, nil, options[:checksum], options[:checksum_type]) begin success = provider.create_provider - @env.ui.success(I18n.t("cloud_command.provider.create_success", provider:provider_name, org: org, box_name: box_name, version: version)) - success = success.delete_if{|_, v|v.nil?} + @env.ui.success(I18n.t("cloud_command.provider.create_success", provider: provider_name, org: org, box_name: box_name, version: version)) + success = success.compact VagrantPlugins::CloudCommand::Util.format_box_results(success, @env) return 0 rescue VagrantCloud::ClientError => e - @env.ui.error(I18n.t("cloud_command.errors.provider.create_fail", provider:provider_name, org: org, box_name: box_name, version: version)) + @env.ui.error(I18n.t("cloud_command.errors.provider.create_fail", provider: provider_name, org: org, box_name: box_name, version: version)) @env.ui.error(e) return 1 end diff --git a/plugins/commands/cloud/provider/update.rb b/plugins/commands/cloud/provider/update.rb index 897b13f2a..5febdd867 100644 --- a/plugins/commands/cloud/provider/update.rb +++ b/plugins/commands/cloud/provider/update.rb @@ -19,6 +19,12 @@ module VagrantPlugins o.on("-u", "--username USERNAME_OR_EMAIL", String, "Vagrant Cloud username or email address") do |u| options[:username] = u end + o.on("-c", "--checksum CHECKSUM_VALUE", String, "Checksum of the box for this provider. --checksum-type option is required.") do |c| + options[:checksum] = c + end + o.on("-C", "--checksum-type TYPE", String, "Type of checksum used (md5, sha1, sha256, sha384, sha512). --checksum option is required.") do |c| + options[:checksum_type] = c + end end # Parse the options @@ -52,7 +58,8 @@ module VagrantPlugins account = VagrantPlugins::CloudCommand::Util.account(org, access_token, server_url) box = VagrantCloud::Box.new(account, box_name, nil, nil, nil, access_token) cloud_version = VagrantCloud::Version.new(box, version, nil, nil, access_token) - provider = VagrantCloud::Provider.new(cloud_version, provider_name, nil, url, org, box_name, access_token) + provider = VagrantCloud::Provider.new(cloud_version, provider_name, nil, url, org, box_name, + access_token, nil, options[:checksum], options[:checksum_type]) begin success = provider.update diff --git a/plugins/commands/cloud/publish.rb b/plugins/commands/cloud/publish.rb index 2583be8b5..632786e88 100644 --- a/plugins/commands/cloud/publish.rb +++ b/plugins/commands/cloud/publish.rb @@ -43,6 +43,12 @@ module VagrantPlugins o.on("-u", "--username USERNAME_OR_EMAIL", String, "Vagrant Cloud username or email address") do |u| options[:username] = u end + o.on("-c", "--checksum CHECKSUM_VALUE", String, "Checksum of the box for this provider. --checksum-type option is required.") do |c| + options[:checksum] = c + end + o.on("-C", "--checksum-type TYPE", String, "Type of checksum used (md5, sha1, sha256, sha384, sha512). --checksum option is required.") do |c| + options[:checksum_type] = c + end end # Parse the options @@ -97,7 +103,8 @@ module VagrantPlugins account = VagrantPlugins::CloudCommand::Util.account(org, access_token, server_url) box = VagrantCloud::Box.new(account, box_name, nil, options[:short_description], options[:description], access_token) cloud_version = VagrantCloud::Version.new(box, version, nil, options[:version_description], access_token) - provider = VagrantCloud::Provider.new(cloud_version, provider_name, nil, options[:url], org, box_name, access_token) + provider = VagrantCloud::Provider.new(cloud_version, provider_name, nil, options[:url], org, box_name, + access_token, nil, options[:checksum], options[:checksum_type]) ui = Vagrant::UI::Prefixed.new(@env.ui, "cloud") diff --git a/plugins/provisioners/shell/config.rb b/plugins/provisioners/shell/config.rb index 18a9f1ebd..74a74cf13 100644 --- a/plugins/provisioners/shell/config.rb +++ b/plugins/provisioners/shell/config.rb @@ -7,6 +7,9 @@ module VagrantPlugins attr_accessor :path attr_accessor :md5 attr_accessor :sha1 + attr_accessor :sha256 + attr_accessor :sha384 + attr_accessor :sha512 attr_accessor :env attr_accessor :upload_path attr_accessor :args @@ -26,6 +29,9 @@ module VagrantPlugins @path = UNSET_VALUE @md5 = UNSET_VALUE @sha1 = UNSET_VALUE + @sha256 = UNSET_VALUE + @sha384 = UNSET_VALUE + @sha512 = UNSET_VALUE @env = UNSET_VALUE @upload_path = UNSET_VALUE @privileged = UNSET_VALUE @@ -45,6 +51,9 @@ module VagrantPlugins @path = nil if @path == UNSET_VALUE @md5 = nil if @md5 == UNSET_VALUE @sha1 = nil if @sha1 == UNSET_VALUE + @sha256 = nil if @sha256 == UNSET_VALUE + @sha384 = nil if @sha384 == UNSET_VALUE + @sha512 = nil if @sha512 == UNSET_VALUE @env = {} if @env == UNSET_VALUE @upload_path = "/tmp/vagrant-shell" if @upload_path == UNSET_VALUE @privileged = true if @privileged == UNSET_VALUE diff --git a/plugins/provisioners/shell/provisioner.rb b/plugins/provisioners/shell/provisioner.rb index 4b7cd0507..8175d82b7 100644 --- a/plugins/provisioners/shell/provisioner.rb +++ b/plugins/provisioners/shell/provisioner.rb @@ -253,7 +253,10 @@ module VagrantPlugins config.path, download_path, md5: config.md5, - sha1: config.sha1 + sha1: config.sha1, + sha256: config.sha256, + sha384: config.sha384, + sha512: config.sha512 ).download! ext = File.extname(config.path) script = download_path.read diff --git a/test/unit/plugins/commands/cloud/provider/create_test.rb b/test/unit/plugins/commands/cloud/provider/create_test.rb index 770b88ee6..841f2cc1d 100644 --- a/test/unit/plugins/commands/cloud/provider/create_test.rb +++ b/test/unit/plugins/commands/cloud/provider/create_test.rb @@ -48,7 +48,7 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Create do it "creates a provider" do allow(VagrantCloud::Provider).to receive(:new). - with(version, "virtualbox", nil, nil, "vagrant", "box-name", client.token). + with(version, "virtualbox", nil, nil, "vagrant", "box-name", client.token, nil, nil, nil). and_return(provider) expect(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results) @@ -59,7 +59,7 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Create do it "displays an error if encoutering a problem with the request" do allow(VagrantCloud::Provider).to receive(:new). - with(version, "virtualbox", nil, nil, "vagrant", "box-name", client.token). + with(version, "virtualbox", nil, nil, "vagrant", "box-name", client.token, nil, nil, nil). and_return(provider) allow(provider).to receive(:create_provider). @@ -73,7 +73,7 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Create do it "creates a provider" do allow(VagrantCloud::Provider).to receive(:new). - with(version, "virtualbox", nil, "https://box.com/box", "vagrant", "box-name", client.token). + with(version, "virtualbox", nil, "https://box.com/box", "vagrant", "box-name", client.token, nil, nil, nil). and_return(provider) expect(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results) diff --git a/test/unit/plugins/commands/cloud/provider/update_test.rb b/test/unit/plugins/commands/cloud/provider/update_test.rb index 0a03d61c3..8d2727919 100644 --- a/test/unit/plugins/commands/cloud/provider/update_test.rb +++ b/test/unit/plugins/commands/cloud/provider/update_test.rb @@ -48,7 +48,7 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Update do it "updates a provider" do allow(VagrantCloud::Provider).to receive(:new). - with(version, "virtualbox", nil, nil, "vagrant", "box-name", client.token). + with(version, "virtualbox", nil, nil, "vagrant", "box-name", client.token, nil, nil, nil). and_return(provider) expect(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results) @@ -59,7 +59,7 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Update do it "displays an error if encoutering a problem with the request" do allow(VagrantCloud::Provider).to receive(:new). - with(version, "virtualbox", nil, nil, "vagrant", "box-name", client.token). + with(version, "virtualbox", nil, nil, "vagrant", "box-name", client.token, nil, nil, nil). and_return(provider) allow(provider).to receive(:update). @@ -73,7 +73,7 @@ describe VagrantPlugins::CloudCommand::ProviderCommand::Command::Update do it "creates a provider" do allow(VagrantCloud::Provider).to receive(:new). - with(version, "virtualbox", nil, "https://box.com/box", "vagrant", "box-name", client.token). + with(version, "virtualbox", nil, "https://box.com/box", "vagrant", "box-name", client.token, nil, nil, nil). and_return(provider) expect(VagrantPlugins::CloudCommand::Util).to receive(:format_box_results) diff --git a/test/unit/plugins/provisioners/shell/provisioner_test.rb b/test/unit/plugins/provisioners/shell/provisioner_test.rb index 0ae5e8a68..b117d76be 100644 --- a/test/unit/plugins/provisioners/shell/provisioner_test.rb +++ b/test/unit/plugins/provisioners/shell/provisioner_test.rb @@ -175,8 +175,16 @@ describe "Vagrant::Shell::Provisioner" do end context "with remote script" do + let(:filechecksum) { double("filechecksum", checksum: checksum_value) } + let(:checksum_value) { double("checksum_value") } + + before do + allow(FileChecksum).to receive(:new).and_return(filechecksum) + allow_any_instance_of(Vagrant::Util::Downloader).to receive(:execute_curl).and_return(true) + end context "that does not have matching sha1 checksum" do + let(:checksum_value) { "INVALID_VALUE" } let(:config) { double( :config, @@ -188,18 +196,97 @@ describe "Vagrant::Shell::Provisioner" do :binary => false, :md5 => nil, :sha1 => 'EXPECTED_VALUE', + :sha256 => nil, + :sha384 => nil, + :sha512 => nil, :reset => false, :reboot => false ) } - let(:digest){ double("digest") } - before do - allow_any_instance_of(Vagrant::Util::Downloader).to receive(:execute_curl).and_return(true) - allow(digest).to receive(:file).and_return(digest) - expect(Digest::SHA1).to receive(:new).and_return(digest) - expect(digest).to receive(:hexdigest).and_return('INVALID_VALUE') + it "should raise an exception" do + vsp = VagrantPlugins::Shell::Provisioner.new(machine, config) + + expect{ vsp.provision }.to raise_error(Vagrant::Errors::DownloaderChecksumError) end + end + + context "that does not have matching sha256 checksum" do + let(:checksum_value) { "INVALID_VALUE" } + let(:config) { + double( + :config, + :args => "doesn't matter", + :env => {}, + :upload_path => "arbitrary", + :remote? => true, + :path => "http://example.com/script.sh", + :binary => false, + :md5 => nil, + :sha1 => nil, + :sha256 => 'EXPECTED_VALUE', + :sha384 => nil, + :sha512 => nil, + :reset => false, + :reboot => false + ) + } + + it "should raise an exception" do + vsp = VagrantPlugins::Shell::Provisioner.new(machine, config) + + expect{ vsp.provision }.to raise_error(Vagrant::Errors::DownloaderChecksumError) + end + end + + context "that does not have matching sha384 checksum" do + let(:checksum_value) { "INVALID_VALUE" } + let(:config) { + double( + :config, + :args => "doesn't matter", + :env => {}, + :upload_path => "arbitrary", + :remote? => true, + :path => "http://example.com/script.sh", + :binary => false, + :md5 => nil, + :sha1 => nil, + :sha256 => nil, + :sha384 => 'EXPECTED_VALUE', + :sha512 => nil, + :reset => false, + :reboot => false + ) + } + + it "should raise an exception" do + vsp = VagrantPlugins::Shell::Provisioner.new(machine, config) + + expect{ vsp.provision }.to raise_error(Vagrant::Errors::DownloaderChecksumError) + end + end + + context "that does not have matching sha512 checksum" do + let(:checksum_value) { "INVALID_VALUE" } + let(:config) { + double( + :config, + :args => "doesn't matter", + :env => {}, + :upload_path => "arbitrary", + :remote? => true, + :path => "http://example.com/script.sh", + :binary => false, + :md5 => nil, + :sha1 => nil, + :sha256 => nil, + :sha384 => nil, + :sha512 => 'EXPECTED_VALUE', + :reset => false, + :reboot => false + ) + } it "should raise an exception" do vsp = VagrantPlugins::Shell::Provisioner.new(machine, config) @@ -209,6 +296,7 @@ describe "Vagrant::Shell::Provisioner" do end context "that does not have matching md5 checksum" do + let(:checksum_value) { "INVALID_VALUE" } let(:config) { double( :config, @@ -220,19 +308,14 @@ describe "Vagrant::Shell::Provisioner" do :binary => false, :md5 => 'EXPECTED_VALUE', :sha1 => nil, + :sha256 => nil, + :sha384 => nil, + :sha512 => nil, :reset => false, :reboot => false ) } - let(:digest){ double("digest") } - before do - allow_any_instance_of(Vagrant::Util::Downloader).to receive(:execute_curl).and_return(true) - allow(digest).to receive(:file).and_return(digest) - expect(Digest::MD5).to receive(:new).and_return(digest) - expect(digest).to receive(:hexdigest).and_return('INVALID_VALUE') - end - it "should raise an exception" do vsp = VagrantPlugins::Shell::Provisioner.new(machine, config) diff --git a/test/unit/vagrant/util/downloader_test.rb b/test/unit/vagrant/util/downloader_test.rb index 67a065cf9..25e9014d1 100644 --- a/test/unit/vagrant/util/downloader_test.rb +++ b/test/unit/vagrant/util/downloader_test.rb @@ -175,23 +175,19 @@ describe Vagrant::Util::Downloader do context "with checksum" do let(:checksum_expected_value){ 'MD5_CHECKSUM_VALUE' } let(:checksum_invalid_value){ 'INVALID_VALUE' } - let(:digest){ double("digest") } + let(:filechecksum) { double("filechecksum", checksum: checksum_value) } + let(:checksum_value) { double("checksum_value") } - before do - allow(digest).to receive(:file).and_return(digest) - end + before { allow(FileChecksum).to receive(:new).with(any_args).and_return(filechecksum) } - [Digest::MD5, Digest::SHA1].each do |klass| + [Digest::MD5, Digest::SHA1, Digest::SHA256, Digest::SHA384, Digest::SHA512].each do |klass| short_name = klass.to_s.split("::").last.downcase context "using #{short_name} digest" do subject { described_class.new(source, destination, short_name.to_sym => checksum_expected_value) } context "that matches expected value" do - before do - expect(klass).to receive(:new).and_return(digest) - expect(digest).to receive(:hexdigest).and_return(checksum_expected_value) - end + let(:checksum_value) { checksum_expected_value } it "should not raise an exception" do expect(subject.download!).to be(true) @@ -199,10 +195,7 @@ describe Vagrant::Util::Downloader do end context "that does not match expected value" do - before do - expect(klass).to receive(:new).and_return(digest) - expect(digest).to receive(:hexdigest).and_return(checksum_invalid_value) - end + let(:checksum_value) { checksum_invalid_value } it "should raise an exception" do expect{ subject.download! }.to raise_error(Vagrant::Errors::DownloaderChecksumError) @@ -213,13 +206,9 @@ describe Vagrant::Util::Downloader do context "using both md5 and sha1 digests" do context "that both match expected values" do - subject { described_class.new(source, destination, md5: checksum_expected_value, sha1: checksum_expected_value) } + let(:checksum_value) { checksum_expected_value } - before do - expect(Digest::MD5).to receive(:new).and_return(digest) - expect(Digest::SHA1).to receive(:new).and_return(digest) - expect(digest).to receive(:hexdigest).and_return(checksum_expected_value).exactly(2).times - end + subject { described_class.new(source, destination, md5: checksum_expected_value, sha1: checksum_expected_value) } it "should not raise an exception" do expect(subject.download!).to be(true) @@ -227,12 +216,14 @@ describe Vagrant::Util::Downloader do end context "that only sha1 matches expected value" do - subject { described_class.new(source, destination, md5: checksum_invalid_value, sha1: checksum_expected_value) } + subject { described_class.new(source, destination, md5: checksum_expected_value, sha1: checksum_expected_value) } + + let(:valid_checksum) { double("valid_checksum", checksum: checksum_expected_value) } + let(:invalid_checksum) { double("invalid_checksum", checksum: checksum_invalid_value) } before do - allow(Digest::MD5).to receive(:new).and_return(digest) - allow(Digest::SHA1).to receive(:new).and_return(digest) - expect(digest).to receive(:hexdigest).and_return(checksum_expected_value).at_least(:once) + allow(FileChecksum).to receive(:new).with(anything, :sha1).and_return(valid_checksum) + allow(FileChecksum).to receive(:new).with(anything, :md5).and_return(invalid_checksum) end it "should raise an exception" do @@ -241,12 +232,14 @@ describe Vagrant::Util::Downloader do end context "that only md5 matches expected value" do - subject { described_class.new(source, destination, md5: checksum_expected_value, sha1: checksum_invalid_value) } + subject { described_class.new(source, destination, md5: checksum_expected_value, sha1: checksum_expected_value) } + + let(:valid_checksum) { double("valid_checksum", checksum: checksum_expected_value) } + let(:invalid_checksum) { double("invalid_checksum", checksum: checksum_invalid_value) } before do - allow(Digest::MD5).to receive(:new).and_return(digest) - allow(Digest::SHA1).to receive(:new).and_return(digest) - expect(digest).to receive(:hexdigest).and_return(checksum_expected_value).at_least(:once) + allow(FileChecksum).to receive(:new).with(anything, :md5).and_return(valid_checksum) + allow(FileChecksum).to receive(:new).with(anything, :sha1).and_return(invalid_checksum) end it "should raise an exception" do @@ -255,14 +248,9 @@ describe Vagrant::Util::Downloader do end context "that none match expected value" do + let(:checksum_value) { checksum_expected_value } subject { described_class.new(source, destination, md5: checksum_invalid_value, sha1: checksum_invalid_value) } - before do - allow(Digest::MD5).to receive(:new).and_return(digest) - allow(Digest::SHA1).to receive(:new).and_return(digest) - expect(digest).to receive(:hexdigest).and_return(checksum_expected_value).at_least(:once) - end - it "should raise an exception" do expect{ subject.download! }.to raise_error(Vagrant::Errors::DownloaderChecksumError) end diff --git a/test/unit/vagrant/util/file_checksum_test.rb b/test/unit/vagrant/util/file_checksum_test.rb index 6812d02a9..c467238d4 100644 --- a/test/unit/vagrant/util/file_checksum_test.rb +++ b/test/unit/vagrant/util/file_checksum_test.rb @@ -20,4 +20,16 @@ describe FileChecksum do instance = described_class.new(file, Digest::SHA1) expect(instance.checksum).to eq("264b207c7913e461c43d0f63d2512f4017af4755") end + + it "should support initialize with class or string" do + file = environment.workdir.join("file") + file.open("w+") { |f| f.write("HELLO!") } + + %w(md5 sha1 sha256 sha384 sha512).each do |type| + klass = Digest.const_get(type.upcase) + t_i = described_class.new(file, type) + k_i = described_class.new(file, klass) + expect(t_i.checksum).to eq(k_i.checksum) + end + end end diff --git a/vagrant.gemspec b/vagrant.gemspec index 5427ba567..2ca4a6972 100644 --- a/vagrant.gemspec +++ b/vagrant.gemspec @@ -34,7 +34,7 @@ Gem::Specification.new do |s| s.add_dependency "winrm", "~> 2.1" s.add_dependency "winrm-fs", "~> 1.0" s.add_dependency "winrm-elevated", "~> 1.1" - s.add_dependency "vagrant_cloud", "~> 2.0.2" + s.add_dependency "vagrant_cloud", "~> 2.0.3" # NOTE: The ruby_dep gem is an implicit dependency from the listen gem. Later versions # of the ruby_dep gem impose an aggressive constraint on the required ruby version (>= 2.2.5). diff --git a/website/source/docs/cli/box.html.md b/website/source/docs/cli/box.html.md index aa8e74110..cfc95725b 100644 --- a/website/source/docs/cli/box.html.md +++ b/website/source/docs/cli/box.html.md @@ -91,7 +91,8 @@ you are not using a catalog). included within the catalog entry. * `--checksum-type TYPE` - The type of checksum that `--checksum` is if it - is specified. Supported values are currently "md5", "sha1", and "sha256". + is specified. Supported values are currently "md5", "sha1", "sha256", + "sha384", and "sha512". * `--name VALUE` - Logical name for the box. This is the value that you would put into `config.vm.box` in your Vagrantfile. When adding a box from diff --git a/website/source/docs/provisioning/shell.html.md b/website/source/docs/provisioning/shell.html.md index 1d955ad6f..218cbc3b1 100644 --- a/website/source/docs/provisioning/shell.html.md +++ b/website/source/docs/provisioning/shell.html.md @@ -83,6 +83,12 @@ The remainder of the available options are optional: * `sha1` (string) - SHA1 checksum used to validate remotely downloaded shell files. +* `sha256` (string) - SHA256 checksum used to validate remotely downloaded shell files. + +* `sha384` (string) - SHA384 checksum used to validate remotely downloaded shell files. + +* `sha512` (string) - SHA512 checksum used to validate remotely downloaded shell files. + * `sensitive` (boolean) - Marks the Hash values used in the `env` option as sensitive and hides them from output. By default this is "false". diff --git a/website/source/docs/vagrantfile/machine_settings.html.md b/website/source/docs/vagrantfile/machine_settings.html.md index 44402dc65..f41e93a0b 100644 --- a/website/source/docs/vagrantfile/machine_settings.html.md +++ b/website/source/docs/vagrantfile/machine_settings.html.md @@ -46,7 +46,7 @@ when Vagrant must download the box. If this is specified, then * `config.vm.box_download_checksum_type` (string) - The type of checksum specified by `config.vm.box_download_checksum` (if any). Supported values are -currently "md5", "sha1", and "sha256". +currently "md5", "sha1", "sha256", "sha384", and "sha512". * `config.vm.box_download_client_cert` (string) - Path to a client certificate to use when downloading the box, if it is necessary. By default, no client