masking 1.1.1 → 1.1.2.pre.alpha
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 +9 -0
- data/CODEOWNERS +1 -0
- data/Dockerfile +3 -3
- data/Dockerfile.ghcr +10 -0
- data/Gemfile.lock +1 -1
- data/README.md +23 -21
- data/acceptance/expected_error_result.txt +2 -0
- data/acceptance/run_test.sh +18 -6
- data/lib/masking/cli/error_message.rb +15 -8
- data/lib/masking/version.rb +1 -1
- metadata +7 -5
- data/lib/masking/cli/error_messages.yml +0 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8fff3fddd7077702babd4aeffafe86e80f79ab5151fb40ba92bba3ebf86513e3
|
|
4
|
+
data.tar.gz: f9f7d5ed2dbd5c1ebb6789d154c6c6fe64b72d4528ee923a6c4d0b8575e869ba
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 909c267ad406fc1bded87cb368cd5b130612270e2a41046c129cc529f9dd3fbb29b1d799a71613e404333463c7af6f2a33f323b0e3a29af204aae0c48c96e54d
|
|
7
|
+
data.tar.gz: 618c7ff871b6ae32fc26095d0e409ffe67f1da6c4759a1a9ae45a93bc3336f1f775352a514d095955882c33bb874133df3d258af9c3040a4f6ed0d7bbf354789
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- adding dockerfile for github container images [#77](https://github.com/kibitan/masking/pull/77)
|
|
13
|
+
- Update README.md about frequent asked question [#74](https://github.com/kibitan/masking/pull/74)
|
|
14
|
+
|
|
15
|
+
### Fix
|
|
16
|
+
|
|
17
|
+
- fix the error on the error message [#74](https://github.com/kibitan/masking/pull/74) relates issue [#73](https://github.com/kibitan/masking/issues/73)
|
|
18
|
+
|
|
10
19
|
## [v1.1.1] - 2023-04-03
|
|
11
20
|
|
|
12
21
|
### Added
|
data/CODEOWNERS
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @kibitan
|
data/Dockerfile
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
ARG
|
|
1
|
+
ARG RUBY_VERSION=3.2
|
|
2
2
|
|
|
3
|
-
FROM ruby:$
|
|
3
|
+
FROM ruby:${RUBY_VERSION}-alpine AS builder
|
|
4
4
|
RUN apk add --no-cache build-base git
|
|
5
5
|
RUN addgroup -S app && adduser -S -G app app
|
|
6
6
|
USER app
|
|
@@ -13,7 +13,7 @@ USER root
|
|
|
13
13
|
RUN apk add --no-cache mysql-client
|
|
14
14
|
USER app
|
|
15
15
|
|
|
16
|
-
FROM ruby:$
|
|
16
|
+
FROM ruby:${RUBY_VERSION}-alpine
|
|
17
17
|
# TODO: remove dependecy of `git` from masking.gemspec:L19
|
|
18
18
|
RUN apk add --no-cache git
|
|
19
19
|
RUN addgroup -S app && adduser -S -G app app
|
data/Dockerfile.ghcr
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# `docker run ghcr.io/kibitan/masking`
|
|
2
|
+
ARG RUBY_VERSION=3.2
|
|
3
|
+
|
|
4
|
+
FROM ruby:$RUBY_VERSION-alpine
|
|
5
|
+
RUN addgroup -S app && adduser -S -G app app
|
|
6
|
+
USER app
|
|
7
|
+
WORKDIR /app
|
|
8
|
+
ARG MASKING_VERSION=1.1.1
|
|
9
|
+
RUN gem install masking -v "${MASKING_VERSION}"
|
|
10
|
+
ENTRYPOINT ["masking"]
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -29,33 +29,35 @@ gem install masking
|
|
|
29
29
|
|
|
30
30
|
1. Setup configuration for anonymizing target tables/columns to `masking.yml`
|
|
31
31
|
|
|
32
|
+
*NOTE: the columns which doesn't mention here will be NOT anonymized, it stays as it is.*
|
|
33
|
+
|
|
32
34
|
```yaml
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
35
|
+
# table_name:
|
|
36
|
+
# column_name: masked_value
|
|
37
|
+
|
|
38
|
+
users:
|
|
39
|
+
string: anonymized string
|
|
40
|
+
email: anonymized+%{n}@example.com # %{n} will be replaced with sequential number
|
|
41
|
+
integer: 12345
|
|
42
|
+
float: 123.45
|
|
43
|
+
boolean: true
|
|
44
|
+
null_column: null
|
|
45
|
+
date: 2018-08-24
|
|
46
|
+
time: 2018-08-24 15:54:06
|
|
47
|
+
binary_or_blob: !binary | # Binary Data Language-Independent Type for YAML™ Version 1.1: http://yaml.org/type/binary.html
|
|
48
|
+
R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5
|
|
49
|
+
OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+
|
|
50
|
+
+f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC
|
|
51
|
+
AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=
|
|
52
|
+
# When a column name is suffixed with `?`, the original NULL value will not be anonymized.
|
|
53
|
+
# This option can be beneficial for simulating SQL execution that closely resembles the original data.
|
|
54
|
+
nullable_string?: anonymized nullable %{n} string
|
|
53
55
|
```
|
|
54
56
|
|
|
55
57
|
A value will be implicitly converted to a compatible type. If you prefer to explicitly convert, you could use a tag as defined in [YAML Version 1.1](http://yaml.org/spec/current.html#id2503753)
|
|
56
58
|
|
|
57
59
|
```yaml
|
|
58
|
-
|
|
60
|
+
not-date: !!str 2002-04-28
|
|
59
61
|
```
|
|
60
62
|
|
|
61
63
|
String should be matched with [MySQL String Type]( https://dev.mysql.com/doc/refman/8.0/en/string-type-overview.html). Integer/Float should be matched with [MySQL Numeric Type](https://dev.mysql.com/doc/refman/8.0/en/numeric-type-overview.html). Date/Time should be matched with [MySQL Date and Time Type](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-type-overview.html).
|
data/acceptance/run_test.sh
CHANGED
|
@@ -10,16 +10,28 @@ MYSQL_DBNAME=${MYSQL_DBNAME:-mydb}
|
|
|
10
10
|
|
|
11
11
|
FILEDIR="$( cd "$( dirname "$0" )" && pwd )"
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
# clear tmp file
|
|
14
14
|
rm "$FILEDIR"/tmp/* || echo 'no tmp file'
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
# import database
|
|
17
17
|
mysql -h "$MYSQL_HOST" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DBNAME" < "$FILEDIR/import_dumpfile.sql"
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
# masking & restore
|
|
20
20
|
mysqldump -h "$MYSQL_HOST" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DBNAME" --complete-insert | exe/masking -c "$FILEDIR/masking.yml" > "$FILEDIR/tmp/masking_dumpfile.sql"
|
|
21
21
|
mysql -h "$MYSQL_HOST" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DBNAME" < "$FILEDIR/tmp/masking_dumpfile.sql"
|
|
22
|
-
|
|
23
|
-
## compare
|
|
22
|
+
## compare the result
|
|
24
23
|
mysql -h "$MYSQL_HOST" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DBNAME" -e 'SELECT * FROM users ORDER BY id;' --vertical > "$FILEDIR/tmp/query_result.txt"
|
|
25
|
-
diff "$FILEDIR/expected_query_result.txt" "$FILEDIR/tmp/query_result.txt"
|
|
24
|
+
diff "$FILEDIR/expected_query_result.txt" "$FILEDIR/tmp/query_result.txt" || (echo 'test failed' && exit 1)
|
|
25
|
+
|
|
26
|
+
# test errors
|
|
27
|
+
set +e
|
|
28
|
+
## without masking.yml
|
|
29
|
+
mysqldump -h "$MYSQL_HOST" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DBNAME" --complete-insert | exe/masking -c "$FILEDIR/no_file.yml" 2>> "$FILEDIR/tmp/errors.txt" 1> /dev/null
|
|
30
|
+
## without `--complete-insert``
|
|
31
|
+
mysqldump -h "$MYSQL_HOST" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DBNAME" | exe/masking -c "$FILEDIR/masking.yml" 2>> "$FILEDIR/tmp/errors.txt" 1> /dev/null
|
|
32
|
+
set -e
|
|
33
|
+
### compare the result
|
|
34
|
+
diff "$FILEDIR/expected_error_result.txt" "$FILEDIR/tmp/errors.txt" || (echo 'error output test failed' && exit 1)
|
|
35
|
+
|
|
36
|
+
echo 'test passed!'
|
|
37
|
+
exit 0
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'pathname'
|
|
4
3
|
require 'erb'
|
|
5
4
|
require 'ostruct'
|
|
5
|
+
require 'masking/errors'
|
|
6
6
|
|
|
7
7
|
module Masking
|
|
8
8
|
class Cli
|
|
@@ -19,19 +19,26 @@ module Masking
|
|
|
19
19
|
|
|
20
20
|
attr_reader :error_class
|
|
21
21
|
|
|
22
|
-
YAML_FILE_PATH = Pathname('lib/masking/cli/error_messages.yml')
|
|
23
|
-
|
|
24
|
-
def error_messages
|
|
25
|
-
@error_messages = YAML.safe_load(YAML_FILE_PATH.read)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
22
|
def error_message(keyword_args)
|
|
29
23
|
ERB.new(
|
|
30
|
-
|
|
24
|
+
ERROR_MESSAGES.fetch(error_class.to_s)
|
|
31
25
|
).result(
|
|
32
26
|
OpenStruct.new(keyword_args).instance_eval { binding } # rubocop:disable Style/OpenStructUse
|
|
33
27
|
)
|
|
34
28
|
end
|
|
29
|
+
|
|
30
|
+
ERROR_MESSAGES = {
|
|
31
|
+
'Masking::Error::ConfigFileDoesNotExist' =>
|
|
32
|
+
'ERROR: config file (<%= config_file_path %>) does not exist',
|
|
33
|
+
'Masking::Error::ConfigFileIsNotFile' =>
|
|
34
|
+
'ERROR: config file (<%= config_file_path %>) is not file',
|
|
35
|
+
'Masking::Error::ConfigFileIsNotValidYaml' =>
|
|
36
|
+
'ERROR: config file (<%= config_file_path %>) is not valid yaml format',
|
|
37
|
+
'Masking::Error::ConfigFileContainsNullAsColumnName' =>
|
|
38
|
+
'ERROR: config file (<%= config_file_path %>) is not valid, column name contains `null`',
|
|
39
|
+
'Masking::Error::InsertStatementParseError' =>
|
|
40
|
+
'ERROR: cannot parse SQL dump file. you may forget to put `--complete-insert` option in mysqldump?'
|
|
41
|
+
}.freeze
|
|
35
42
|
end
|
|
36
43
|
end
|
|
37
44
|
end
|
data/lib/masking/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: masking
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1.
|
|
4
|
+
version: 1.1.2.pre.alpha
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chikahiro Tokoro
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-04-
|
|
11
|
+
date: 2023-04-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Command line tool for anonymizing database records by parsing a SQL dump
|
|
14
14
|
file and build new SQL dump file with masking sensitive/credential data.
|
|
@@ -31,13 +31,16 @@ files:
|
|
|
31
31
|
- ".rubocop_todo.yml"
|
|
32
32
|
- ".ruby-version"
|
|
33
33
|
- CHANGELOG.md
|
|
34
|
+
- CODEOWNERS
|
|
34
35
|
- CODE_OF_CONDUCT.md
|
|
35
36
|
- Dockerfile
|
|
37
|
+
- Dockerfile.ghcr
|
|
36
38
|
- Gemfile
|
|
37
39
|
- Gemfile.lock
|
|
38
40
|
- LICENSE.txt
|
|
39
41
|
- README.md
|
|
40
42
|
- Rakefile
|
|
43
|
+
- acceptance/expected_error_result.txt
|
|
41
44
|
- acceptance/expected_query_result.txt
|
|
42
45
|
- acceptance/import_dumpfile.sql
|
|
43
46
|
- acceptance/masking.yml
|
|
@@ -76,7 +79,6 @@ files:
|
|
|
76
79
|
- lib/masking.rb
|
|
77
80
|
- lib/masking/cli.rb
|
|
78
81
|
- lib/masking/cli/error_message.rb
|
|
79
|
-
- lib/masking/cli/error_messages.yml
|
|
80
82
|
- lib/masking/config.rb
|
|
81
83
|
- lib/masking/config/target_columns.rb
|
|
82
84
|
- lib/masking/config/target_columns/column.rb
|
|
@@ -120,9 +122,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
120
122
|
version: '2.6'
|
|
121
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
122
124
|
requirements:
|
|
123
|
-
- - "
|
|
125
|
+
- - ">"
|
|
124
126
|
- !ruby/object:Gem::Version
|
|
125
|
-
version:
|
|
127
|
+
version: 1.3.1
|
|
126
128
|
requirements: []
|
|
127
129
|
rubygems_version: 3.4.6
|
|
128
130
|
signing_key:
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
Masking::Error::ConfigFileDoesNotExist:
|
|
2
|
-
"ERROR: config file (<%= config_file_path %>) does not exist"
|
|
3
|
-
Masking::Error::ConfigFileIsNotFile:
|
|
4
|
-
"ERROR: config file (<%= config_file_path %>) is not file"
|
|
5
|
-
Masking::Error::ConfigFileIsNotValidYaml:
|
|
6
|
-
"ERROR: config file (<%= config_file_path %>) is not valid yaml format"
|
|
7
|
-
Masking::Error::ConfigFileContainsNullAsColumnName:
|
|
8
|
-
"ERROR: config file (<%= config_file_path %>) is not valid, column name contains `null`"
|
|
9
|
-
Masking::Error::InsertStatementParseError:
|
|
10
|
-
"ERROR: cannot parse SQL dump file. you may forget to put `--complete-insert` option in mysqldump?"
|