fluent-plugin-masking 1.0.8 → 1.1.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: 02c98ca4f43cdef94bd6ec5615355f76601d5fa7ec28307ffc7c2748a629a0dd
4
- data.tar.gz: a25640c10af2bd1724acb5381cd512eeb129719376824a2be0f98aa3e3d6bd55
3
+ metadata.gz: '08a7033570c7aaca9dc0a4830f4550ef5e353b9e5195dc3cfcc79eb68880fcae'
4
+ data.tar.gz: '0845c7ee9ae72c13652cd9a517a71f0289c88f2144cf2afcad18370c1f1fa358'
5
5
  SHA512:
6
- metadata.gz: 77b885170c3d95b1abcb60df6e0a86958bce0e137718375179cbf17d6a824144034dfa4954c69397b9d1d8f127be5c218c81dc120340c0546def8cd5df27ceff
7
- data.tar.gz: 139d6cfec14a8e970653d44bbf85b5ef9de0765f03bd6b0d67ee3fb0c9da2b94f6635c7915e63c64cbb77a6d98e46ffed83821f9a340680e6d7d64bae75db988
6
+ metadata.gz: 61a8a367ec559746eee72fd7e33a4d62b6f38777a18b3d5560c82dffcee5c65332ef8fbfd39e018b5dec34930e8a13cdbfa41356a796b4afc9c858eac7ce13d2
7
+ data.tar.gz: 92b95fad73c342b281ce44d451ce0d52ddcce490d1b0753498671320b38ffb840840b02a44a2ab184d7be0fc636aa2f78ba6dbed6e1a3e8c32f4ebcd71ebe3dd
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fluent-plugin-masking (1.0.7)
4
+ fluent-plugin-masking (1.1.0)
5
5
  fluentd (>= 0.14.0)
6
6
 
7
7
  GEM
@@ -10,7 +10,7 @@ GEM
10
10
  concurrent-ruby (1.1.5)
11
11
  cool.io (1.5.4)
12
12
  dig_rb (1.0.1)
13
- fluentd (1.7.2)
13
+ fluentd (1.7.4)
14
14
  cool.io (>= 1.4.5, < 2.0.0)
15
15
  dig_rb (~> 1.0.0)
16
16
  http_parser.rb (>= 0.5.1, < 0.7.0)
@@ -26,7 +26,7 @@ GEM
26
26
  power_assert (1.1.5)
27
27
  rake (12.3.3)
28
28
  rr (1.2.1)
29
- serverengine (2.1.1)
29
+ serverengine (2.2.0)
30
30
  sigdump (~> 0.2.2)
31
31
  sigdump (0.2.4)
32
32
  strptime (0.2.3)
data/README.md CHANGED
@@ -19,11 +19,15 @@ Install with gem:
19
19
  ## Setup
20
20
  In order to setup this plugin, the parameter `fieldsToMaskFilePath` needs to be a valid path to a file containing a list of all the fields to mask. The file should have a unique field on each line. These fields **are** case-sensitive (`Name` != `name`).
21
21
 
22
+ In addition, there's an optional parameter called `fieldsToExcludeJSONPaths` which receives as input a comma separated string of JSON fields that should be excluded in the masking procedure. Nested JSON fields are supported by `dot notation` (i.e: `path.to.excluded.field.in.record.nestedExcludedField`)
23
+ The JSON fields that are excluded are comma separated.
24
+ This can be used for logs of registration services or audit log entries which do not need to be masked.
22
25
  This is configured as shown below:
23
26
  ```
24
27
  <filter "**">
25
28
  @type masking
26
29
  fieldsToMaskFilePath "/path/to/fields-to-mask-file"
30
+ fieldsToExcludeJSONPaths "excludedField,exclude.path.nestedExcludedField"
27
31
  </filter>
28
32
  ```
29
33
 
@@ -52,6 +56,7 @@ phone
52
56
  <filter "**">
53
57
  @type masking
54
58
  fieldsToMaskFilePath "/path/to/fields-to-mask-file"
59
+ fieldsToExcludeJSONPaths "excludedField,exclude.path.nestedExcludedField"
55
60
  </filter>
56
61
 
57
62
  <match "**">
