fluent-plugin-syscheck 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 277e0647f0be28efd0add255e8a1082cc4b35523da31f1bc3ad106ed53deb1b8
4
- data.tar.gz: 3349b001ba0a1868ad26a2bb2b64b0485aa12291d0d637434a2c416b1c9395af
3
+ metadata.gz: 793b60b98e80ea983169dec24aaf13725d3dfa93e0f73c05c49a325a9a8103ab
4
+ data.tar.gz: 976bc5154d1b1a93047f75aaa2bcd933844bb604e07e53619d9d6dc97b8cf471
5
5
  SHA512:
6
- metadata.gz: d87e0d84a7c82f21fb498b183d0d50ab7fa5af7e08c49aa1d5691558d8dd879ab0306a4fac80783a52944a9c066eb505ab9118a1a035424c3b52ce706f136212
7
- data.tar.gz: 924b6fd66acb1cbf11bd0cabbf8392db47205fbd586484ea0ca3d3ff483b46797d416dcaa7c06b8c16e7bd2b8110eeecc0961e6f8b81e9862f1d4c597e3beccf
6
+ metadata.gz: daeb3dbc21f3bce7b804eeb060475285bdfcb103860d84c2845c12e18da7ff80b423e6859013dca7c25b2e49fae3329275b00b109c54d02476e29a06431bdc51
7
+ data.tar.gz: '08c092e9e4552c8f2177bfab4496157ba9f6088adaba318f7766f4fbeb23e7baa5ce616378efe25591e8fbefc3b5f3843b38848b7654a7838229e6c3045140aa'
data/.rubocop.yml CHANGED
@@ -4,7 +4,7 @@ plugins:
4
4
  - rubocop-rake
5
5
 
6
6
  AllCops:
7
- TargetRubyVersion: 3.1
7
+ TargetRubyVersion: 3.2
8
8
  NewCops: enable
9
9
 
10
10
  Gemspec/DevelopmentDependencies:
data/README.md CHANGED
@@ -32,11 +32,58 @@ $ bundle
32
32
 
33
33
  ### configuration
34
34
 
35
+ Parameters are:
36
+
37
+ | parameter | type | purpose |
38
+ |-------------------|--------|------------------------------------------|
39
+ | tag | string | tag to emit event on |
40
+ | interval | time | interval to exec mount check |
41
+ | timeout | time | timeout for a mountpoint check |
42
+ | enabled_fs_types | array | list of fstype to enable only |
43
+ | disabled_fs_types | array | list of fstype to disable explicitly |
44
+ | error_only | bool | generate event on mount check error only |
45
+
46
+ ### examples
47
+
48
+ ``` text
49
+ <source>
50
+ @type syscheck_mounts
51
+
52
+ tag test
53
+ interval 10
54
+ enabled_fs_types zfs, xfs
55
+ error_only false
56
+ </source>
57
+ ```
58
+
59
+ ## plugin : syscheck_sockets
60
+
61
+ ### configuration
62
+
63
+ Parameters are:
64
+
65
+ | parameter | type | purpose |
66
+ |-------------------------|--------|----------------------------------------------|
67
+ | tag | string | tag to emit event on |
68
+ | interval | time | interval to exec mount check |
69
+ | first_run_wait_interval | bool | first collect wait interval before execution |
70
+ | list_sockets | bool | dump sockets information |
71
+
35
72
  ### examples
36
73
 
74
+ ``` text
75
+ <source>
76
+ @type syscheck_sockets
77
+
78
+ tag test
79
+ interval 60
80
+ first_run_wait_interval false
81
+ list_sockets true
82
+ </source>
83
+ ```
37
84
 
38
85
  ## Copyright
39
86
 
40
- * Copyright(c) 2025- Thomas Tych
87
+ * Copyright(c) 2025-2026 Thomas Tych
41
88
  * License
42
89
  * Apache License, Version 2.0
@@ -15,11 +15,9 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
- require 'ostruct'
19
-
20
18
  require 'fluent/plugin/input'
21
19
 
22
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
20
+ # rubocop:disable-next Metrics/AbcSize, Metrics/ClassLength, Metrics/MethodLength
23
21
  module Fluent
