fluent-plugin-jfrog-siem 0.1.5 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +36 -0
- data/README.md +10 -3
- data/fluent-plugin-jfrog-siem.gemspec +1 -1
- data/lib/fluent/plugin/in_jfrog_siem.rb +51 -26
- data/test/plugin/test_in_jfrog_siem.rb +3 -2
- metadata +3 -4
- data/elastic.conf +0 -18
- data/splunk.conf +0 -18
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 306eb5d59fd5e00e2e8feda0339a3b635f1e61aaabff9312ad372dc714c3ff8f
|
|
4
|
+
data.tar.gz: 469ea7950f9d96236a88159a797f17077b31f5c3d7ddc19ca91f4d6209963a9a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 02db6faa97750196fd42a0b04a8a8f517dfa0a26ad585778b8283b4cce9814ff239d96eb0a9ca34ef02a2f66bab9bb632cf8c0194afe7a3e4902ea08f4d9fd77
|
|
7
|
+
data.tar.gz: 745bef31330a205aac78d2f49e2b25f6f924f52c3d8a0be35d3d1f4aee77f1c862b8e8124a95ed62d90befc3e5a351061cbe1b902482484e3778081404737527
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
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
|
+
|
data/README.md
CHANGED
|
@@ -68,20 +68,27 @@ Splunk:
|
|
|
68
68
|
|
|
69
69
|
Splunk setup can be found at [README.](https://github.com/jfrog/log-analytics-splunk/blob/master/README.md)
|
|
70
70
|
````text
|
|
71
|
-
wget https://raw.githubusercontent.com/jfrog/log-analytics/master/
|
|
71
|
+
wget https://raw.githubusercontent.com/jfrog/log-analytics-splunk/master/siem/splunk_siem.conf
|
|
72
72
|
````
|
|
73
73
|
Elasticsearch:
|
|
74
74
|
|
|
75
75
|
Elasticsearch Kibana setup can be found at [README.](https://github.com/jfrog/log-analytics-elastic/blob/master/README.md)
|
|
76
76
|
````text
|
|
77
|
-
wget https://raw.githubusercontent.com/jfrog/log-analytics/master/
|
|
77
|
+
wget https://raw.githubusercontent.com/jfrog/log-analytics-elastic/master/siem/elastic_siem.conf
|
|
78
|
+
````
|
|
79
|
+
Datadog:
|
|
80
|
+
|
|
81
|
+
Datadog setup can be found at [README.](https://github.com/jfrog/log-analytics-datadog/blob/master/README.md)
|
|
82
|
+
````text
|
|
83
|
+
wget https://raw.githubusercontent.com/jfrog/log-analytics-datadog/master/siem/datadog_siem.conf
|
|
78
84
|
````
|
|
79
85
|
|
|
80
86
|
#### Configuration parameters
|
|
81
87
|
Integration is done by setting up Xray. Obtain JPD url and access token for API. Configure the source directive parameters specified below
|
|
82
88
|
* **tag** (string) (required): The value is the tag assigned to the generated events.
|
|
83
89
|
* **jpd_url** (string) (required): JPD url required to pull Xray SIEM violations
|
|
84
|
-
* **
|
|
90
|
+
* **apikey** (string) (required): API Key is the [Artifactory API Key](https://www.jfrog.com/confluence/display/JFROG/User+Profile#UserProfile-APIKey) for authentication
|
|
91
|
+
* **username** (string) (required): USER is the Artifactory username for authentication
|
|
85
92
|
* **pos_file** (string) (required): Position file to record last SIEM violation pulled
|
|
86
93
|
* **batch_size** (integer) (optional): Batch size for processing violations
|
|
87
94
|
* Default value: `25`
|
|
@@ -3,7 +3,7 @@ $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 = "0.
|
|
6
|
+
spec.version = "1.0.0"
|
|
7
7
|
spec.authors = ["John Peterson", "Mahitha Byreddy"]
|
|
8
8
|
spec.email = ["johnp@jfrog.com", "mahithab@jfrog.com"]
|
|
9
9
|
|
|
@@ -30,7 +30,8 @@ module Fluent
|
|
|
30
30
|
# `:default` means that the parameter is optional.
|
|
31
31
|
config_param :tag, :string, default: ""
|
|
32
32
|
config_param :jpd_url, :string, default: ""
|
|
33
|
-
config_param :
|
|
33
|
+
config_param :username, :string, default: ""
|
|
34
|
+
config_param :apikey, :string, default: ""
|
|
34
35
|
config_param :pos_file, :string, default: ""
|
|
35
36
|
config_param :batch_size, :integer, default: 25
|
|
36
37
|
config_param :thread_count, :integer, default: 5
|
|
@@ -50,8 +51,12 @@ module Fluent
|
|
|
50
51
|
raise Fluent::ConfigError, "Must define the JPD URL to pull Xray SIEM violations."
|
|
51
52
|
end
|
|
52
53
|
|
|
53
|
-
if @
|
|
54
|
-
raise Fluent::ConfigError, "Must define the
|
|
54
|
+
if @username == ""
|
|
55
|
+
raise Fluent::ConfigError, "Must define the username to use for authentication."
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
if @apikey == ""
|
|
59
|
+
raise Fluent::ConfigError, "Must define the API Key to use for authentication."
|
|
55
60
|
end
|
|
56
61
|
|
|
57
62
|
if @pos_file == ""
|
|
@@ -89,7 +94,7 @@ module Fluent
|
|
|
89
94
|
|
|
90
95
|
|
|
91
96
|
def run
|
|
92
|
-
call_home(@jpd_url
|
|
97
|
+
call_home(@jpd_url)
|
|
93
98
|
# runs the violation pull
|
|
94
99
|
last_created_date_string = get_last_item_create_date()
|
|
95
100
|
begin
|
|
@@ -104,7 +109,7 @@ module Fluent
|
|
|
104
109
|
|
|
105
110
|
while true
|
|
106
111
|
# Grab the batch of records
|
|
107
|
-
resp=get_xray_violations(xray_json, @jpd_url
|
|
112
|
+
resp=get_xray_violations(xray_json, @jpd_url)
|
|
108
113
|
number_of_violations = JSON.parse(resp)['total_violations']
|
|
109
114
|
if left_violations <= 0
|
|
110
115
|
left_violations = number_of_violations
|
|
@@ -124,8 +129,14 @@ module Fluent
|
|
|
124
129
|
if waiting_for_violations
|
|
125
130
|
if created_date <= last_created_date
|
|
126
131
|
# "not persisting it - waiting for violations"
|
|
132
|
+
# waiting and same last timestamp (left violations in batch)
|
|
127
133
|
persistItem = false
|
|
128
134
|
end
|
|
135
|
+
if created_date > last_created_date
|
|
136
|
+
# new violation while waiting
|
|
137
|
+
persistItem = true
|
|
138
|
+
waiting_for_violations = false
|
|
139
|
+
end
|
|
129
140
|
else
|
|
130
141
|
if created_date < last_created_date
|
|
131
142
|
# "persisting everything"
|
|
@@ -159,7 +170,7 @@ module Fluent
|
|
|
159
170
|
thread_pool = Thread.pool(thread_count)
|
|
160
171
|
thread_pool.process {
|
|
161
172
|
for xray_violation_url in xray_violation_urls_list do
|
|
162
|
-
pull_violation_details(xray_violation_url
|
|
173
|
+
pull_violation_details(xray_violation_url)
|
|
163
174
|
end
|
|
164
175
|
}
|
|
165
176
|
thread_pool.shutdown
|
|
@@ -188,48 +199,53 @@ module Fluent
|
|
|
188
199
|
end
|
|
189
200
|
|
|
190
201
|
#call home functionality
|
|
191
|
-
def call_home(jpd_url
|
|
202
|
+
def call_home(jpd_url)
|
|
192
203
|
call_home_json = { "productId": "jfrogLogAnalytics/v0.5.1", "features": [ { "featureId": "Platform/Xray" }, { "featureId": "Channel/xrayeventsiem" } ] }
|
|
193
204
|
response = RestClient::Request.new(
|
|
194
205
|
:method => :post,
|
|
195
206
|
:url => jpd_url + "/artifactory/api/system/usage",
|
|
196
207
|
:payload => call_home_json.to_json,
|
|
197
|
-
:
|
|
208
|
+
:user => @username,
|
|
209
|
+
:password => @apikey,
|
|
210
|
+
:headers => { :accept => :json, :content_type => :json}
|
|
198
211
|
).execute do |response, request, result|
|
|
199
212
|
puts "Posting call home information"
|
|
200
213
|
end
|
|
201
214
|
end
|
|
202
215
|
|
|
203
216
|
# queries the xray API for violations based upon the input json
|
|
204
|
-
def get_xray_violations_detail(xray_violation_detail_url
|
|
217
|
+
def get_xray_violations_detail(xray_violation_detail_url)
|
|
205
218
|
response = RestClient::Request.new(
|
|
206
219
|
:method => :get,
|
|
207
220
|
:url => xray_violation_detail_url,
|
|
208
|
-
|
|
221
|
+
:user => @username,
|
|
222
|
+
:password => @apikey
|
|
209
223
|
).execute do |response, request, result|
|
|
210
224
|
case response.code
|
|
211
225
|
when 200
|
|
212
226
|
return response.to_str
|
|
213
227
|
else
|
|
214
|
-
raise Fluent::
|
|
228
|
+
raise Fluent::ConfigError, "Cannot reach Artifactory URL to pull Xray SIEM violations."
|
|
215
229
|
end
|
|
216
230
|
end
|
|
217
231
|
end
|
|
218
232
|
|
|
219
233
|
|
|
220
234
|
# queries the xray API for violations based upon the input json
|
|
221
|
-
def get_xray_violations(xray_json, jpd_url
|
|
235
|
+
def get_xray_violations(xray_json, jpd_url)
|
|
222
236
|
response = RestClient::Request.new(
|
|
223
237
|
:method => :post,
|
|
224
238
|
:url => jpd_url + "/xray/api/v1/violations",
|
|
225
239
|
:payload => xray_json.to_json,
|
|
226
|
-
:
|
|
240
|
+
:user => @username,
|
|
241
|
+
:password => @apikey,
|
|
242
|
+
:headers => { :accept => :json, :content_type => :json}
|
|
227
243
|
).execute do |response, request, result|
|
|
228
244
|
case response.code
|
|
229
245
|
when 200
|
|
230
246
|
return response.to_str
|
|
231
247
|
else
|
|
232
|
-
raise Fluent::
|
|
248
|
+
raise Fluent::ConfigError, "Cannot reach Artifactory URL to pull Xray SIEM violations."
|
|
233
249
|
end
|
|
234
250
|
end
|
|
235
251
|
end
|
|
@@ -240,6 +256,8 @@ module Fluent
|
|
|
240
256
|
cve = []
|
|
241
257
|
cvss_v2_list = []
|
|
242
258
|
cvss_v3_list = []
|
|
259
|
+
policy_list = []
|
|
260
|
+
rule_list = []
|
|
243
261
|
impacted_artifact_url_list = []
|
|
244
262
|
if detailResp_json.key?('properties')
|
|
245
263
|
properties = detailResp_json['properties']
|
|
@@ -269,31 +287,38 @@ module Fluent
|
|
|
269
287
|
detailResp_json["cvss_version"] = cvss_version
|
|
270
288
|
end
|
|
271
289
|
|
|
290
|
+
if detailResp_json.key?('matched_policies')
|
|
291
|
+
matched_policies = detailResp_json['matched_policies']
|
|
292
|
+
for index in 0..matched_policies.length-1 do
|
|
293
|
+
if matched_policies[index].key?('policy')
|
|
294
|
+
policy_list.push(matched_policies[index]['policy'])
|
|
295
|
+
end
|
|
296
|
+
if matched_policies[index].key?('rule')
|
|
297
|
+
rule_list.push(matched_policies[index]['rule'])
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
detailResp_json['policies'] = policy_list
|
|
301
|
+
detailResp_json['rules'] = rule_list
|
|
302
|
+
end
|
|
303
|
+
|
|
272
304
|
impacted_artifacts = detailResp_json['impacted_artifacts']
|
|
273
305
|
for impacted_artifact in impacted_artifacts do
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
repo_name = impacted_artifact.split('/', -1)[1]
|
|
277
|
-
image_name = impacted_artifact.split('/', -1)[2]
|
|
278
|
-
tag_name = impacted_artifact.split('/', -1)[3]
|
|
279
|
-
impacted_artifact_url = "/api/docker/" + repo_name + "/v2/" + image_name + "/manifests/" + tag_name
|
|
280
|
-
else
|
|
281
|
-
impacted_artifact_url = impacted_artifact.gsub("default", "")
|
|
282
|
-
end
|
|
306
|
+
matchdata = impacted_artifact.match /default\/(?<repo_name>[^\/]*)\/(?<path>.*)/
|
|
307
|
+
impacted_artifact_url = matchdata['repo_name'] + ":" + matchdata['path'] + " "
|
|
283
308
|
impacted_artifact_url_list.append(impacted_artifact_url)
|
|
284
309
|
end
|
|
285
310
|
detailResp_json['impacted_artifacts_url'] = impacted_artifact_url_list
|
|
286
311
|
return detailResp_json
|
|
287
312
|
end
|
|
288
313
|
|
|
289
|
-
def pull_violation_details(xray_violation_detail_url
|
|
314
|
+
def pull_violation_details(xray_violation_detail_url)
|
|
290
315
|
begin
|
|
291
|
-
detailResp=get_xray_violations_detail(xray_violation_detail_url
|
|
316
|
+
detailResp=get_xray_violations_detail(xray_violation_detail_url)
|
|
292
317
|
time = Fluent::Engine.now
|
|
293
318
|
detailResp_json = data_normalization(detailResp)
|
|
294
319
|
router.emit(@tag, time, detailResp_json)
|
|
295
320
|
rescue
|
|
296
|
-
raise Fluent::
|
|
321
|
+
raise Fluent::ConfigError, "Error pulling violation details url #{xray_violation_detail_url}"
|
|
297
322
|
end
|
|
298
323
|
end
|
|
299
324
|
|
|
@@ -13,8 +13,9 @@ class JfrogSiemInputTest < Test::Unit::TestCase
|
|
|
13
13
|
# Default configuration for tests
|
|
14
14
|
CONFIG = %[
|
|
15
15
|
tag "test_tag"
|
|
16
|
-
jpd_url
|
|
17
|
-
|
|
16
|
+
jpd_url JPD_URL
|
|
17
|
+
username USER
|
|
18
|
+
apikey API_KEY
|
|
18
19
|
pos_file "test_pos.txt"
|
|
19
20
|
]
|
|
20
21
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fluent-plugin-jfrog-siem
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- John Peterson
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2021-
|
|
12
|
+
date: 2021-05-18 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: bundler
|
|
@@ -124,14 +124,13 @@ executables: []
|
|
|
124
124
|
extensions: []
|
|
125
125
|
extra_rdoc_files: []
|
|
126
126
|
files:
|
|
127
|
+
- CHANGELOG.md
|
|
127
128
|
- Gemfile
|
|
128
129
|
- LICENSE
|
|
129
130
|
- README.md
|
|
130
131
|
- Rakefile
|
|
131
|
-
- elastic.conf
|
|
132
132
|
- fluent-plugin-jfrog-siem.gemspec
|
|
133
133
|
- lib/fluent/plugin/in_jfrog_siem.rb
|
|
134
|
-
- splunk.conf
|
|
135
134
|
- test/helper.rb
|
|
136
135
|
- test/plugin/test_in_jfrog_siem.rb
|
|
137
136
|
homepage: https://github.com/jfrog/log-analytics
|
data/elastic.conf
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
<source>
|
|
2
|
-
@type jfrog_siem
|
|
3
|
-
tag elastic_jfrog
|
|
4
|
-
jpd_url <jpd_url>
|
|
5
|
-
access_token <access_token>
|
|
6
|
-
pos_file "elastic_pos.txt"
|
|
7
|
-
</source>
|
|
8
|
-
<match elastic*>
|
|
9
|
-
@type elasticsearch
|
|
10
|
-
@id elasticsearch
|
|
11
|
-
host elasticsearch
|
|
12
|
-
port 9200
|
|
13
|
-
user <username>
|
|
14
|
-
password <password>
|
|
15
|
-
index_name xray_siem
|
|
16
|
-
include_tag_key true
|
|
17
|
-
type_name fluentd
|
|
18
|
-
</match>
|
data/splunk.conf
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
<source>
|
|
2
|
-
@type jfrog_siem
|
|
3
|
-
tag splunk_jfrog
|
|
4
|
-
jpd_url <jpd_url>
|
|
5
|
-
access_token <access_token>
|
|
6
|
-
pos_file "splunk_pos.txt"
|
|
7
|
-
</source>
|
|
8
|
-
<match splunk*>
|
|
9
|
-
@type splunk_hec
|
|
10
|
-
host HEC_HOST
|
|
11
|
-
port HEC_PORT
|
|
12
|
-
token HEC_TOKEN
|
|
13
|
-
format json
|
|
14
|
-
sourcetype_key log_source
|
|
15
|
-
use_fluentd_time false
|
|
16
|
-
index violations
|
|
17
|
-
flush_interval 10s
|
|
18
|
-
</match>
|