@@ -83,3 +88,13 @@ This sample result is created from the above configuration file `fluent.conf`. A
83
88
  ```
84
89
  2019-09-15 16:12:50.359191000 +0300 maskme: {"message":"{ :body => \"{\\\"first_name\\\":\\\"*******\\\", \\\"type\\\":\\\"puggle\\\", \\\"last_name\\\":\\\"*******\\\", \\\"password\\\":\\\"*******\\\"}\"}"}
85
90
  ```
91
+
92
+ A sample with exclude in use:
93
+ ```
94
+ fluentd -c fluent.conf
95
+ echo '{ :body => "{\"first_name\":\"mickey\", \"type\":\"puggle\", \"last_name\":\"the-dog\", \"password\":\"d0g43u39\"}", "excludeMaskFields"=>"first_name,last_name"}' > /tmp/test.log
96
+ ```
97
+
98
+ ```
99
+ 2019-12-01 14:25:53.385681000 +0300 maskme: {"message":"{ :body => \"{\\\"first_name\\\":\\\"mickey\\\", \\\"type\\\":\\\"puggle\\\", \\\"last_name\\\":\\\"the-dog\\\", \\\"password\\\":\\\"*******\\\"}\"}"}
100
+ ```
@@ -15,11 +15,19 @@ module Fluent
15
15
  # error safe method - if any error occurs the original record is returned
16
16
  def maskRecord(record)
17
17
  maskedRecord = record
18
-
19
- begin
18
+ excludedFields = []
19
+ @fieldsToExcludeJSONPathsArray.each do | field |
20
+ field_value = record.dig(*field)
21
+ if field_value != nil
22
+ excludedFields = excludedFields + field_value.split(',')
23
+ end
24
+ end
25
+ begin
20
26
  recordStr = record.to_s
21
27
  @fields_to_mask_regex.each do | fieldToMaskRegex, fieldToMaskRegexStringReplacement |
22
- recordStr = recordStr.gsub(fieldToMaskRegex, fieldToMaskRegexStringReplacement)
28
+ if !(excludedFields.include? @fields_to_mask_keys[fieldToMaskRegex])
29
+ recordStr = recordStr.gsub(fieldToMaskRegex, fieldToMaskRegexStringReplacement)
30
+ end
23
31
  end
24
32
 
25
33
  maskedRecord = strToHash(recordStr)
@@ -35,12 +43,27 @@ module Fluent
35
43
  super
36
44
  @fields_to_mask = []
37
45
  @fields_to_mask_regex = {}
46
+ @fields_to_mask_keys = {}
47
+ @fieldsToExcludeJSONPathsArray = []
38
48
  end
39
49
 
40
50
  # this method only called ones (on startup time)
41
51
  def configure(conf)
42
52
  super
43
53
  fieldsToMaskFilePath = conf['fieldsToMaskFilePath']
54
+ fieldsToExcludeJSONPaths = conf['fieldsToExcludeJSONPaths']
55
+
56
+ if fieldsToExcludeJSONPaths != nil && fieldsToExcludeJSONPaths.size() > 0
57
+ fieldsToExcludeJSONPaths.split(",").each do | field |
58
+ # To save splits we'll save the path as an array
59
+ splitArray = field.split(".")
60
+ symArray = []
61
+ splitArray.each do | pathPortion |
62
+ symArray.push(pathPortion.to_sym)
63
+ end
64
+ @fieldsToExcludeJSONPathsArray.push(symArray)
65
+ end
66
+ end
44
67
 
45
68
  File.open(fieldsToMaskFilePath, "r") do |f|
46
69
  f.each_line do |line|