24
22
  module Plugin
25
23
  class SyscheckMountsInput < Fluent::Plugin::Input
@@ -36,17 +34,43 @@ module Fluent
36
34
  desc 'interval for probe execution'
37
35
  config_param :interval, :time, default: INTERVAL
38
36
  desc 'The timeout in second for the check execution'
39
- config_param :timeout, :integer, default: TIMEOUT
40
-
41
- ENABLED_FS_TYPE = nil
42
- DISABLED_FS_TYPE = %w[sysfs proc devpts bpf devtmpfs debugfs tracefs binfmt_misc
43
- efivarfs cgroup cgroup2 securityfs configfs fusectl mqueue
44
- pstore hugetlbfs].freeze
37
+ config_param :timeout, :time, default: TIMEOUT
38
+
39
+ ENABLED_FS_TYPES = nil
40
+ DISABLED_FS_TYPES = %w[
41
+ binfmt_misc
42
+ bpf
43
+ cgroup
44
+ cgroup2
45
+ configfs
46
+ debugfs
47
+ devpts
48
+ devtmpfs
49
+ efivarfs
50
+ fusectl
51
+ hugetlbfs
52
+ mqueue
53
+ proc
54
+ pstore
55
+ rpc_pipefs
56
+ securityfs
57
+ squashfs
58
+ sysfs
59
+ tracefs
60
+ ].freeze
45
61
 
46
62
  desc 'Enabled FS types'
47
- config_param :enabled_fs_types, :array, value_type: :string, default: ENABLED_FS_TYPE
63
+ config_param :enabled_fs_types, :array, value_type: :string, default: ENABLED_FS_TYPES
48
64
  desc 'Disabled FS types'
49
- config_param :disabled_fs_types, :array, value_type: :string, default: DISABLED_FS_TYPE
65
+ config_param :disabled_fs_types, :array, value_type: :string, default: DISABLED_FS_TYPES
66
+
67
+ ENABLED_PATHS = nil
68
+ DISABLED_PATHS = [].freeze
69
+
70
+ desc 'Enabled Paths'
71
+ config_param :enabled_paths, :array, value_type: :regexp, default: ENABLED_PATHS
72
+ desc 'Disabled Paths'
73
+ config_param :disabled_paths, :array, value_type: :regexp, default: DISABLED_PATHS
50
74
 
51
75
  ERROR_ONLY = true
52
76
 
@@ -56,9 +80,7 @@ module Fluent
56
80
  def configure(conf)
57
81
  super
58
82
 
59
- raise Fluent::ConfigError, 'tag should not be empty' if tag.empty?
60
-
61
- true
83
+ raise Fluent::ConfigError, 'tag should not be empty' if tag.nil? || tag.empty?
62
84
  end
63
85
 
64
86
  def start
@@ -82,13 +104,35 @@ module Fluent
82
104
  def system_mounts
83
105
  File.readlines('/proc/mounts').map do |mount_line|
84
106
  device, mountpoint, fstype, _rest = mount_line.split
85
- next if enabled_fs_types && !enabled_fs_types.include?(fstype)
86
- next if disabled_fs_types&.include?(fstype)
107
+ next unless enabled_fs_type?(fstype)
108
+ next if disabled_fs_type?(fstype)
109
+ next unless enabled_path?(mountpoint)
110
+ next if disabled_path?(mountpoint)
87
111
 
88
112
  SysMount.new(device: device, mountpoint: mountpoint, fstype: fstype)
89
113
  end.compact
90
114
  end
91
115
 
116
+ def enabled_fs_type?(fstype)
117
+ return true unless enabled_fs_types
118
+
119
+ enabled_fs_types.include?(fstype)
120
+ end
121
+
122
+ def disabled_fs_type?(fstype)
123
+ disabled_fs_types&.include?(fstype)
124
+ end
125
+
126
+ def enabled_path?(path)
127
+ return true unless enabled_paths
128
+
129
+ enabled_paths.any? { |path_pattern| path_pattern.match?(path) }
130
+ end
131
+
132
+ def disabled_path?(path)
133
+ disabled_paths.any? { |path_pattern| path_pattern.match?(path) }
134
+ end
135
+
92
136
  def stat_async(mount)
