Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standardised SSL settings #42

Merged
merged 5 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 2 additions & 18 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,3 @@
---
sudo: false
language: ruby
cache: bundler

script: bundle exec rspec spec
jdk: openjdk8
matrix:
include:
- rvm: jruby-9.2.20.1
env: LOGSTASH_BRANCH=8.0
- rvm: jruby-9.2.20.1
env: LOGSTASH_BRANCH=7.16
- rvm: jruby-9.1.13.0
env: LOGSTASH_BRANCH=6.7
- rvm: jruby-9.2.7.0
env: LOGSTASH_BRANCH=6.8
fast_finish: true
before_install: gem install bundler -v '< 2'
import:
- logstash-plugins/.ci:travis/travis.yml@1.x
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
## 7.3.0
- Standardized SSL settings: [#42](https://github.com/logstash-plugins/logstash-mixin-http_client/pull/42)
- Deprecated `cacert` in favor of `ssl_certificate_authorities`
- Deprecated`client_cert` in favor of `ssl_certificate`
edmocosta marked this conversation as resolved.
Show resolved Hide resolved
- Deprecated `client_key` in favor of `ssl_key`
- Deprecated `keystore` in favor of `ssl_keystore_path`
- Deprecated `keystore_password` in favor of `ssl_keystore_password`
- Deprecated `keystore_type` in favor of `ssl_keystore_type`
- Deprecated `truststore` in favor of `ssl_truststore_path`
- Deprecated `truststore_password` in favor of `ssl_truststore_password`
- Deprecated `truststore_type` in favor of `ssl_truststore_type`
edmocosta marked this conversation as resolved.
Show resolved Hide resolved
- Added a module configuration to disable the deprecated SSL configs `:with_deprecated`
edmocosta marked this conversation as resolved.
Show resolved Hide resolved
- Added the `ssl_cipher_suites` option

## 7.2.0
- Feat: add `ssl_supported_protocols` option [#40](https://github.com/logstash-plugins/logstash-mixin-http_client/pull/40)

Expand Down
8 changes: 8 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,11 @@ source 'https://rubygems.org'

# Specify your gem's dependencies in logstash-mass_effect.gemspec
gemspec

logstash_path = ENV["LOGSTASH_PATH"] || "../../logstash"
use_logstash_source = ENV["LOGSTASH_SOURCE"] && ENV["LOGSTASH_SOURCE"].to_s == "1"

if Dir.exist?(logstash_path) && use_logstash_source
gem 'logstash-core', :path => "#{logstash_path}/logstash-core"
gem 'logstash-core-plugin-api', :path => "#{logstash_path}/logstash-core-plugin-api"
end
337 changes: 182 additions & 155 deletions lib/logstash/plugin_mixins/http_client.rb

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
module LogStash::PluginMixins::HttpClient
module DeprecatedSslConfigSupport
def self.included(base)
fail ArgumentError unless base <= LogStash::PluginMixins::HttpClient::Implementation

require 'logstash/plugin_mixins/normalize_config_support'
base.include(LogStash::PluginMixins::NormalizeConfigSupport)

# If you need to use a custom X.509 CA (.pem certs) specify the path to that here
base.config :cacert, :validate => :path, :deprecated => 'Use `ssl_certificate_authorities` instead'
# If you'd like to use a client certificate (note, most people don't want this) set the path to the x509 cert here
base.config :client_cert, :validate => :path, :deprecated => 'Use `ssl_certificate` instead'
# If you're using a client certificate specify the path to the encryption key here
base.config :client_key, :validate => :path, :deprecated => 'Use `ssl_key` instead'
# If you need to use a custom keystore (`.jks`) specify that here. This does not work with .pem keys!
base.config :keystore, :validate => :path, :deprecated => 'Use `ssl_keystore_path` instead'
# Specify the keystore password here.
# Note, most .jks files created with keytool require a password!
base.config :keystore_password, :validate => :password, :deprecated => 'Use `ssl_keystore_password` instead'
# Specify the keystore type here. One of `JKS` or `PKCS12`. Default is `JKS`
base.config :keystore_type, :validate => :string, :default => 'JKS', :deprecated => 'Use `ssl_keystore_type` instead'
# If you need to use a custom truststore (`.jks`) specify that here. This does not work with .pem certs!
base.config :truststore, :validate => :path, :deprecated => 'Use `ssl_truststore_path` instead'
# Specify the truststore password here.
# Note, most .jks files created with keytool require a password!
base.config :truststore_password, :validate => :password, :deprecated => 'Use `ssl_truststore_password` instead'
# Specify the truststore type here. One of `JKS` or `PKCS12`. Default is `JKS`
base.config :truststore_type, :validate => :string, :default => 'JKS', :deprecated => 'Use `ssl_truststore_type` instead'
# NOTE: the default setting [] uses Java SSL engine defaults.
end

def initialize(*a)
super

@ssl_certificate_authorities = normalize_config(:ssl_certificate_authorities) do |normalize|
normalize.with_deprecated_mapping(:cacert) do |cacert|
[cacert]
end
end

params['ssl_certificate_authorities'] = @ssl_certificate_authorities unless @ssl_certificate_authorities.nil?

@ssl_certificate = normalize_config(:ssl_certificate) do |normalize|
normalize.with_deprecated_alias(:client_cert)
end

params['ssl_certificate'] = @ssl_certificate unless @ssl_certificate.nil?

@ssl_key = normalize_config(:ssl_key) do |normalize|
normalize.with_deprecated_alias(:client_key)
end

params['ssl_key'] = @ssl_key unless @ssl_key.nil?

%w[keystore truststore].each do |store|
%w[path type password].each do |variable|
config_name = "ssl_#{store}_#{variable}"
normalized_value = normalize_config(config_name) do |normalize|
deprecated_config_alias = variable == 'path' ? store : "#{store}_#{variable}"
normalize.with_deprecated_alias(deprecated_config_alias.to_sym)
end
instance_variable_set("@#{config_name}", normalized_value)
params[config_name.to_s] = normalized_value unless normalized_value.nil?
end
end
end

def ssl_options
fail(InvalidHTTPConfigError, "When `client_cert` is provided, `client_key` must also be provided") if @client_cert && !@client_key
fail(InvalidHTTPConfigError, "A `client_key` is not allowed unless a `client_cert` is provided") if @client_key && !@client_cert

fail(LogStash::ConfigurationError, "When `keystore` is provided, `keystore_password` must also be provided") if @keystore && !@keystore_password
fail(LogStash::ConfigurationError, "A `keystore_password` is not allowed unless a `keystore` is provided") if @keystore_password && !@keystore

fail(LogStash::ConfigurationError, "When `truststore` is provided, `truststore_password` must also be provided") if @truststore && !@truststore_password
fail(LogStash::ConfigurationError, "A `truststore_password` is not allowed unless a `truststore` is provided") if @truststore_password && !@truststore

super
end
end
end
3 changes: 2 additions & 1 deletion logstash-mixin-http_client.gemspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = 'logstash-mixin-http_client'
s.version = '7.2.0'
s.version = '7.3.0'
s.licenses = ['Apache License (2.0)']
s.summary = "AWS mixins to provide a unified interface for Amazon Webservice"
s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program"
Expand All @@ -19,6 +19,7 @@ Gem::Specification.new do |s|
s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
s.add_runtime_dependency 'logstash-codec-plain'
s.add_runtime_dependency 'manticore', '>= 0.8.0', '< 1.0.0'
s.add_runtime_dependency 'logstash-mixin-normalize_config_support', '~>1.0'

s.add_development_dependency 'logstash-devutils'
s.add_development_dependency 'stud'
Expand Down
177 changes: 1 addition & 176 deletions spec/plugin_mixin/http_client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

class Dummy < LogStash::Inputs::Base
include LogStash::PluginMixins::HttpClient
config_name 'dummy'
end

describe LogStash::PluginMixins::HttpClient do
Expand All @@ -29,51 +30,6 @@ class Dummy < LogStash::Inputs::Base
expect(impl.send(:client)).to eql(impl.client)
end

shared_examples "setting ca bundles" do |key, type|
subject { Dummy.new(conf).send(:client_config) }

it "should correctly set the path" do
expect(subject[:ssl][key]).to eql(path), "Expected to find path for #{key}"
end

if type == :jks
let(:store_password) { conf["#{key}_password"] }
let(:store_type) { conf["#{key}_type"]}

it "should set the bundle password" do
expect(subject[:ssl]["#{key}_password".to_sym]).to eql(store_password)
end

it "should set the bundle type" do
expect(subject[:ssl]["#{key}_type".to_sym]).to eql(store_type)
end
end
end

describe "with a custom ssl bundle" do
let(:file) { Stud::Temporary.file }
let(:path) { file.path }
after { File.unlink(path)}

context "with x509" do
let(:conf) { basic_config.merge("cacert" => path) }

include_examples("setting ca bundles", :ca_file)
end

context "with JKS" do
let(:conf) {
basic_config.merge(
"truststore" => path,
"truststore_password" => "foobar",
"truststore_type" => "jks"
)
}

include_examples("setting ca bundles", :truststore, :jks)
end
end

describe "with a custom validate_after_activity" do
subject { Dummy.new(client_config).send(:client_config) }

Expand Down Expand Up @@ -120,135 +76,4 @@ class Dummy < LogStash::Inputs::Base
end
end
end

["keystore", "truststore"].each do |store|
describe "with a custom #{store}" do
let(:file) { Stud::Temporary.file }
let(:path) { file.path }
let(:password) { "foo" }
after { File.unlink(path)}

let(:conf) {
basic_config.merge(
store => path,
"#{store}_password" => password,
"#{store}_type" => "jks"
)
}

include_examples("setting ca bundles", store.to_sym, :jks)

context "with no password set" do
let(:password) { nil }

it "should raise an error" do
expect do
Dummy.new(conf).client_config
end.to raise_error(LogStash::ConfigurationError)
end
end
end
end

describe "with a client cert" do
let(:file) { Stud::Temporary.file }
let(:path) { file.path }
after { File.unlink(path)}

context "with correct client certs" do
let(:conf) { basic_config.merge("client_cert" => path, "client_key" => path) }

it "should create without error" do
expect {
Dummy.new(conf).client_config
}.not_to raise_error
end
end

shared_examples("raising a configuration error") do
it "should raise an error error" do
expect {
Dummy.new(conf).client_config
}.to raise_error(LogStash::PluginMixins::HttpClient::InvalidHTTPConfigError)
end
end

context "without a key" do
let(:conf) { basic_config.merge("client_cert" => path) }

include_examples("raising a configuration error")
end

context "without a cert" do
let(:conf) { basic_config.merge("client_key" => path) }

include_examples("raising a configuration error")
end
end

describe "with verify mode" do
let(:file) { Stud::Temporary.file }
let(:path) { file.path }
after { File.unlink(path)}

context "default" do
let(:conf) { basic_config }

it "sets manticore verify to :strict" do
expect( Dummy.new(conf).client_config[:ssl] ).to include :verify => :strict
end
end

context "'full'" do
let(:conf) { basic_config.merge("ssl_verification_mode" => 'full') }

it "sets manticore verify to :strict" do
expect( Dummy.new(conf).client_config[:ssl] ).to include :verify => :strict
end
end

context "'none'" do
let(:conf) { basic_config.merge("ssl_verification_mode" => 'none') }

it "sets manticore verify to :disable" do
expect( Dummy.new(conf).client_config[:ssl] ).to include :verify => :disable
end
end

end

describe "with supported protocols" do
context "default" do
let(:conf) { basic_config }

it "does not set manticore protocols option" do
expect( Dummy.new(conf).client_config[:ssl] ).to_not include :protocols
end
end

context "empty" do
let(:conf) { basic_config.merge("ssl_supported_protocols" => []) }

it "does not set manticore protocols option" do
expect( Dummy.new(conf).client_config[:ssl] ).to_not include :protocols
end
end

context "'TLSv1.3'" do
let(:conf) { basic_config.merge("ssl_supported_protocols" => ['TLSv1.3']) }

it "sets manticore protocols option" do
expect( Dummy.new(conf).client_config[:ssl] ).to include :protocols => ['TLSv1.3']
end
end

context "'TLSv1.2' and 'TLSv1.3'" do
let(:conf) { basic_config.merge("ssl_supported_protocols" => ['TLSv1.3', 'TLSv1.2']) }

it "sets manticore protocols option" do
expect( Dummy.new(conf).client_config[:ssl] ).to include :protocols => ['TLSv1.3', 'TLSv1.2']
end
end

end
end