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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6cfb13538b236dbfd917cf58038dab5e76d945fa0af419240fdd5508e976af1c
4
- data.tar.gz: 9725242bcb3230a23f457b146bcf5e39cf562aad9abbcfbcc1ea390de2853093
3
+ metadata.gz: 306eb5d59fd5e00e2e8feda0339a3b635f1e61aaabff9312ad372dc714c3ff8f
4
+ data.tar.gz: 469ea7950f9d96236a88159a797f17077b31f5c3d7ddc19ca91f4d6209963a9a
5
5
  SHA512:
6
- metadata.gz: e63137fd91a16f2ab65d3ecdc2e841d1c098e201a8a47b2d0687a80833e05bfa3fb0e4e6cf606245d58c884ef3740d7c4efa3fbbb9a4c095445e05ba3ee60b10
7
- data.tar.gz: cc5dcb1ef463eb4d8c57bd246d4968b3a47639296f994913ebb75f01bb49496a44800197efe7bcc97e23bff0f84dc48570ba08d9157c0690715e00b9a0e5cfb5
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/fluentd/plugins/input/fluent-plugin-jfrog-siem/splunk.conf
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/fluentd/plugins/input/fluent-plugin-jfrog-siem/elastic.conf
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
- * **access_token** (string) (required): [Access token](https://www.jfrog.com/confluence/display/JFROG/Access+Tokens) to authenticate Xray
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.1.5"
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 :access_token, :string, default: ""
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 @access_token == ""
54
- raise Fluent::ConfigError, "Must define the access token to use for authentication."
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, @access_token)
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, @access_token)
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, @access_token)
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, access_token)
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
- :headers => { :accept => :json, :content_type => :json, Authorization:'Bearer ' + access_token }
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, access_token)
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
- headers: {Authorization:'Bearer ' + access_token}
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::StandardError, "Cannot reach Artifactory URL to pull Xray SIEM violations."
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, access_token)
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
- :headers => { :accept => :json, :content_type => :json, Authorization:'Bearer ' + access_token }
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::StandardError, "Cannot reach Artifactory URL to pull Xray SIEM violations."
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
- if impacted_artifact.split('/', -1)[-1] == "manifest.json"
275
- #docker formatting
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, access_token)
314
+ def pull_violation_details(xray_violation_detail_url)
290
315
  begin
291
- detailResp=get_xray_violations_detail(xray_violation_detail_url, access_token)
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::StandardError, "Error pulling violation details url #{xray_violation_detail_url}"
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 <jpd_url>
17
- access_token <access_token>
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.1.5
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-03-29 00:00:00.000000000 Z
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>