93
137
  reader, writer = IO.pipe
94
138
 
@@ -119,8 +163,6 @@ module Fluent
119
163
  SysMountStatus.new(result)
120
164
  end
121
165
 
122
-
123
-
124
166
  def emit_mount_status(mount, status)
125
167
  log.debug "#{mount.mountpoint} (#{mount.fstype}): status - #{status}"
126
168
 
@@ -178,4 +220,3 @@ module Fluent
178
220
  end
179
221
  end
180
222
  end
181
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2026- Thomas Tych
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require 'fluent/plugin/input'
19
+
20
+ require 'procfs_rb'
21
+ require 'procfs_rb/proc_fs/parser/net_tcp_parser'
22
+
23
+ module Fluent
24
+ module Plugin
25
+ class SyscheckSocketsInput < Fluent::Plugin::Input
26
+ NAME = 'syscheck_sockets'
27
+ Fluent::Plugin.register_input(NAME, self)
28
+
29
+ helpers :event_emitter, :timer
30
+
31
+ INTERVAL = 300
32
+
33
+ DEFAULT_LIST = false
34
+ DEFAULT_FIRST_RUN_WAIT_INTERVAL = true
35
+
36
+ desc 'The tag of the event is emitted on'
37
+ config_param :tag, :string
38
+ desc 'interval for probe execution'
39
+ config_param :interval, :time, default: INTERVAL
40
+ desc 'Wait interval for first execution'
41
+ config_param :first_run_wait_interval, :bool, default: DEFAULT_FIRST_RUN_WAIT_INTERVAL
42
+
43
+ desc 'List sockets'
44
+ config_param :list_sockets, :bool, default: DEFAULT_LIST
45
+
46
+ def configure(conf)
47
+ super
48
+
49
+ raise Fluent::ConfigError, 'tag should not be empty' if tag.nil? || tag.empty?
50
+ end
51
+
52
+ def start
53
+ super
54
+
55
+ timer_execute(:run_check_first, 1, repeat: false, &method(:run_check)) unless first_run_wait_interval
56
+ timer_execute(:run_check, interval, repeat: true, &method(:run_check))
57
+ end
58
+
59
+ def run_check
60
+ run_check_tcp4
61
+ end
62
+
63
+ def run_check_tcp4
64
+ tcp4_content = read_file_content('/proc/net/tcp')
65
+ parser = ProcFS::Parser::NetTcpParser.new
66
+ tcp4_info = parser.parse(tcp4_content)
67
+
68
+ emit_list_sockets(tcp4_info) if list_sockets
69
+ end
70
+
71
+ def emit_list_sockets(sockets)
72
+ log.debug "#{NAME}: emit list_sockets"
73
+
74
+ event_time = Fluent::EventTime.from_time(sockets.timestamp)
75
+ sockets.each do |socket|
76
+ router.emit(
77
+ tag,
78
+ event_time,
79
+ socket.to_h
80
+ .merge('timestamp' => sockets.timestamp.iso8601(3))
81
+ )
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ def read_file_content(path)
88
+ File.read(path)
89
+ rescue Errno::ENOENT => e
90
+ log.error "#{NAME}: can't read \"#{path}\" content: #{e}"
91
+ end
92
+ end
93
+ end
94
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-syscheck
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Tych
@@ -29,114 +29,128 @@ dependencies:
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: '2.5'
32
+ version: '4.0'
33
33
  - - ">="
34
34
  - !ruby/object:Gem::Version
35
- version: 2.5.9
35
+ version: 4.0.21
36
36
  type: :development
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
40
  - - "~>"
41
41
  - !ruby/object:Gem::Version
42
- version: '2.5'
42
+ version: '4.0'
43
43
  - - ">="
44
44
  - !ruby/object:Gem::Version
45
- version: 2.5.9
45
+ version: 4.0.21
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: byebug
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  requirements:
50
50
  - - "~>"
51
51
  - !ruby/object:Gem::Version
52
- version: '11.1'
52
+ version: '13.0'
53
+ type: :development
54
+ prerelease: false
55
+ version_requirements: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '13.0'
60
+ - !ruby/object:Gem::Dependency
61
+ name: irb
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '1.18'
53
67
  - - ">="
