diff options
Diffstat (limited to 'vendor/gems/bundler-checksum/lib/bundler_checksum')
5 files changed, 196 insertions, 0 deletions
diff --git a/vendor/gems/bundler-checksum/lib/bundler_checksum/command.rb b/vendor/gems/bundler-checksum/lib/bundler_checksum/command.rb new file mode 100644 index 00000000000..c6c71431538 --- /dev/null +++ b/vendor/gems/bundler-checksum/lib/bundler_checksum/command.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module BundlerChecksum + module Command + autoload :Init, File.expand_path("command/init", __dir__) + autoload :Verify, File.expand_path("command/verify", __dir__) + autoload :Helper, File.expand_path("command/helper", __dir__) + + def self.execute(args) + if args.empty? + $stderr.puts 'A command must be given [init,update,verify]' + end + + if args.first == 'init' + Init.execute + elsif args.first == 'update' + $stderr.puts 'Not implemented, please use init' + elsif args.first == 'verify' + verified = Verify.execute + + unless verified + exit 1 + end + end + end + end +end diff --git a/vendor/gems/bundler-checksum/lib/bundler_checksum/command/helper.rb b/vendor/gems/bundler-checksum/lib/bundler_checksum/command/helper.rb new file mode 100644 index 00000000000..515f5926106 --- /dev/null +++ b/vendor/gems/bundler-checksum/lib/bundler_checksum/command/helper.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'json' +require 'net/http' + +module BundlerChecksum::Command + module Helper + extend self + + def remote_checksums_for_gem(gem_name, gem_version) + response = Net::HTTP.get_response(URI( + "https://rubygems.org/api/v1/versions/#{gem_name}.json" + )) + + return [] unless response.code == '200' + + gem_candidates = JSON.parse(response.body, symbolize_names: true) + gem_candidates.select! { |g| g[:number] == gem_version.to_s } + + gem_candidates.map { + |g| {:name => gem_name, :version => gem_version, :platform => g[:platform], :checksum => g[:sha]} + } + + rescue JSON::ParserError + [] + end + end +end diff --git a/vendor/gems/bundler-checksum/lib/bundler_checksum/command/init.rb b/vendor/gems/bundler-checksum/lib/bundler_checksum/command/init.rb new file mode 100644 index 00000000000..1d8db7d78fa --- /dev/null +++ b/vendor/gems/bundler-checksum/lib/bundler_checksum/command/init.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true + +require 'openssl' + +module BundlerChecksum::Command + module Init + extend self + + def execute + $stderr.puts "Initializing checksum file #{checksum_file}" + + checksums = [] + + compact_index_cache = Bundler::Fetcher::CompactIndex + .new(nil, Bundler::Source::Rubygems::Remote.new(Bundler::URI("https://rubygems.org")), nil) + .send(:compact_index_client) + .instance_variable_get(:@cache) + + Bundler.definition.resolve.sort_by(&:name).each do |spec| + next unless spec.source.is_a?(Bundler::Source::Rubygems) + spec_identifier = "#{spec.name}==#{spec.version}" + + previous_checksum = previous_checksums.select do |checksum| + checksum[:name] == spec.name && checksum[:version] == spec.version.to_s + end + + if !previous_checksum.empty? + $stderr.puts "Using #{spec_identifier}" + checksums += previous_checksum + + next + end + + $stderr.puts "Adding #{spec_identifier}" + + compact_index_dependencies = compact_index_cache.dependencies(spec.name).select { |item| item.first == spec.version.to_s } + + if !compact_index_dependencies.empty? + compact_index_checksums = compact_index_dependencies.map do |version, platform, dependencies, requirements| + { + name: spec.name, + version: spec.version.to_s, + platform: Gem::Platform.new(platform).to_s, + checksum: requirements.detect { |requirement| requirement.first == 'checksum' }.flatten[1] + } + end + + checksums += compact_index_checksums.sort_by { |hash| hash.values } + else + remote_checksum = Helper.remote_checksums_for_gem(spec.name, spec.version) + + if remote_checksum.empty? + raise "#{spec.name} #{spec.version} not found on Rubygems!" + end + + checksums += remote_checksum.sort_by { |hash| hash.values } + end + end + + File.write(checksum_file, JSON.generate(checksums, array_nl: "\n") + "\n") + end + + private + + def previous_checksums + @previous_checksums ||= + if File.exist?(checksum_file) + ::BundlerChecksum.checksums_from_file + else + [] + end + end + + def checksum_file + ::BundlerChecksum.checksum_file + end + + def lockfile + lockfile_path = Bundler.default_lockfile + lockfile = Bundler::LockfileParser.new(Bundler.read_file(lockfile_path)) + end + end +end diff --git a/vendor/gems/bundler-checksum/lib/bundler_checksum/command/verify.rb b/vendor/gems/bundler-checksum/lib/bundler_checksum/command/verify.rb new file mode 100644 index 00000000000..e6a52ded42c --- /dev/null +++ b/vendor/gems/bundler-checksum/lib/bundler_checksum/command/verify.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +module BundlerChecksum::Command + module Verify + extend self + + def execute + $stderr.puts 'Verifying bundle checksums' + + verified = true + + local_checksums.each do |gem| + name = gem.fetch(:name) + version = gem.fetch(:version) + platform = gem.fetch(:platform) + checksum = gem.fetch(:checksum) + + $stderr.puts "Verifying #{name}==#{version} #{platform}" + unless validate_gem_checksum(name, version, platform, checksum) + verified = false + end + end + + verified + end + + private + + def local_checksums + ::BundlerChecksum.checksums_from_file + end + + def validate_gem_checksum(gem_name, gem_version, gem_platform, local_checksum) + remote_checksums = Helper.remote_checksums_for_gem(gem_name, gem_version) + if remote_checksums.empty? + $stderr.puts "#{gem_name} #{gem_version} not found on Rubygems, skipping" + return false + end + + remote_platform_checksum = remote_checksums.find { |g| g[:name] == gem_name && g[:platform] == gem_platform.to_s } + + if local_checksum == remote_platform_checksum[:checksum] + true + else + $stderr.puts "Gem #{gem_name} #{gem_version} #{gem_platform} failed checksum verification" + $stderr.puts "LOCAL: #{local_checksum}" + $stderr.puts "REMOTE: #{remote_platform_checksum[:checksum]}" + return false + end + end + end +end diff --git a/vendor/gems/bundler-checksum/lib/bundler_checksum/version.rb b/vendor/gems/bundler-checksum/lib/bundler_checksum/version.rb new file mode 100644 index 00000000000..367a9e49a47 --- /dev/null +++ b/vendor/gems/bundler-checksum/lib/bundler_checksum/version.rb @@ -0,0 +1,6 @@ +# frozen_string_literal: true + +module BundlerChecksum + # bundler-checksum version + VERSION = '0.1.0' +end |