@@ -54,10 +77,12 @@ module Fluent
54
77
  hashObjectRegex = Regexp.new(/(?::#{value}=>")(.*?)(?:")/m) # mask element in hash object
55
78
  hashObjectRegexStringReplacement = ":#{value}=>\"#{MASK_STRING}\""
56
79
  @fields_to_mask_regex[hashObjectRegex] = hashObjectRegexStringReplacement
80
+ @fields_to_mask_keys[hashObjectRegex] = value
57
81
 
58
82
  innerJSONStringRegex = Regexp.new(/(\\+)"#{value}\\+":\\+.+?((?=(})|,( *|)(\s|\\+)\")|(?=}"$))/m) # mask element in json string using capture groups that count the level of escaping inside the json string
59
83
  innerJSONStringRegexStringReplacement = "\\1\"#{value}\\1\":\\1\"#{MASK_STRING}\\1\""
60
84
  @fields_to_mask_regex[innerJSONStringRegex] = innerJSONStringRegexStringReplacement
85
+ @fields_to_mask_keys[innerJSONStringRegex] = value
61
86
  end
62
87
  end
63
88
 
@@ -1,3 +1,3 @@
1
1
  module FilterMasking
2
- VERSION = "1.0.8"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -17,6 +17,12 @@ class YourOwnFilterTest < Test::Unit::TestCase
17
17
  # default configuration for tests
18
18
  CONFIG = %[
19
19
  fieldsToMaskFilePath test/fields-to-mask
20
+ fieldsToExcludeJSONPaths excludedField,exclude.path.nestedExcludedField
21
+ ]
22
+
23
+ # configuration for tests without exclude parameter
24
+ CONFIG_NO_EXCLUDE = %[
25
+ fieldsToMaskFilePath test/fields-to-mask
20
26
  ]
21
27
 
22
28
  def create_driver(conf = CONFIG)
@@ -35,7 +41,7 @@ class YourOwnFilterTest < Test::Unit::TestCase
35
41
 
36
42
  sub_test_case 'plugin will mask all fields that need masking' do
37
43
  test 'mask field in hash object' do
38
- conf = CONFIG
44
+ conf = CONFIG_NO_EXCLUDE
39
45
  messages = [
40
46
  {:not_masked_field=>"mickey-the-dog", :email=>"mickey-the-dog@zooz.com"}
41
47
  ]
@@ -93,5 +99,38 @@ class YourOwnFilterTest < Test::Unit::TestCase
93
99
  filtered_records = filter(conf, messages)
94
100
  assert_equal(expected, filtered_records)
95
101
  end
102
+ test 'mask field in hash object with exclude' do
103
+ conf = CONFIG
104
+ messages = [
105
+ {:not_masked_field=>"mickey-the-dog", :email=>"mickey-the-dog@zooz.com", :first_name=>"Micky", :excludedField=>"first_name"}
106
+ ]
107
+ expected = [
108
+ {:not_masked_field=>"mickey-the-dog", :email=>MASK_STRING, :first_name=>"Micky", :excludedField=>"first_name"}
109
+ ]
110
+ filtered_records = filter(conf, messages)
111
+ assert_equal(expected, filtered_records)
112
+ end
113
+ test 'mask field in hash object with nested exclude' do
114
+ conf = CONFIG
115
+ messages = [
116
+ {:not_masked_field=>"mickey-the-dog", :last_name=>"the dog", :email=>"mickey-the-dog@zooz.com", :first_name=>"Micky", :exclude=>{:path=>{:nestedExcludedField=>"first_name,last_name"}}}
117
+ ]
118
+ expected = [
119
+ {:not_masked_field=>"mickey-the-dog", :last_name=>"the dog", :email=>MASK_STRING, :first_name=>"Micky", :exclude=>{:path=>{:nestedExcludedField=>"first_name,last_name"}}}
120
+ ]
121
+ filtered_records = filter(conf, messages)
122
+ assert_equal(expected, filtered_records)
123
+ end
124
+ test 'mask field in hash object with base and nested exclude' do
125
+ conf = CONFIG
126
+ messages = [
127
+ {:not_masked_field=>"mickey-the-dog", :last_name=>"the dog", :email=>"mickey-the-dog@zooz.com", :first_name=>"Micky", :excludedField=>"first_name", :exclude=>{:path=>{:nestedExcludedField=>"last_name"}}}
128
+ ]
129
+ expected = [
130
+ {:not_masked_field=>"mickey-the-dog", :last_name=>"the dog", :email=>MASK_STRING, :first_name=>"Micky", :excludedField=>"first_name", :exclude=>{:path=>{:nestedExcludedField=>"last_name"}}}
131
+ ]
132
+ filtered_records = filter(conf, messages)
133
+ assert_equal(expected, filtered_records)
134
+ end
96
135
  end
97
136
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fluent-plugin-masking
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.8
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shai Moria
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2019-09-22 00:00:00.000000000 Z
12
+ date: 2019-12-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fluentd
@@ -119,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
119
  - !ruby/object:Gem::Version
120
120
  version: '0'
121
121
  requirements: []
122
- rubygems_version: 3.0.4
122
+ rubygems_version: 3.0.3
123
123
  signing_key:
124
124
  specification_version: 4
125
125
  summary: Fluentd filter plugin to mask sensitive or privacy records with `*******`