54
68
  - !ruby/object:Gem::Version
55
- version: 11.1.3
69
+ version: 1.18.0
56
70
  type: :development
57
71
  prerelease: false
58
72
  version_requirements: !ruby/object:Gem::Requirement
59
73
  requirements:
60
74
  - - "~>"
61
75
  - !ruby/object:Gem::Version
62
- version: '11.1'
76
+ version: '1.18'
63
77
  - - ">="
64
78
  - !ruby/object:Gem::Version
65
- version: 11.1.3
79
+ version: 1.18.0
66
80
  - !ruby/object:Gem::Dependency
67
81
  name: mocha
68
82
  requirement: !ruby/object:Gem::Requirement
69
83
  requirements:
70
84
  - - "~>"
71
85
  - !ruby/object:Gem::Version
72
- version: '2.7'
86
+ version: '3.1'
73
87
  - - ">="
74
88
  - !ruby/object:Gem::Version
75
- version: 2.7.1
89
+ version: 3.1.0
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: '2.7'
96
+ version: '3.1'
83
97
  - - ">="
84
98
  - !ruby/object:Gem::Version
85
- version: 2.7.1
99
+ version: 3.1.0
86
100
  - !ruby/object:Gem::Dependency
87
101
  name: rake
88
102
  requirement: !ruby/object:Gem::Requirement
89
103
  requirements:
90
104
  - - "~>"
91
105
  - !ruby/object:Gem::Version
92
- version: '13.2'
106
+ version: '13.4'
93
107
  - - ">="
94
108
  - !ruby/object:Gem::Version
95
- version: 13.2.1
109
+ version: 13.4.2
96
110
  type: :development
97
111
  prerelease: false
98
112
  version_requirements: !ruby/object:Gem::Requirement
99
113
  requirements:
100
114
  - - "~>"
101
115
  - !ruby/object:Gem::Version
102
- version: '13.2'
116
+ version: '13.4'
103
117
  - - ">="
104
118
  - !ruby/object:Gem::Version
105
- version: 13.2.1
119
+ version: 13.4.2
106
120
  - !ruby/object:Gem::Dependency
107
121
  name: reek
108
122
  requirement: !ruby/object:Gem::Requirement
109
123
  requirements:
110
124
  - - "~>"
111
125
  - !ruby/object:Gem::Version
112
- version: '6.4'
126
+ version: '6.5'
113
127
  type: :development
114
128
  prerelease: false
115
129
  version_requirements: !ruby/object:Gem::Requirement
116
130
  requirements:
117
131
  - - "~>"
118
132
  - !ruby/object:Gem::Version
119
- version: '6.4'
133
+ version: '6.5'
120
134
  - !ruby/object:Gem::Dependency
121
135
  name: rubocop
122
136
  requirement: !ruby/object:Gem::Requirement
123
137
  requirements:
124
138
  - - "~>"
125
139
  - !ruby/object:Gem::Version
126
- version: '1.73'
140
+ version: '1.91'
127
141
  - - ">="
128
142
  - !ruby/object:Gem::Version
129
- version: 1.73.1
143
+ version: 1.91.0
130
144
  type: :development
131
145
  prerelease: false
132
146
  version_requirements: !ruby/object:Gem::Requirement
133
147
  requirements:
134
148
  - - "~>"
135
149
  - !ruby/object:Gem::Version
136
- version: '1.73'
150
+ version: '1.91'
137
151
  - - ">="
138
152
  - !ruby/object:Gem::Version
139
- version: 1.73.1
153
+ version: 1.91.0
140
154
  - !ruby/object:Gem::Dependency
141
155
  name: rubocop-rake
142
156
  requirement: !ruby/object:Gem::Requirement
@@ -163,34 +177,40 @@ dependencies:
163
177
  requirements:
164
178
  - - "~>"
165
179
  - !ruby/object:Gem::Version
166
- version: '0.22'
180
+ version: '1.3'
181
+ - - ">="
182
+ - !ruby/object:Gem::Version
183
+ version: 1.3.1
167
184
  type: :development
