logstash-mixin-http_client 7.2.0 → 7.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile +8 -0
- data/lib/logstash/plugin_mixins/http_client/deprecated_ssl_config_support.rb +74 -0
- data/lib/logstash/plugin_mixins/http_client.rb +182 -155
- data/logstash-mixin-http_client.gemspec +2 -1
- data/spec/plugin_mixin/http_client_spec.rb +1 -176
- data/spec/plugin_mixin/http_client_ssl_spec.rb +438 -0
- metadata +20 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc464a55d52c603e85ea2660d4421e299cf84a876c0535b42e96eb7b6ab6a39c
|
4
|
+
data.tar.gz: 147afafc098bc8b326a21200ac7354e80ecbbefb1736d7dbee2c49a50d9eba69
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 966d167f986302dfb50b7c83ad4101c77c23ce08c998749a184339516c7021c96da5c6f389fa71b6c8a06869fc0ac66a72988ac3ba8666dd5defb070333d4ae5
|
7
|
+
data.tar.gz: 8fe68d119b1ad22a102aaa810c39b364127911a7b2814e7330f7a04f70de36985b413c30a65a8d617edd9b8139c181dfe302777502efb8eaa579deecb1f9d553
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## 7.3.0
|
2
|
+
- Adds standardized SSL settings and deprecates their non-standard counterparts. Deprecated settings will continue to work, and will provide pipeline maintainers with guidance toward using their standardized counterparts [#42](https://github.com/logstash-plugins/logstash-mixin-http_client/pull/42)
|
3
|
+
- Adds new `ssl_truststore_path`, `ssl_truststore_password`, and `ssl_truststore_type` settings for configuring SSL-trust using a PKCS-12 or JKS trust store, deprecating their `truststore`, `truststore_password`, and `truststore_type` counterparts.
|
4
|
+
- Adds new `ssl_certificate_authorities` setting for configuring SSL-trust using a PEM-formated list certificate authorities, deprecating its `cacert` counterpart.
|
5
|
+
- Adds new `ssl_keystore_path`, `ssl_keystore_password`, and `ssl_keystore_type` settings for configuring SSL-identity using a PKCS-12 or JKS key store, deprecating their `keystore`, `keystore_password`, and `keystore_type` counterparts.
|
6
|
+
- Adds new `ssl_certificate` and `ssl_key` settings for configuring SSL-identity using a PEM-formatted certificate/key pair, deprecating their `client_cert` and `client_key` counterparts.
|
7
|
+
- Added a way for plugin maintainers to include this mixin _without_ supporting the now-deprecated SSL options.
|
8
|
+
- Added the `ssl_cipher_suites` option
|
9
|
+
|
1
10
|
## 7.2.0
|
2
11
|
- Feat: add `ssl_supported_protocols` option [#40](https://github.com/logstash-plugins/logstash-mixin-http_client/pull/40)
|
3
12
|
|
data/Gemfile
CHANGED
@@ -2,3 +2,11 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in logstash-mass_effect.gemspec
|
4
4
|
gemspec
|
5
|
+
|
6
|
+
logstash_path = ENV["LOGSTASH_PATH"] || "../../logstash"
|
7
|
+
use_logstash_source = ENV["LOGSTASH_SOURCE"] && ENV["LOGSTASH_SOURCE"].to_s == "1"
|
8
|
+
|
9
|
+
if Dir.exist?(logstash_path) && use_logstash_source
|
10
|
+
gem 'logstash-core', :path => "#{logstash_path}/logstash-core"
|
11
|
+
gem 'logstash-core-plugin-api', :path => "#{logstash_path}/logstash-core-plugin-api"
|
12
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module LogStash::PluginMixins::HttpClient
|
2
|
+
module DeprecatedSslConfigSupport
|
3
|
+
def self.included(base)
|
4
|
+
fail ArgumentError unless base <= LogStash::PluginMixins::HttpClient::Implementation
|
5
|
+
|
6
|
+
require 'logstash/plugin_mixins/normalize_config_support'
|
7
|
+
base.include(LogStash::PluginMixins::NormalizeConfigSupport)
|
8
|
+
|
9
|
+
# If you need to use a custom X.509 CA (.pem certs) specify the path to that here
|
10
|
+
base.config :cacert, :validate => :path, :deprecated => 'Use `ssl_certificate_authorities` instead'
|
11
|
+
# If you'd like to use a client certificate (note, most people don't want this) set the path to the x509 cert here
|
12
|
+
base.config :client_cert, :validate => :path, :deprecated => 'Use `ssl_certificate` instead'
|
13
|
+
# If you're using a client certificate specify the path to the encryption key here
|
14
|
+
base.config :client_key, :validate => :path, :deprecated => 'Use `ssl_key` instead'
|
15
|
+
# If you need to use a custom keystore (`.jks`) specify that here. This does not work with .pem keys!
|
16
|
+
base.config :keystore, :validate => :path, :deprecated => 'Use `ssl_keystore_path` instead'
|
17
|
+
# Specify the keystore password here.
|
18
|
+
# Note, most .jks files created with keytool require a password!
|
19
|
+
base.config :keystore_password, :validate => :password, :deprecated => 'Use `ssl_keystore_password` instead'
|
20
|
+
# Specify the keystore type here. One of `JKS` or `PKCS12`. Default is `JKS`
|
21
|
+
base.config :keystore_type, :validate => :string, :default => 'JKS', :deprecated => 'Use `ssl_keystore_type` instead'
|
22
|
+
# If you need to use a custom truststore (`.jks`) specify that here. This does not work with .pem certs!
|
23
|
+
base.config :truststore, :validate => :path, :deprecated => 'Use `ssl_truststore_path` instead'
|
24
|
+
# Specify the truststore password here.
|
25
|
+
# Note, most .jks files created with keytool require a password!
|
26
|
+
base.config :truststore_password, :validate => :password, :deprecated => 'Use `ssl_truststore_password` instead'
|
27
|
+
# Specify the truststore type here. One of `JKS` or `PKCS12`. Default is `JKS`
|
28
|
+
base.config :truststore_type, :validate => :string, :default => 'JKS', :deprecated => 'Use `ssl_truststore_type` instead'
|
29
|
+
# NOTE: the default setting [] uses Java SSL engine defaults.
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize(*a)
|
33
|
+
super
|
34
|
+
|
35
|
+
@ssl_certificate_authorities = normalize_config(:ssl_certificate_authorities) do |normalize|
|
36
|
+
normalize.with_deprecated_mapping(:cacert) do |cacert|
|
37
|
+
[cacert]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
@ssl_certificate = normalize_config(:ssl_certificate) do |normalize|
|
42
|
+
normalize.with_deprecated_alias(:client_cert)
|
43
|
+
end
|
44
|
+
|
45
|
+
@ssl_key = normalize_config(:ssl_key) do |normalize|
|
46
|
+
normalize.with_deprecated_alias(:client_key)
|
47
|
+
end
|
48
|
+
|
49
|
+
%w[keystore truststore].each do |store|
|
50
|
+
%w[path type password].each do |variable|
|
51
|
+
config_name = "ssl_#{store}_#{variable}"
|
52
|
+
normalized_value = normalize_config(config_name) do |normalize|
|
53
|
+
deprecated_config_alias = variable == 'path' ? store : "#{store}_#{variable}"
|
54
|
+
normalize.with_deprecated_alias(deprecated_config_alias.to_sym)
|
55
|
+
end
|
56
|
+
instance_variable_set("@#{config_name}", normalized_value)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def ssl_options
|
62
|
+
fail(InvalidHTTPConfigError, "When `client_cert` is provided, `client_key` must also be provided") if @client_cert && !@client_key
|
63
|
+
fail(InvalidHTTPConfigError, "A `client_key` is not allowed unless a `client_cert` is provided") if @client_key && !@client_cert
|
64
|
+
|
65
|
+
fail(LogStash::ConfigurationError, "When `keystore` is provided, `keystore_password` must also be provided") if @keystore && !@keystore_password
|
66
|
+
fail(LogStash::ConfigurationError, "A `keystore_password` is not allowed unless a `keystore` is provided") if @keystore_password && !@keystore
|
67
|
+
|
68
|
+
fail(LogStash::ConfigurationError, "When `truststore` is provided, `truststore_password` must also be provided") if @truststore && !@truststore_password
|
69
|
+
fail(LogStash::ConfigurationError, "A `truststore_password` is not allowed unless a `truststore` is provided") if @truststore_password && !@truststore
|
70
|
+
|
71
|
+
super
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -7,203 +7,230 @@ require "logstash/config/mixin"
|
|
7
7
|
module LogStash::PluginMixins::HttpClient
|
8
8
|
class InvalidHTTPConfigError < StandardError; end
|
9
9
|
|
10
|
+
def self.[](**a)
|
11
|
+
Adapter.new(**a)
|
12
|
+
end
|
13
|
+
|
10
14
|
def self.included(base)
|
11
|
-
|
12
|
-
|
13
|
-
|
15
|
+
# TODO: deprecate the act of including this mixin directly,
|
16
|
+
# in a way that turns focus to plugin maintainers since
|
17
|
+
# an end-user cannot act to resolve the issue.
|
18
|
+
base.include(Adapter.new(with_deprecated: true))
|
14
19
|
end
|
15
20
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
21
|
+
class Adapter < Module
|
22
|
+
def initialize(with_deprecated: false)
|
23
|
+
@include_dep = with_deprecated
|
24
|
+
end
|
20
25
|
|
21
|
-
|
22
|
-
|
26
|
+
def included(base)
|
27
|
+
base.include(Implementation)
|
28
|
+
if @include_dep
|
29
|
+
require_relative 'http_client/deprecated_ssl_config_support'
|
30
|
+
base.include(DeprecatedSslConfigSupport)
|
31
|
+
end
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
private_constant :Adapter
|
23
36
|
|
24
|
-
|
25
|
-
|
37
|
+
module Implementation
|
38
|
+
def self.included(base)
|
39
|
+
require 'manticore'
|
26
40
|
|
27
|
-
|
28
|
-
|
41
|
+
# Timeout (in seconds) for the entire request
|
42
|
+
base.config :request_timeout, :validate => :number, :default => 60
|
29
43
|
|
30
|
-
|
31
|
-
|
44
|
+
# Timeout (in seconds) to wait for data on the socket. Default is `10s`
|
45
|
+
base.config :socket_timeout, :validate => :number, :default => 10
|
32
46
|
|
33
|
-
|
34
|
-
|
47
|
+
# Timeout (in seconds) to wait for a connection to be established. Default is `10s`
|
48
|
+
base.config :connect_timeout, :validate => :number, :default => 10
|
35
49
|
|
36
|
-
|
37
|
-
|
38
|
-
config :keepalive, :validate => :boolean, :default => true
|
50
|
+
# Should redirects be followed? Defaults to `true`
|
51
|
+
base.config :follow_redirects, :validate => :boolean, :default => true
|
39
52
|
|
40
|
-
|
41
|
-
|
42
|
-
# Note: if `retry_non_idempotent` is set only GET, HEAD, PUT, DELETE, OPTIONS, and TRACE requests will be retried.
|
43
|
-
config :automatic_retries, :validate => :number, :default => 1
|
53
|
+
# Max number of concurrent connections. Defaults to `50`
|
54
|
+
base.config :pool_max, :validate => :number, :default => 50
|
44
55
|
|
45
|
-
|
46
|
-
|
56
|
+
# Max number of concurrent connections to a single host. Defaults to `25`
|
57
|
+
base.config :pool_max_per_route, :validate => :number, :default => 25
|
47
58
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
# 'Defines period of inactivity in milliseconds after which persistent connections must be re-validated prior to being leased to the consumer. Non-positive value passed to this method disables connection validation. This check helps detect connections that have become stale (half-closed) while kept inactive in the pool.'
|
52
|
-
# See https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.html#setValidateAfterInactivity(int)[these docs for more info]
|
53
|
-
config :validate_after_inactivity, :validate => :number, :default => 200
|
59
|
+
# Turn this on to enable HTTP keepalive support. We highly recommend setting `automatic_retries` to at least
|
60
|
+
# one with this to fix interactions with broken keepalive implementations.
|
61
|
+
base.config :keepalive, :validate => :boolean, :default => true
|
54
62
|
|
55
|
-
|
56
|
-
|
63
|
+
# How many times should the client retry a failing URL. We highly recommend NOT setting this value
|
64
|
+
# to zero if keepalive is enabled. Some servers incorrectly end keepalives early requiring a retry!
|
65
|
+
# Note: if `retry_non_idempotent` is set only GET, HEAD, PUT, DELETE, OPTIONS, and TRACE requests will be retried.
|
66
|
+
base.config :automatic_retries, :validate => :number, :default => 1
|
57
67
|
|
58
|
-
|
59
|
-
|
60
|
-
# If you're using a client certificate specify the path to the encryption key here
|
61
|
-
config :client_key, :validate => :path
|
68
|
+
# If `automatic_retries` is enabled this will cause non-idempotent HTTP verbs (such as POST) to be retried.
|
69
|
+
base.config :retry_non_idempotent, :validate => :boolean, :default => false
|
62
70
|
|
63
|
-
|
64
|
-
|
71
|
+
# How long to wait before checking if the connection is stale before executing a request on a connection using keepalive.
|
72
|
+
# # You may want to set this lower, possibly to 0 if you get connection errors regularly
|
73
|
+
# Quoting the Apache commons docs (this client is based Apache Commmons):
|
74
|
+
# 'Defines period of inactivity in milliseconds after which persistent connections must be re-validated prior to being leased to the consumer. Non-positive value passed to this method disables connection validation. This check helps detect connections that have become stale (half-closed) while kept inactive in the pool.'
|
75
|
+
# See https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.html#setValidateAfterInactivity(int)[these docs for more info]
|
76
|
+
base.config :validate_after_inactivity, :validate => :number, :default => 200
|
65
77
|
|
66
|
-
|
67
|
-
|
68
|
-
config :keystore_password, :validate => :password
|
78
|
+
# If you need to use a custom X.509 CA (.pem certs) specify the path to that here
|
79
|
+
base.config :ssl_certificate_authorities, :validate => :path, :list => :true
|
69
80
|
|
70
|
-
|
71
|
-
|
81
|
+
# If you'd like to use a client certificate (note, most people don't want this) set the path to the x509 cert here
|
82
|
+
base.config :ssl_certificate, :validate => :path
|
72
83
|
|
73
|
-
|
74
|
-
|
75
|
-
# server’s hostname (or IP address) matches the names identified within the certificate
|
76
|
-
# none: no verification of the server’s certificate
|
77
|
-
config :ssl_verification_mode, :validate => ['full', 'none'], :default => 'full'
|
84
|
+
# If you're using a client certificate specify the path to the encryption key here
|
85
|
+
base.config :ssl_key, :validate => :path
|
78
86
|
|
79
|
-
|
80
|
-
|
87
|
+
# If you need to use a custom keystore (`.jks`) specify that here. This does not work with .pem keys!
|
88
|
+
base.config :ssl_keystore_path, :validate => :path
|
81
89
|
|
82
|
-
|
83
|
-
|
90
|
+
# Specify the keystore password here.
|
91
|
+
# Note, most .jks files created with keytool require a password!
|
92
|
+
base.config :ssl_keystore_password, :validate => :password
|
84
93
|
|
85
|
-
|
86
|
-
|
87
|
-
|
94
|
+
# Specify the keystore type here. One of `jks` or `pkcs12`.
|
95
|
+
# The default value is inferred from the filename.
|
96
|
+
# Note: If it's unable to determine the type based on the filename, it uses the
|
97
|
+
# `keystore.type` security property, or "jks" as default value.
|
98
|
+
base.config :ssl_keystore_type, :validate => %w(pkcs12 jks)
|
88
99
|
|
89
|
-
|
90
|
-
|
100
|
+
# Naming aligned with the Elastic stack.
|
101
|
+
# full: verifies that the provided certificate is signed by a trusted authority (CA) and also verifies that the
|
102
|
+
# server’s hostname (or IP address) matches the names identified within the certificate
|
103
|
+
# none: no verification of the server’s certificate
|
104
|
+
base.config :ssl_verification_mode, :validate => ['full', 'none'], :default => 'full'
|
91
105
|
|
92
|
-
|
93
|
-
|
94
|
-
|
106
|
+
# The list of cipher suites to use, listed by priorities.
|
107
|
+
# Supported cipher suites vary depending on which version of Java is used.
|
108
|
+
base.config :ssl_cipher_suites, :validate => :string, :list => true
|
95
109
|
|
96
|
-
|
97
|
-
|
98
|
-
# 1. Proxy host in form: `http://proxy.org:1234`
|
99
|
-
# 2. Proxy host in form: `{host => "proxy.org", port => 80, scheme => 'http', user => 'username@host', password => 'password'}`
|
100
|
-
# 3. Proxy host in form: `{url => 'http://proxy.org:1234', user => 'username@host', password => 'password'}`
|
101
|
-
config :proxy
|
110
|
+
# NOTE: the default setting [] uses Java SSL engine defaults.
|
111
|
+
base.config :ssl_supported_protocols, :validate => ['TLSv1.1', 'TLSv1.2', 'TLSv1.3'], :default => [], :list => true
|
102
112
|
|
103
|
-
|
104
|
-
|
113
|
+
# If you need to use a custom truststore (`.jks`) specify that here. This does not work with .pem certs!
|
114
|
+
base.config :ssl_truststore_path, :validate => :path
|
105
115
|
|
106
|
-
|
107
|
-
|
108
|
-
|
116
|
+
# Specify the truststore password here.
|
117
|
+
# Note, most .jks files created with keytool require a password!
|
118
|
+
base.config :ssl_truststore_password, :validate => :password
|
119
|
+
|
120
|
+
# Specify the truststore type here. One of `JKS` or `PKCS12`.
|
121
|
+
# The default value is inferred from the filename.
|
122
|
+
# Note: If it's unable to determine the type based on the filename, it uses the
|
123
|
+
# `keystore.type` security property, or "jks" as default value.
|
124
|
+
base.config :ssl_truststore_type, :validate => %w(pkcs12 jks)
|
125
|
+
|
126
|
+
# Enable cookie support. With this enabled the client will persist cookies
|
127
|
+
# across requests as a normal web browser would. Enabled by default
|
128
|
+
base.config :cookies, :validate => :boolean, :default => true
|
109
129
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
cookies: @cookies,
|
123
|
-
keepalive: @keepalive
|
124
|
-
}
|
125
|
-
|
126
|
-
if @proxy
|
127
|
-
# Symbolize keys if necessary
|
128
|
-
c[:proxy] = @proxy.is_a?(Hash) ?
|
129
|
-
@proxy.reduce({}) {|memo,(k,v)| memo[k.to_sym] = v; memo} :
|
130
|
-
@proxy
|
130
|
+
# If you'd like to use an HTTP proxy . This supports multiple configuration syntaxes:
|
131
|
+
#
|
132
|
+
# 1. Proxy host in form: `http://proxy.org:1234`
|
133
|
+
# 2. Proxy host in form: `{host => "proxy.org", port => 80, scheme => 'http', user => 'username@host', password => 'password'}`
|
134
|
+
# 3. Proxy host in form: `{url => 'http://proxy.org:1234', user => 'username@host', password => 'password'}`
|
135
|
+
base.config :proxy
|
136
|
+
|
137
|
+
# Username to use for HTTP auth.
|
138
|
+
base.config :user, :validate => :string
|
139
|
+
|
140
|
+
# Password to use for HTTP auth
|
141
|
+
base.config :password, :validate => :password
|
131
142
|
end
|
132
143
|
|
133
|
-
|
134
|
-
|
135
|
-
|
144
|
+
public
|
145
|
+
|
146
|
+
def client_config
|
147
|
+
c = {
|
148
|
+
connect_timeout: @connect_timeout,
|
149
|
+
socket_timeout: @socket_timeout,
|
150
|
+
request_timeout: @request_timeout,
|
151
|
+
follow_redirects: @follow_redirects,
|
152
|
+
automatic_retries: @automatic_retries,
|
153
|
+
retry_non_idempotent: @retry_non_idempotent,
|
154
|
+
check_connection_timeout: @validate_after_inactivity,
|
155
|
+
pool_max: @pool_max,
|
156
|
+
pool_max_per_route: @pool_max_per_route,
|
157
|
+
cookies: @cookies,
|
158
|
+
keepalive: @keepalive
|
159
|
+
}
|
160
|
+
|
161
|
+
if @proxy
|
162
|
+
# Symbolize keys if necessary
|
163
|
+
c[:proxy] = @proxy.is_a?(Hash) ?
|
164
|
+
@proxy.reduce({}) {|memo,(k,v)| memo[k.to_sym] = v; memo} :
|
165
|
+
@proxy
|
136
166
|
end
|
137
167
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
168
|
+
if @user
|
169
|
+
if !@password || !@password.value
|
170
|
+
raise ::LogStash::ConfigurationError, "User '#{@user}' specified without password!"
|
171
|
+
end
|
172
|
+
|
173
|
+
# Symbolize keys if necessary
|
174
|
+
c[:auth] = {
|
175
|
+
:user => @user,
|
176
|
+
:password => @password.value,
|
177
|
+
:eager => true
|
178
|
+
}
|
179
|
+
end
|
145
180
|
|
146
|
-
|
147
|
-
|
148
|
-
c
|
181
|
+
c[:ssl] = ssl_options
|
182
|
+
|
183
|
+
c
|
149
184
|
end
|
150
185
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
186
|
+
private
|
187
|
+
|
188
|
+
def ssl_options
|
189
|
+
|
190
|
+
options = {}
|
191
|
+
if @ssl_certificate_authorities&.any?
|
192
|
+
raise LogStash::ConfigurationError, 'Multiple values on `ssl_certificate_authorities` are not supported by this plugin' if @ssl_certificate_authorities.size > 1
|
193
|
+
|
194
|
+
options[:ca_file] = @ssl_certificate_authorities.first
|
160
195
|
end
|
161
|
-
end
|
162
196
|
|
163
|
-
|
164
|
-
|
165
|
-
:
|
166
|
-
:
|
167
|
-
|
168
|
-
|
197
|
+
if @ssl_truststore_path
|
198
|
+
options[:truststore] = @ssl_truststore_path
|
199
|
+
options[:truststore_type] = @ssl_truststore_type if @ssl_truststore_type
|
200
|
+
options[:truststore_password] = @ssl_truststore_password.value if @ssl_truststore_password
|
201
|
+
elsif @ssl_truststore_password
|
202
|
+
fail LogStash::ConfigurationError, "An `ssl_truststore_password` cannot be specified unless `ssl_truststore_path` is also provided."
|
203
|
+
end
|
169
204
|
|
170
|
-
if
|
171
|
-
|
205
|
+
if @ssl_keystore_path
|
206
|
+
options[:keystore] = @ssl_keystore_path
|
207
|
+
options[:keystore_type] = @ssl_keystore_type if @ssl_keystore_type
|
208
|
+
options[:keystore_password] = @ssl_keystore_password.value if @ssl_keystore_password
|
209
|
+
elsif @ssl_keystore_password
|
210
|
+
fail LogStash::ConfigurationError, "An `ssl_keystore_password` cannot be specified unless `ssl_keystore_path` is also provided."
|
172
211
|
end
|
173
|
-
end
|
174
212
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
213
|
+
if @ssl_certificate && @ssl_key
|
214
|
+
options[:client_cert] = @ssl_certificate
|
215
|
+
options[:client_key] = @ssl_key
|
216
|
+
elsif !!@ssl_certificate ^ !!@ssl_key
|
217
|
+
raise InvalidHTTPConfigError, "You must specify both `ssl_certificate` and `ssl_key` for an HTTP client, or neither!"
|
218
|
+
end
|
181
219
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
#
|
186
|
-
# supporting `ssl_verification_mode => strict` the same way ES does might require upstream Manticore
|
187
|
-
# changes -> as in ES/Beats setting `strict` means: "if the SAN is empty return an error"
|
188
|
-
c[:ssl][:verify] = :strict # :default
|
189
|
-
when 'none'
|
190
|
-
c[:ssl][:verify] = :disable
|
191
|
-
end
|
220
|
+
options[:verify] = @ssl_verification_mode == 'full' ? :strict : :disable
|
221
|
+
options[:protocols] = @ssl_supported_protocols if @ssl_supported_protocols&.any?
|
222
|
+
options[:cipher_suites] = @ssl_cipher_suites if @ssl_cipher_suites&.any?
|
192
223
|
|
193
|
-
|
194
|
-
c[:ssl][:protocols] = @ssl_supported_protocols
|
224
|
+
options
|
195
225
|
end
|
196
226
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
private
|
201
|
-
def make_client
|
202
|
-
Manticore::Client.new(client_config)
|
203
|
-
end
|
227
|
+
def make_client
|
228
|
+
Manticore::Client.new(client_config)
|
229
|
+
end
|
204
230
|
|
205
|
-
|
206
|
-
|
207
|
-
|
231
|
+
public
|
232
|
+
def client
|
233
|
+
@client ||= make_client
|
234
|
+
end
|
208
235
|
end
|
209
|
-
end
|
236
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'logstash-mixin-http_client'
|
3
|
-
s.version = '7.
|
3
|
+
s.version = '7.3.0'
|
4
4
|
s.licenses = ['Apache License (2.0)']
|
5
5
|
s.summary = "AWS mixins to provide a unified interface for Amazon Webservice"
|
6
6
|
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"
|
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
|
20
20
|
s.add_runtime_dependency 'logstash-codec-plain'
|
21
21
|
s.add_runtime_dependency 'manticore', '>= 0.8.0', '< 1.0.0'
|
22
|
+
s.add_runtime_dependency 'logstash-mixin-normalize_config_support', '~>1.0'
|
22
23
|
|
23
24
|
s.add_development_dependency 'logstash-devutils'
|
24
25
|
s.add_development_dependency 'stud'
|
@@ -5,6 +5,7 @@ require "stud/temporary"
|
|
5
5
|
|
6
6
|
class Dummy < LogStash::Inputs::Base
|
7
7
|
include LogStash::PluginMixins::HttpClient
|
8
|
+
config_name 'dummy'
|
8
9
|
end
|
9
10
|
|
10
11
|
describe LogStash::PluginMixins::HttpClient do
|
@@ -29,51 +30,6 @@ describe LogStash::PluginMixins::HttpClient do
|
|
29
30
|
expect(impl.send(:client)).to eql(impl.client)
|
30
31
|
end
|
31
32
|
|
32
|
-
shared_examples "setting ca bundles" do |key, type|
|
33
|
-
subject { Dummy.new(conf).send(:client_config) }
|
34
|
-
|
35
|
-
it "should correctly set the path" do
|
36
|
-
expect(subject[:ssl][key]).to eql(path), "Expected to find path for #{key}"
|
37
|
-
end
|
38
|
-
|
39
|
-
if type == :jks
|
40
|
-
let(:store_password) { conf["#{key}_password"] }
|
41
|
-
let(:store_type) { conf["#{key}_type"]}
|
42
|
-
|
43
|
-
it "should set the bundle password" do
|
44
|
-
expect(subject[:ssl]["#{key}_password".to_sym]).to eql(store_password)
|
45
|
-
end
|
46
|
-
|
47
|
-
it "should set the bundle type" do
|
48
|
-
expect(subject[:ssl]["#{key}_type".to_sym]).to eql(store_type)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
describe "with a custom ssl bundle" do
|
54
|
-
let(:file) { Stud::Temporary.file }
|
55
|
-
let(:path) { file.path }
|
56
|
-
after { File.unlink(path)}
|
57
|
-
|
58
|
-
context "with x509" do
|
59
|
-
let(:conf) { basic_config.merge("cacert" => path) }
|
60
|
-
|
61
|
-
include_examples("setting ca bundles", :ca_file)
|
62
|
-
end
|
63
|
-
|
64
|
-
context "with JKS" do
|
65
|
-
let(:conf) {
|
66
|
-
basic_config.merge(
|
67
|
-
"truststore" => path,
|
68
|
-
"truststore_password" => "foobar",
|
69
|
-
"truststore_type" => "jks"
|
70
|
-
)
|
71
|
-
}
|
72
|
-
|
73
|
-
include_examples("setting ca bundles", :truststore, :jks)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
33
|
describe "with a custom validate_after_activity" do
|
78
34
|
subject { Dummy.new(client_config).send(:client_config) }
|
79
35
|
|
@@ -120,135 +76,4 @@ describe LogStash::PluginMixins::HttpClient do
|
|
120
76
|
end
|
121
77
|
end
|
122
78
|
end
|
123
|
-
|
124
|
-
["keystore", "truststore"].each do |store|
|
125
|
-
describe "with a custom #{store}" do
|
126
|
-
let(:file) { Stud::Temporary.file }
|
127
|
-
let(:path) { file.path }
|
128
|
-
let(:password) { "foo" }
|
129
|
-
after { File.unlink(path)}
|
130
|
-
|
131
|
-
let(:conf) {
|
132
|
-
basic_config.merge(
|
133
|
-
store => path,
|
134
|
-
"#{store}_password" => password,
|
135
|
-
"#{store}_type" => "jks"
|
136
|
-
)
|
137
|
-
}
|
138
|
-
|
139
|
-
include_examples("setting ca bundles", store.to_sym, :jks)
|
140
|
-
|
141
|
-
context "with no password set" do
|
142
|
-
let(:password) { nil }
|
143
|
-
|
144
|
-
it "should raise an error" do
|
145
|
-
expect do
|
146
|
-
Dummy.new(conf).client_config
|
147
|
-
end.to raise_error(LogStash::ConfigurationError)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
describe "with a client cert" do
|
154
|
-
let(:file) { Stud::Temporary.file }
|
155
|
-
let(:path) { file.path }
|
156
|
-
after { File.unlink(path)}
|
157
|
-
|
158
|
-
context "with correct client certs" do
|
159
|
-
let(:conf) { basic_config.merge("client_cert" => path, "client_key" => path) }
|
160
|
-
|
161
|
-
it "should create without error" do
|
162
|
-
expect {
|
163
|
-
Dummy.new(conf).client_config
|
164
|
-
}.not_to raise_error
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
shared_examples("raising a configuration error") do
|
169
|
-
it "should raise an error error" do
|
170
|
-
expect {
|
171
|
-
Dummy.new(conf).client_config
|
172
|
-
}.to raise_error(LogStash::PluginMixins::HttpClient::InvalidHTTPConfigError)
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
context "without a key" do
|
177
|
-
let(:conf) { basic_config.merge("client_cert" => path) }
|
178
|
-
|
179
|
-
include_examples("raising a configuration error")
|
180
|
-
end
|
181
|
-
|
182
|
-
context "without a cert" do
|
183
|
-
let(:conf) { basic_config.merge("client_key" => path) }
|
184
|
-
|
185
|
-
include_examples("raising a configuration error")
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
describe "with verify mode" do
|
190
|
-
let(:file) { Stud::Temporary.file }
|
191
|
-
let(:path) { file.path }
|
192
|
-
after { File.unlink(path)}
|
193
|
-
|
194
|
-
context "default" do
|
195
|
-
let(:conf) { basic_config }
|
196
|
-
|
197
|
-
it "sets manticore verify to :strict" do
|
198
|
-
expect( Dummy.new(conf).client_config[:ssl] ).to include :verify => :strict
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
context "'full'" do
|
203
|
-
let(:conf) { basic_config.merge("ssl_verification_mode" => 'full') }
|
204
|
-
|
205
|
-
it "sets manticore verify to :strict" do
|
206
|
-
expect( Dummy.new(conf).client_config[:ssl] ).to include :verify => :strict
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
context "'none'" do
|
211
|
-
let(:conf) { basic_config.merge("ssl_verification_mode" => 'none') }
|
212
|
-
|
213
|
-
it "sets manticore verify to :disable" do
|
214
|
-
expect( Dummy.new(conf).client_config[:ssl] ).to include :verify => :disable
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
end
|
219
|
-
|
220
|
-
describe "with supported protocols" do
|
221
|
-
context "default" do
|
222
|
-
let(:conf) { basic_config }
|
223
|
-
|
224
|
-
it "does not set manticore protocols option" do
|
225
|
-
expect( Dummy.new(conf).client_config[:ssl] ).to_not include :protocols
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
context "empty" do
|
230
|
-
let(:conf) { basic_config.merge("ssl_supported_protocols" => []) }
|
231
|
-
|
232
|
-
it "does not set manticore protocols option" do
|
233
|
-
expect( Dummy.new(conf).client_config[:ssl] ).to_not include :protocols
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
context "'TLSv1.3'" do
|
238
|
-
let(:conf) { basic_config.merge("ssl_supported_protocols" => ['TLSv1.3']) }
|
239
|
-
|
240
|
-
it "sets manticore protocols option" do
|
241
|
-
expect( Dummy.new(conf).client_config[:ssl] ).to include :protocols => ['TLSv1.3']
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
context "'TLSv1.2' and 'TLSv1.3'" do
|
246
|
-
let(:conf) { basic_config.merge("ssl_supported_protocols" => ['TLSv1.3', 'TLSv1.2']) }
|
247
|
-
|
248
|
-
it "sets manticore protocols option" do
|
249
|
-
expect( Dummy.new(conf).client_config[:ssl] ).to include :protocols => ['TLSv1.3', 'TLSv1.2']
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
end
|
254
79
|
end
|
@@ -0,0 +1,438 @@
|
|
1
|
+
require 'logstash/devutils/rspec/spec_helper'
|
2
|
+
require 'logstash/plugin_mixins/http_client'
|
3
|
+
require 'logstash/plugin_mixins/http_client/deprecated_ssl_config_support'
|
4
|
+
require 'stud/temporary'
|
5
|
+
|
6
|
+
shared_examples 'setting ca bundles' do |key, type|
|
7
|
+
subject(:client_config) { plugin_class.new(conf).send(:client_config) }
|
8
|
+
|
9
|
+
it 'should correctly set the path' do
|
10
|
+
expect(client_config[:ssl][key]).to eql(path), "Expected to find path for #{key}"
|
11
|
+
end
|
12
|
+
|
13
|
+
if type == :jks
|
14
|
+
let(:store_password) { conf["#{use_deprecated_config ? '' : 'ssl_'}#{key}_password"] }
|
15
|
+
let(:store_type) { conf["#{use_deprecated_config ? '' : 'ssl_'}#{key}_type"]}
|
16
|
+
|
17
|
+
it 'should set the bundle password' do
|
18
|
+
expect(client_config[:ssl]["#{key}_password".to_sym]).to eql(store_password)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should set the bundle type' do
|
22
|
+
expect(client_config[:ssl]["#{key}_type".to_sym]).to eql(store_type)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
shared_examples 'a deprecated setting with guidance' do |deprecations_and_guidance|
|
28
|
+
|
29
|
+
let(:logger_stub) { double('Logger').as_null_object }
|
30
|
+
|
31
|
+
before(:each) do
|
32
|
+
allow(plugin_class).to receive(:logger).and_return(logger_stub)
|
33
|
+
end
|
34
|
+
|
35
|
+
deprecations_and_guidance.each do |deprecated_setting_name, canonical_setting_name|
|
36
|
+
it "emits a warning about the setting `#{deprecated_setting_name}` being deprecated and provides guidance to use `#{canonical_setting_name}`" do
|
37
|
+
plugin_class.new(conf)
|
38
|
+
|
39
|
+
deprecation_text = "deprecated config setting \"#{deprecated_setting_name}\" set"
|
40
|
+
guidance_text = "Use `#{canonical_setting_name}` instead"
|
41
|
+
|
42
|
+
expect(logger_stub).to have_received(:warn).with(a_string_including(deprecation_text).and(including(guidance_text)), anything)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
shared_examples 'with common ssl options' do
|
48
|
+
describe 'with verify mode' do
|
49
|
+
let(:file) { Stud::Temporary.file }
|
50
|
+
let(:path) { file.path }
|
51
|
+
after { File.unlink(path)}
|
52
|
+
|
53
|
+
context 'default' do
|
54
|
+
let(:conf) { basic_config }
|
55
|
+
|
56
|
+
it 'sets manticore verify to :strict' do
|
57
|
+
expect(plugin_class.new(conf).client_config[:ssl]).to include :verify => :strict
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "'full'" do
|
62
|
+
let(:conf) { basic_config.merge('ssl_verification_mode' => 'full') }
|
63
|
+
|
64
|
+
it 'sets manticore verify to :strict' do
|
65
|
+
expect(plugin_class.new(conf).client_config[:ssl]).to include :verify => :strict
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "'none'" do
|
70
|
+
let(:conf) { basic_config.merge('ssl_verification_mode' => 'none') }
|
71
|
+
|
72
|
+
it 'sets manticore verify to :disable' do
|
73
|
+
expect(plugin_class.new(conf).client_config[:ssl]).to include :verify => :disable
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe 'with supported protocols' do
|
79
|
+
context 'default' do
|
80
|
+
let(:conf) { basic_config }
|
81
|
+
|
82
|
+
it 'does not set manticore protocols option' do
|
83
|
+
expect(plugin_class.new(conf).client_config[:ssl]).to_not include :protocols
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'empty' do
|
88
|
+
let(:conf) { basic_config.merge('ssl_supported_protocols' => []) }
|
89
|
+
|
90
|
+
it 'does not set manticore protocols option' do
|
91
|
+
expect(plugin_class.new(conf).client_config[:ssl]).to_not include :protocols
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "'TLSv1.3'" do
|
96
|
+
let(:conf) { basic_config.merge('ssl_supported_protocols' => ['TLSv1.3']) }
|
97
|
+
|
98
|
+
it 'sets manticore protocols option' do
|
99
|
+
expect(plugin_class.new(conf).client_config[:ssl]).to include :protocols => ['TLSv1.3']
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "'TLSv1.2' and 'TLSv1.3'" do
|
104
|
+
let(:conf) { basic_config.merge('ssl_supported_protocols' => ['TLSv1.3', 'TLSv1.2']) }
|
105
|
+
|
106
|
+
it 'sets manticore protocols option' do
|
107
|
+
expect(plugin_class.new(conf).client_config[:ssl]).to include :protocols => ['TLSv1.3', 'TLSv1.2']
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe 'with ssl_cipher_suites' do
|
113
|
+
context 'default' do
|
114
|
+
let(:conf) { basic_config }
|
115
|
+
|
116
|
+
it 'does not set manticore cipher_suites option' do
|
117
|
+
expect(plugin_class.new(conf).client_config[:ssl]).to_not include :cipher_suites
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'empty' do
|
122
|
+
let(:conf) { basic_config.merge('ssl_cipher_suites' => []) }
|
123
|
+
|
124
|
+
it 'does not set manticore cipher_suites option' do
|
125
|
+
expect(plugin_class.new(conf).client_config[:ssl]).to_not include :cipher_suites
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context "set to ['TLS_AES_256_GCM_SHA384']" do
|
130
|
+
let(:conf) { basic_config.merge('ssl_cipher_suites' => ['TLS_AES_256_GCM_SHA384']) }
|
131
|
+
|
132
|
+
it 'sets manticore cipher_suites option' do
|
133
|
+
expect(plugin_class.new(conf).client_config[:ssl]).to include :cipher_suites => ['TLS_AES_256_GCM_SHA384']
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
shared_examples("raise an http config error") do |message|
|
140
|
+
it "should raise an error error" do
|
141
|
+
expect {
|
142
|
+
plugin_class.new(conf).client_config
|
143
|
+
}.to raise_error(LogStash::PluginMixins::HttpClient::InvalidHTTPConfigError, message)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
shared_examples 'a client with deprecated ssl options' do
|
148
|
+
describe LogStash::PluginMixins::HttpClient do
|
149
|
+
let(:basic_config) { {} }
|
150
|
+
let(:impl) { plugin_class.new(basic_config) }
|
151
|
+
let(:use_deprecated_config) { true }
|
152
|
+
|
153
|
+
include_examples 'with common ssl options'
|
154
|
+
|
155
|
+
describe 'with a custom ssl bundle' do
|
156
|
+
let(:file) { Stud::Temporary.file }
|
157
|
+
let(:path) { file.path }
|
158
|
+
after { File.unlink(path)}
|
159
|
+
|
160
|
+
context 'with x509' do
|
161
|
+
let(:conf) { basic_config.merge('cacert' => path) }
|
162
|
+
|
163
|
+
include_examples('setting ca bundles', :ca_file)
|
164
|
+
|
165
|
+
it_behaves_like('a deprecated setting with guidance',
|
166
|
+
'cacert' => 'ssl_certificate_authorities')
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'with JKS' do
|
170
|
+
let(:conf) {
|
171
|
+
basic_config.merge(
|
172
|
+
'truststore' => path,
|
173
|
+
'truststore_password' => 'foobar',
|
174
|
+
'truststore_type' => 'jks'
|
175
|
+
)
|
176
|
+
}
|
177
|
+
|
178
|
+
include_examples('setting ca bundles', :truststore, :jks)
|
179
|
+
|
180
|
+
it_behaves_like('a deprecated setting with guidance',
|
181
|
+
'truststore' => 'ssl_truststore_path',
|
182
|
+
'truststore_password' => 'ssl_truststore_password',
|
183
|
+
'truststore_type' => 'ssl_truststore_type')
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe 'with a client cert' do
|
188
|
+
let(:file) { Stud::Temporary.file }
|
189
|
+
let(:path) { file.path }
|
190
|
+
after { File.unlink(path)}
|
191
|
+
|
192
|
+
context 'with correct client certs' do
|
193
|
+
let(:conf) { basic_config.merge('client_cert' => path, 'client_key' => path) }
|
194
|
+
|
195
|
+
it 'should create without error' do
|
196
|
+
expect {
|
197
|
+
plugin_class.new(conf).client_config
|
198
|
+
}.not_to raise_error
|
199
|
+
end
|
200
|
+
|
201
|
+
it_behaves_like('a deprecated setting with guidance',
|
202
|
+
'client_cert' => 'ssl_certificate',
|
203
|
+
'client_key' => 'ssl_key')
|
204
|
+
end
|
205
|
+
|
206
|
+
context 'without a key' do
|
207
|
+
let(:conf) { basic_config.merge('client_cert' => path) }
|
208
|
+
|
209
|
+
include_examples('raise an http config error', 'When `client_cert` is provided, `client_key` must also be provided')
|
210
|
+
end
|
211
|
+
|
212
|
+
context 'without a cert' do
|
213
|
+
let(:conf) { basic_config.merge('client_key' => path) }
|
214
|
+
|
215
|
+
include_examples('raise an http config error', 'A `client_key` is not allowed unless a `client_cert` is provided')
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
%w[keystore truststore].each do |store|
|
220
|
+
describe "with a custom #{store}" do
|
221
|
+
let(:file) { Stud::Temporary.file }
|
222
|
+
let(:path) { file.path }
|
223
|
+
let(:password) { "foo" }
|
224
|
+
after { File.unlink(path)}
|
225
|
+
|
226
|
+
let(:conf) {
|
227
|
+
basic_config.merge(
|
228
|
+
store => path,
|
229
|
+
"#{store}_password" => password,
|
230
|
+
"#{store}_type" => "jks"
|
231
|
+
).compact
|
232
|
+
}
|
233
|
+
|
234
|
+
include_examples("setting ca bundles", store.to_sym, :jks)
|
235
|
+
|
236
|
+
it_behaves_like('a deprecated setting with guidance',
|
237
|
+
"#{store}" => "ssl_#{store}_path",
|
238
|
+
"#{store}_password" => "ssl_#{store}_password",
|
239
|
+
"#{store}_type" => "ssl_#{store}_type")
|
240
|
+
|
241
|
+
context "with no password set" do
|
242
|
+
let(:password) { nil }
|
243
|
+
|
244
|
+
it "should raise an error" do
|
245
|
+
expect do
|
246
|
+
plugin_class.new(conf).client_config
|
247
|
+
end.to raise_error(LogStash::ConfigurationError)
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
shared_examples 'a client with standardized ssl options' do
|
256
|
+
describe LogStash::PluginMixins::HttpClient do
|
257
|
+
let(:basic_config) { {} }
|
258
|
+
let(:impl) { plugin_class.new(basic_config) }
|
259
|
+
let(:use_deprecated_config) { false }
|
260
|
+
|
261
|
+
include_examples 'with common ssl options'
|
262
|
+
|
263
|
+
describe 'with a custom ssl bundle' do
|
264
|
+
let(:file) { Stud::Temporary.file }
|
265
|
+
let(:path) { file.path }
|
266
|
+
after { File.unlink(path)}
|
267
|
+
|
268
|
+
context 'with x509' do
|
269
|
+
let(:conf) { basic_config.merge('ssl_certificate_authorities' => path) }
|
270
|
+
|
271
|
+
include_examples('setting ca bundles', :ca_file)
|
272
|
+
end
|
273
|
+
|
274
|
+
context 'with JKS' do
|
275
|
+
let(:conf) {
|
276
|
+
basic_config.merge(
|
277
|
+
'ssl_truststore_path' => path,
|
278
|
+
'ssl_truststore_password' => 'foobar',
|
279
|
+
'ssl_truststore_type' => 'jks'
|
280
|
+
)
|
281
|
+
}
|
282
|
+
|
283
|
+
include_examples('setting ca bundles', :truststore, :jks)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
describe 'with a client cert' do
|
288
|
+
let(:file) { Stud::Temporary.file }
|
289
|
+
let(:path) { file.path }
|
290
|
+
after { File.unlink(path)}
|
291
|
+
|
292
|
+
context 'with correct client certs' do
|
293
|
+
let(:conf) { basic_config.merge('ssl_certificate' => path, 'ssl_key' => path) }
|
294
|
+
|
295
|
+
it 'should create without error' do
|
296
|
+
expect {
|
297
|
+
plugin_class.new(conf).client_config
|
298
|
+
}.not_to raise_error
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
context 'without an ssl_key' do
|
303
|
+
let(:conf) { basic_config.merge('ssl_certificate' => path) }
|
304
|
+
|
305
|
+
include_examples('raise an http config error', 'You must specify both `ssl_certificate` and `ssl_key` for an HTTP client, or neither!')
|
306
|
+
end
|
307
|
+
|
308
|
+
context 'without an ssl_certificate' do
|
309
|
+
let(:conf) { basic_config.merge('ssl_key' => path) }
|
310
|
+
include_examples('raise an http config error', 'You must specify both `ssl_certificate` and `ssl_key` for an HTTP client, or neither!')
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
%w[keystore truststore].each do |store|
|
315
|
+
describe "with a custom #{store}" do
|
316
|
+
let(:file) { Stud::Temporary.file }
|
317
|
+
let(:path) { file.path }
|
318
|
+
let(:password) { "foo" }
|
319
|
+
after { File.unlink(path)}
|
320
|
+
|
321
|
+
let(:conf) {
|
322
|
+
basic_config.merge(
|
323
|
+
"ssl_#{store}_path" => path,
|
324
|
+
"ssl_#{store}_password" => password,
|
325
|
+
"ssl_#{store}_type" => "jks"
|
326
|
+
).compact
|
327
|
+
}
|
328
|
+
|
329
|
+
include_examples("setting ca bundles", store.to_sym, :jks)
|
330
|
+
|
331
|
+
context "with no password set" do
|
332
|
+
let(:password) { nil }
|
333
|
+
|
334
|
+
it "should not raise an error" do
|
335
|
+
expect do
|
336
|
+
plugin_class.new(conf).client_config
|
337
|
+
end.to_not raise_error
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
345
|
+
class PluginWithNoModuleConfig < LogStash::Inputs::Base
|
346
|
+
include LogStash::PluginMixins::HttpClient
|
347
|
+
config_name 'no_config'
|
348
|
+
end
|
349
|
+
|
350
|
+
class PluginWithDeprecatedTrue < LogStash::Inputs::Base
|
351
|
+
include LogStash::PluginMixins::HttpClient[:with_deprecated => true]
|
352
|
+
config_name 'with_deprecated'
|
353
|
+
end
|
354
|
+
|
355
|
+
class PluginWithDeprecatedFalse < LogStash::Inputs::Base
|
356
|
+
include LogStash::PluginMixins::HttpClient[:with_deprecated => false]
|
357
|
+
config_name 'without_deprecated'
|
358
|
+
end
|
359
|
+
|
360
|
+
describe PluginWithNoModuleConfig do
|
361
|
+
let(:plugin_class) { PluginWithNoModuleConfig }
|
362
|
+
|
363
|
+
it_behaves_like 'a client with deprecated ssl options'
|
364
|
+
|
365
|
+
it 'includes DeprecatedSslConfigSupport module' do
|
366
|
+
expect(plugin_class.ancestors).to include(LogStash::PluginMixins::HttpClient::DeprecatedSslConfigSupport)
|
367
|
+
end
|
368
|
+
end
|
369
|
+
|
370
|
+
describe PluginWithDeprecatedFalse do
|
371
|
+
let(:plugin_class) { PluginWithDeprecatedFalse }
|
372
|
+
|
373
|
+
it_behaves_like 'a client with standardized ssl options'
|
374
|
+
|
375
|
+
it 'does not include DeprecatedSslConfigSupport module' do
|
376
|
+
expect(plugin_class.ancestors).to_not include(LogStash::PluginMixins::HttpClient::DeprecatedSslConfigSupport)
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
describe PluginWithDeprecatedTrue do
|
381
|
+
let(:plugin_class) { PluginWithDeprecatedTrue }
|
382
|
+
|
383
|
+
it_behaves_like 'a client with deprecated ssl options'
|
384
|
+
|
385
|
+
it_behaves_like 'a client with standardized ssl options'
|
386
|
+
|
387
|
+
context 'setting deprecate configs' do
|
388
|
+
let(:cacert) { Stud::Temporary.file.path }
|
389
|
+
let(:client_cert) { Stud::Temporary.file.path }
|
390
|
+
let(:client_key) { Stud::Temporary.file.path }
|
391
|
+
let(:keystore) { Stud::Temporary.file.path }
|
392
|
+
let(:keystore_type) { 'pkcs12' }
|
393
|
+
let(:keystore_password) { 'bar' }
|
394
|
+
let(:truststore) { Stud::Temporary.file.path }
|
395
|
+
let(:truststore_type) { 'pkcs12' }
|
396
|
+
let(:truststore_password) { 'foo' }
|
397
|
+
|
398
|
+
let(:settings) do
|
399
|
+
{
|
400
|
+
'cacert' => cacert,
|
401
|
+
'client_cert' => client_cert,
|
402
|
+
'client_key' => client_key,
|
403
|
+
'keystore' => keystore,
|
404
|
+
'keystore_password' => keystore_password,
|
405
|
+
'keystore_type' => keystore_type,
|
406
|
+
'truststore' => truststore,
|
407
|
+
'truststore_password' => truststore_password,
|
408
|
+
'truststore_type' => truststore_type
|
409
|
+
}
|
410
|
+
end
|
411
|
+
|
412
|
+
subject(:plugin_instance) { plugin_class.new(settings) }
|
413
|
+
|
414
|
+
after do
|
415
|
+
File.unlink(cacert)
|
416
|
+
File.unlink(client_cert)
|
417
|
+
File.unlink(client_key)
|
418
|
+
File.unlink(keystore)
|
419
|
+
File.unlink(truststore)
|
420
|
+
end
|
421
|
+
|
422
|
+
it 'normalizes deprecated settings' do
|
423
|
+
expect(plugin_instance.ssl_certificate_authorities).to eq([cacert])
|
424
|
+
expect(plugin_instance.ssl_certificate).to eq(client_cert)
|
425
|
+
expect(plugin_instance.ssl_key).to eq(client_key)
|
426
|
+
expect(plugin_instance.ssl_keystore_path).to eq(keystore)
|
427
|
+
expect(plugin_instance.ssl_keystore_password.value).to eq(keystore_password)
|
428
|
+
expect(plugin_instance.ssl_keystore_type).to eq(keystore_type)
|
429
|
+
expect(plugin_instance.ssl_truststore_path).to eq(truststore)
|
430
|
+
expect(plugin_instance.ssl_truststore_password.value).to eq(truststore_password)
|
431
|
+
expect(plugin_instance.ssl_truststore_type).to eq(truststore_type)
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
it 'includes DeprecatedSslConfigSupport module' do
|
436
|
+
expect(plugin_class.ancestors).to include(LogStash::PluginMixins::HttpClient::DeprecatedSslConfigSupport)
|
437
|
+
end
|
438
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: logstash-mixin-http_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.
|
4
|
+
version: 7.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elastic
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-08-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -64,6 +64,20 @@ dependencies:
|
|
64
64
|
- - "<"
|
65
65
|
- !ruby/object:Gem::Version
|
66
66
|
version: 1.0.0
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
requirement: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - "~>"
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '1.0'
|
73
|
+
name: logstash-mixin-normalize_config_support
|
74
|
+
prerelease: false
|
75
|
+
type: :runtime
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '1.0'
|
67
81
|
- !ruby/object:Gem::Dependency
|
68
82
|
requirement: !ruby/object:Gem::Requirement
|
69
83
|
requirements:
|
@@ -106,8 +120,10 @@ files:
|
|
106
120
|
- LICENSE
|
107
121
|
- README.md
|
108
122
|
- lib/logstash/plugin_mixins/http_client.rb
|
123
|
+
- lib/logstash/plugin_mixins/http_client/deprecated_ssl_config_support.rb
|
109
124
|
- logstash-mixin-http_client.gemspec
|
110
125
|
- spec/plugin_mixin/http_client_spec.rb
|
126
|
+
- spec/plugin_mixin/http_client_ssl_spec.rb
|
111
127
|
homepage: http://www.elastic.co/guide/en/logstash/current/index.html
|
112
128
|
licenses:
|
113
129
|
- Apache License (2.0)
|
@@ -127,9 +143,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
127
143
|
- !ruby/object:Gem::Version
|
128
144
|
version: '0'
|
129
145
|
requirements: []
|
130
|
-
rubygems_version: 3.
|
146
|
+
rubygems_version: 3.2.33
|
131
147
|
signing_key:
|
132
148
|
specification_version: 4
|
133
149
|
summary: AWS mixins to provide a unified interface for Amazon Webservice
|
134
150
|
test_files:
|
135
151
|
- spec/plugin_mixin/http_client_spec.rb
|
152
|
+
- spec/plugin_mixin/http_client_ssl_spec.rb
|