fluent-plugin-jfrog-siem 1.0.0 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,111 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause
4
+ # this file to always be loaded, without a need to explicitly require it in any
5
+ # files.
6
+ #
7
+ # Given that it is always loaded, you are encouraged to keep this file as
8
+ # light-weight as possible. Requiring heavyweight dependencies from this file
9
+ # will add to the boot time of your test suite on EVERY test run, even for an
10
+ # individual file that may not need all of that loaded. Instead, consider making
11
+ # a separate helper file that requires the additional dependencies and performs
12
+ # the additional setup, and require it from the spec files that actually need
13
+ # it.
14
+ #
15
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
16
+
17
+ [
18
+ File.join(File.dirname(__FILE__), '..'),
19
+ File.join(File.dirname(__FILE__), '..', 'lib/fluent/plugin'),
20
+ File.join(File.dirname(__FILE__), '..', 'spec'),
21
+ ].each do |dir|
22
+ $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir)
23
+ end
24
+
25
+ require 'xray'
26
+
27
+ RSpec.configure do |config|
28
+ # rspec-expectations config goes here. You can use an alternate
29
+ # assertion/expectation library such as wrong or the stdlib/minitest
30
+ # assertions if you prefer.
31
+ config.expect_with :rspec do |expectations|
32
+ # This option will default to `true` in RSpec 4. It makes the `description`
33
+ # and `failure_message` of custom matchers include text for helper methods
34
+ # defined using `chain`, e.g.:
35
+ # be_bigger_than(2).and_smaller_than(4).description
36
+ # # => "be bigger than 2 and smaller than 4"
37
+ # ...rather than:
38
+ # # => "be bigger than 2"
39
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
40
+ end
41
+
42
+ # rspec-mocks config goes here. You can use an alternate test double
43
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
44
+ config.mock_with :rspec do |mocks|
45
+ # Prevents you from mocking or stubbing a method that does not exist on
46
+ # a real object. This is generally recommended, and will default to
47
+ # `true` in RSpec 4.
48
+ mocks.verify_partial_doubles = true
49
+ end
50
+
51
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
52
+ # have no way to turn it off -- the option exists only for backwards
53
+ # compatibility in RSpec 3). It causes shared context metadata to be
54
+ # inherited by the metadata hash of host groups and examples, rather than
55
+ # triggering implicit auto-inclusion in groups with matching metadata.
56
+ config.shared_context_metadata_behavior = :apply_to_host_groups
57
+
58
+ # The settings below are suggested to provide a good initial experience
59
+ # with RSpec, but feel free to customize to your heart's content.
60
+ =begin
61
+ # This allows you to limit a spec run to individual examples or groups
62
+ # you care about by tagging them with `:focus` metadata. When nothing
63
+ # is tagged with `:focus`, all examples get run. RSpec also provides
64
+ # aliases for `it`, `describe`, and `context` that include `:focus`
65
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
66
+ config.filter_run_when_matching :focus
67
+
68
+ # Allows RSpec to persist some state between runs in order to support
69
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
70
+ # you configure your source control system to ignore this file.
71
+ config.example_status_persistence_file_path = "spec/examples.txt"
72
+
73
+ # Limits the available syntax to the non-monkey patched syntax that is
74
+ # recommended. For more details, see:
75
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
76
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
77
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
78
+ config.disable_monkey_patching!
79
+
80
+ # This setting enables warnings. It's recommended, but in some cases may
81
+ # be too noisy due to issues in dependencies.
82
+ config.warnings = true
83
+
84
+ # Many RSpec users commonly either run the entire suite or an individual
85
+ # file, and it's useful to allow more verbose output when running an
86
+ # individual spec file.
87
+ if config.files_to_run.one?
88
+ # Use the documentation formatter for detailed output,
89
+ # unless a formatter has already been configured
90
+ # (e.g. via a command-line flag).
91
+ config.default_formatter = "doc"
92
+ end
93
+
94
+ # Print the 10 slowest examples and example groups at the
95
+ # end of the spec run, to help surface which specs are running
96
+ # particularly slow.
97
+ config.profile_examples = 10
98
+
99
+ # Run specs in random order to surface order dependencies. If you find an
100
+ # order dependency and want to debug it, you can fix the order by providing
101
+ # the seed, which is printed after each run.
102
+ # --seed 1234
103
+ config.order = :random
104
+
105
+ # Seed global randomization in this process using the `--seed` CLI option.
106
+ # Setting this allows you to use `--seed` to deterministically reproduce
107
+ # test failures related to randomization by passing the same `--seed` value
108
+ # as the one that triggered the failure.
109
+ Kernel.srand config.seed
110
+ =end
111
+ end
data/spec/xray_spec.rb ADDED
@@ -0,0 +1,135 @@
1
+ [
2
+ File.join(File.dirname(__FILE__), '..'),
3
+ File.join(File.dirname(__FILE__), '..', 'lib/fluent/plugin'),
4
+ File.join(File.dirname(__FILE__), '..', 'spec'),
5
+ ].each do |dir|
6
+ $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir)
7
+ end
8
+
9
+ require 'xray'
10
+ require 'date'
11
+ require 'rspec'
12
+ require 'rest-client'
13
+
14
+
15
+ RSpec.describe Xray do
16
+ describe "#violation_details" do
17
+
18
+ let(:violation1){ { "created": Date.parse(Date.today.to_s).strftime("%Y-%m-%dT%H:%M:%SZ"),
19
+ "watch_name": "watch1",
20
+ "issue_id": "55444",
21
+ "violation_details_url": "http://www.com"}
22
+ }
23
+ let(:violation2){ { "created": Date.parse(Date.today.to_s).strftime("%Y-%m-%dT%H:%M:%SZ"),
24
+ "watch_name": "watch2",
25
+ "issue_id": "55443",
26
+ "violation_details_url": "http://www.com"}
27
+ }
28
+
29
+ let(:violations) { Concurrent::Array.new }
30
+
31
+ it "creates a future for every violation" do
32
+ xray = Xray.new(@jpd_url, @username, @apikey, @wait_interval, @batch_size, @pos_file_path, @router, @tag)
33
+
34
+ (1..5).each do |i|
35
+ violations << i
36
+ end
37
+
38
+ promises = class_double("Concurrent::Promises").as_stubbed_const(:transfer_nested_constants => true)
39
+ expect(promises).to receive(:future).exactly(5).times
40
+
41
+ xray.violation_details(violations)
42
+ end
43
+
44
+ it "updates pos file for every violation (cannot do exactly tests since stubs with Concurrent ruby are broken)" do
45
+ router = double('router')
46
+ pos_file_path = `pwd`
47
+ xray = Xray.new(@jpd_url, @username, @apikey, @wait_interval, @batch_size, pos_file_path, router, @tag)
48
+
49
+ violations << JSON.parse(violation1.to_json)
50
+ violations << JSON.parse(violation2.to_json)
51
+
52
+ promises = class_double("Concurrent::Promises").as_stubbed_const(:transfer_nested_constants => true)
53
+ allow(promises).to receive(:future).and_yield(violation1).and_yield(violation2)
54
+
55
+ rest_client = double("RestClient::Request")
56
+ allow(RestClient::Request).to receive(:new).and_return rest_client
57
+ allow(rest_client).to receive(:execute).and_return(JSON.parse({'impacted_artifacts': []}.to_json))
58
+
59
+ pos_file = double(PositionFile)
60
+ allow(PositionFile).to receive(:new).and_return pos_file
61
+ allow(pos_file).to receive(:write)
62
+
63
+ fluent = class_double("Fluent::Engine").as_stubbed_const(:transfer_nested_constants => true)
64
+ allow(fluent).to receive(:now).and_return(DateTime.now)
65
+ allow(router).to receive(:emit)
66
+
67
+ xray.violation_details(JSON.parse(violations.to_json))
68
+ end
69
+ end
70
+
71
+ describe "#violations" do
72
+ it "runs a timer task to process violations periodically" do
73
+ batch_size = 25
74
+ pos_file_path = `pwd`
75
+ router = double('router')
76
+ xray = Xray.new(@jpd_url, @username, @apikey, @wait_interval, batch_size, pos_file_path, router, @tag)
77
+
78
+ channel = double(Concurrent::Channel)
79
+ expect(Concurrent::Channel).to receive(:new).with(capacity: batch_size).and_return(channel)
80
+
81
+ timer_task = double(Concurrent::TimerTask)
82
+ expect(Concurrent::TimerTask).to receive(:new).and_return timer_task
83
+
84
+ expect(timer_task).to receive(:execute)
85
+ xray.violations(Date.today)
86
+ end
87
+
88
+ end
89
+
90
+ describe "#process" do
91
+ let(:violation1){ { "created": Date.parse(Date.today.to_s).strftime("%Y-%m-%dT%H:%M:%SZ"),
92
+ "watch_name": "watch1",
93
+ "issue_id": "55444",
94
+ "violation_details_url": "http://www.com"}
95
+ }
96
+ let(:violation2){ { "created": Date.parse(Date.today.to_s).strftime("%Y-%m-%dT%H:%M:%SZ"),
97
+ "watch_name": "watch2",
98
+ "issue_id": "55443",
99
+ "violation_details_url": "http://www.com"}
100
+ }
101
+
102
+ let(:violations_channel) { Concurrent::Array.new }
103
+
104
+ it "skips processed violation" do
105
+ pos_file_path = `pwd`
106
+ xray = Xray.new(@jpd_url, @username, @apikey, @wait_interval, @batch_size, @pos_file_path, @router, @tag)
107
+
108
+ violations_channel << violation1
109
+
110
+ pos_file = double(PositionFile)
111
+ allow(PositionFile).to receive(:new).and_return pos_file
112
+ allow(pos_file).to receive(:processed?).and_return true
113
+
114
+ xray.process(violation1, violations_channel)
115
+
116
+ expect(violations_channel.size).to eq 1
117
+ end
118
+
119
+ it "adds unprocessed violation to the channel" do
120
+ pos_file_path = `pwd`
121
+ xray = Xray.new(@jpd_url, @username, @apikey, @wait_interval, @batch_size, @pos_file_path, @router, @tag)
122
+
123
+ violations_channel << violation1
124
+
125
+ pos_file = double(PositionFile)
126
+ allow(PositionFile).to receive(:new).and_return pos_file
127
+ allow(pos_file).to receive(:processed?).and_return false
128
+
129
+ xray.process(violation2, violations_channel)
130
+
131
+ expect(violations_channel.size).to eq 2
132
+ end
133
+ end
134
+
135
+ end
data/test/helper.rb CHANGED
@@ -4,5 +4,6 @@ require "fluent/test"
4
4
  require "fluent/test/driver/input"