168
185
  prerelease: false
169
186
  version_requirements: !ruby/object:Gem::Requirement
170
187
  requirements:
171
188
  - - "~>"
172
189
  - !ruby/object:Gem::Version
173
- version: '0.22'
190
+ version: '1.3'
191
+ - - ">="
192
+ - !ruby/object:Gem::Version
193
+ version: 1.3.1
174
194
  - !ruby/object:Gem::Dependency
175
195
  name: test-unit
176
196
  requirement: !ruby/object:Gem::Requirement
177
197
  requirements:
178
198
  - - "~>"
179
199
  - !ruby/object:Gem::Version
180
- version: '3.6'
200
+ version: '3.7'
181
201
  - - ">="
182
202
  - !ruby/object:Gem::Version
183
- version: 3.6.7
203
+ version: 3.7.8
184
204
  type: :development
185
205
  prerelease: false
186
206
  version_requirements: !ruby/object:Gem::Requirement
187
207
  requirements:
188
208
  - - "~>"
189
209
  - !ruby/object:Gem::Version
190
- version: '3.6'
210
+ version: '3.7'
191
211
  - - ">="
192
212
  - !ruby/object:Gem::Version
193
- version: 3.6.7
213
+ version: 3.7.8
194
214
  - !ruby/object:Gem::Dependency
195
215
  name: timecop
196
216
  requirement: !ruby/object:Gem::Requirement
@@ -200,7 +220,7 @@ dependencies:
200
220
  version: '0.9'
201
221
  - - ">="
202
222
  - !ruby/object:Gem::Version
203
- version: 0.9.10
223
+ version: 0.9.11
204
224
  type: :development
205
225
  prerelease: false
206
226
  version_requirements: !ruby/object:Gem::Requirement
@@ -210,7 +230,7 @@ dependencies:
210
230
  version: '0.9'
211
231
  - - ">="
212
232
  - !ruby/object:Gem::Version
213
- version: 0.9.10
233
+ version: 0.9.11
214
234
  - !ruby/object:Gem::Dependency
215
235
  name: fluentd
216
236
  requirement: !ruby/object:Gem::Requirement
@@ -231,6 +251,26 @@ dependencies:
231
251
  - - "<"
232
252
  - !ruby/object:Gem::Version
233
253
  version: '2'
254
+ - !ruby/object:Gem::Dependency
255
+ name: procfs_rb
256
+ requirement: !ruby/object:Gem::Requirement
257
+ requirements:
258
+ - - "~>"
259
+ - !ruby/object:Gem::Version
260
+ version: '0.1'
261
+ - - ">="
262
+ - !ruby/object:Gem::Version
263
+ version: 0.1.1
264
+ type: :runtime
265
+ prerelease: false
266
+ version_requirements: !ruby/object:Gem::Requirement
267
+ requirements:
268
+ - - "~>"
269
+ - !ruby/object:Gem::Version
270
+ version: '0.1'
271
+ - - ">="
272
+ - !ruby/object:Gem::Version
273
+ version: 0.1.1
234
274
  email:
235
275
  - thomas.tych@gmail.com
236
276
  executables: []
@@ -242,6 +282,7 @@ files:
242
282
  - README.md
243
283
  - Rakefile
244
284
  - lib/fluent/plugin/in_syscheck_mounts.rb
285
+ - lib/fluent/plugin/in_syscheck_sockets.rb
245
286
  homepage: https://gitlab.com/ttych/fluent-plugin-syscheck
246
287
  licenses:
247
288
  - Apache-2.0
@@ -256,14 +297,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
256
297
  requirements:
257
298
  - - ">="
258
299
  - !ruby/object:Gem::Version
259
- version: 3.1.0
300
+ version: 3.2.0
260
301
  required_rubygems_version: !ruby/object:Gem::Requirement
261
302
  requirements:
262
303
  - - ">="
263
304
  - !ruby/object:Gem::Version
264
305
  version: '0'
265
306
  requirements: []
266
- rubygems_version: 3.6.7
307
+ rubygems_version: 4.0.21
267
308
  specification_version: 4
268
309
  summary: fluentd plugin to check system part
269
310
  test_files: []