logstash-integration-rabbitmq 7.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +9 -0
  3. data/CONTRIBUTORS +27 -0
  4. data/Gemfile +11 -0
  5. data/LICENSE +13 -0
  6. data/NOTICE.TXT +5 -0
  7. data/README.md +98 -0
  8. data/docs/index.asciidoc +29 -0
  9. data/docs/input-rabbitmq.asciidoc +398 -0
  10. data/docs/output-rabbitmq.asciidoc +272 -0
  11. data/lib/logstash/inputs/rabbitmq.rb +317 -0
  12. data/lib/logstash/outputs/rabbitmq.rb +131 -0
  13. data/lib/logstash/plugin_mixins/rabbitmq_connection.rb +234 -0
  14. data/lib/logstash_registry.rb +7 -0
  15. data/logstash-integration-rabbitmq.gemspec +53 -0
  16. data/spec/fixtures/README.md +150 -0
  17. data/spec/fixtures/client/cert.pem +69 -0
  18. data/spec/fixtures/client/key.pem +27 -0
  19. data/spec/fixtures/client/keycert.p12 +0 -0
  20. data/spec/fixtures/client/req.pem +15 -0
  21. data/spec/fixtures/client_untrusted/cert.pem +19 -0
  22. data/spec/fixtures/client_untrusted/key.pem +28 -0
  23. data/spec/fixtures/client_untrusted/keycert.p12 +0 -0
  24. data/spec/fixtures/server/cert.pem +69 -0
  25. data/spec/fixtures/server/key.pem +27 -0
  26. data/spec/fixtures/server/key_password +1 -0
  27. data/spec/fixtures/server/keycert.p12 +0 -0
  28. data/spec/fixtures/server/rabbitmq.config +10 -0
  29. data/spec/fixtures/server/req.pem +15 -0
  30. data/spec/fixtures/testca/cacert.cer +0 -0
  31. data/spec/fixtures/testca/cacert.pem +17 -0
  32. data/spec/fixtures/testca/certs/01.pem +18 -0
  33. data/spec/fixtures/testca/certs/02.pem +18 -0
  34. data/spec/fixtures/testca/certs/05.pem +69 -0
  35. data/spec/fixtures/testca/certs/06.pem +69 -0
  36. data/spec/fixtures/testca/index.txt +4 -0
  37. data/spec/fixtures/testca/index.txt.attr +1 -0
  38. data/spec/fixtures/testca/index.txt.attr.old +1 -0
  39. data/spec/fixtures/testca/index.txt.old +3 -0
  40. data/spec/fixtures/testca/openssl.cnf +53 -0
  41. data/spec/fixtures/testca/private/cakey.pem +27 -0
  42. data/spec/fixtures/testca/serial +1 -0
  43. data/spec/fixtures/testca/serial.old +1 -0
  44. data/spec/inputs/rabbitmq_spec.rb +279 -0
  45. data/spec/outputs/rabbitmq_spec.rb +232 -0
  46. data/spec/plugin_mixins/rabbitmq_connection_spec.rb +175 -0
  47. metadata +256 -0