5
5
  require "fluent/test/helpers"
6
6
 
7
+
7
8
  Test::Unit::TestCase.include(Fluent::Test::Helpers)
8
9
  Test::Unit::TestCase.extend(Fluent::Test::Helpers)
@@ -12,12 +12,15 @@ class JfrogSiemInputTest < Test::Unit::TestCase
12
12
 
13
13
  # Default configuration for tests
14
14
  CONFIG = %[
15
- tag "test_tag"
16
- jpd_url JPD_URL
17
- username USER
18
- apikey API_KEY
19
- pos_file "test_pos.txt"
20
- ]
15
+ tag "jfrog.xray.siem.vulnerabilities"
16
+ jpd_url "JPDURL"
17
+ username "admin"
18
+ apikey "APIKEY"
19
+ pos_file_path "#{ENV['JF_PRODUCT_DATA_INTERNAL']}/log/"
20
+ wait_interval 10
21
+ from_date "2016-01-01"
22
+ batch_size 25
23
+ ]
21
24
 
22
25
  private
23
26
 
@@ -28,7 +31,11 @@ class JfrogSiemInputTest < Test::Unit::TestCase
28
31
  sub_test_case 'Testing' do
29
32
  test 'Testing plugin in_jfrog_siem' do
30
33
  d = create_driver(CONFIG)
