fluent-plugin-syslog-tls-long-timeout 0.6.0 → 2.0.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 +30 -6
- data/Gemfile.lock +44 -45
- data/README.md +4 -12
- data/docs/configuration.md +16 -6
- data/fluent-plugin-syslog-tls.gemspec +7 -8
- data/lib/fluent/plugin/out_syslog_tls.rb +36 -20
- data/lib/syslog_tls/protocol.rb +8 -3
- data/lib/syslog_tls/ssl_transport.rb +110 -11
- data/lib/syslog_tls/version.rb +2 -2
- data/test/fluent/test_out_syslog_tls.rb +33 -41
- data/test/helper.rb +0 -6
- data/test/syslog_tls/test_ssl_transport.rb +2 -2
- metadata +20 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5a1ddda33cd3b20fd4d0fd9b8afa1fa1a223bcf3
|
4
|
+
data.tar.gz: fed039db676f7d7ad542afb25be5715c1455be72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ade57f3044da97a10e90cb9084a4e778cc5e363291b5987701ba2f96ec026779b271da607d6ce00dd77181c5a005feeb073239c63ac810e4e547fb6cd5d0522c
|
7
|
+
data.tar.gz: 7e3480a90714b3070ebbaa9c387e9e3e61175660070e7a53daa679bcbd9d5c6251228180a884f6ddb0f62e13f1e7c6ba453ca965d6ae950db5a638cfc5a58fca
|
data/CHANGELOG.md
CHANGED
@@ -1,17 +1,41 @@
|
|
1
|
-
|
1
|
+
#### 2.0.0
|
2
2
|
|
3
|
-
|
4
|
-
*
|
5
|
-
|
3
|
+
* Require Ruby 2.4
|
4
|
+
* Support SNI and enable cert name verification by default. **This changes the default behavior** and may cause issues if the remote server's cert does not match the configured hostname.
|
5
|
+
* Add `verify_cert_name` to enable (default) or disable cert name verification.
|
6
|
+
Note: `ca_cert` verifies the certificate signing chain. `verify_cert_name` verifies the CN/SAN name on the cert.
|
6
7
|
|
7
8
|
|
8
|
-
####
|
9
|
+
#### 1.2.1
|
10
|
+
|
11
|
+
* Support Fluentd 1.0 (same API as 0.14).
|
12
|
+
|
13
|
+
|
14
|
+
#### 1.2.0
|
15
|
+
|
16
|
+
* Improve compliance with Fluentd 0.14 API.
|
17
|
+
* Eliminate excess Message#header object creation.
|
18
|
+
|
19
|
+
|
20
|
+
#### 1.1.0
|
9
21
|
|
10
|
-
|
22
|
+
* Renamed `cert` and `key` to `client_cert` and `client_key` respectively.
|
23
|
+
* Change to short timeouts on network calls so logging doesn't go dead for extended periods.
|
24
|
+
* Added `idle_timeout` to force upstream reconnection after a period of time with no traffic for a particular tag. Useful for low-traffic senders. Not recommended for high-traffic.
|
25
|
+
* Added `ca_cert` to validate the remote certificate. Defaults to 'system' which uses the system certificate store.
|
26
|
+
|
27
|
+
|
28
|
+
#### 1.0.0
|
11
29
|
|
12
30
|
* Standard fluent formatting plugins are supported. Json output remains the default.
|
13
31
|
* `token` (Structured Data in syslog terms) is now optional, for syslog hosts that don't require it.
|
14
32
|
* Message payload in the syslog packet no longer duplicates Time or includes Tag by default.
|
33
|
+
* Requires Fluent 0.14.
|
34
|
+
|
35
|
+
|
36
|
+
#### 0.5.0
|
37
|
+
|
38
|
+
Comparable to v1.0.0, but compatible with Fluent 0.12.
|
15
39
|
|
16
40
|
|
17
41
|
#### < 0.2.0
|
data/Gemfile.lock
CHANGED
@@ -1,72 +1,71 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
fluent-plugin-syslog-tls (0.
|
5
|
-
|
6
|
-
fluentd (~> 0.12.0)
|
4
|
+
fluent-plugin-syslog-tls (2.0.0)
|
5
|
+
fluentd (>= 0.14.0, < 2)
|
7
6
|
|
8
7
|
GEM
|
9
8
|
remote: https://rubygems.org/
|
10
9
|
specs:
|
11
|
-
addressable (2.
|
12
|
-
public_suffix (
|
13
|
-
cool.io (1.5.
|
14
|
-
coveralls (0.8.
|
10
|
+
addressable (2.6.0)
|
11
|
+
public_suffix (>= 2.0.2, < 4.0)
|
12
|
+
cool.io (1.5.4)
|
13
|
+
coveralls (0.8.23)
|
15
14
|
json (>= 1.8, < 3)
|
16
|
-
simplecov (~> 0.
|
15
|
+
simplecov (~> 0.16.1)
|
17
16
|
term-ansicolor (~> 1.3)
|
18
|
-
thor (
|
17
|
+
thor (>= 0.19.4, < 2.0)
|
19
18
|
tins (~> 1.6)
|
20
19
|
crack (0.4.3)
|
21
20
|
safe_yaml (~> 1.0.0)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
cool.io (>= 1.2.2, < 2.0.0)
|
21
|
+
dig_rb (1.0.1)
|
22
|
+
docile (1.3.1)
|
23
|
+
fluentd (1.5.0)
|
24
|
+
cool.io (>= 1.4.5, < 2.0.0)
|
25
|
+
dig_rb (~> 1.0.0)
|
28
26
|
http_parser.rb (>= 0.5.1, < 0.7.0)
|
29
|
-
|
30
|
-
|
27
|
+
msgpack (>= 0.7.0, < 2.0.0)
|
28
|
+
serverengine (>= 2.0.4, < 3.0.0)
|
31
29
|
sigdump (~> 0.2.2)
|
32
|
-
|
33
|
-
tzinfo (
|
34
|
-
tzinfo-data (
|
30
|
+
strptime (>= 0.2.2, < 1.0.0)
|
31
|
+
tzinfo (~> 1.0)
|
32
|
+
tzinfo-data (~> 1.0)
|
35
33
|
yajl-ruby (~> 1.0)
|
36
|
-
hashdiff (0.
|
34
|
+
hashdiff (0.4.0)
|
37
35
|
http_parser.rb (0.6.0)
|
38
|
-
json (2.
|
39
|
-
minitest (5.
|
40
|
-
minitest-stub_any_instance (1.0.
|
41
|
-
msgpack (1.
|
42
|
-
power_assert (1.
|
43
|
-
public_suffix (
|
44
|
-
rake (
|
45
|
-
safe_yaml (1.0.
|
36
|
+
json (2.2.0)
|
37
|
+
minitest (5.11.3)
|
38
|
+
minitest-stub_any_instance (1.0.2)
|
39
|
+
msgpack (1.2.10)
|
40
|
+
power_assert (1.1.4)
|
41
|
+
public_suffix (3.1.0)
|
42
|
+
rake (12.3.2)
|
43
|
+
safe_yaml (1.0.5)
|
44
|
+
serverengine (2.1.1)
|
45
|
+
sigdump (~> 0.2.2)
|
46
46
|
sigdump (0.2.4)
|
47
|
-
simplecov (0.
|
48
|
-
docile (~> 1.1
|
47
|
+
simplecov (0.16.1)
|
48
|
+
docile (~> 1.1)
|
49
49
|
json (>= 1.8, < 3)
|
50
50
|
simplecov-html (~> 0.10.0)
|
51
|
-
simplecov-html (0.10.
|
52
|
-
|
53
|
-
term-ansicolor (1.
|
51
|
+
simplecov-html (0.10.2)
|
52
|
+
strptime (0.2.3)
|
53
|
+
term-ansicolor (1.7.1)
|
54
54
|
tins (~> 1.0)
|
55
|
-
test-unit (3.
|
55
|
+
test-unit (3.3.3)
|
56
56
|
power_assert
|
57
|
-
thor (0.
|
57
|
+
thor (0.20.3)
|
58
58
|
thread_safe (0.3.6)
|
59
|
-
tins (1.
|
60
|
-
tzinfo (1.2.
|
59
|
+
tins (1.20.3)
|
60
|
+
tzinfo (1.2.5)
|
61
61
|
thread_safe (~> 0.1)
|
62
|
-
tzinfo-data (1.
|
62
|
+
tzinfo-data (1.2019.1)
|
63
63
|
tzinfo (>= 1.0.0)
|
64
|
-
|
65
|
-
webmock (2.3.2)
|
64
|
+
webmock (3.5.1)
|
66
65
|
addressable (>= 2.3.6)
|
67
66
|
crack (>= 0.3.2)
|
68
67
|
hashdiff
|
69
|
-
yajl-ruby (1.
|
68
|
+
yajl-ruby (1.4.1)
|
70
69
|
|
71
70
|
PLATFORMS
|
72
71
|
ruby
|
@@ -76,10 +75,10 @@ DEPENDENCIES
|
|
76
75
|
fluent-plugin-syslog-tls!
|
77
76
|
minitest (~> 5.8)
|
78
77
|
minitest-stub_any_instance (~> 1.0.0)
|
79
|
-
rake
|
78
|
+
rake
|
80
79
|
simplecov (~> 0.11)
|
81
80
|
test-unit (~> 3.1)
|
82
|
-
webmock (~>
|
81
|
+
webmock (~> 3.0)
|
83
82
|
|
84
83
|
BUNDLED WITH
|
85
|
-
1.
|
84
|
+
1.17.3
|
data/README.md
CHANGED
@@ -10,14 +10,14 @@ Tested with [Papertrail](https://papertrailapp.com) and should also work with [S
|
|
10
10
|
## Installation
|
11
11
|
|
12
12
|
```sh
|
13
|
-
$ gem install fluent-plugin-syslog-tls
|
13
|
+
$ gem install fluent-plugin-syslog-tls
|
14
14
|
```
|
15
15
|
or
|
16
16
|
```sh
|
17
|
-
$ td-agent-gem install fluent-plugin-syslog-tls
|
17
|
+
$ td-agent-gem install fluent-plugin-syslog-tls
|
18
18
|
```
|
19
19
|
|
20
|
-
|
20
|
+
Note: `fluent-plugin-syslog-tls` is compatible with Fluent 1.0 (and 0.14). For Fluent 0.12, see the `fluent-0.12` branch.
|
21
21
|
|
22
22
|
|
23
23
|
## Configuration
|
@@ -48,17 +48,9 @@ Papertrail:
|
|
48
48
|
For more configuration options see [configuration docs](docs/configuration.md)
|
49
49
|
|
50
50
|
|
51
|
-
## Version Compatibility
|
52
|
-
|
53
|
-
* v0.x.x of this plugin is compatible with the Fluentd 0.12 series.
|
54
|
-
* v1.x.x of this plugin is compatible with the Fluentd 0.14 series.
|
55
|
-
|
56
|
-
Note that the v1.x series has more features and is more robust than the v0.x series.
|
57
|
-
|
58
|
-
|
59
51
|
## Origin/History
|
60
52
|
|
61
|
-
This plugin is derived from [Fluent::Plugin::SumologicCloudSyslog](https://github.com/acquia/fluent-plugin-sumologic-cloud-syslog). Changes
|
53
|
+
This plugin is derived from [Fluent::Plugin::SumologicCloudSyslog](https://github.com/acquia/fluent-plugin-sumologic-cloud-syslog). Changes are in the [Changelog](CHANGELOG.md).
|
62
54
|
|
63
55
|
|
64
56
|
## License
|
data/docs/configuration.md
CHANGED
@@ -15,23 +15,31 @@ Host represents DNS name of endpoint where should be data sent. Example: `syslog
|
|
15
15
|
|
16
16
|
Example: `6514`
|
17
17
|
|
18
|
+
### idle_timeout
|
19
|
+
|
20
|
+
If a given tag has gone this many seconds between log messages, disconnect and reconnect before sending logs. Useful in low-traffic logging situations with remote hosts that disconnect after a period of time. Disabled by default. Example: `600`
|
21
|
+
|
18
22
|
### ca_cert
|
19
23
|
|
20
|
-
Whether and how to verify the server's TLS certificate. Examples:
|
24
|
+
Whether and how to verify the server's TLS certificate signing chain. Examples:
|
21
25
|
* ca_cert system - Default; use the system CA certificate store (which must then be configured correctly)
|
22
26
|
* ca_cert false - Disable verification; not recommended
|
23
27
|
* ca_cert /path/to/file - A path+filename to a single CA file
|
24
28
|
* ca_cert /path/to/dir/ - A directory of CA files (in format that OpenSSL can parse); must end with /
|
25
29
|
|
30
|
+
### verify_cert_name
|
31
|
+
|
32
|
+
Whether to verify that the server's cert matches `host`. Enabled by default (except when `ca_cert false`). Recommended; helps prevent MitM attacks. Example: `true`
|
33
|
+
|
26
34
|
### token
|
27
35
|
|
28
36
|
Some services require a token to identify the account. Example: `ABABABABABABA@99999`. Not required for Papertrail.
|
29
37
|
|
30
|
-
###
|
38
|
+
### client_cert
|
31
39
|
|
32
40
|
Optionally path to client certificate for TLS connection. Example: `/path/to/crt/file.crt`
|
33
41
|
|
34
|
-
###
|
42
|
+
### client_key
|
35
43
|
|
36
44
|
Optionally path to client private key for TLS connection. Example: `/path/to/key/file.key`
|
37
45
|
|
@@ -80,6 +88,7 @@ Optionally record key where to get msgid from the record. If not provided nil va
|
|
80
88
|
@type syslog_tls
|
81
89
|
host logs1.papertrailapp.com
|
82
90
|
port 12345
|
91
|
+
idle_timeout 720
|
83
92
|
|
84
93
|
hostname static-hostname
|
85
94
|
facility SYSLOG
|
@@ -95,7 +104,7 @@ Optionally record key where to get msgid from the record. If not provided nil va
|
|
95
104
|
msgid_key ...
|
96
105
|
|
97
106
|
# Fluent's standard formatting options are supported. Default is 'json'.
|
98
|
-
# Example: For Docker logs sent to Papertrail,
|
107
|
+
# Example: For Docker logs sent to Papertrail, send only the log text:
|
99
108
|
format single_value
|
100
109
|
message_key log
|
101
110
|
</match>
|
@@ -107,8 +116,9 @@ Optionally record key where to get msgid from the record. If not provided nil va
|
|
107
116
|
host syslog.collection.us1.sumologic.com
|
108
117
|
port 6514
|
109
118
|
token [token]@[iana-id]
|
110
|
-
|
111
|
-
|
119
|
+
client_cert /path/to/cert/file.crt
|
120
|
+
client_key /path/to/key/file.key
|
121
|
+
verify_cert_name true
|
112
122
|
|
113
123
|
hostname static-hostname
|
114
124
|
facility SYSLOG
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Copyright 2016 Acquia, Inc.
|
2
|
-
# Copyright 2016 t.e.morgan.
|
2
|
+
# Copyright 2016-2019 t.e.morgan.
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
# you may not use this file except in compliance with the License.
|
@@ -20,8 +20,8 @@ require 'syslog_tls/version'
|
|
20
20
|
Gem::Specification.new do |s|
|
21
21
|
s.name = 'fluent-plugin-syslog-tls-long-timeout'
|
22
22
|
s.version = SyslogTls::VERSION
|
23
|
-
s.authors = ['thomas morgan']
|
24
|
-
s.email = ['tm@iprog.com']
|
23
|
+
s.authors = ['thomas morgan', 'lukasz stanik']
|
24
|
+
s.email = ['tm@iprog.com', 'stanik.lukasz@outlook.com']
|
25
25
|
s.summary = %q{Fluent Syslog TLS output plugin}
|
26
26
|
s.description = %q{Syslog TLS output plugin with formatting support, for Fluentd}
|
27
27
|
s.homepage = 'https://github.com/zarqman/fluent-plugin-syslog-tls'
|
@@ -30,15 +30,14 @@ Gem::Specification.new do |s|
|
|
30
30
|
s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
31
31
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
32
32
|
s.require_paths = ['lib']
|
33
|
-
s.required_ruby_version = '>= 2.
|
33
|
+
s.required_ruby_version = '>= 2.4'
|
34
34
|
|
35
|
-
s.add_runtime_dependency 'fluentd',
|
36
|
-
s.add_runtime_dependency 'fluent-mixin-config-placeholders', '~> 0.3'
|
35
|
+
s.add_runtime_dependency 'fluentd', [">= 0.14.0", "< 2"]
|
37
36
|
|
38
37
|
s.add_development_dependency 'minitest', '~> 5.8'
|
39
38
|
s.add_development_dependency 'minitest-stub_any_instance', '~> 1.0.0'
|
40
|
-
s.add_development_dependency 'rake'
|
39
|
+
s.add_development_dependency 'rake'
|
41
40
|
s.add_development_dependency 'test-unit', '~> 3.1'
|
42
|
-
s.add_development_dependency 'webmock', '~>
|
41
|
+
s.add_development_dependency 'webmock', '~> 3.0'
|
43
42
|
s.add_development_dependency 'simplecov', '~> 0.11'
|
44
43
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Copyright 2016 Acquia, Inc.
|
2
|
-
# Copyright 2016 t.e.morgan.
|
2
|
+
# Copyright 2016-2019 t.e.morgan.
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
# you may not use this file except in compliance with the License.
|
@@ -13,26 +13,28 @@
|
|
13
13
|
# See the License for the specific language governing permissions and
|
14
14
|
# limitations under the License.
|
15
15
|
|
16
|
-
require 'fluent/mixin/config_placeholders'
|
17
16
|
require 'socket'
|
17
|
+
require 'syslog_tls/logger'
|
18
|
+
require 'fluent/plugin/output'
|
18
19
|
|
19
|
-
module Fluent
|
20
|
-
class SyslogTlsOutput <
|
20
|
+
module Fluent::Plugin
|
21
|
+
class SyslogTlsOutput < Output
|
21
22
|
Fluent::Plugin.register_output('syslog_tls', self)
|
22
23
|
|
23
|
-
|
24
|
-
include Fluent::HandleTagNameMixin
|
24
|
+
helpers :inject, :formatter, :compat_parameters
|
25
25
|
|
26
26
|
DEFAULT_FORMAT_TYPE = 'json'
|
27
27
|
|
28
28
|
config_param :host, :string
|
29
29
|
config_param :port, :integer
|
30
|
+
config_param :idle_timeout, :integer, default: nil
|
30
31
|
config_param :ca_cert, :string, default: 'system'
|
31
|
-
config_param :
|
32
|
-
config_param :
|
33
|
-
config_param :
|
34
|
-
config_param :
|
35
|
-
config_param :
|
32
|
+
config_param :verify_cert_name, :bool, default: true
|
33
|
+
config_param :token, :string, default: nil
|
34
|
+
config_param :client_cert, :string, default: nil
|
35
|
+
config_param :client_key, :string, default: nil
|
36
|
+
config_param :hostname, :string, default: nil
|
37
|
+
config_param :facility, :string, default: 'LOCAL0'
|
36
38
|
|
37
39
|
# Allow to map keys from record to syslog message headers
|
38
40
|
SYSLOG_HEADERS = [
|
@@ -40,25 +42,33 @@ module Fluent
|
|
40
42
|
]
|
41
43
|
|
42
44
|
SYSLOG_HEADERS.each do |key_name|
|
43
|
-
config_param "#{key_name}_key".to_sym, :string, :
|
45
|
+
config_param "#{key_name}_key".to_sym, :string, default: nil
|
44
46
|
end
|
45
47
|
|
46
|
-
|
48
|
+
config_section :format do
|
49
|
+
config_set_default :@type, DEFAULT_FORMAT_TYPE
|
50
|
+
end
|
51
|
+
|
52
|
+
attr_accessor :formatter
|
47
53
|
|
48
54
|
|
49
55
|
def initialize
|
50
56
|
super
|
51
|
-
require 'syslog_tls/logger'
|
52
57
|
@loggers = {}
|
53
58
|
end
|
54
59
|
|
55
60
|
def shutdown
|
56
|
-
super
|
57
61
|
@loggers.values.each(&:close)
|
62
|
+
super
|
58
63
|
end
|
59
64
|
|
60
65
|
# This method is called before starting.
|
61
66
|
def configure(conf)
|
67
|
+
if conf['output_type'] && !conf['format']
|
68
|
+
conf['format'] = conf['output_type']
|
69
|
+
end
|
70
|
+
compat_parameters_convert(conf, :inject, :formatter)
|
71
|
+
|
62
72
|
super
|
63
73
|
@host = conf['host']
|
64
74
|
@port = conf['port']
|
@@ -72,8 +82,7 @@ module Fluent
|
|
72
82
|
@mappings[key_name] = conf[conf_key] if conf.key?(conf_key)
|
73
83
|
end
|
74
84
|
|
75
|
-
@formatter =
|
76
|
-
@formatter.configure(conf)
|
85
|
+
@formatter = formatter_create(conf: conf.elements('format').first, default_type: DEFAULT_FORMAT_TYPE)
|
77
86
|
end
|
78
87
|
|
79
88
|
# Get logger for given tag
|
@@ -90,7 +99,14 @@ module Fluent
|
|
90
99
|
end
|
91
100
|
|
92
101
|
def new_logger(tag)
|
93
|
-
transport = ::SyslogTls::SSLTransport.new(host, port,
|
102
|
+
transport = ::SyslogTls::SSLTransport.new(host, port,
|
103
|
+
idle_timeout: idle_timeout,
|
104
|
+
ca_cert: ca_cert,
|
105
|
+
client_cert: client_cert,
|
106
|
+
client_key: client_key,
|
107
|
+
verify_cert_name: verify_cert_name,
|
108
|
+
max_retries: 30,
|
109
|
+
)
|
94
110
|
logger = ::SyslogTls::Logger.new(transport, token)
|
95
111
|
logger.facility(facility)
|
96
112
|
logger.hostname(hostname)
|
@@ -99,11 +115,11 @@ module Fluent
|
|
99
115
|
end
|
100
116
|
|
101
117
|
def format(tag, time, record)
|
118
|
+
record = inject_values_to_record(tag, time, record)
|
102
119
|
@formatter.format(tag, time, record)
|
103
120
|
end
|
104
121
|
|
105
|
-
def
|
106
|
-
chain.next
|
122
|
+
def process(tag, es)
|
107
123
|
es.each do |time, record|
|
108
124
|
record.each_pair do |_, v|
|
109
125
|
v.force_encoding('utf-8') if v.is_a?(String)
|
data/lib/syslog_tls/protocol.rb
CHANGED
@@ -25,7 +25,8 @@ module SyslogTls
|
|
25
25
|
|
26
26
|
# All headers by specification wrapped in single object
|
27
27
|
class Header
|
28
|
-
attr_accessor :
|
28
|
+
attr_accessor :version, :hostname, :app_name, :procid, :msgid
|
29
|
+
attr_reader :facility, :severity, :timestamp
|
29
30
|
|
30
31
|
FACILITIES = {}
|
31
32
|
SEVERITIES = {}
|
@@ -110,12 +111,16 @@ module SyslogTls
|
|
110
111
|
|
111
112
|
# Message represents full message that can be sent to syslog
|
112
113
|
class Message
|
113
|
-
attr_accessor :
|
114
|
+
attr_accessor :structured_data, :msg
|
115
|
+
attr_writer :header
|
114
116
|
|
115
117
|
def initialize
|
116
118
|
@msg = ''
|
117
119
|
@structured_data = []
|
118
|
-
|
120
|
+
end
|
121
|
+
|
122
|
+
def header
|
123
|
+
@header ||= Header.new
|
119
124
|
end
|
120
125
|
|
121
126
|
def assemble
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# Copyright 2016 Acquia, Inc.
|
2
|
+
# Copyright 2016-2019 t.e.morgan.
|
2
3
|
#
|
3
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
5
|
# you may not use this file except in compliance with the License.
|
@@ -18,18 +19,24 @@ require 'openssl'
|
|
18
19
|
module SyslogTls
|
19
20
|
# Supports SSL connection to remote host
|
20
21
|
class SSLTransport
|
22
|
+
CONNECT_TIMEOUT = 10000
|
23
|
+
# READ_TIMEOUT = 5
|
24
|
+
WRITE_TIMEOUT = 10000
|
25
|
+
|
21
26
|
attr_accessor :socket
|
22
27
|
|
23
|
-
attr_reader :host, :port, :ca_cert, :
|
28
|
+
attr_reader :host, :port, :idle_timeout, :ca_cert, :client_cert, :client_key, :verify_cert_name, :ssl_version
|
24
29
|
|
25
30
|
attr_writer :retries
|
26
31
|
|
27
|
-
def initialize(host, port, ca_cert: 'system',
|
28
|
-
@ca_cert = ca_cert
|
32
|
+
def initialize(host, port, idle_timeout: nil, ca_cert: 'system', client_cert: nil, client_key: nil, verify_cert_name: true, ssl_version: :TLSv1_2, max_retries: 1)
|
29
33
|
@host = host
|
30
34
|
@port = port
|
31
|
-
@
|
32
|
-
@
|
35
|
+
@idle_timeout = idle_timeout
|
36
|
+
@ca_cert = ca_cert
|
37
|
+
@client_cert = client_cert
|
38
|
+
@client_key = client_key
|
39
|
+
@verify_cert_name = verify_cert_name
|
33
40
|
@ssl_version = ssl_version
|
34
41
|
@retries = max_retries
|
35
42
|
connect
|
@@ -37,22 +44,69 @@ module SyslogTls
|
|
37
44
|
|
38
45
|
def connect
|
39
46
|
@socket = get_ssl_connection
|
40
|
-
|
47
|
+
begin
|
48
|
+
begin
|
49
|
+
@socket.connect_nonblock
|
50
|
+
rescue Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitReadable
|
51
|
+
select_with_timeout(@socket, :connect_read) && retry
|
52
|
+
rescue IO::WaitWritable
|
53
|
+
select_with_timeout(@socket, :connect_write) && retry
|
54
|
+
end
|
55
|
+
rescue Errno::ETIMEDOUT
|
56
|
+
raise 'Socket timeout during connect'
|
57
|
+
end
|
58
|
+
@last_write = Time.now if idle_timeout
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_tcp_connection
|
62
|
+
tcp = nil
|
63
|
+
|
64
|
+
family = Socket::Constants::AF_UNSPEC
|
65
|
+
sock_type = Socket::Constants::SOCK_STREAM
|
66
|
+
addr_info = Socket.getaddrinfo(host, port, family, sock_type, nil, nil, false).first
|
67
|
+
_, port, _, address, family, sock_type = addr_info
|
68
|
+
|
69
|
+
begin
|
70
|
+
sock_addr = Socket.sockaddr_in(port, address)
|
71
|
+
tcp = Socket.new(family, sock_type, 0)
|
72
|
+
tcp.setsockopt(Socket::SOL_SOCKET, Socket::Constants::SO_REUSEADDR, true)
|
73
|
+
tcp.setsockopt(Socket::SOL_SOCKET, Socket::Constants::SO_REUSEPORT, true)
|
74
|
+
tcp.connect_nonblock(sock_addr)
|
75
|
+
rescue Errno::EINPROGRESS
|
76
|
+
select_with_timeout(tcp, :connect_write)
|
77
|
+
begin
|
78
|
+
tcp.connect_nonblock(sock_addr)
|
79
|
+
rescue Errno::EISCONN
|
80
|
+
# all good
|
81
|
+
rescue SystemCallError
|
82
|
+
tcp.close rescue nil
|
83
|
+
raise
|
84
|
+
end
|
85
|
+
rescue SystemCallError
|
86
|
+
tcp.close rescue nil
|
87
|
+
raise
|
88
|
+
end
|
89
|
+
|
90
|
+
tcp.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, true)
|
91
|
+
tcp
|
41
92
|
end
|
42
93
|
|
43
94
|
def get_ssl_connection
|
44
|
-
tcp =
|
95
|
+
tcp = get_tcp_connection
|
45
96
|
|
46
97
|
ctx = OpenSSL::SSL::SSLContext.new
|
47
|
-
ctx.
|
98
|
+
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
48
99
|
ctx.ssl_version = ssl_version
|
49
100
|
|
101
|
+
ctx.verify_hostname = verify_cert_name != false
|
102
|
+
|
50
103
|
case ca_cert
|
51
104
|
when true, 'true', 'system'
|
52
105
|
# use system certs, same as openssl cli
|
53
106
|
ctx.cert_store = OpenSSL::X509::Store.new
|
54
107
|
ctx.cert_store.set_default_paths
|
55
108
|
when false, 'false'
|
109
|
+
ctx.verify_hostname = false
|
56
110
|
ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
57
111
|
when %r{/$} # ends in /
|
58
112
|
ctx.ca_path = ca_cert
|
@@ -60,20 +114,30 @@ module SyslogTls
|
|
60
114
|
ctx.ca_file = ca_cert
|
61
115
|
end
|
62
116
|
|
63
|
-
ctx.cert = OpenSSL::X509::Certificate.new(File.read(
|
64
|
-
ctx.key = OpenSSL::PKey::read(File.read(
|
117
|
+
ctx.cert = OpenSSL::X509::Certificate.new(File.read(client_cert)) if client_cert
|
118
|
+
ctx.key = OpenSSL::PKey::read(File.read(client_key)) if client_key
|
65
119
|
socket = OpenSSL::SSL::SSLSocket.new(tcp, ctx)
|
120
|
+
socket.hostname = host
|
66
121
|
socket.sync_close = true
|
67
122
|
socket
|
68
123
|
end
|
69
124
|
|
70
125
|
# Allow to retry on failed writes
|
71
126
|
def write(s)
|
127
|
+
if idle_timeout
|
128
|
+
if (t=Time.now) > @last_write + idle_timeout
|
129
|
+
@socket.close rescue nil
|
130
|
+
connect
|
131
|
+
else
|
132
|
+
@last_write = t
|
133
|
+
end
|
134
|
+
end
|
72
135
|
begin
|
73
136
|
retry_id ||= 0
|
74
|
-
|
137
|
+
do_write(s)
|
75
138
|
rescue => e
|
76
139
|
if (retry_id += 1) < @retries
|
140
|
+
@socket.close rescue nil
|
77
141
|
connect
|
78
142
|
retry
|
79
143
|
else
|
@@ -82,6 +146,41 @@ module SyslogTls
|
|
82
146
|
end
|
83
147
|
end
|
84
148
|
|
149
|
+
def do_write(data)
|
150
|
+
data.force_encoding('BINARY') # so we can break in the middle of multi-byte characters
|
151
|
+
loop do
|
152
|
+
sent = 0
|
153
|
+
begin
|
154
|
+
sent = @socket.write_nonblock(data)
|
155
|
+
rescue OpenSSL::SSL::SSLError, Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitWritable => e
|
156
|
+
if e.is_a?(OpenSSL::SSL::SSLError) && e.message !~ /write would block/
|
157
|
+
raise e
|
158
|
+
else
|
159
|
+
select_with_timeout(@socket, :write) && retry
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
break if sent >= data.size
|
164
|
+
data = data[sent, data.size]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def select_with_timeout(tcp, type)
|
169
|
+
case type
|
170
|
+
when :connect_read
|
171
|
+
args = [[tcp], nil, nil, CONNECT_TIMEOUT]
|
172
|
+
when :connect_write
|
173
|
+
args = [nil, [tcp], nil, CONNECT_TIMEOUT]
|
174
|
+
# when :read
|
175
|
+
# args = [[tcp], nil, nil, READ_TIMEOUT]
|
176
|
+
when :write
|
177
|
+
args = [nil, [tcp], nil, WRITE_TIMEOUT]
|
178
|
+
else
|
179
|
+
raise "Unknown select type #{type}"
|
180
|
+
end
|
181
|
+
IO.select(*args) || raise("Socket timeout during #{type}")
|
182
|
+
end
|
183
|
+
|
85
184
|
# Forward any methods directly to SSLSocket
|
86
185
|
def method_missing(method_sym, *arguments, &block)
|
87
186
|
@socket.send(method_sym, *arguments, &block)
|
data/lib/syslog_tls/version.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# Copyright 2016 Acquia, Inc.
|
2
|
-
# Copyright 2016 t.e.morgan.
|
2
|
+
# Copyright 2016-2019 t.e.morgan.
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
# you may not use this file except in compliance with the License.
|
@@ -14,5 +14,5 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
|
16
16
|
module SyslogTls
|
17
|
-
VERSION = '0.
|
17
|
+
VERSION = '2.0.0'
|
18
18
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Copyright 2016 Acquia, Inc.
|
2
|
-
# Copyright 2016 t.e.morgan.
|
2
|
+
# Copyright 2016-2019 t.e.morgan.
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
5
|
# you may not use this file except in compliance with the License.
|
@@ -18,6 +18,7 @@ require 'ssl'
|
|
18
18
|
require 'date'
|
19
19
|
require 'minitest/mock'
|
20
20
|
require 'fluent/plugin/out_syslog_tls'
|
21
|
+
require 'fluent/test/driver/output'
|
21
22
|
|
22
23
|
class SyslogTlsOutputTest < Test::Unit::TestCase
|
23
24
|
include SSLTestHelper
|
@@ -27,8 +28,8 @@ class SyslogTlsOutputTest < Test::Unit::TestCase
|
|
27
28
|
@driver = nil
|
28
29
|
end
|
29
30
|
|
30
|
-
def driver(
|
31
|
-
@driver ||= Fluent::Test::
|
31
|
+
def driver(conf='')
|
32
|
+
@driver ||= Fluent::Test::Driver::Output.new(Fluent::Plugin::SyslogTlsOutput).configure(conf)
|
32
33
|
end
|
33
34
|
|
34
35
|
def sample_record
|
@@ -45,23 +46,25 @@ class SyslogTlsOutputTest < Test::Unit::TestCase
|
|
45
46
|
def mock_logger(token='TOKEN')
|
46
47
|
io = StringIO.new
|
47
48
|
io.set_encoding('utf-8')
|
48
|
-
|
49
|
+
::SyslogTls::Logger.new(io, token)
|
49
50
|
end
|
50
51
|
|
51
52
|
def test_configure
|
52
53
|
config = %{
|
53
54
|
host syslog.collection.us1.sumologic.com
|
54
55
|
port 6514
|
55
|
-
|
56
|
-
|
56
|
+
client_cert
|
57
|
+
client_key
|
58
|
+
verify_cert_name true
|
57
59
|
token 1234567890
|
58
60
|
}
|
59
|
-
instance = driver(
|
61
|
+
instance = driver(config).instance
|
60
62
|
|
61
63
|
assert_equal 'syslog.collection.us1.sumologic.com', instance.host
|
62
64
|
assert_equal '6514', instance.port
|
63
|
-
assert_equal '', instance.
|
64
|
-
assert_equal '', instance.
|
65
|
+
assert_equal '', instance.client_cert
|
66
|
+
assert_equal '', instance.client_key
|
67
|
+
assert_equal true, instance.verify_cert_name
|
65
68
|
assert_equal '1234567890', instance.token
|
66
69
|
end
|
67
70
|
|
@@ -69,19 +72,17 @@ class SyslogTlsOutputTest < Test::Unit::TestCase
|
|
69
72
|
config = %{
|
70
73
|
host syslog.collection.us1.sumologic.com
|
71
74
|
port 6514
|
72
|
-
|
73
|
-
|
75
|
+
client_cert
|
76
|
+
client_key
|
74
77
|
}
|
75
|
-
instance = driver(
|
78
|
+
instance = driver(config).instance
|
76
79
|
|
77
80
|
time = Time.now
|
78
81
|
record = sample_record
|
79
82
|
logger = mock_logger(instance.token)
|
80
83
|
|
81
84
|
instance.stub(:new_logger, logger) do
|
82
|
-
|
83
|
-
chain.expect(:next, nil)
|
84
|
-
instance.emit('test', {time.to_i => record}, chain)
|
85
|
+
instance.process('test', {time.to_i => record})
|
85
86
|
end
|
86
87
|
|
87
88
|
assert_equal "<134>1 #{time.to_datetime.rfc3339} - - - - - #{record.to_json.to_s}\n\n", logger.transport.string
|
@@ -91,24 +92,22 @@ class SyslogTlsOutputTest < Test::Unit::TestCase
|
|
91
92
|
config = %{
|
92
93
|
host syslog.collection.us1.sumologic.com
|
93
94
|
port 6514
|
94
|
-
|
95
|
-
|
95
|
+
client_cert
|
96
|
+
client_key
|
96
97
|
token 1234567890
|
97
98
|
hostname_key hostname
|
98
99
|
procid_key procid
|
99
100
|
app_name_key app_name
|
100
101
|
msgid_key msgid
|
101
102
|
}
|
102
|
-
instance = driver(
|
103
|
+
instance = driver(config).instance
|
103
104
|
|
104
105
|
time = Time.now
|
105
106
|
record = sample_record
|
106
107
|
logger = mock_logger
|
107
108
|
|
108
109
|
instance.stub(:new_logger, logger) do
|
109
|
-
|
110
|
-
chain.expect(:next, nil)
|
111
|
-
instance.emit('test', {time.to_i => record}, chain)
|
110
|
+
instance.process('test', {time.to_i => record})
|
112
111
|
end
|
113
112
|
|
114
113
|
assert_true logger.transport.string.start_with?("<134>1 #{time.to_datetime.rfc3339} host app #{$$} 1000 [TOKEN]")
|
@@ -118,21 +117,19 @@ class SyslogTlsOutputTest < Test::Unit::TestCase
|
|
118
117
|
config = %{
|
119
118
|
host syslog.collection.us1.sumologic.com
|
120
119
|
port 6514
|
121
|
-
|
122
|
-
|
120
|
+
client_cert
|
121
|
+
client_key
|
123
122
|
token 1234567890
|
124
123
|
severity_key severity
|
125
124
|
}
|
126
|
-
instance = driver(
|
125
|
+
instance = driver(config).instance
|
127
126
|
|
128
127
|
time = Time.now
|
129
128
|
record = sample_record
|
130
129
|
logger = mock_logger
|
131
130
|
|
132
131
|
instance.stub(:new_logger, logger) do
|
133
|
-
|
134
|
-
chain.expect(:next, nil)
|
135
|
-
instance.emit('test', {time.to_i => record}, chain)
|
132
|
+
instance.process('test', {time.to_i => record})
|
136
133
|
end
|
137
134
|
|
138
135
|
assert_true logger.transport.string.start_with?("<128>1")
|
@@ -142,22 +139,20 @@ class SyslogTlsOutputTest < Test::Unit::TestCase
|
|
142
139
|
config = %{
|
143
140
|
host syslog.collection.us1.sumologic.com
|
144
141
|
port 6514
|
145
|
-
|
146
|
-
|
142
|
+
client_cert
|
143
|
+
client_key
|
147
144
|
token 1234567890
|
148
145
|
format out_file
|
149
|
-
|
146
|
+
localtime false
|
150
147
|
}
|
151
|
-
instance = driver(
|
148
|
+
instance = driver(config).instance
|
152
149
|
|
153
150
|
time = Time.now
|
154
151
|
record = sample_record
|
155
152
|
logger = mock_logger
|
156
153
|
|
157
154
|
instance.stub(:new_logger, logger) do
|
158
|
-
|
159
|
-
chain.expect(:next, nil)
|
160
|
-
instance.emit('test', {time.to_i => record}, chain)
|
155
|
+
instance.process('test', {time.to_i => record})
|
161
156
|
end
|
162
157
|
|
163
158
|
formatted_time = time.dup.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
|
@@ -178,21 +173,18 @@ class SyslogTlsOutputTest < Test::Unit::TestCase
|
|
178
173
|
config = %{
|
179
174
|
host localhost
|
180
175
|
port #{server.addr[1]}
|
181
|
-
|
182
|
-
|
176
|
+
client_cert
|
177
|
+
client_key
|
183
178
|
token 1234567890
|
184
179
|
hostname_key hostname
|
185
180
|
procid_key procid
|
186
181
|
app_name_key app_name
|
187
182
|
msgid_key msgid
|
188
183
|
}
|
189
|
-
instance = driver(
|
190
|
-
|
191
|
-
chain = Minitest::Mock.new
|
192
|
-
chain.expect(:next, nil)
|
184
|
+
instance = driver(config).instance
|
193
185
|
|
194
186
|
SyslogTls::SSLTransport.stub_any_instance(:get_ssl_connection, ssl_client) do
|
195
|
-
instance.
|
187
|
+
instance.process('test', {time.to_i => record})
|
196
188
|
end
|
197
189
|
|
198
190
|
st.join
|
data/test/helper.rb
CHANGED
@@ -19,12 +19,6 @@ SimpleCov.start
|
|
19
19
|
|
20
20
|
Coveralls.wear! if ENV['TRAVIS']
|
21
21
|
|
22
|
-
# Fluentd sets default encoding to ASCII-8BIT, but coverall can load git data which can contain UTF-8 characters
|
23
|
-
at_exit do
|
24
|
-
Encoding.default_internal = 'UTF-8' if defined?(Encoding) && Encoding.respond_to?(:default_internal)
|
25
|
-
Encoding.default_external = 'UTF-8' if defined?(Encoding) && Encoding.respond_to?(:default_external)
|
26
|
-
end
|
27
|
-
|
28
22
|
require 'test/unit'
|
29
23
|
require 'fluent/test'
|
30
24
|
require 'minitest/pride'
|
metadata
CHANGED
@@ -1,43 +1,36 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-syslog-tls-long-timeout
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- thomas morgan
|
8
|
+
- lukasz stanik
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2019-09-
|
12
|
+
date: 2019-09-09 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: fluentd
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
16
17
|
requirements:
|
17
|
-
- - "
|
18
|
+
- - ">="
|
18
19
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
20
|
-
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
20
|
+
version: 0.14.0
|
21
|
+
- - "<"
|
25
22
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: fluent-mixin-config-placeholders
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0.3'
|
23
|
+
version: '2'
|
34
24
|
type: :runtime
|
35
25
|
prerelease: false
|
36
26
|
version_requirements: !ruby/object:Gem::Requirement
|
37
27
|
requirements:
|
38
|
-
- - "
|
28
|
+
- - ">="
|
39
29
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
30
|
+
version: 0.14.0
|
31
|
+
- - "<"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2'
|
41
34
|
- !ruby/object:Gem::Dependency
|
42
35
|
name: minitest
|
43
36
|
requirement: !ruby/object:Gem::Requirement
|
@@ -70,16 +63,16 @@ dependencies:
|
|
70
63
|
name: rake
|
71
64
|
requirement: !ruby/object:Gem::Requirement
|
72
65
|
requirements:
|
73
|
-
- - "
|
66
|
+
- - ">="
|
74
67
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
68
|
+
version: '0'
|
76
69
|
type: :development
|
77
70
|
prerelease: false
|
78
71
|
version_requirements: !ruby/object:Gem::Requirement
|
79
72
|
requirements:
|
80
|
-
- - "
|
73
|
+
- - ">="
|
81
74
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
75
|
+
version: '0'
|
83
76
|
- !ruby/object:Gem::Dependency
|
84
77
|
name: test-unit
|
85
78
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,14 +93,14 @@ dependencies:
|
|
100
93
|
requirements:
|
101
94
|
- - "~>"
|
102
95
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
96
|
+
version: '3.0'
|
104
97
|
type: :development
|
105
98
|
prerelease: false
|
106
99
|
version_requirements: !ruby/object:Gem::Requirement
|
107
100
|
requirements:
|
108
101
|
- - "~>"
|
109
102
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
103
|
+
version: '3.0'
|
111
104
|
- !ruby/object:Gem::Dependency
|
112
105
|
name: simplecov
|
113
106
|
requirement: !ruby/object:Gem::Requirement
|
@@ -125,6 +118,7 @@ dependencies:
|
|
125
118
|
description: Syslog TLS output plugin with formatting support, for Fluentd
|
126
119
|
email:
|
127
120
|
- tm@iprog.com
|
121
|
+
- stanik.lukasz@outlook.com
|
128
122
|
executables: []
|
129
123
|
extensions: []
|
130
124
|
extra_rdoc_files: []
|
@@ -166,7 +160,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
166
160
|
requirements:
|
167
161
|
- - ">="
|
168
162
|
- !ruby/object:Gem::Version
|
169
|
-
version: 2.
|
163
|
+
version: '2.4'
|
170
164
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
171
165
|
requirements:
|
172
166
|
- - ">="
|