fluent-plugin-splunk-enterprise 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e9f7860fa269758ff447858638a8f18ad6ca9e63
4
+ data.tar.gz: deb978c15f15e0a0ab9ebcf4a464c7b26952b97a
5
+ SHA512:
6
+ metadata.gz: a8508a4814b1ec801c7869ba96e80f2ff33a1b9e55fbb17afe086c542d77428d97e43e6e0358bed93ad1dcdaac326b583363c37bef49aeafa8c24c509cf9dbd7
7
+ data.tar.gz: 3589f5e56f7f368950eace44eaebeca01f654506aace6a95695d77a9572ba37fd9e58debb172181a448515a8fe8243d8c62fe8c522e5ab5471e204578ac483a6
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
@@ -0,0 +1,5 @@
1
+ # Release v0.9.0 - 2018/05/03
2
+
3
+ ## New Features
4
+
5
+ * Open sourced from fluentd enterprise: out_splunk_tcp and out_splunk_hec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-plugin-splunk.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright 2011-2018 Fluentd Authors
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
@@ -0,0 +1,185 @@
1
+ # out_splunk_hec - Splunk HTTP Event Collector Output Plugin
2
+
3
+ ## Table of Contents
4
+
5
+ * [Example Configuration](#example-configuration)
6
+ * [Parameters](#parameters)
7
+ * [type (required)](#type-required)
8
+ * [host (required)](#host-required)
9
+ * [port (required)](#port-required)
10
+ * [token (required)](#token-required)
11
+ * [default_host](#default_host)
12
+ * [host_key](#host_key)
13
+ * [defaout_source](#defaout_source)
14
+ * [source_key](#source_key)
15
+ * [default_index](#default_index)
16
+ * [index_key](#index_key)
17
+ * [sourcetype](#sourcetype)
18
+ * [use_fluentd_time](#use_fluentd_time)
19
+ * [use_ack](#use_ack)
20
+ * [channel](#channel)
21
+ * [ack_interval](#ack_interval)
22
+ * [ack_retry_limit](#ack_retry_limit)
23
+ * [raw](#raw)
24
+ * [event_key](#event_key)
25
+ * [line_breaker](#line_breaker)
26
+ * [use_ssl](#use_ssl)
27
+ * [ssl_verify](#ssl_verify)
28
+ * [ca_file](#ca_file)
29
+ * [client_cert](#client_cert)
30
+ * [client_key](#client_key)
31
+ * [client_key_pass](#client_key_pass)
32
+
33
+ ## Example Configuration
34
+
35
+ ```
36
+ <match splunk.**>
37
+ @type splunk_hec
38
+ host example.com
39
+ port 8089
40
+ token 00000000-0000-0000-0000-000000000000
41
+
42
+ # metadata parameter
43
+ default_source fluentd
44
+
45
+ # ack parameter
46
+ use_ack true
47
+ channel 8e69d7b3-f266-e9f3-2747-cc5b7f809897
48
+ ack_retry 8
49
+
50
+ # ssl parameter
51
+ use_ssl true
52
+ ca_file /path/to/ca.pem
53
+
54
+ # buffered output parameter
55
+ buffer 10s
56
+ </match>
57
+ ```
58
+
59
+ ## Parameters
60
+
61
+ ### type (required)
62
+
63
+ The value must be `splunk_hec`.
64
+
65
+ ### host (required)
66
+
67
+ The Splunk hostname.
68
+
69
+ ### port (required)
70
+
71
+ The Splunk port.
72
+
73
+ ### token (required)
74
+
75
+ The token for HTTP Event Collector.
76
+
77
+ ### default_host
78
+
79
+ If you set this, the value is set as host metadata.
80
+
81
+ ### host_key
82
+
83
+ If you set this, the value associated with this key in each record is used as host metadata. When the key is missing, `default_host` is used.
84
+
85
+ ### defaout_source
86
+
87
+ If you set this, the value is set as source metadata.
88
+
89
+ ### source_key
90
+
91
+ If you set this, the value associated with this key in each record is used as source metadata. When the key is missing, `default_source` is used.
92
+
93
+ ### default_index
94
+
95
+ If you set this, the value is set as index metadata.
96
+
97
+ ### index_key
98
+
99
+ If you set this, the value associated with this key in each record is used as index metadata. When the key is missing, `default_index` is used.
100
+
101
+ ### sourcetype
102
+
103
+ If you set this, the value is set as sourcetype metadata.
104
+
105
+ ### use_fluentd_time
106
+
107
+ The default: `true`
108
+
109
+ If set true, fluentd's timestamp is used as time metadata. If the record already has its own time value, this options should be `false`.
110
+
111
+ ### use_ack
112
+
113
+ Enable/Disable [Indexer acknowledgement](https://www.google.co.jp/search?q=splunk+http+ack&oq=splunk+http+ack&aqs=chrome..69i57j69i60l2.2725j0j9&sourceid=chrome&ie=UTF-8). When this is set `true`, `channel` parameter is required.
114
+
115
+ ### channel
116
+
117
+ This is used as [channel identifier](http://dev.splunk.com/view/event-collector/SP-CAAAE8X#aboutchannels).
118
+ When you set `use_ack` or `raw`, this parameter is required.
119
+
120
+ ### ack_interval
121
+
122
+ The default: `1`
123
+
124
+ Specify how many seconds the plugin should wait between checks for Indexer acknowledgement.
125
+
126
+ ### ack_retry_limit
127
+
128
+ The default: `3`
129
+
130
+ Specify how many times the plugin check Indexer acknowledgement.
131
+
132
+ ### raw
133
+
134
+ Enable [raw mode](http://dev.splunk.com/view/event-collector/SP-CAAAE8Y#raw).
135
+
136
+ On raw mode, the plugin can't configure metadata at event level and time metadata. So `*_key` and `use_fluentd_time` parameters are ignored.
137
+ When this is set `true`, `event_key` and `channel` parameter must also be set.
138
+
139
+ Example:
140
+
141
+ * configuration: `raw = true, event_key = "log"`
142
+ * fluentd record: `1490924392 {"foo": "bar", "log": "GET / HTTP/1.1 200"}`
143
+ * sent as: `GET / HTTP/1.1 200`
144
+
145
+ ### event_key
146
+
147
+ Only for raw mode. The value specified by this key is sent as an event.
148
+ When `raw` is set to `true`, this parameter is required.
149
+
150
+ * fluentd record: `1490924392 {"log": "GET / HTTP/1.1 200"}`
151
+ * sent as: `GET / HTTP/1.1 200`
152
+
153
+ ### line_breaker
154
+
155
+ The default: `"\n"`
156
+
157
+ The line breaker used when multiple records are sent at once.
158
+
159
+ ### use_ssl
160
+
161
+ The default: `false`
162
+
163
+ Use SSL when connecting to Splunk.
164
+
165
+ ### ssl_verify
166
+
167
+ The default: `true`
168
+
169
+ Enable/Disable SSL certificate verification.
170
+
171
+ ### ca_file
172
+
173
+ The path of CA file.
174
+
175
+ ### client_cert
176
+
177
+ The path of client certificate file.
178
+
179
+ ### client_key
180
+
181
+ The path of client key file
182
+
183
+ ### client_key_pass
184
+
185
+ The passphrase of client key.
@@ -0,0 +1,43 @@
1
+ # fluent-plugin-splunk-enterprise
2
+
3
+ ## Table of Contents
4
+
5
+ * [Installation](#installation)
6
+ * [out_splunk_hec](#out_splunk_hec)
7
+ * [out_splunk_tcp](#out_splunk_tcp)
8
+ * [Running test](#running-tests)
9
+
10
+ ## Installation
11
+
12
+ ```
13
+ $ fluent-gem install fluent-plugin-splunk-enterprise
14
+ ```
15
+
16
+ ## [out_splunk_hec](/README.hec.md)
17
+
18
+ Splunk HTTP Event Collector Output plugin
19
+
20
+ http://dev.splunk.com/view/event-collector/SP-CAAAE6M
21
+
22
+ ## [out_splunk_tcp](/README.tcp.md)
23
+
24
+ Splunk TCP inputs Output Plugin
25
+
26
+ http://docs.splunk.com/Documentation/Splunk/latest/Data/Monitornetworkports
27
+
28
+ ## Running tests
29
+
30
+ Available Splunk versions in tests are `6.5.2`, `6.4.6`, `6.3.9`, `6,2.12`, `6.1.13` and `6.0.14`.
31
+
32
+ Start a docker instance Splunk.
33
+
34
+ ```
35
+ $ ./docker.sh login
36
+ $ ./docker.sh debug_run <splunk_version>
37
+ ```
38
+
39
+ Run tests.
40
+
41
+ ```
42
+ $ SPLUNK_VERSION=<splunk_version> bundle exec rake test
43
+ ```
@@ -0,0 +1,231 @@
1
+ # out_splunk_tcp - Splunk TCP inputs Output Plugin
2
+
3
+ ## Table of Contents
4
+
5
+ * [Example Configuration](#example-configuration)
6
+ * [not formatted by the plugin](#not-formatted-by-the-plugin)
7
+ * [formatted by the plugin](#formatted-by-the-plugin)
8
+ * [Parameters](#parameters)
9
+ * [type (required)](#type-required)
10
+ * [host (required)](#host-required)
11
+ * [port (required)](#port-required)
12
+ * [format](#format)
13
+ * [event_key](#event_key)
14
+ * [use_fluentd_time](#use_fluentd_time)
15
+ * [time_key](#time_key)
16
+ * [time_format](#time_format)
17
+ * [localtime](#localtime)
18
+ * [line_breaker](#line_breaker)
19
+ * [use_ssl](#use_ssl)
20
+ * [ssl_verify](#ssl_verify)
21
+ * [ca_file](#ca_file)
22
+ * [client_cert](#client_cert)
23
+ * [client_key](#client_key)
24
+ * [client_key_pass](#client_key_pass)
25
+
26
+ ## Example Configuration
27
+
28
+ ### not formatted by the plugin
29
+
30
+ * fluentd record: `1490924392 {"log": "GET / HTTP/1.1 200"}`
31
+ * sent as: `GET / HTTP/1.1 200`
32
+
33
+
34
+ ```
35
+ <match splunk.**>
36
+ @type splunk_tcp
37
+ host example.com
38
+ port 8089
39
+
40
+ # format parameter
41
+ format raw
42
+ event_key log
43
+
44
+ # ssl parameter
45
+ use_ssl true
46
+ ca_file /path/to/ca.pem
47
+
48
+ # buffered output parameter
49
+ flush_interval 10s
50
+ </match>
51
+ ```
52
+
53
+ ### formatted by the plugin
54
+
55
+ This example shows json format.
56
+
57
+ * fluentd record: `1490924392 {"method": "GET", path: "/", code: 200}`
58
+ * sent as: `{"time": 1490924392, "method": "GET", path: "/", code: 200}`
59
+
60
+ ```
61
+ <match splunk.**>
62
+ @type splunk_tcp
63
+ host example.com
64
+ port 8089
65
+
66
+ format json
67
+
68
+ # ssl parameter
69
+ use_ssl true
70
+ ca_file /path/to/ca.pem
71
+
72
+ # flush
73
+ flush_interval 10s
74
+ </match>
75
+ ```
76
+
77
+ You can use a sourcetype configuration like the following.
78
+
79
+ ```
80
+ [fluentd]
81
+ TIME_PREFIX=\"time\":
82
+ TIME_FORMAT=%s
83
+ KV_MODE=json
84
+ ```
85
+
86
+ ## Parameters
87
+
88
+ ### type (required)
89
+
90
+ The value must be `splunk_tcp`.
91
+
92
+ ### host (required)
93
+
94
+ The Splunk hostname.
95
+
96
+ ### port (required)
97
+
98
+ The Splunk port.
99
+
100
+ ### format
101
+
102
+ #### `raw` (the default)
103
+
104
+ The value specified by `event_key` parameter is sent to Splunk as an event.
105
+ If the key missing in a record, nothing is sent.
106
+
107
+ ##### Related parameters
108
+ * event_key
109
+
110
+ #### `json`
111
+
112
+ `KV_MODE=json` can be used as sourcetype configuration.
113
+
114
+ ##### Related parameters
115
+ * use_fluentd_time
116
+ * time_key
117
+ * time_format
118
+ * localtime
119
+
120
+ #### `kv`
121
+
122
+ Key-value pairs like the following.
123
+
124
+ ```
125
+ time=1490862563 method="GET" path="/" code=200
126
+ ```
127
+
128
+ `KV_MODE=auto` can be used as sourcetype configuration.
129
+
130
+ ##### Related parameters
131
+ * use_fluentd_time
132
+ * time_key
133
+ * time_format
134
+ * localtime
135
+
136
+ ### event_key
137
+
138
+ For `raw` format.
139
+
140
+ This parameter is required when the format is `raw`.
141
+
142
+ ### use_fluentd_time
143
+
144
+ For `json` and `kv` format.
145
+ The default: `true`
146
+
147
+ If set to `true`, fluentd's timestamp is injected to the top of the record before sent to Splunk.
148
+
149
+ For example, the first record is converted to the next one.
150
+
151
+ ```
152
+ {"method": "GET", path: "/", code: 200}
153
+ ```
154
+
155
+ ```
156
+ {"time": 1490862563, "method": "GET", path: "/", code: 200}
157
+ ```
158
+
159
+ If your record already has the column for a timestamp, this parameter should be `false`.
160
+
161
+ ### time_key
162
+
163
+ For `json` and `kv` format.
164
+ The default: `time`
165
+
166
+ The key which is inserted into a record by `use_fluend_time` parameter.
167
+
168
+ ### time_format
169
+
170
+ For `json` and `kv` format.
171
+ The default: `unixtime`
172
+
173
+ The format of timestamp which is inserted by `use_fluentd_time` parameter.
174
+ You can specify a strftime format or `unixtime` (unix timestamp as integer).
175
+
176
+ For example,
177
+
178
+ ```
179
+ time_format %Y-%m-%dT%H:%M:%S%z
180
+ ```
181
+
182
+ the first record record is converted to the next one by this `time_format`.
183
+
184
+ ```
185
+ {"method": "GET", path: "/", code: 200}
186
+ ```
187
+
188
+ ```
189
+ {"time": "2017-03-30T08:29:23+0000", "method": "GET", path: "/", code: 200}
190
+ ```
191
+
192
+ ### localtime
193
+
194
+ For `json` and `kv` format
195
+ The default: `false`
196
+
197
+ If `true`, use local time when the timestamp formatted as the strftime format. Otherwise UTC is used.
198
+
199
+ ### line_breaker
200
+
201
+ The default: `"\n"`
202
+
203
+ The line breaker used when multiple records are sent at once.
204
+
205
+ ### use_ssl
206
+
207
+ The default: `false`
208
+
209
+ Use SSL when connecting to Splunk.
210
+
211
+ ### ssl_verify
212
+
213
+ The default: `true`
214
+
215
+ Enable/Disable SSL certificate verification.
216
+
217
+ ### ca_file
218
+
219
+ The path of CA file.
220
+
221
+ ### client_cert
222
+
223
+ The path of client certificate file.
224
+
225
+ ### client_key
226
+
227
+ The path of client key file
228
+
229
+ ### client_key_pass
230
+
231
+ The passphrase of client key.
@@ -0,0 +1,15 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |test|
5
+ test.libs << 'test'
6
+ test.pattern = 'test/test_*.rb'
7
+ test.verbose = true
8
+ end
9
+
10
+ task default: :test
11
+
12
+ task :coverage do |t|
13
+ ENV['SIMPLE_COV'] = '1'
14
+ Rake::Task['test'].invoke
15
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "fluent/plugin/splunk"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "fluent-plugin-splunk-enterprise"
7
+ spec.version = "0.9.0"
8
+ spec.authors = ["Yuki Ito", "Masahiro Nakagawa"]
9
+ spec.email = ["yito@treasure-data.com", "repeatedly@gmail.com"]
10
+
11
+ spec.summary = %q{Splunk output plugin for Fluentd}
12
+ spec.description = spec.summary
13
+ spec.homepage = ""
14
+ spec.has_rdoc = false
15
+ spec.license = "Apache-2.0"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_dependency 'fluentd', [">= 0.12.0"]
25
+ spec.add_dependency 'json'
26
+ spec.add_dependency 'httpclient'
27
+
28
+ spec.add_development_dependency "rake", "~> 10.0"
29
+ spec.add_development_dependency "test-unit", ">= 3.0.8"
30
+ spec.add_development_dependency "simplecov", ">= 0.10.0"
31
+ end
@@ -0,0 +1,162 @@
1
+ require 'fluent/output'
2
+ require 'httpclient'
3
+ require 'json'
4
+
5
+ # http://dev.splunk.com/view/event-collector/SP-CAAAE6P
6
+
7
+ module Fluent
8
+ class SplunkHECOutput < ObjectBufferedOutput
9
+ Fluent::Plugin.register_output('splunk_hec', self)
10
+
11
+ config_param :host, :string
12
+ config_param :port, :integer
13
+ config_param :token, :string
14
+
15
+ # for metadata
16
+ config_param :default_host, :string, default: nil
17
+ config_param :host_key, :string, default: nil
18
+ config_param :default_source, :string, default: nil
19
+ config_param :source_key, :string, default: nil
20
+ config_param :default_index, :string, default: nil
21
+ config_param :index_key, :string, default: nil
22
+ config_param :sourcetype, :string, default: nil
23
+ config_param :use_fluentd_time, :bool, default: true
24
+
25
+ # for Indexer acknowledgement
26
+ config_param :use_ack, :bool, default: false
27
+ config_param :channel, :string, default: nil
28
+ config_param :ack_interval, :integer, default: 1
29
+ config_param :ack_retry_limit, :integer, default: 3
30
+
31
+ # for raw events
32
+ config_param :raw, :bool, default: false
33
+ config_param :event_key, :string, default: nil
34
+
35
+ # misc
36
+ config_param :line_breaker, :string, default: "\n"
37
+
38
+ ## For SSL
39
+ config_param :use_ssl, :bool, default: false
40
+ config_param :ssl_verify, :bool, default: true
41
+ config_param :ca_file, :string, default: nil
42
+ config_param :client_cert, :string, default: nil
43
+ config_param :client_key, :string, default: nil
44
+ config_param :client_key_pass, :string, default: nil
45
+
46
+ def configure(conf)
47
+ super
48
+ raise ConfigError, "'channel' parameter is required when 'use_ack' is true" if @use_ack && !@channel
49
+ raise ConfigError, "'ack_interval' parameter must be a non negative integer" if @use_ack && @ack_interval < 0
50
+ raise ConfigError, "'event_key' parameter is required when 'raw' is true" if @raw && !@event_key
51
+ raise ConfigError, "'channel' parameter is required when 'raw' is true" if @raw && !@channel
52
+
53
+ # build hash for query string
54
+ if @raw
55
+ @query = {}
56
+ @query['host'] = @default_host if @default_host
57
+ @query['source'] = @default_source if @default_source
58
+ @query['index'] = @default_index if @default_index
59
+ @query['sourcetype'] = @sourcetype if @sourcetype
60
+ end
61
+ end
62
+
63
+ def start
64
+ setup_client
65
+ super
66
+ end
67
+
68
+ def shutdown
69
+ super
70
+ end
71
+
72
+ def write_objects(_tag, chunk)
73
+ return if chunk.empty?
74
+
75
+ payload = ''
76
+ chunk.msgpack_each do |time, record|
77
+ payload << (@raw ? format_event_raw(record) : format_event(time, record))
78
+ end
79
+ post_payload(payload) unless payload.empty?
80
+ end
81
+
82
+ private
83
+ def setup_client
84
+ header = {'Content-type' => 'application/json',
85
+ 'Authorization' => "Splunk #{@token}"}
86
+ header['X-Splunk-Request-Channel'] = @channel if @channel
87
+ base_url = @use_ssl ? URI::HTTPS.build(host: @host, port: @port) : URI::HTTP.build(host: @host, port: @port)
88
+ @client = HTTPClient.new(default_header: header,
89
+ base_url: base_url)
90
+ if @use_ssl
91
+ verify_mode = (@ssl_verify ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE)
92
+ @client.ssl_config.verify_mode = verify_mode
93
+ @client.ssl_config.add_trust_ca(@ca_file) if @ca_file
94
+ @client.ssl_config.set_client_cert_file(@client_cert, @client_key, @client_key_pass) if @client_cert && @client_key
95
+ end
96
+ end
97
+
98
+ def format_event(time, record)
99
+ msg = {'event' => record}
100
+ msg['time'] = time if @use_fluentd_time
101
+
102
+ # metadata
103
+ msg['sourcetype'] = @sourcetype if @sourcetype
104
+
105
+ if record[@host_key]
106
+ msg['host'] = record[@host_key]
107
+ elsif @default_host
108
+ msg['host'] = @default_host
109
+ end
110
+
111
+ if record[@source_key]
112
+ msg['source'] = record[@source_key]
113
+ elsif @default_source
114
+ msg['source'] = @default_source
115
+ end
116
+
117
+ if record[@index_key]
118
+ msg['index'] = record[@index_key]
119
+ elsif @default_index
120
+ msg['index'] = @default_index
121
+ end
122
+
123
+ msg.to_json + "\n"
124
+ end
125
+
126
+ def format_event_raw(record)
127
+ (record[@event_key] || '') + @line_breaker
128
+ end
129
+
130
+ def post(path, body, query = {})
131
+ @client.post(path, body: body, query: query)
132
+ end
133
+
134
+ def post_payload(payload)
135
+ res = nil
136
+ if @raw
137
+ res = post('/services/collector/raw', payload, @query)
138
+ else
139
+ res = post('/services/collector', payload)
140
+ end
141
+ log.debug "Splunk response: #{res.body}"
142
+ if @use_ack
143
+ res_json = JSON.parse(res.body)
144
+ ack_id = res_json['ackId']
145
+ check_ack(ack_id, @ack_retry_limit)
146
+ end
147
+ end
148
+
149
+ def check_ack(ack_id, retries)
150
+ raise "failed to index the data ack_id=#{ack_id}" if retries < 0
151
+
152
+ ack_res = post('/services/collector/ack', {'acks' => [ack_id]}.to_json)
153
+ ack_res_json = JSON.parse(ack_res.body)
154
+ if ack_res_json['acks'] && ack_res_json['acks'][ack_id.to_s]
155
+ return
156
+ else
157
+ sleep(@ack_interval)
158
+ check_ack(ack_id, retries - 1)
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,152 @@
1
+ require 'fluent/output'
2
+ require 'fluent/formatter'
3
+ require 'fluent/config/error'
4
+ require 'socket'
5
+ require 'openssl'
6
+ require 'json'
7
+
8
+ # http://dev.splunk.com/view/event-collector/SP-CAAAE6P
9
+
10
+ module Fluent
11
+ class SplunkTCPOutput < ObjectBufferedOutput
12
+ Fluent::Plugin.register_output('splunk_tcp', self)
13
+
14
+ config_param :host, :string
15
+ config_param :port, :integer
16
+
17
+ config_param :format, :string, default: 'raw'
18
+
19
+ # for raw format
20
+ config_param :event_key, :string, default: nil
21
+
22
+ # for json, kv format
23
+ config_param :use_fluentd_time, :bool, default: true
24
+ config_param :time_key, :string, default: 'time'
25
+ config_param :time_format, :string, default: 'unixtime'
26
+ config_param :localtime, :bool, default: false
27
+
28
+ config_param :line_breaker, :string, default: "\n"
29
+
30
+ ## For SSL
31
+ config_param :use_ssl, :bool, default: false
32
+ config_param :ssl_verify, :bool, default: true
33
+ config_param :ca_file, :string, default: nil
34
+ config_param :client_cert, :string, default: nil
35
+ config_param :client_key, :string, default: nil
36
+ config_param :client_key_pass, :string, default: nil
37
+
38
+ def implement?(feature)
39
+ if feature == :custom_format
40
+ return false
41
+ end
42
+ super
43
+ end
44
+
45
+ def configure(conf)
46
+ super
47
+
48
+ case @time_format
49
+ when 'unixtime'
50
+ @time_formatter = lambda {|time| time }
51
+ else
52
+ @timef = Fluent::TimeFormatter.new(@time_format, @localtime)
53
+ @time_formatter = lambda {|time| @timef.format(time) }
54
+ end
55
+
56
+ case @format
57
+ when 'json'
58
+ if @use_fluentd_time
59
+ @formatter = lambda {|time, record| insert_time_to_front(time, record).to_json }
60
+ else
61
+ @formatter = lambda {|_time, record| record.to_json }
62
+ end
63
+ when 'kv'
64
+ if @use_fluentd_time
65
+ @formatter = lambda {|time, record| format_kv(insert_time_to_front(time, record)) }
66
+ else
67
+ @formatter = lambda {|_time, record| format_kv(record) }
68
+ end
69
+ when 'raw'
70
+ unless @event_key
71
+ raise ConfigError, "'event_key' option is required for format 'raw'"
72
+ end
73
+ @formatter = lambda {|_time, record| record[@event_key] || '' }
74
+ else
75
+ raise ConfigError, "invalid 'format' option: #{@format}"
76
+ end
77
+ end
78
+
79
+ def start
80
+ super
81
+ end
82
+
83
+ def shutdown
84
+ super
85
+ end
86
+
87
+ def write_objects(_tag, chunk)
88
+ return if chunk.empty?
89
+
90
+ payload = ''
91
+ chunk.msgpack_each do |time, record|
92
+ event = @formatter.call(time, record)
93
+ payload << (event + @line_breaker) unless event.empty?
94
+ end
95
+
96
+ unless payload.empty?
97
+ sock = create_socket
98
+ sock.write(payload)
99
+ sock.close
100
+ end
101
+ end
102
+
103
+ private
104
+ def insert_time_to_front(time, record)
105
+ record.delete(@time_key)
106
+ {@time_key => @time_formatter.call(time)}.merge(record)
107
+ end
108
+
109
+ def format_kv(record)
110
+ record.map{|k,v|
111
+ case v
112
+ when nil
113
+ "#{k}="
114
+ when Integer
115
+ "#{k}=#{v}"
116
+ when Float
117
+ "#{k}=#{v}"
118
+ else
119
+ "#{k}=\"#{v.to_s.gsub('"', '\"')}\""
120
+ end
121
+ }.join(' ')
122
+ end
123
+
124
+ def create_socket
125
+ @use_ssl ? create_ssl_socket : create_tcp_socket
126
+ end
127
+
128
+ def create_ssl_socket
129
+ ctx = OpenSSL::SSL::SSLContext.new
130
+ verify_mode = (@ssl_verify ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE)
131
+ ctx.verify_mode = verify_mode
132
+ ctx.cert = OpenSSL::X509::Certificate.new(File.read(@client_cert)) if @client_cert
133
+ ctx.key = OpenSSL::PKey::RSA.new(File.read(@client_key), @client_key_pass) if @client_key
134
+
135
+ cert_store = OpenSSL::X509::Store.new
136
+ cert_store.set_default_paths
137
+ cert_store.add_file(@ca_file) if @ca_file
138
+
139
+ ctx.cert_store = cert_store
140
+
141
+ tcpsock = create_tcp_socket
142
+ sock = OpenSSL::SSL::SSLSocket.new(tcpsock, ctx)
143
+ sock.sync_close = true
144
+ sock.connect
145
+ sock
146
+ end
147
+
148
+ def create_tcp_socket
149
+ TCPSocket.open(@host, @port)
150
+ end
151
+ end
152
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-splunk-enterprise
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Yuki Ito
8
+ - Masahiro Nakagawa
9
+ autorequire:
10
+ bindir: exe
11
+ cert_chain: []
12
+ date: 2018-05-03 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: fluentd
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: 0.12.0
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: 0.12.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: json
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: httpclient
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rake
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '10.0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '10.0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: test-unit
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: 3.0.8
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: 3.0.8
84
+ - !ruby/object:Gem::Dependency
85
+ name: simplecov
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 0.10.0
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: 0.10.0
98
+ description: Splunk output plugin for Fluentd
99
+ email:
100
+ - yito@treasure-data.com
101
+ - repeatedly@gmail.com
102
+ executables: []
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - ".gitignore"
107
+ - CHANGELOG.md
108
+ - Gemfile
109
+ - LICENSE
110
+ - README.hec.md
111
+ - README.md
112
+ - README.tcp.md
113
+ - Rakefile
114
+ - bin/console
115
+ - bin/setup
116
+ - fluent-plugin-splunk-enterprise.gemspec
117
+ - lib/fluent/plugin/out_splunk_hec.rb
118
+ - lib/fluent/plugin/out_splunk_tcp.rb
119
+ homepage: ''
120
+ licenses:
121
+ - Apache-2.0
122
+ metadata: {}
123
+ post_install_message:
124
+ rdoc_options: []
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ requirements: []
138
+ rubyforge_project:
139
+ rubygems_version: 2.6.14.1
140
+ signing_key:
141
+ specification_version: 4
142
+ summary: Splunk output plugin for Fluentd
143
+ test_files: []