fluent-plugin-jfrog-siem 0.1.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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>