Skip to content

Commit bd796ea

Browse files
committed
[GEM] Adds validation for Elasticsearch
1 parent ba9cec3 commit bd796ea

File tree

8 files changed

+477
-13
lines changed

8 files changed

+477
-13
lines changed

elasticsearch/Rakefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18-
require "bundler/gem_tasks"
18+
require 'bundler/gem_tasks'
19+
20+
task(:default) { system 'rake --tasks' }
1921

2022
desc 'Run unit tests'
2123
task test: 'test:spec'

elasticsearch/elasticsearch.gemspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Gem::Specification.new do |s|
5656
s.add_development_dependency 'rspec'
5757
s.add_development_dependency 'ruby-prof' unless defined?(JRUBY_VERSION) || defined?(Rubinius)
5858
s.add_development_dependency 'simplecov'
59+
s.add_development_dependency 'webmock'
5960
s.add_development_dependency 'yard'
6061

6162
s.description = <<-DESC.gsub(/^ /, '')

elasticsearch/lib/elasticsearch.rb

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,79 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18-
require "elasticsearch/version"
19-
18+
require 'elasticsearch/version'
2019
require 'elasticsearch/transport'
2120
require 'elasticsearch/api'
2221

2322
module Elasticsearch
24-
module Transport
25-
class Client
26-
include Elasticsearch::API
23+
SECURITY_PRIVILEGES_VALIDATION_WARNING = 'The client is unable to verify that the server is Elasticsearch due to security privileges on the server side.'.freeze
24+
NOT_ELASTICSEARCH_WARNING = 'The client noticed that the server is not Elasticsearch and we do not support this unknown product.'.freeze
25+
YOU_KNOW_FOR_SEARCH = 'You know, for Search'.freeze
26+
27+
class Client
28+
include Elasticsearch::API
29+
30+
def initialize(arguments = {}, &block)
31+
@verified = false
32+
@transport = Elasticsearch::Transport::Client.new(arguments, &block)
33+
end
34+
35+
def method_missing(name, *args, &block)
36+
if name == :perform_request
37+
verify_elasticsearch unless @verified
38+
@transport.perform_request(*args, &block)
39+
else
40+
super
41+
end
42+
end
43+
44+
private
45+
46+
def verify_elasticsearch
47+
begin
48+
response = @transport.perform_request('GET', '/')
49+
rescue Elasticsearch::Transport::Transport::Errors::Unauthorized,
50+
Elasticsearch::Transport::Transport::Errors::Forbidden
51+
@verified = true
52+
warn(SECURITY_PRIVILEGES_VALIDATION_WARNING)
53+
return
54+
end
55+
56+
verify_with_version_or_header(response)
57+
end
58+
59+
def verify_with_version_or_header(response)
60+
version = response.body.dig('version', 'number')
61+
raise Elasticsearch::NotElasticsearchError if version.nil? || version < '6.0.0'
62+
63+
if version == '7.x-SNAPSHOT' || Gem::Version.new(version) >= Gem::Version.new('7.14-SNAPSHOT')
64+
raise Elasticsearch::NotElasticsearchError unless response.headers['x-elastic-product'] == 'Elasticsearch'
65+
66+
@verified = true
67+
elsif Gem::Version.new(version) > Gem::Version.new('6.0.0') &&
68+
Gem::Version.new(version) < Gem::Version.new('7.0.0')
69+
raise Elasticsearch::NotElasticsearchError unless
70+
response.body.dig('version', 'tagline') == YOU_KNOW_FOR_SEARCH
71+
72+
@verified = true
73+
elsif Gem::Version.new(version) >= Gem::Version.new('7.0.0') &&
74+
Gem::Version.new(version) < Gem::Version.new('7.14-SNAPSHOT')
75+
raise Elasticsearch::NotElasticsearchError unless
76+
response.body.dig('version', 'tagline') == YOU_KNOW_FOR_SEARCH &&
77+
response.body.dig('version', 'build_flavor') == 'default'
78+
79+
@verified = true
80+
end
81+
end
82+
end
83+
84+
class NotElasticsearchError < StandardError
85+
def initialize
86+
super(NOT_ELASTICSEARCH_WARNING)
2787
end
2888
end
2989
end
90+
3091
module Elastic
3192
# If the version is X.X.X.pre/alpha/beta, use X.X.Xp for the meta-header:
3293
def self.client_meta_version

elasticsearch/spec/integration/client_integration_spec.rb

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17-
ELASTICSEARCH_URL = ENV['TEST_ES_SERVER'] || "http://localhost:#{(ENV['PORT'] || 9200)}"
18-
raise URI::InvalidURIError unless ELASTICSEARCH_URL =~ /\A#{URI::DEFAULT_PARSER.make_regexp}\z/
19-
20-
require 'elasticsearch'
17+
require 'spec_helper'
2118
require 'logger'
22-
require 'rspec'
2319

2420
context 'Elasticsearch client' do
2521
let(:logger) { Logger.new($stderr) }
@@ -53,7 +49,7 @@
5349
end
5450

5551
context 'Reports the right meta header' do
56-
it 'Reports es service name and gem versio' do
52+
it 'Reports es service name and gem version' do
5753
headers = client.transport.connections.first.connection.headers
5854
expect(headers['x-elastic-client-meta']).to match /^es=#{Elasticsearch::VERSION}/
5955
end
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Licensed to Elasticsearch B.V. under one or more contributor
2+
# license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright
4+
# ownership. Elasticsearch B.V. licenses this file to you under
5+
# the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
require 'spec_helper'
18+
require 'logger'
19+
20+
describe 'Elasticsearch validation integration' do
21+
it 'Validates for Elasticsearch > 7.14' do
22+
client = Elasticsearch::Client.new(
23+
host: ELASTICSEARCH_URL,
24+
logger: Logger.new($stderr)
25+
)
26+
expect(client.instance_variable_get('@verified')).to be false
27+
client.count
28+
expect(client.instance_variable_get('@verified')).to be true
29+
end
30+
end

elasticsearch/spec/spec_helper.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717

1818
require 'elasticsearch'
1919
require 'rspec'
20-
require 'webmock/rspec'
20+
21+
ELASTICSEARCH_URL = ENV['TEST_ES_SERVER'] || "http://localhost:#{(ENV['PORT'] || 9200)}"
22+
raise URI::InvalidURIError unless ELASTICSEARCH_URL =~ /\A#{URI::DEFAULT_PARSER.make_regexp}\z/
2123

2224
RSpec.configure do |config|
2325
config.formatter = :documentation

0 commit comments

Comments
 (0)