fluent-plugin-jfrog-siem 2.0.7 → 2.0.9
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/Gemfile.lock +30 -19
- data/fluent-plugin-jfrog-siem.gemspec +3 -5
- data/lib/fluent/plugin/xray.rb +18 -5
- data/spec/data_normalization_spec.rb +300 -0
- metadata +7 -48
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 74c423ae40c052a7a8f53ff8f8d744ffcaa2032553f9c331866fdc1b186ce076
|
|
4
|
+
data.tar.gz: e7e096bda67598350f0502f91f0602542d616fb0406dfa1f1274a7b82ab0f0e0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ecc3e648b0a7f9d68262e0aed5a403c3c3ebc7ab345234f7156997079c37a3ed5548a33cac35f80be129bfd5cfae665672ed64db58ed197b2340af61a702d099
|
|
7
|
+
data.tar.gz: cc261ed12d53934671349002785cb037b064a4abac399bf7dca783568a4586da8dcb4c9d665e6cd885654aca0a6fe1f51a7f3aaaffbba04f6627a53bb0115d45
|
data/Gemfile.lock
CHANGED
|
@@ -1,41 +1,49 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
fluent-plugin-jfrog-siem (
|
|
5
|
-
concurrent-ruby (~> 1.1.8)
|
|
4
|
+
fluent-plugin-jfrog-siem (2.0.9)
|
|
6
5
|
concurrent-ruby-edge
|
|
7
6
|
fluentd (>= 0.14.10, < 2)
|
|
7
|
+
rest-client (~> 2.0)
|
|
8
8
|
|
|
9
9
|
GEM
|
|
10
10
|
remote: https://rubygems.org/
|
|
11
11
|
specs:
|
|
12
|
+
base64 (0.2.0)
|
|
12
13
|
concurrent-ruby (1.1.8)
|
|
13
14
|
concurrent-ruby-edge (0.6.0)
|
|
14
15
|
concurrent-ruby (~> 1.1.6)
|
|
15
|
-
cool.io (1.
|
|
16
|
+
cool.io (1.9.0)
|
|
17
|
+
csv (3.3.0)
|
|
16
18
|
diff-lcs (1.4.4)
|
|
17
19
|
domain_name (0.5.20190701)
|
|
18
20
|
unf (>= 0.0.5, < 1.0.0)
|
|
19
|
-
|
|
21
|
+
drb (2.2.1)
|
|
22
|
+
fluentd (1.17.1)
|
|
23
|
+
base64 (~> 0.2)
|
|
20
24
|
bundler
|
|
21
25
|
cool.io (>= 1.4.5, < 2.0.0)
|
|
22
|
-
|
|
26
|
+
csv (~> 3.2)
|
|
27
|
+
drb (~> 2.2)
|
|
28
|
+
http_parser.rb (>= 0.5.1, < 0.9.0)
|
|
29
|
+
logger (~> 1.6)
|
|
23
30
|
msgpack (>= 1.3.1, < 2.0.0)
|
|
24
|
-
serverengine (>= 2.
|
|
25
|
-
sigdump (~> 0.2.
|
|
26
|
-
strptime (>= 0.2.
|
|
31
|
+
serverengine (>= 2.3.2, < 3.0.0)
|
|
32
|
+
sigdump (~> 0.2.5)
|
|
33
|
+
strptime (>= 0.2.4, < 1.0.0)
|
|
27
34
|
tzinfo (>= 1.0, < 3.0)
|
|
28
35
|
tzinfo-data (~> 1.0)
|
|
29
|
-
webrick (
|
|
36
|
+
webrick (~> 1.4)
|
|
30
37
|
yajl-ruby (~> 1.0)
|
|
31
38
|
http-accept (1.7.0)
|
|
32
39
|
http-cookie (1.0.3)
|
|
33
40
|
domain_name (~> 0.5)
|
|
34
|
-
http_parser.rb (0.
|
|
41
|
+
http_parser.rb (0.8.0)
|
|
42
|
+
logger (1.6.1)
|
|
35
43
|
mime-types (3.3.1)
|
|
36
44
|
mime-types-data (~> 3.2015)
|
|
37
45
|
mime-types-data (3.2021.0225)
|
|
38
|
-
msgpack (1.
|
|
46
|
+
msgpack (1.7.3)
|
|
39
47
|
netrc (0.11.0)
|
|
40
48
|
power_assert (2.0.0)
|
|
41
49
|
rake (12.3.3)
|
|
@@ -57,28 +65,31 @@ GEM
|
|
|
57
65
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
58
66
|
rspec-support (~> 3.10.0)
|
|
59
67
|
rspec-support (3.10.2)
|
|
60
|
-
serverengine (2.
|
|
68
|
+
serverengine (2.4.0)
|
|
69
|
+
base64 (~> 0.1)
|
|
70
|
+
logger (~> 1.4)
|
|
61
71
|
sigdump (~> 0.2.2)
|
|
62
|
-
sigdump (0.2.
|
|
72
|
+
sigdump (0.2.5)
|
|
63
73
|
strptime (0.2.5)
|
|
64
74
|
test-unit (3.4.2)
|
|
65
75
|
power_assert
|
|
66
|
-
tzinfo (2.0.
|
|
76
|
+
tzinfo (2.0.6)
|
|
67
77
|
concurrent-ruby (~> 1.0)
|
|
68
|
-
tzinfo-data (1.
|
|
78
|
+
tzinfo-data (1.2024.2)
|
|
69
79
|
tzinfo (>= 1.0.0)
|
|
70
80
|
unf (0.1.4)
|
|
71
81
|
unf_ext
|
|
72
82
|
unf_ext (0.0.7.7)
|
|
73
|
-
webrick (1.
|
|
74
|
-
yajl-ruby (1.4.
|
|
83
|
+
webrick (1.9.0)
|
|
84
|
+
yajl-ruby (1.4.3)
|
|
75
85
|
|
|
76
86
|
PLATFORMS
|
|
87
|
+
arm64-darwin-23
|
|
77
88
|
x86_64-darwin-20
|
|
89
|
+
x86_64-linux
|
|
78
90
|
|
|
79
91
|
DEPENDENCIES
|
|
80
92
|
bundler (~> 2.0)
|
|
81
|
-
concurrent-ruby (~> 1.1.8)
|
|
82
93
|
concurrent-ruby-edge
|
|
83
94
|
fluent-plugin-jfrog-siem!
|
|
84
95
|
rake (~> 12.0)
|
|
@@ -87,4 +98,4 @@ DEPENDENCIES
|
|
|
87
98
|
test-unit (~> 3.0)
|
|
88
99
|
|
|
89
100
|
BUNDLED WITH
|
|
90
|
-
2.
|
|
101
|
+
2.4.19
|
|
@@ -3,9 +3,9 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
|
3
3
|
|
|
4
4
|
Gem::Specification.new do |spec|
|
|
5
5
|
spec.name = "fluent-plugin-jfrog-siem"
|
|
6
|
-
spec.version = "2.0.
|
|
7
|
-
spec.authors = ["Mahitha Byreddy", "
|
|
8
|
-
spec.email = ["
|
|
6
|
+
spec.version = "2.0.9"
|
|
7
|
+
spec.authors = ["Mahitha Byreddy", "Ben Harosh"]
|
|
8
|
+
spec.email = ["partner-support@jfrog.com"]
|
|
9
9
|
|
|
10
10
|
spec.summary = %q{JFrog SIEM fluent input plugin will send the SIEM events from JFrog Xray to Fluentd}
|
|
11
11
|
spec.description = %q{JFrog SIEM fluent input plugin will send the SIEM events from JFrog Xray to Fluentd which can then be delivered to whatever output plugin specified}
|
|
@@ -24,12 +24,10 @@ Gem::Specification.new do |spec|
|
|
|
24
24
|
spec.add_development_dependency "rake", "~> 12.0"
|
|
25
25
|
spec.add_development_dependency "test-unit", "~> 3.0"
|
|
26
26
|
spec.add_development_dependency "rest-client", "~> 2.0"
|
|
27
|
-
spec.add_development_dependency "concurrent-ruby", "~> 1.1.8" , "< 1.1.10"
|
|
28
27
|
spec.add_development_dependency "concurrent-ruby-edge", '>= 0'
|
|
29
28
|
spec.add_development_dependency 'rspec', '~> 3.10.0'
|
|
30
29
|
|
|
31
30
|
spec.add_runtime_dependency "rest-client", "~> 2.0"
|
|
32
|
-
spec.add_runtime_dependency "concurrent-ruby", "~> 1.1.8" , "< 1.1.10"
|
|
33
31
|
spec.add_runtime_dependency "concurrent-ruby-edge", '>= 0'
|
|
34
32
|
spec.add_runtime_dependency "fluentd", [">= 0.14.10", "< 2"]
|
|
35
33
|
end
|
data/lib/fluent/plugin/xray.rb
CHANGED
|
@@ -90,6 +90,7 @@ class Xray
|
|
|
90
90
|
cve = []
|
|
91
91
|
cvss_v2_list = []
|
|
92
92
|
cvss_v3_list = []
|
|
93
|
+
cvss_v4_list = []
|
|
93
94
|
policy_list = []
|
|
94
95
|
rule_list = []
|
|
95
96
|
impacted_artifact_url_list = []
|
|
@@ -105,20 +106,32 @@ class Xray
|
|
|
105
106
|
if properties[index].key?('cvss_v3')
|
|
106
107
|
cvss_v3_list.push(properties[index]['cvss_v3'])
|
|
107
108
|
end
|
|
109
|
+
if properties[index].key?('cvss_v4')
|
|
110
|
+
cvss_v4_list.push(properties[index]['cvss_v4'])
|
|
111
|
+
end
|
|
108
112
|
end
|
|
109
113
|
|
|
110
114
|
detailResp_json["cve"] = cve.sort.reverse[0]
|
|
111
115
|
cvss_v2 = cvss_v2_list.sort.reverse[0]
|
|
112
116
|
cvss_v3 = cvss_v3_list.sort.reverse[0]
|
|
117
|
+
cvss_v4 = cvss_v4_list.sort.reverse[0]
|
|
118
|
+
# cvss_v4 is only a fallback so the reported score doesn't change for violations that also have v3/v2
|
|
113
119
|
if !cvss_v3.nil?
|
|
114
120
|
cvss = cvss_v3
|
|
115
121
|
elsif !cvss_v2.nil?
|
|
116
122
|
cvss = cvss_v2
|
|
123
|
+
elsif !cvss_v4.nil?
|
|
124
|
+
cvss = cvss_v4
|
|
125
|
+
end
|
|
126
|
+
if !cvss.nil?
|
|
127
|
+
cvss_score = cvss[0..2]
|
|
128
|
+
detailResp_json["cvss_score"] = cvss_score
|
|
129
|
+
# A score without a vector (e.g. "2.4") has no ':' to take the version from
|
|
130
|
+
cvss_version_part = cvss.split(':')[1]
|
|
131
|
+
if !cvss_version_part.nil?
|
|
132
|
+
detailResp_json["cvss_version"] = cvss_version_part[0..2]
|
|
133
|
+
end
|
|
117
134
|
end
|
|
118
|
-
cvss_score = cvss[0..2]
|
|
119
|
-
cvss_version = cvss.split(':')[1][0..2]
|
|
120
|
-
detailResp_json["cvss_score"] = cvss_score
|
|
121
|
-
detailResp_json["cvss_version"] = cvss_version
|
|
122
135
|
end
|
|
123
136
|
|
|
124
137
|
if detailResp_json.key?('matched_policies')
|
|
@@ -135,7 +148,7 @@ class Xray
|
|
|
135
148
|
detailResp_json['rules'] = rule_list
|
|
136
149
|
end
|
|
137
150
|
|
|
138
|
-
detailResp_json['impacted_artifacts'].each do |impacted_artifact|
|
|
151
|
+
(detailResp_json['impacted_artifacts'] || []).each do |impacted_artifact|
|
|
139
152
|
matchdata = impacted_artifact.match /default\/(?<repo_name>[^\/]*)\/(?<path>.*)/
|
|
140
153
|
if matchdata
|
|
141
154
|
impacted_artifact_url = matchdata['repo_name'] + ":" + matchdata['path'] + " "
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
# spec/data_normalization_spec.rb
|
|
2
|
+
#
|
|
3
|
+
# Tests for Xray#data_normalization covering JOBS-2850:
|
|
4
|
+
# When violation properties lack cvss_v2 / cvss_v3 (e.g. Security violations
|
|
5
|
+
# for issues with no CVSS score, or only a CVSS v4 score) the method must NOT
|
|
6
|
+
# raise NoMethodError on `cvss[0..2]`.
|
|
7
|
+
#
|
|
8
|
+
# Expected results before the fix:
|
|
9
|
+
# - Violations without CVSS v2/v3 data → FAIL (demonstrates the bug)
|
|
10
|
+
# - CVSS score without a vector → FAIL
|
|
11
|
+
# - Missing impacted_artifacts → FAIL
|
|
12
|
+
# - Security-with-CVSS v2/v3 tests → PASS (existing logic is correct)
|
|
13
|
+
|
|
14
|
+
[
|
|
15
|
+
File.join(File.dirname(__FILE__), '..'),
|
|
16
|
+
File.join(File.dirname(__FILE__), '..', 'lib/fluent/plugin'),
|
|
17
|
+
File.join(File.dirname(__FILE__), '..', 'spec'),
|
|
18
|
+
].each do |dir|
|
|
19
|
+
$LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
require 'spec_helper'
|
|
23
|
+
|
|
24
|
+
RSpec.describe Xray, '#data_normalization' do
|
|
25
|
+
# Build an Xray instance with all dummy/nil params — we only need the method.
|
|
26
|
+
# Constructor signature: (jpd_url, username, api_key, token, wait_interval,
|
|
27
|
+
# batch_size, pos_file_path, router, tag)
|
|
28
|
+
subject(:xray) do
|
|
29
|
+
Xray.new(nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
33
|
+
# JOBS-2850: License violation — properties have no cvss_v2 / cvss_v3
|
|
34
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
35
|
+
describe 'License violation without CVSS data' do
|
|
36
|
+
let(:license_violation) do
|
|
37
|
+
{
|
|
38
|
+
'issue_id' => 'Apache-2.0',
|
|
39
|
+
'type' => 'License',
|
|
40
|
+
'properties' => [{ 'license' => 'Apache-2.0' }],
|
|
41
|
+
'impacted_artifacts' => ['default/maven-repo-1/com/example/foo/bar.jar']
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'does not raise an error (regression for JOBS-2850)' do
|
|
46
|
+
# BUG: cvss is nil → cvss[0..2] raises NoMethodError undefined method '[]' for nil
|
|
47
|
+
expect { xray.data_normalization(license_violation) }.not_to raise_error
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it 'returns a Hash' do
|
|
51
|
+
result = xray.data_normalization(license_violation)
|
|
52
|
+
expect(result).to be_a(Hash)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'does not set cvss_score when CVSS data is absent' do
|
|
56
|
+
result = xray.data_normalization(license_violation)
|
|
57
|
+
expect(result).not_to have_key('cvss_score')
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'does not set cvss_version when CVSS data is absent' do
|
|
61
|
+
result = xray.data_normalization(license_violation)
|
|
62
|
+
expect(result).not_to have_key('cvss_version')
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
67
|
+
# JOBS-2850: Operational Risk violation — properties have no cvss_v2 / cvss_v3
|
|
68
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
69
|
+
describe 'Operational Risk violation without CVSS data' do
|
|
70
|
+
let(:op_risk_violation) do
|
|
71
|
+
{
|
|
72
|
+
'issue_id' => 'EOL-component-1234',
|
|
73
|
+
'type' => 'Operational Risk',
|
|
74
|
+
'properties' => [{ 'end_of_life' => 'true' }],
|
|
75
|
+
'impacted_artifacts' => ['default/npm-repo/lodash/-/lodash-4.0.0.tgz']
|
|
76
|
+
}
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'does not raise an error (regression for JOBS-2850)' do
|
|
80
|
+
# BUG: same as License — cvss stays nil, cvss[0..2] crashes
|
|
81
|
+
expect { xray.data_normalization(op_risk_violation) }.not_to raise_error
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'returns a Hash' do
|
|
85
|
+
result = xray.data_normalization(op_risk_violation)
|
|
86
|
+
expect(result).to be_a(Hash)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'does not set cvss_score when CVSS data is absent' do
|
|
90
|
+
result = xray.data_normalization(op_risk_violation)
|
|
91
|
+
expect(result).not_to have_key('cvss_score')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'does not set cvss_version when CVSS data is absent' do
|
|
95
|
+
result = xray.data_normalization(op_risk_violation)
|
|
96
|
+
expect(result).not_to have_key('cvss_version')
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
101
|
+
# JOBS-2850: Security violation with a CVE but no CVSS data at all
|
|
102
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
103
|
+
describe 'Security violation with a CVE but without CVSS data' do
|
|
104
|
+
let(:security_violation_no_cvss) do
|
|
105
|
+
{
|
|
106
|
+
'issue_id' => 'SIEMTEST-NOCVSS-1',
|
|
107
|
+
'type' => 'Security',
|
|
108
|
+
'properties' => [{ 'cve' => 'CVE-2099-28500' }],
|
|
109
|
+
'impacted_artifacts' => ['default/npm-siem-test/siem-mit-pkg/-/siem-mit-pkg-1.0.0.tgz']
|
|
110
|
+
}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it 'does not raise an error (regression for JOBS-2850)' do
|
|
114
|
+
expect { xray.data_normalization(security_violation_no_cvss) }.not_to raise_error
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it 'still sets the cve' do
|
|
118
|
+
result = xray.data_normalization(security_violation_no_cvss)
|
|
119
|
+
expect(result['cve']).to eq('CVE-2099-28500')
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'does not set cvss_score or cvss_version' do
|
|
123
|
+
result = xray.data_normalization(security_violation_no_cvss)
|
|
124
|
+
expect(result).not_to have_key('cvss_score')
|
|
125
|
+
expect(result).not_to have_key('cvss_version')
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
130
|
+
# JOBS-2850: Security violation with only a CVSS v4 score
|
|
131
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
132
|
+
describe 'Security violation with only CVSS v4 data' do
|
|
133
|
+
let(:security_violation_v4) do
|
|
134
|
+
{
|
|
135
|
+
'issue_id' => 'XRAY-1073490',
|
|
136
|
+
'type' => 'Security',
|
|
137
|
+
'properties' => [
|
|
138
|
+
{
|
|
139
|
+
'cve' => 'CVE-2026-84445',
|
|
140
|
+
'cwe' => ['CWE-129', 'CWE-248'],
|
|
141
|
+
'cvss_v4' => '8.7/CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N'
|
|
142
|
+
}
|
|
143
|
+
],
|
|
144
|
+
'impacted_artifacts' => ['default/build-info/some-build']
|
|
145
|
+
}
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it 'does not raise an error (regression for JOBS-2850)' do
|
|
149
|
+
expect { xray.data_normalization(security_violation_v4) }.not_to raise_error
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it 'sets cvss_score from cvss_v4' do
|
|
153
|
+
result = xray.data_normalization(security_violation_v4)
|
|
154
|
+
expect(result['cvss_score']).to eq('8.7')
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it 'sets cvss_version from cvss_v4' do
|
|
158
|
+
result = xray.data_normalization(security_violation_v4)
|
|
159
|
+
expect(result['cvss_version']).to eq('4.0')
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
164
|
+
# Security violation with both CVSS v3 and v4 — v3 is kept
|
|
165
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
166
|
+
describe 'Security violation with both CVSS v3 and v4 (v3 kept)' do
|
|
167
|
+
let(:security_violation_v3_v4) do
|
|
168
|
+
{
|
|
169
|
+
'issue_id' => 'CVE-2024-5678',
|
|
170
|
+
'type' => 'Security',
|
|
171
|
+
'properties' => [
|
|
172
|
+
{
|
|
173
|
+
'cve' => 'CVE-2024-5678',
|
|
174
|
+
'cvss_v3' => '7.5/CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H',
|
|
175
|
+
'cvss_v4' => '8.7/CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N'
|
|
176
|
+
}
|
|
177
|
+
],
|
|
178
|
+
'impacted_artifacts' => ['default/maven-repo/some-lib/1.0/some-lib-1.0.jar']
|
|
179
|
+
}
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it 'uses cvss_v3, not cvss_v4' do
|
|
183
|
+
result = xray.data_normalization(security_violation_v3_v4)
|
|
184
|
+
expect(result['cvss_score']).to eq('7.5')
|
|
185
|
+
expect(result['cvss_version']).to eq('3.1')
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
190
|
+
# Security violation with a CVSS score but no vector (e.g. custom issues)
|
|
191
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
192
|
+
describe 'Security violation with a CVSS score but no vector' do
|
|
193
|
+
let(:security_violation_score_only) do
|
|
194
|
+
{
|
|
195
|
+
'issue_id' => 'CUSTOM-ISSUE-1',
|
|
196
|
+
'type' => 'Security',
|
|
197
|
+
'properties' => [{ 'cve' => 'CVE-2017-1000386', 'cvss_v2' => '2.4' }],
|
|
198
|
+
'impacted_artifacts' => ['default/maven-repo/aero/aero/0.2.3/aero-0.2.3.jar']
|
|
199
|
+
}
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
it 'does not raise an error' do
|
|
203
|
+
expect { xray.data_normalization(security_violation_score_only) }.not_to raise_error
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
it 'sets cvss_score' do
|
|
207
|
+
result = xray.data_normalization(security_violation_score_only)
|
|
208
|
+
expect(result['cvss_score']).to eq('2.4')
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it 'does not set cvss_version' do
|
|
212
|
+
result = xray.data_normalization(security_violation_score_only)
|
|
213
|
+
expect(result).not_to have_key('cvss_version')
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
218
|
+
# Violation without impacted_artifacts (key absent or null)
|
|
219
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
220
|
+
describe 'Violation without impacted_artifacts' do
|
|
221
|
+
it 'does not raise an error when the key is absent' do
|
|
222
|
+
violation = { 'issue_id' => 'CVE-2099-28500', 'type' => 'Security', 'properties' => [{ 'cve' => 'CVE-2099-28500' }] }
|
|
223
|
+
expect { xray.data_normalization(violation) }.not_to raise_error
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it 'sets an empty impacted_artifacts_url when the value is null' do
|
|
227
|
+
violation = { 'issue_id' => 'CVE-2099-28500', 'type' => 'Security', 'impacted_artifacts' => nil }
|
|
228
|
+
result = xray.data_normalization(violation)
|
|
229
|
+
expect(result['impacted_artifacts_url']).to eq([])
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
234
|
+
# Security violation WITH CVSS v3 only (existing behaviour must keep working)
|
|
235
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
236
|
+
describe 'Security violation with CVSS v3 data' do
|
|
237
|
+
let(:security_violation_v3) do
|
|
238
|
+
{
|
|
239
|
+
'issue_id' => 'CVE-2021-44228',
|
|
240
|
+
'type' => 'Security',
|
|
241
|
+
'properties' => [
|
|
242
|
+
{
|
|
243
|
+
'cve' => 'CVE-2021-44228',
|
|
244
|
+
'cvss_v3' => '9.8/CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H'
|
|
245
|
+
}
|
|
246
|
+
],
|
|
247
|
+
'impacted_artifacts' => ['default/maven-repo/log4j/core/2.14.1/log4j-core-2.14.1.jar']
|
|
248
|
+
}
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
it 'does not raise an error' do
|
|
252
|
+
expect { xray.data_normalization(security_violation_v3) }.not_to raise_error
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
it 'sets cvss_score to the leading numeric score (e.g. "9.8")' do
|
|
256
|
+
result = xray.data_normalization(security_violation_v3)
|
|
257
|
+
expect(result['cvss_score']).to eq('9.8')
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
it 'sets cvss_version to the CVSS major.minor version (e.g. "3.1")' do
|
|
261
|
+
result = xray.data_normalization(security_violation_v3)
|
|
262
|
+
expect(result['cvss_version']).to eq('3.1')
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
267
|
+
# Security violation WITH both CVSS v2 AND v3 — v3 must be preferred
|
|
268
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
269
|
+
describe 'Security violation with both CVSS v2 and v3 (v3 preferred)' do
|
|
270
|
+
let(:security_violation_both) do
|
|
271
|
+
{
|
|
272
|
+
'issue_id' => 'CVE-2020-1234',
|
|
273
|
+
'type' => 'Security',
|
|
274
|
+
'properties' => [
|
|
275
|
+
{
|
|
276
|
+
'cve' => 'CVE-2020-1234',
|
|
277
|
+
'cvss_v2' => '7.5/AV:N/AC:L/Au:N/C:P/I:P/A:P',
|
|
278
|
+
'cvss_v3' => '9.8/CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H'
|
|
279
|
+
}
|
|
280
|
+
],
|
|
281
|
+
'impacted_artifacts' => ['default/maven-repo/some-lib/1.0/some-lib-1.0.jar']
|
|
282
|
+
}
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
it 'does not raise an error' do
|
|
286
|
+
expect { xray.data_normalization(security_violation_both) }.not_to raise_error
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
it 'uses cvss_v3 score (not cvss_v2) when both are present' do
|
|
290
|
+
result = xray.data_normalization(security_violation_both)
|
|
291
|
+
# v3 score is 9.8; v2 score is 7.5 — the result must reflect v3
|
|
292
|
+
expect(result['cvss_score']).to eq('9.8')
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
it 'sets cvss_version from cvss_v3 when both are present' do
|
|
296
|
+
result = xray.data_normalization(security_violation_both)
|
|
297
|
+
expect(result['cvss_version']).to eq('3.1')
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
end
|
metadata
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fluent-plugin-jfrog-siem
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.9
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mahitha Byreddy
|
|
8
|
-
-
|
|
9
|
-
- Giridharan Ramasamy
|
|
8
|
+
- Ben Harosh
|
|
10
9
|
autorequire:
|
|
11
10
|
bindir: bin
|
|
12
11
|
cert_chain: []
|
|
13
|
-
date:
|
|
12
|
+
date: 2026-10-13 00:00:00.000000000 Z
|
|
14
13
|
dependencies:
|
|
15
14
|
- !ruby/object:Gem::Dependency
|
|
16
15
|
name: bundler
|
|
@@ -68,26 +67,6 @@ dependencies:
|
|
|
68
67
|
- - "~>"
|
|
69
68
|
- !ruby/object:Gem::Version
|
|
70
69
|
version: '2.0'
|
|
71
|
-
- !ruby/object:Gem::Dependency
|
|
72
|
-
name: concurrent-ruby
|
|
73
|
-
requirement: !ruby/object:Gem::Requirement
|
|
74
|
-
requirements:
|
|
75
|
-
- - "~>"
|
|
76
|
-
- !ruby/object:Gem::Version
|
|
77
|
-
version: 1.1.8
|
|
78
|
-
- - "<"
|
|
79
|
-
- !ruby/object:Gem::Version
|
|
80
|
-
version: 1.1.10
|
|
81
|
-
type: :development
|
|
82
|
-
prerelease: false
|
|
83
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
84
|
-
requirements:
|
|
85
|
-
- - "~>"
|
|
86
|
-
- !ruby/object:Gem::Version
|
|
87
|
-
version: 1.1.8
|
|
88
|
-
- - "<"
|
|
89
|
-
- !ruby/object:Gem::Version
|
|
90
|
-
version: 1.1.10
|
|
91
70
|
- !ruby/object:Gem::Dependency
|
|
92
71
|
name: concurrent-ruby-edge
|
|
93
72
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -130,26 +109,6 @@ dependencies:
|
|
|
130
109
|
- - "~>"
|
|
131
110
|
- !ruby/object:Gem::Version
|
|
132
111
|
version: '2.0'
|
|
133
|
-
- !ruby/object:Gem::Dependency
|
|
134
|
-
name: concurrent-ruby
|
|
135
|
-
requirement: !ruby/object:Gem::Requirement
|
|
136
|
-
requirements:
|
|
137
|
-
- - "~>"
|
|
138
|
-
- !ruby/object:Gem::Version
|
|
139
|
-
version: 1.1.8
|
|
140
|
-
- - "<"
|
|
141
|
-
- !ruby/object:Gem::Version
|
|
142
|
-
version: 1.1.10
|
|
143
|
-
type: :runtime
|
|
144
|
-
prerelease: false
|
|
145
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
146
|
-
requirements:
|
|
147
|
-
- - "~>"
|
|
148
|
-
- !ruby/object:Gem::Version
|
|
149
|
-
version: 1.1.8
|
|
150
|
-
- - "<"
|
|
151
|
-
- !ruby/object:Gem::Version
|
|
152
|
-
version: 1.1.10
|
|
153
112
|
- !ruby/object:Gem::Dependency
|
|
154
113
|
name: concurrent-ruby-edge
|
|
155
114
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -187,9 +146,7 @@ dependencies:
|
|
|
187
146
|
description: JFrog SIEM fluent input plugin will send the SIEM events from JFrog Xray
|
|
188
147
|
to Fluentd which can then be delivered to whatever output plugin specified
|
|
189
148
|
email:
|
|
190
|
-
-
|
|
191
|
-
- sudhindrar@jfrog.com
|
|
192
|
-
- girir@jfrog.com
|
|
149
|
+
- partner-support@jfrog.com
|
|
193
150
|
executables: []
|
|
194
151
|
extensions: []
|
|
195
152
|
extra_rdoc_files: []
|
|
@@ -206,6 +163,7 @@ files:
|
|
|
206
163
|
- lib/fluent/plugin/test_violations.rb
|
|
207
164
|
- lib/fluent/plugin/violations.json
|
|
208
165
|
- lib/fluent/plugin/xray.rb
|
|
166
|
+
- spec/data_normalization_spec.rb
|
|
209
167
|
- spec/position_file_spec.rb
|
|
210
168
|
- spec/spec_helper.rb
|
|
211
169
|
- spec/xray_spec.rb
|
|
@@ -230,12 +188,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
230
188
|
- !ruby/object:Gem::Version
|
|
231
189
|
version: '0'
|
|
232
190
|
requirements: []
|
|
233
|
-
rubygems_version: 3.
|
|
191
|
+
rubygems_version: 3.4.19
|
|
234
192
|
signing_key:
|
|
235
193
|
specification_version: 4
|
|
236
194
|
summary: JFrog SIEM fluent input plugin will send the SIEM events from JFrog Xray
|
|
237
195
|
to Fluentd
|
|
238
196
|
test_files:
|
|
197
|
+
- spec/data_normalization_spec.rb
|
|
239
198
|
- spec/position_file_spec.rb
|
|
240
199
|
- spec/spec_helper.rb
|
|
241
200
|
- spec/xray_spec.rb
|