Skip to content

Commit

Permalink
ensure that solr checksum verification does not obscure 404 responses…
Browse files Browse the repository at this point in the history
… or tcp/http errors
  • Loading branch information
Brian Hoffman committed Mar 22, 2022
1 parent 65ce43b commit dff330a
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 18 deletions.
2 changes: 1 addition & 1 deletion backend/app/main.rb
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def self.plugins_loaded_hook(&block)
Solr.verify_checksums!
Log.info('Solr config checksum verification ok.')
else
Log.warn('Solr config checksum verification disabled.')
Log.warn('Solr config checksum verification disabled: Solr may be offline or misconfigured')
end

ordered_plugin_backend_dirs = ASUtils.order_plugins(ASUtils.find_local_directories('backend'))
Expand Down
20 changes: 18 additions & 2 deletions backend/app/model/solr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
require 'advanced_search'

class Solr

class ChecksumMismatchError < StandardError; end
class NotFound < StandardError; end

module Checksums
def checksum_valid?
internal_checksum == external_checksum
Expand All @@ -20,7 +24,19 @@ def internal_checksum

def lookup_external_checksum
url = URI(File.join(@url, @path))
@external_checksum = Digest::SHA2.hexdigest(Net::HTTP.get_response(url).body)
response = Net::HTTP.get_response(url)
if response.code == '200'
@external_checksum = Digest::SHA2.hexdigest(response.body)
else
# if we made it this far, solr (or another server) is probably there
# but cannot find the documents we want, most likely because the core
# has not been set up correctly.
message = "Status #{response.code} when trying to verify #{@url}"
if response.body
message += "Server response:\n#{response.body}"
end
raise NotFound.new(message)
end
end

def lookup_internal_checksum
Expand Down Expand Up @@ -76,7 +92,7 @@ def self.verify_checksums!
def self.verify_checksum!(config)
return true if config.checksum_valid?

raise "Solr checksum verification failed (#{config.name}): expected [#{config.internal_checksum}] got [#{config.external_checksum}]"
raise ChecksumMismatchError.new "Solr checksum verification failed (#{config.name}): expected [#{config.internal_checksum}] got [#{config.external_checksum}]"
end

class Query
Expand Down
42 changes: 27 additions & 15 deletions backend/spec/model_solr_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -210,28 +210,40 @@ def response.code; '200'; end
end

describe 'Checksums' do
let(:schema) { Solr::Schema.new(AppConfig[:solr_url]) }
let(:solrconfig) { Solr::Solrconfig.new(AppConfig[:solr_url]) }
let(:response) { instance_double(Net::HTTPResponse) }

it 'will be valid when the internal and external checksums match' do
expect(schema.checksum_valid?).to be true
expect(solrconfig.checksum_valid?).to be true
def solrfile(file)
File.read(File.join(*[ ASUtils.find_base_directory, 'solr', file]))
end

it 'will be invalid when the external checksums do not match' do
allow(schema).to receive(:external_checksum) { 'nope' }
allow(solrconfig).to receive(:external_checksum) { "this_aint'it" }
it 'will be valid when the internal and external checksums match' do
allow(response).to receive(:code).and_return('200')
allow(response).to receive(:body).and_return(solrfile('schema.xml'), solrfile('solrconfig.xml'))
allow(Net::HTTP).to receive(:get_response).and_return(response)
expect { Solr.verify_checksums! }.not_to raise_error
end

expect(schema.checksum_valid?).to be false
expect(solrconfig.checksum_valid?).to be false
it 'will be invalid when the schema checksum does not match' do
allow(response).to receive(:code).and_return('200')
bad_schema = solrfile('schema.xml').sub('archivesspace', 'example')
allow(response).to receive(:body).and_return(bad_schema, solrfile('solrconfig.xml'))
allow(Net::HTTP).to receive(:get_response).and_return(response)
expect { Solr.verify_checksums! }.to raise_error(Solr::ChecksumMismatchError)
end

it 'will be invalid when the internal checksums do not match' do
allow(schema).to receive(:internal_checksum) { 'nope' }
allow(solrconfig).to receive(:internal_checksum) { "this_aint'it" }
it 'will be invalid when the config checksum does not match' do
allow(response).to receive(:code).and_return('200')
bad_config = solrfile('solrconfig.xml').sub('solr', 'foobar')
allow(response).to receive(:body).and_return(solrfile('schema.xml'), bad_config)
allow(Net::HTTP).to receive(:get_response).and_return(response)
expect { Solr.verify_checksums! }.to raise_error(Solr::ChecksumMismatchError)
end

expect(schema.checksum_valid?).to be false
expect(solrconfig.checksum_valid?).to be false
it 'will raise an error when the solr server returns a 404' do
allow(response).to receive(:code).and_return('404')
allow(response).to receive(:body).and_return("NOT FOUND")
allow(Net::HTTP).to receive(:get_response).and_return(response)
expect { Solr.verify_checksums! }.to raise_error(Solr::NotFound)
end
end

Expand Down

0 comments on commit dff330a

Please sign in to comment.