31
- d.run
34
+ begin
35
+ d.run
36
+ rescue => e
37
+ raise "Test failed due to #{e}"
38
+ end
32
39
  end
33
40
  end
34
41
  end
metadata CHANGED
@@ -1,15 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-jfrog-siem
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
- - John Peterson
8
7
  - Mahitha Byreddy
9
- autorequire:
8
+ - Sudhindra Rao
9
+ - Giridharan Ramasamy
10
+ autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2021-05-18 00:00:00.000000000 Z
13
+ date: 2022-03-16 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: bundler
@@ -68,33 +69,89 @@ dependencies:
68
69
  - !ruby/object:Gem::Version
69
70
  version: '2.0'
70
71
  - !ruby/object:Gem::Dependency
71
- name: thread
72
+ name: concurrent-ruby
72
73
  requirement: !ruby/object:Gem::Requirement
73
74
  requirements:
74
75
  - - "~>"
75
76
  - !ruby/object:Gem::Version
76
- version: 0.2.2
77
+ version: 1.1.8
77
78
  type: :development
78
79
  prerelease: false
79
80
  version_requirements: !ruby/object:Gem::Requirement
80
81
  requirements:
81
82
  - - "~>"
82
83
  - !ruby/object:Gem::Version
83
- version: 0.2.2
84
+ version: 1.1.8
84
85
  - !ruby/object:Gem::Dependency
85
- name: thread
86
+ name: concurrent-ruby-edge
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ type: :development
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ - !ruby/object:Gem::Dependency
100
+ name: rspec
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - "~>"
104
+ - !ruby/object:Gem::Version
105
+ version: 3.10.0
106
+ type: :development
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - "~>"
111
+ - !ruby/object:Gem::Version
112
+ version: 3.10.0
113
+ - !ruby/object:Gem::Dependency
114
+ name: rest-client
86
115
  requirement: !ruby/object:Gem::Requirement
87
116
  requirements:
88
117
  - - "~>"
89
118
  - !ruby/object:Gem::Version
90
- version: 0.2.2
119
+ version: '2.0'
91
120
  type: :runtime
92
121
  prerelease: false
