logstash/qa/integration/specs/webserver_spec.rb

144 lines
5.6 KiB
Ruby

# Licensed to Elasticsearch B.V. under one or more contributor
# license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright
# ownership. Elasticsearch B.V. licenses this file to you under
# the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
require 'openssl'
require 'logstash/util'
require 'logstash/webserver'
require "stud/try"
require "manticore"
describe 'api webserver' do
let!(:logger) { double("Logger").as_null_object }
let!(:agent) { double("Agent").as_null_object }
subject(:webserver) { LogStash::WebServer.new(logger, agent, webserver_options) }
let(:webserver_options) { Hash.new }
# provide a shared context to take care of ensuring that the webserver
# is running during the spec runs of examples in the including context
shared_context 'running webserver' do
let(:webserver) { defined?(super()) ? super() : fail("included context requires `webserver` to be present") }
# since we are running the webserver on another
# thread, ensure that a crash doesn't go unnoticed.
around(:each) do |example|
abort = Thread.abort_on_exception
example.call
Thread.abort_on_exception = abort
end
# If webmock is active, allow real network connections
before(:each) { WebMock.allow_net_connect! if defined?(WebMock) }
# ensure our API webserver is running with the provided config
# before running our specs that validate responses
let!(:webserver_thread) { Thread.new(webserver, &:run) }
before(:each) do
Stud.try(10.times) { fail('API WebServer not running yet...') unless webserver.port }
end
after(:each) do
webserver.stop
webserver_thread.join
end
end
context "when configured with api.ssl.supported_protocols" do
let(:ca_file) { File.join(certs_path, "root.crt") }
let(:certs_path) { File.expand_path("../../fixtures/webserver_certs/generated", __FILE__) }
let(:keystore_path) { File.join(certs_path, "server_from_root.p12") }
let(:keystore_password) { "12345678" }
let(:supported_protocols) { %w[TLSv1.3] }
let(:ssl_params) { {:supported_protocols => supported_protocols, :keystore_path => keystore_path, :keystore_password => LogStash::Util::Password.new(keystore_password)} }
let(:webserver_options) { super().merge(:ssl_params => ssl_params) }
let(:client_protocols) { nil }
let(:client) { Manticore::Client.new(ssl: { ca_file: ca_file, protocols: client_protocols }) }
let(:response) { client.get("https://127.0.0.1:#{webserver.port}") }
include_context 'running webserver'
context 'an HTTPS request using TLSv1.3' do
let(:client_protocols) { %w[TLSv1.3] }
it 'succeeds' do
expect(response.code).to eq(200)
end
end
context 'an HTTPS request using TLSv1.2' do
let(:client_protocols) { %w[TLSv1.2] }
it 'fails' do
expect { response.code }.to raise_error(Manticore::ClientProtocolException, a_string_including("handshake"))
end
end
end
%w(
server_from_root.p12
server_from_intermediate.p12
server_from_root.jks
server_from_intermediate.jks
).each do |keystore_name|
context "when configured with keystore #{keystore_name}" do
let(:ca_file) { File.join(certs_path, "root.crt") }
let(:certs_path) { File.expand_path("../../fixtures/webserver_certs/generated", __FILE__) }
let(:keystore_path) { File.join(certs_path, "#{keystore_name}") }
let(:keystore_password) { "12345678" }
let(:ssl_params) { {:keystore_path => keystore_path, :keystore_password => LogStash::Util::Password.new(keystore_password)} }
let(:webserver_options) { super().merge(:ssl_params => ssl_params) }
context 'and invalid credentials' do
let(:keystore_password) { "wrong" }
it 'raises a helpful error' do
expect { webserver }.to raise_error(ArgumentError, a_string_including("keystore password was incorrect"))
end
end
context "when started" do
include_context 'running webserver'
context 'an HTTPS request' do
it 'succeeds' do
client = Manticore::Client.new(ssl: { ca_file: ca_file })
response = client.get("https://127.0.0.1:#{webserver.port}")
expect(response.code).to eq(200)
end
# this is mostly a sanity check for our testing methodology
# If this fails, we cannot trust success from the other specs
context 'without providing CA' do
it 'fails' do
client = Manticore::Client.new(ssl: { })
expect do
client.get("https://127.0.0.1:#{webserver.port}").code
end.to raise_error(Manticore::ClientProtocolException, a_string_including("unable to find valid certification path to requested target"))
end
end
end
context 'an HTTP request' do
it 'fails' do
client = Manticore::Client.new
expect do
client.get("http://127.0.0.1:#{webserver.port}").code
end.to raise_error(Manticore::ClientProtocolException, a_string_including("failed to respond"))
end
end
end
end
end
end