@@ -0,0 +1,131 @@
1
+ # encoding: UTF-8
2
+ require "logstash/pipeline"
3
+ require_relative '../plugin_mixins/rabbitmq_connection'
4
+ java_import java.util.concurrent.TimeoutException
5
+ java_import com.rabbitmq.client.AlreadyClosedException
6
+
7
+ require 'back_pressure'
8
+
9
+ # Push events to a RabbitMQ exchange. Requires RabbitMQ 2.x
10
+ # or later version (3.x is recommended).
11
+ #
12
+ # Relevant links:
13
+ #
14
+ # * http://www.rabbitmq.com/[RabbitMQ]
15
+ # * http://rubymarchhare.info[March Hare]
16
+ module LogStash
17
+ module Outputs
18
+ class RabbitMQ < LogStash::Outputs::Base
19
+ include LogStash::PluginMixins::RabbitMQConnection
20
+
21
+ config_name "rabbitmq"
22
+
23
+ concurrency :shared
24
+
25
+ # The default codec for this plugin is JSON. You can override this to suit your particular needs however.
26
+ default :codec, "json"
27
+
28
+ # Key to route to by default. Defaults to 'logstash'
29
+ #
30
+ # * Routing keys are ignored on fanout exchanges.
31
+ config :key, :validate => :string, :default => "logstash"
32
+
33
+ # The name of the exchange
34
+ config :exchange, :validate => :string, :required => true
35
+
36
+ # The exchange type (fanout, topic, direct)
37
+ config :exchange_type, :validate => EXCHANGE_TYPES, :required => true
38
+
39
+ # Is this exchange durable? (aka; Should it survive a broker restart?)
40
+ config :durable, :validate => :boolean, :default => true
41
+
42
+ # Should RabbitMQ persist messages to disk?
43
+ config :persistent, :validate => :boolean, :default => true
44
+
45
+ # Properties to be passed along with the message
46
+ config :message_properties, :validate => :hash, :default => {}
47
+
48
+ def register
49
+ connect!
50
+ @hare_info.exchange = declare_exchange!(@hare_info.channel, @exchange, @exchange_type, @durable)
51
+ # The connection close should close all channels, so it is safe to store thread locals here without closing them
52
+ @thread_local_channel = java.lang.ThreadLocal.new
53
+ @thread_local_exchange = java.lang.ThreadLocal.new
54
+
55
+ @gated_executor = back_pressure_provider_for_connection(@hare_info.connection)
56
+ end
57
+
58
+ def symbolize(myhash)
59
+ Hash[myhash.map{|(k,v)| [k.to_sym,v]}]
60
+ end
61
+
62
+ def multi_receive_encoded(events_and_data)
63
+ events_and_data.each do |event, data|
64
+ publish(event, data)
65
+ end
66
+ end
67
+
68
+ def publish(event, message)
69
+ raise ArgumentError, "No exchange set in HareInfo!!!" unless @hare_info.exchange
70
+ @gated_executor.execute do
71
+ local_exchange.publish(message, :routing_key => event.sprintf(@key), :properties => symbolize(@message_properties.merge(:persistent => @persistent)))
72
+ end
73
+ rescue MarchHare::Exception, IOError, AlreadyClosedException, TimeoutException => e
74
+ @logger.error("Error while publishing. Will retry.",
75
+ :message => e.message,
76
+ :exception => e.class,
77
+ :backtrace => e.backtrace)
78
+
79
+ sleep_for_retry
80
+ retry
81
+ end
82
+
83
+ def local_exchange
84
+ exchange = @thread_local_exchange.get
85
+ if !exchange
86
+ exchange = declare_exchange!(local_channel, @exchange, @exchange_type, @durable)
87
+ @thread_local_exchange.set(exchange)
88
+ end
89
+ exchange
90
+ end
91
+
92
+ def local_channel
93
+ channel = @thread_local_channel.get
94
+ if !channel
95
+ channel = @hare_info.connection.create_channel
96
+ @thread_local_channel.set(channel)
97
+ end
98
+ channel
99
+ end
100
+
101
+ def close
102
+ close_connection
103
+ end
104
+
105
+ private
106
+
107
+ # When the other end of a RabbitMQ connection is either unwilling or unable to continue reading bytes from
108
+ # its underlying TCP stream, the connection is flagged as "blocked", but attempts to publish onto exchanges
109
+ # using the connection will not block in the client.
110
+ #
111
+ # Here we hook into notifications of connection-blocked state to set up a `BackPressure::GatedExecutor`,
112
+ # which is used elsewhere to prevent runaway writes when publishing to an exchange on a blocked connection.
113
+ def back_pressure_provider_for_connection(march_hare_connection)
114
+ BackPressure::GatedExecutor.new(description: "RabbitMQ[#{self.id}]", logger: logger).tap do |executor|
115
+ march_hare_connection.on_blocked do |reason|
116
+ executor.engage_back_pressure("connection flagged as blocked: `#{reason}`")
117
+ end
118
+ march_hare_connection.on_unblocked do
119
+ executor.remove_back_pressure('connection flagged as unblocked')
120
+ end
121
+ march_hare_connection.on_recovery_started do
122
+ executor.engage_back_pressure("connection is being recovered")
123
+ end
124
+ march_hare_connection.on_recovery do
125
+ executor.remove_back_pressure('connection recovered')
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,234 @@
1
+ # encoding: utf-8
2
+ require "logstash/namespace"
3
+ require "march_hare"
4
+ require "java"
5
+
6
+ # Common functionality for the rabbitmq input/output
7
+ module LogStash
8
+ module PluginMixins
9
+ module RabbitMQConnection
10
+ EXCHANGE_TYPES = ["fanout", "direct", "topic", "x-consistent-hash", "x-modulus-hash"]
11
+
12
+ HareInfo = Struct.new(:connection, :channel, :exchange, :queue)
13
+
14
+ def self.included(base)
15
+ base.extend(self)
16
+ base.setup_rabbitmq_connection_config
17
+ end
18
+
19
+ def setup_rabbitmq_connection_config
20
+ # RabbitMQ server address(es)
21
+ # host can either be a single host, or a list of hosts
22
+ # i.e.
23
+ # host => "localhost"
24
+ # or
25
+ # host => ["host01", "host02]
26
+ #
27
+ # if multiple hosts are provided on the initial connection and any subsequent
28
+ # recovery attempts of the hosts is chosen at random and connected to.
29
+ # Note that only one host connection is active at a time.
30
+ config :host, :validate => :string, :required => true , :list => true
31
+
32
+ # RabbitMQ port to connect on
33
+ config :port, :validate => :number, :default => 5672
34
+
35
+ # RabbitMQ username
36
+ config :user, :validate => :string, :default => "guest"
37
+
38
+ # RabbitMQ password
39
+ config :password, :validate => :password, :default => "guest"
40
+
41
+ # The vhost (virtual host) to use. If you don't know what this
42
+ # is, leave the default. With the exception of the default
43
+ # vhost ("/"), names of vhosts should not begin with a forward
44
+ # slash.
45
+ config :vhost, :validate => :string, :default => "/"
46
+
47
+ # Enable or disable SSL.
48
+ # Note that by default remote certificate verification is off.
49
+ # Specify ssl_certificate_path and ssl_certificate_password if you need
50
+ # certificate verification
51
+ config :ssl, :validate => :boolean
52
+
53
+ # Version of the SSL protocol to use.
54
+ config :ssl_version, :validate => :string, :default => "TLSv1.2"
55
+
56
+ config :verify_ssl, :validate => :boolean, :default => false,
57
+ :obsolete => "This function did not actually function correctly and was removed." +
58
+ "If you wish to validate SSL certs use the ssl_certificate_path and ssl_certificate_password options."
59
+
60
+ # Path to an SSL certificate in PKCS12 (.p12) format used for verifying the remote host
61
+ config :ssl_certificate_path, :validate => :path
62
+
63
+ # Password for the encrypted PKCS12 (.p12) certificate file specified in ssl_certificate_path
64
+ config :ssl_certificate_password, :validate => :password
65
+
66
+ config :debug, :validate => :boolean, :obsolete => "Use the logstash --debug flag for this instead."
67
+
68
+ # Set this to automatically recover from a broken connection. You almost certainly don't want to override this!!!
69
+ config :automatic_recovery, :validate => :boolean, :default => true
70
+
71
+ # Time in seconds to wait before retrying a connection
72
+ config :connect_retry_interval, :validate => :number, :default => 1
73
+
74
+ # The default connection timeout in milliseconds. If not specified the timeout is infinite.
75
+ config :connection_timeout, :validate => :number
76
+
77
+ # Heartbeat delay in seconds. If unspecified no heartbeats will be sent
78
+ config :heartbeat, :validate => :number
79
+
80
+ # Passive queue creation? Useful for checking queue existance without modifying server state
81
+ config :passive, :validate => :boolean, :default => false
82
+
83
+ # TLS certifcate path
84
+ config :tls_certificate_path, :validate => :path, :obsolete => "This setting is obsolete. Use ssl_certificate_path instead"
85
+
86
+ # TLS certificate password
87
+ config :tls_certificate_password, :validate => :string, :obsolete => "This setting is obsolete. Use ssl_certificate_password instead"
88
+
89
+ # Extra queue arguments as an array.
90
+ # To make a RabbitMQ queue mirrored, use: `{"x-ha-policy" => "all"}`
91
+ config :arguments, :validate => :array, :default => {}
92
+ end
93
+
94
+ def conn_str
95
+ "amqp://#{@user}@#{@host}:#{@port}#{@vhost}"
96
+ end
97
+
98
+ def close_connection
99
+ @rabbitmq_connection_stopping = true
100
+ @hare_info.channel.close if channel_open?
101
+ @hare_info.connection.close if connection_open?
102
+ end
103
+
104
+ def rabbitmq_settings
105
+ return @rabbitmq_settings if @rabbitmq_settings
106
+
107
+ s = {
108
+ :vhost => @vhost,
109
+ :hosts => @host,
110
+ :port => @port,
111
+ :user => @user,
112
+ :automatic_recovery => @automatic_recovery,
113
+ :pass => @password ? @password.value : "guest",
114
+ }
115
+
116
+ s[:timeout] = @connection_timeout || 0
117
+ s[:heartbeat] = @heartbeat || 0
118
+
119
+ if @ssl
120
+ s[:tls] = @ssl_version
121
+
122
+ cert_path = @ssl_certificate_path
123
+ cert_pass = @ssl_certificate_password.value if @ssl_certificate_password
124
+
125
+ if !!cert_path ^ !!cert_pass
126
+ raise LogStash::ConfigurationError, "RabbitMQ requires both ssl_certificate_path AND ssl_certificate_password to be set!"
127
+ end
128
+
129
+ s[:tls_certificate_path] = cert_path
130
+ s[:tls_certificate_password] = cert_pass
131
+ end
132
+
133
+ @rabbitmq_settings = s
134
+ end
135
+
136
+ def connect!
137
+ @hare_info = connect() unless @hare_info # Don't duplicate the conn!
138
+ rescue MarchHare::Exception, java.io.IOException => e
139
+ error_message = if e.message.empty? && e.is_a?(java.io.IOException)
140
+ # IOException with an empty message is probably an instance of
141
+ # these problems:
142
+ # https://github.com/logstash-plugins/logstash-output-rabbitmq/issues/52
143
+ # https://github.com/rabbitmq/rabbitmq-java-client/issues/100
144
+ #
145
+ # Best guess is to help the user understand that there is probably
146
+ # some kind of configuration problem causing the error, but we
147
+ # can't really offer any more detailed hints :\
148
+ "An unknown error occurred. RabbitMQ gave no hints as to the cause. Maybe this is a configuration error (invalid vhost, for example). I recommend checking the RabbitMQ server logs for clues about this failure."
149
+ else
150
+ e.message
151
+ end
152
+
153
+ if @logger.debug?
154
+ @logger.error("RabbitMQ connection error, will retry.",
155
+ :error_message => error_message,
156
+ :exception => e.class.name,
157
+ :backtrace => e.backtrace)
158
+ else
159
+ @logger.error("RabbitMQ connection error, will retry.",
160
+ :error_message => error_message,
161
+ :exception => e.class.name)
162
+ end
163
+
164
+ sleep_for_retry
165
+ retry
166
+ end
167
+
168
+ def channel_open?
169
+ @hare_info && @hare_info.channel && @hare_info.channel.open?
170
+ end
171
+
172
+ def connection_open?
173
+ @hare_info && @hare_info.connection && @hare_info.connection.open?
174
+ end
175
+
176
+ def connected?
177
+ return nil unless @hare_info && @hare_info.connection
178
+ @hare_info.connection.connected?
179
+ end
180
+
181
+ private
182
+
183
+ def declare_exchange!(channel, exchange, exchange_type, durable)
184
+ @logger.debug? && @logger.debug("Declaring an exchange", :name => exchange,
185
+ :type => exchange_type, :durable => durable)
186
+ exchange = channel.exchange(exchange, :type => exchange_type.to_sym, :durable => durable)
187
+ @logger.debug? && @logger.debug("Exchange declared")
188
+ exchange
189
+ rescue StandardError => e
190
+ @logger.error("Could not declare exchange!",
191
+ :exchange => exchange, :type => exchange_type,
192
+ :durable => durable, :error_class => e.class.name,
193
+ :error_message => e.message, :backtrace => e.backtrace)
194
+ raise e
195
+ end
196
+
197
+ def connect
198
+ @logger.debug? && @logger.debug("Connecting to RabbitMQ. Settings: #{rabbitmq_settings.inspect}")
199
+
200
+ connection = MarchHare.connect(rabbitmq_settings)
201
+
202
+ connection.on_shutdown do |conn, cause|
203
+ @logger.warn("RabbitMQ connection was closed!",
204
+ :url => connection_url(conn),
205
+ :automatic_recovery => @automatic_recovery,
206
+ :cause => cause)
207
+ end
208
+ connection.on_blocked do
209
+ @logger.warn("RabbitMQ connection blocked! Check your RabbitMQ instance!",
210
+ :url => connection_url(connection))
211
+ end
212
+ connection.on_unblocked do
213
+ @logger.warn("RabbitMQ connection unblocked!", :url => connection_url(connection))
214
+ end
215
+
216
+ channel = connection.create_channel
217
+ @logger.info("Connected to RabbitMQ at #{rabbitmq_settings[:host]}")
218
+
219
+ HareInfo.new(connection, channel)
220
+ end
221
+
222
+ # Mostly used for printing debug logs
223
+ def connection_url(connection)
224
+ user_pass = connection.user ? "#{connection.user}:XXXXXX@" : ""
225
+ protocol = params["ssl"] ? "amqps" : "amqp"
226
+ "#{protocol}://#{user_pass}#{connection.host}:#{connection.port}#{connection.vhost}"
227
+ end
228
+
229
+ def sleep_for_retry
230
+ Stud.stoppable_sleep(@connect_retry_interval) { @rabbitmq_connection_stopping }
231
+ end
232
+ end
233
+ end
234
+ end
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+ require "logstash/plugins/registry"
3
+ require "logstash/inputs/rabbitmq"
4
+ require "logstash/outputs/rabbitmq"
5
+
6
+ LogStash::PLUGIN_REGISTRY.add(:input, "rabbitmq", LogStash::Inputs::RabbitMQ)
7
+ LogStash::PLUGIN_REGISTRY.add(:output, "rabbitmq", LogStash::Outputs::RabbitMQ)
@@ -0,0 +1,53 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'logstash-integration-rabbitmq'
3
+ s.version = '7.0.0'
4
+ s.licenses = ['Apache License (2.0)']
5
+ s.summary = "Integration with RabbitMQ - input and output plugins"
6
+ s.description = "This gem is a Logstash plugin required to be installed on top of the Logstash core pipeline "+
7
+ "using $LS_HOME/bin/logstash-plugin install gemname. This gem is not a stand-alone program."
8
+ s.authors = ["Elastic"]
9
+ s.email = 'info@elastic.co'
10
+ s.homepage = "http://www.elastic.co/guide/en/logstash/current/index.html"
11
+ s.require_paths = ["lib"]
12
+
13
+ # Files
14
+ s.files = Dir.glob(%w(
15
+ lib/**/*
16
+ spec/**/*
17
+ *.gemspec
18
+ *.md
19
+ CONTRIBUTORS
20
+ Gemfile
21
+ LICENSE
22
+ NOTICE.TXT
23
+ vendor/jar-dependencies/**/*.jar
24
+ vendor/jar-dependencies/**/*.rb
25
+ VERSION docs/**/*
26
+ ))
27
+
28
+ # Tests
29
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
30
+
31
+ # Special flag to let us know this is actually a logstash plugin
32
+ s.metadata = {
33
+ "logstash_plugin" => "true",
34
+ "logstash_group" => "integration",
35
+ "integration_plugins" => "logstash-input-rabbitmq,logstash-output-rabbitmq"
36
+ }
37
+
38
+ s.platform = RUBY_PLATFORM
39
+
40
+ # Gem dependencies
41
+ s.add_runtime_dependency "logstash-core-plugin-api", ">= 1.60", "<= 2.99"
42
+ s.add_runtime_dependency "logstash-core", ">= 6.5.0"
43
+
44
+ s.add_runtime_dependency 'logstash-codec-json'
45
+
46
+ s.add_runtime_dependency 'march_hare', ['~> 4.0'] #(MIT license)
47
+ s.add_runtime_dependency 'stud', '~> 0.0.22'
48
+ s.add_runtime_dependency 'back_pressure', '~> 1.0'
49
+
50
+ s.add_development_dependency 'logstash-devutils'
51
+ s.add_development_dependency 'logstash-input-generator'
52
+ s.add_development_dependency 'logstash-codec-plain'
53
+ end
@@ -0,0 +1,150 @@
1
+ # TLS Testing notes
2
+
3
+ Currently all TLS integration style testing is manual. This fixture may be used to help test.
4
+
5
+ * client - has the key store with client public/private key and the server public key
6
+ * server - has the key store with server public/private key and the client public key
7
+ * client_untrusted - has a keystore with public/private key that is self signed
8
+
9
+ logstash config
10
+ ---------
11
+ ```
12
+ input {
13
+ rabbitmq {
14
+ host => "localhost"
15
+ port => 5671
16
+ queue => "hello"
17
+ codec => plain
18
+ ssl => true
19
+ ssl_certificate_path => "/Users/jake/workspace/plugins/logstash-mixin-rabbitmq_connection/spec/fixtures/client/keycert.p12"
20
+ ssl_certificate_password => "MySecretPassword"
21
+ }
22
+ }
23
+
24
+ output{ stdout { codec => rubydebug } }
25
+ ```
26
+
27
+ rabbit mq install
28
+ --------
29
+ (mac)
30
+
31
+ ```
32
+ brew install rabbitmq
33
+ export PATH=$PATH:/usr/local/sbin
34
+ vim /usr/local/etc/rabbitmq/rabbitmq.config
35
+
36
+ ```
37
+ ```
38
+ [
39
+ {rabbit, [
40
+ {ssl_listeners, [5671]},
41
+ {ssl_options, [{cacertfile,"/Users/jake/workspace/plugins/logstash-mixin-rabbitmq_connection/spec/fixtures/testca/cacert.pem"},
42
+ {certfile,"/Users/jake/workspace/plugins/logstash-mixin-rabbitmq_connection/spec/fixtures/server/cert.pem"},
43
+ {keyfile,"/Users/jake/workspace/plugins/logstash-mixin-rabbitmq_connection/spec/fixtures/server/key.pem"},
44
+ {verify,verify_peer},
45
+ {fail_if_no_peer_cert,false}]}
46
+ ]}
47
+ ].
48
+ ```
49
+ ```
50
+ export PATH=$PATH:/usr/local/sbin
51
+ rabbitmq-server
52
+ tail -f /usr/local/var/log/rabbitmq/rabbit@localhost.log
53
+ ```
54
+
55
+ sending a test message with ruby
56
+ ----------
57
+ https://www.rabbitmq.com/tutorials/tutorial-one-ruby.html
58
+
59
+ ```
60
+ gem install bunny --version ">= 2.6.4"
61
+ ```
62
+ Create a file called send.rb
63
+ ```
64
+ #!/usr/bin/env ruby
65
+ # encoding: utf-8
66
+
67
+ require "bunny"
68
+
69
+ conn = Bunny.new(:automatically_recover => false)
70
+ conn.start
71
+
72
+ ch = conn.create_channel
73
+ q = ch.queue("hello")
74
+
75
+ ch.default_exchange.publish("Test message", :routing_key => q.name)
76
+ puts "Message sent'"
77
+
78
+ conn.close
79
+ ```
80
+ Send the message with Logstash running as the consumer
81
+ ```
82
+ ruby send.rb
83
+ ```
84
+
85
+ password for all files
86
+ --------
87
+ MySecretPassword
88
+
89
+ start from testca dir
90
+ ---------
91
+ ```
92
+ cd testca
93
+ ```
94
+
95
+ client
96
+ -------
97
+ ```
98
+ openssl genrsa -out ../client/key.pem 2048
99
+ openssl req -config openssl.cnf -key ../client/key.pem -new -sha256 -out ../client/req.pem
100
+ # for hostname use localhost, O=client
101
+ openssl ca -config openssl.cnf -in ../client/req.pem -out ../client/cert.pem
102
+ openssl x509 -in ../client/cert.pem -text -noout
103
+ openssl pkcs12 -export -out ../client/keycert.p12 -inkey ../client/key.pem -in ../client/cert.pem
104
+ ```
105
+
106
+ server
107
+ -------
108
+ ```
109
+ openssl genrsa -out ../server/key.pem 2048
110
+ openssl req -config openssl.cnf -key ../server/key.pem -new -sha256 -out ../server/req.pem
111
+ # for hostname use localhost, O=server
112
+ openssl ca -config openssl.cnf -in ../server/req.pem -out ../server/cert.pem
113
+ openssl x509 -in ../server/cert.pem -text -noout
114
+ openssl pkcs12 -export -out ../server/keycert.p12 -inkey ../server/key.pem -in ../server/cert.pem
115
+ ```
116
+
117
+ establish trust
118
+ ----------
119
+ ```
120
+ cd server
121
+ keytool -import -file ../client/cert.pem -alias client_cert -keystore keycert.p12
122
+ cd client
123
+ keytool -import -file ../server/cert.pem -alias server_cert -keystore keycert.p12
124
+ ```
125
+
126
+ reading
127
+ -----------
128
+ ```
129
+ openssl x509 -in cert.pem -text -noout
130
+ keytool -list -v -keystore keycert.p12
131
+ ```
132
+
133
+ self signed cert (untrusted)
134
+ -------
135
+ ```
136
+ openssl req -x509 -batch -nodes -newkey rsa:2048 -keyout key.pem -out cert.pem -subj "/CN=localhost, O=client" -days 10000
137
+ openssl pkcs12 -export -out keycert.p12 -inkey key.pem -in cert.pem
138
+
139
+ ```
140
+
141
+ Issue [44](https://github.com/logstash-plugins/logstash-mixin-rabbitmq_connection/issues/44) validation
142
+ ---------
143
+ configure Logstash to the untrusted cert :`ssl_certificate_path => "/Users/jake/workspace/plugins/logstash-mixin-rabbitmq_connection/spec/fixtures/client_untrusted/keycert.p12"`
144
+
145
+ This _SHOULD_ fail an error like the following:
146
+ ```
147
+ Using TLS/SSL version TLSv1.2
148
+ [2017-12-19T12:47:12,891][ERROR][logstash.inputs.rabbitmq ] RabbitMQ connection error, will retry. {:error_message=>"sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target", :exception=>"Java::JavaxNetSsl::SSLHandshakeException"}
149
+ ```
150
+ There should _NOT_ be any warnings about a NullTrustManager or disabling verification, and you should _NOT_ be able to send messages.