93
122
  version_requirements: !ruby/object:Gem::Requirement
94
123
  requirements:
95
124
  - - "~>"
96
125
  - !ruby/object:Gem::Version
97
- version: 0.2.2
126
+ version: '2.0'
127
+ - !ruby/object:Gem::Dependency
128
+ name: concurrent-ruby
129
+ requirement: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - "~>"
132
+ - !ruby/object:Gem::Version
133
+ version: 1.1.8
134
+ type: :runtime
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - "~>"
139
+ - !ruby/object:Gem::Version
140
+ version: 1.1.8
141
+ - !ruby/object:Gem::Dependency
142
+ name: concurrent-ruby-edge
143
+ requirement: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ type: :runtime
149
+ prerelease: false
150
+ version_requirements: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
98
155
  - !ruby/object:Gem::Dependency
99
156
  name: fluentd
100
157
  requirement: !ruby/object:Gem::Requirement
@@ -118,26 +175,34 @@ dependencies:
118
175
  description: JFrog SIEM fluent input plugin will send the SIEM events from JFrog Xray
119
176
  to Fluentd which can then be delivered to whatever output plugin specified
120
177
  email:
121
- - johnp@jfrog.com
122
178
  - mahithab@jfrog.com
179
+ - sudhindrar@jfrog.com
180
+ - girir@jfrog.com
123
181
  executables: []
124
182
  extensions: []
125
183
  extra_rdoc_files: []
126
184
  files:
127
- - CHANGELOG.md
185
+ - ".rspec"
128
186
  - Gemfile
187
+ - Gemfile.lock
129
188
  - LICENSE
130
189
  - README.md
131
190
  - Rakefile
132
191
  - fluent-plugin-jfrog-siem.gemspec
133
192
  - lib/fluent/plugin/in_jfrog_siem.rb
193
+ - lib/fluent/plugin/position_file.rb
194
+ - lib/fluent/plugin/violations.json
195
+ - lib/fluent/plugin/xray.rb
196
+ - spec/position_file_spec.rb
197
+ - spec/spec_helper.rb
198
+ - spec/xray_spec.rb
134
199
  - test/helper.rb
135
200
  - test/plugin/test_in_jfrog_siem.rb
136
- homepage: https://github.com/jfrog/log-analytics
201
+ homepage: https://github.com/jfrog/fluent-plugin-jfrog-siem
137
202
  licenses:
138
203
  - Apache-2.0
139
204
  metadata: {}
140
- post_install_message:
205
+ post_install_message:
141
206
  rdoc_options: []
142
207
  require_paths:
143
208
  - lib
@@ -152,11 +217,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
152
217
  - !ruby/object:Gem::Version
153
218
  version: '0'
154
219
  requirements: []
155
- rubygems_version: 3.0.3
156
- signing_key:
220
+ rubygems_version: 3.1.6
221
+ signing_key:
157
222
  specification_version: 4
158
223
  summary: JFrog SIEM fluent input plugin will send the SIEM events from JFrog Xray
159
224
  to Fluentd
160
225
  test_files:
226
+ - spec/position_file_spec.rb
227
+ - spec/spec_helper.rb
228
+ - spec/xray_spec.rb
161
229
  - test/helper.rb
162
230
  - test/plugin/test_in_jfrog_siem.rb
data/CHANGELOG.md DELETED
@@ -1,36 +0,0 @@
1
- # JFrog Fluentd SIEM Input Plugin Changelog
2
- All changes to the SIEM plugin will be documented in this file.
3
-
4
- ## [1.0.0] - May 18, 2020
5
- * [BREAKING] Using JFrog API Key for authentication
6
-
7
- ## [0.1.9] - May 17, 2021
8
- * Handling the case where violations are left in a batch to be processed
9
-
10
- ## [0.1.8] - May 10, 2021
11
- * Fixing persist, not persist item conditions
12
-
13
- ## [0.1.7] - April 21, 2021
14
- * Adding policies and rules to payload
15
-
16
- ## [0.1.6] - April 13, 2021
17
- * Adding additonal parameters to match with access logs for correlation
18
-
19
- ## [0.1.5] - March 29, 2021
20
- * Normalizing the format of Impacted Artifact, fixing properties not found case
21
-
22
- ## [0.1.4] - February 02, 2021
23
- * Adding dependencies, gemspec updates
24
-
25
- ## [0.1.3] - January 21, 2021
26
- * Fixing thread pool issues (moving loop inside a thread pool)
27
-
28
- ## [0.1.2] - November 17, 2020
29
- * Changes to better README
30
-
31
- ## [0.1.1] - November 17, 2020
32
- * Adding dependencies to gemspec
33
-
34
- ## [0.1.0] - October 05, 2020
35
- * Initial release of Jfrog Logs Analytic integration
36
-