masking 0.0.3 → 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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +30 -0
  3. data/.codeclimate.yml +4 -0
  4. data/.dockerignore +18 -0
  5. data/.github/workflows/acceptance_test_mariadb.yml +56 -0
  6. data/.github/workflows/acceptance_test_mysql.yml +40 -0
  7. data/.github/workflows/check_changelog.yml +13 -0
  8. data/.gitignore +3 -0
  9. data/.mdlrc +1 -0
  10. data/.ruby-version +1 -1
  11. data/CHANGELOG.md +11 -0
  12. data/Dockerfile +24 -0
  13. data/Gemfile.lock +3 -3
  14. data/README.md +61 -12
  15. data/acceptance/expected_query_result.txt +33 -0
  16. data/acceptance/import_dumpfile.sql +59 -0
  17. data/acceptance/masking.yml +15 -0
  18. data/acceptance/run_test.sh +25 -0
  19. data/docker-compose-ci.yml +6 -0
  20. data/docker-compose.yml +11 -0
  21. data/docker-compose/acceptance_test.sh +8 -0
  22. data/docker-compose/mariadb100.yml +17 -0
  23. data/docker-compose/mariadb101.yml +17 -0
  24. data/docker-compose/mariadb102.yml +17 -0
  25. data/docker-compose/mariadb103.yml +17 -0
  26. data/docker-compose/mariadb104.yml +17 -0
  27. data/docker-compose/mariadb55.yml +17 -0
  28. data/docker-compose/mysql55.yml +17 -0
  29. data/docker-compose/mysql56.yml +17 -0
  30. data/docker-compose/mysql57.yml +17 -0
  31. data/docker-compose/mysql80.yml +19 -0
  32. data/docker-compose/wait-for-mysql.sh +19 -0
  33. data/exe/masking +3 -0
  34. data/lib/masking/cli.rb +8 -0
  35. data/lib/masking/cli/error_messages.yml +4 -0
  36. data/lib/masking/config/target_columns.rb +2 -0
  37. data/lib/masking/config/target_columns/column.rb +3 -0
  38. data/lib/masking/errors.rb +3 -0
  39. data/lib/masking/insert_statement.rb +3 -0
  40. data/lib/masking/version.rb +1 -1
  41. data/masking.gemspec +1 -1
  42. data/masking.yml.sample +1 -1
  43. metadata +31 -6
  44. data/.travis.yml +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a65d39a6c96c94bf473883d1ef9877f1abdd16cfcae97da27e99f8c7afa9963
4
- data.tar.gz: 109965dbb6e2ee880f9fd955e4f0d05f6a3dfbc8cbecd153315f9bcad275bf86
3
+ metadata.gz: 34f66d96cbd6ffe36c28c91073edb927d60eba4aa520d6fcc025bb5dd156d5a7
4
+ data.tar.gz: 492f56f9002a98220fefe58b18232dd1b6d0a340be796fc10ae863043ccb843e
5
5
  SHA512:
6
- metadata.gz: 03010bd6d5fb1c90ed1c6dca9dff8f7d84bfe934d65bf48fab28feb3aa6c67381c0c1c6d85ba055b21334919ad1b075a166e23ab3d01fc76f09575f08c1ccac0
7
- data.tar.gz: ff9ddd10f8f30c72427815177bb37d68e46fedd7d104d1141d5655449c7ae3811e4d2d0135113b2145b4b809d5774752b9c0100337927d6a59949a9c4fe35580
6
+ metadata.gz: 6057d19706c939b4ab70a0349f57dc550ac95ea98726938ae6d48fa6eac4cd389169715d985883769870752fc8dee2a6a28d68727005b87c3fb9ff5589ee2267
7
+ data.tar.gz: e9be5add5db208a607096e4b0a2c27b8214a55f796b23ff575aaed8cf138ed5de9de40cdb2199ffcdbba33f804c39bef6b4df60f66a8ef0d9f64f9046a58cba1
@@ -0,0 +1,30 @@
1
+ version: 2.1
2
+
3
+ test_attributes: &test_attributes
4
+ machine: true
5
+ steps:
6
+ - checkout
7
+ - run: docker build -t masking-$RUBY_VERSION-$CIRCLE_SHA1 --build-arg ruby_version=$RUBY_VERSION .
8
+ - run: docker run --entrypoint sh masking-$RUBY_VERSION-$CIRCLE_SHA1 -c "ruby -v" # debug
9
+ - run: docker run --entrypoint sh -e CI -e COVERALLS_REPO_TOKEN masking-$RUBY_VERSION-$CIRCLE_SHA1 -c "bundle exec rspec"
10
+
11
+ jobs:
12
+ test-rubyrc:
13
+ <<: *test_attributes
14
+ environment:
15
+ RUBY_VERSION: rc
16
+ test-ruby26:
17
+ <<: *test_attributes
18
+ environment:
19
+ RUBY_VERSION: '2.6'
20
+ test-ruby25:
21
+ <<: *test_attributes
22
+ environment:
23
+ RUBY_VERSION: '2.5'
24
+
25
+ workflows:
26
+ 'CircleCI: build':
27
+ jobs:
28
+ - test-ruby26
29
+ - test-ruby25
30
+ - test-rubyrc
@@ -5,6 +5,10 @@ plugins:
5
5
  markdownlint:
6
6
  enabled: true
7
7
  checks:
8
+ MD013: # MD013/Line length
9
+ enabled: false
10
+ MD033: # MD033/no-inline-html
11
+ enabled: false
8
12
  # below 3 checks are disabled because Codeclimate's Markdownlint is not latest version (0.5.0)
9
13
  MD023:
10
14
  enabled: false
@@ -0,0 +1,18 @@
1
+ /.bundle/
2
+ /_yardoc/
3
+ /coverage/*
4
+ /doc/
5
+ /pkg/
6
+ /spec/reports/*
7
+ /tmp/*
8
+ /profile/
9
+ /vendor/
10
+ .DS_Store
11
+
12
+ # rspec failure tracking
13
+ .rspec_status
14
+
15
+ Dockerfile
16
+ docker-compose.yml
17
+ docker-compose-ci.yml
18
+ docker-compose/*.yml
@@ -0,0 +1,56 @@
1
+ name: Acceptance Test MariaDB
2
+ on:
3
+ push:
4
+ branches:
5
+ - master
6
+ pull_request:
7
+
8
+ jobs:
9
+ mariadb104:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v1
13
+ with:
14
+ fetch-depth: 1 # shallow clone
15
+ - name: run test
16
+ run: docker-compose/acceptance_test.sh mariadb104 docker-compose-ci.yml
17
+ mariadb103:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v1
21
+ with:
22
+ fetch-depth: 1 # shallow clone
23
+ - name: run test
24
+ run: docker-compose/acceptance_test.sh mariadb103 docker-compose-ci.yml
25
+ mariadb102:
26
+ runs-on: ubuntu-latest
27
+ steps:
28
+ - uses: actions/checkout@v1
29
+ with:
30
+ fetch-depth: 1 # shallow clone
31
+ - name: run test
32
+ run: docker-compose/acceptance_test.sh mariadb102 docker-compose-ci.yml
33
+ mariadb101:
34
+ runs-on: ubuntu-latest
35
+ steps:
36
+ - uses: actions/checkout@v1
37
+ with:
38
+ fetch-depth: 1 # shallow clone
39
+ - name: run test
40
+ run: docker-compose/acceptance_test.sh mariadb101 docker-compose-ci.yml
41
+ mariadb100:
42
+ runs-on: ubuntu-latest
43
+ steps:
44
+ - uses: actions/checkout@v1
45
+ with:
46
+ fetch-depth: 1 # shallow clone
47
+ - name: run test
48
+ run: docker-compose/acceptance_test.sh mariadb100 docker-compose-ci.yml
49
+ mariadb55:
50
+ runs-on: ubuntu-latest
51
+ steps:
52
+ - uses: actions/checkout@v1
53
+ with:
54
+ fetch-depth: 1 # shallow clone
55
+ - name: run test
56
+ run: docker-compose/acceptance_test.sh mariadb55 docker-compose-ci.yml
@@ -0,0 +1,40 @@
1
+ name: Acceptance Test MySQL
2
+ on:
3
+ push:
4
+ branches:
5
+ - master
6
+ pull_request:
7
+
8
+ jobs:
9
+ mysql80:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v1
13
+ with:
14
+ fetch-depth: 1 # shallow clone
15
+ - name: run test
16
+ run: docker-compose/acceptance_test.sh mysql80 docker-compose-ci.yml
17
+ mysql57:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/checkout@v1
21
+ with:
22
+ fetch-depth: 1 # shallow clone
23
+ - name: run test
24
+ run: docker-compose/acceptance_test.sh mysql57 docker-compose-ci.yml
25
+ mysql56:
26
+ runs-on: ubuntu-latest
27
+ steps:
28
+ - uses: actions/checkout@v1
29
+ with:
30
+ fetch-depth: 1 # shallow clone
31
+ - name: run test
32
+ run: docker-compose/acceptance_test.sh mysql56 docker-compose-ci.yml
33
+ mysql55:
34
+ runs-on: ubuntu-latest
35
+ steps:
36
+ - uses: actions/checkout@v1
37
+ with:
38
+ fetch-depth: 1 # shallow clone
39
+ - name: run test
40
+ run: docker-compose/acceptance_test.sh mysql55 docker-compose-ci.yml
@@ -0,0 +1,13 @@
1
+ # inspired from: https://github.com/rails/sprockets/pull/631
2
+ name: Check Changelog
3
+
4
+ on: [pull_request]
5
+
6
+ jobs:
7
+ build:
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - uses: actions/checkout@v1
11
+ - name: Check that CHANGELOG is touched
12
+ run: |
13
+ cat $GITHUB_EVENT_PATH | jq .pull_request.title | grep -i '\[changelog skip\]\|\[skip changelog\]' || git diff remotes/origin/${{ github.base_ref }} --name-only | grep CHANGELOG.md
data/.gitignore CHANGED
@@ -14,3 +14,6 @@
14
14
 
15
15
  # config
16
16
  /masking.yml
17
+
18
+ # artifacts of acceptance test
19
+ acceptance/tmp
data/.mdlrc CHANGED
@@ -1 +1,2 @@
1
1
  rules "~MD013"
2
+ rules "~MD033"
@@ -1 +1 @@
1
- 2.6.0
1
+ 2.6.5
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [v1.0.0] - 2019-11-10
11
+
12
+ ### Added
13
+
14
+ - `masking --version` option [#31](https://github.com/kibitan/masking/pull/31)
15
+ - add friendly parse error message [#26](https://github.com/kibitan/masking/pull/26) [#38](https://github.com/kibitan/masking/pull/38)
16
+ - Setup Docker and Acceptance test [#32](https://github.com/kibitan/masking/pull/32) [#36](https://github.com/kibitan/masking/pull/36)
17
+ - setup acceptance test for ci [#34](https://github.com/kibitan/masking/pull/34)
18
+ - add Ruby2.7(preview) [#35](https://github.com/kibitan/masking/pull/35)
19
+ - setup ci for changelog checker [#41](https://github.com/kibitan/masking/pull/41)
20
+
10
21
  ## [v0.0.3] - 2019-07-07
11
22
 
12
23
  ### Changed
@@ -0,0 +1,24 @@
1
+ ARG ruby_version=2.6
2
+
3
+ FROM ruby:$ruby_version-alpine AS builder
4
+ RUN apk add --no-cache build-base git
5
+ WORKDIR /app
6
+ RUN addgroup -S app && adduser -S -G app app
7
+ USER app
8
+ COPY --chown=app . ./
9
+ RUN gem install bundler:2.0.2 && bundle install -j "$(nproc)"
10
+
11
+ FROM builder AS with-mysql-client
12
+ USER root
13
+ RUN apk add --no-cache mysql-client
14
+ USER app
15
+
16
+ FROM ruby:$ruby_version-alpine
17
+ WORKDIR /app
18
+ # TODO: remove dependecy of `git` from masking.gemspec:L19
19
+ RUN apk add --no-cache git
20
+ RUN addgroup -S app && adduser -S -G app app
21
+ USER app
22
+ COPY --from=builder /usr/local/bundle/ /usr/local/bundle/
23
+ COPY --chown=app . ./
24
+ ENTRYPOINT ["bundle", "exec", "exe/masking"]
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- masking (0.0.3)
4
+ masking (1.0.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -101,7 +101,7 @@ PLATFORMS
101
101
  ruby
102
102
 
103
103
  DEPENDENCIES
104
- bundler (~> 1.16)
104
+ bundler (~> 2.0)
105
105
  coveralls
106
106
  masking!
107
107
  mdl
@@ -116,4 +116,4 @@ DEPENDENCIES
116
116
  tapp
117
117
 
118
118
  BUNDLED WITH
119
- 1.17.3
119
+ 2.0.2
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  # MasKING🤴
2
2
 
3
- [![Build Status](https://travis-ci.org/kibitan/masking.svg?branch=master)](https://travis-ci.org/kibitan/masking)
3
+ [![CircleCI](https://circleci.com/gh/kibitan/masking/tree/master.svg?style=svg)](https://circleci.com/gh/kibitan/masking/tree/master)
4
+ [![Acceptance Test MySQL Status](https://github.com/kibitan/masking/workflows/Acceptance%20Test%20MySQL/badge.svg?branch=master)](https://github.com/kibitan/masking/actions?query=workflow%3A%22Acceptance+Test+MySQL%22+branch%3Amaster)
5
+ [![Acceptance Test MariaDB Status](https://github.com/kibitan/masking/workflows/Acceptance%20Test%20MariaDB/badge.svg?branch=master)](https://github.com/kibitan/masking/actions?query=workflow%3A%22Acceptance+Test+MariaDB%22+branch%3Amaster)
6
+
4
7
  [![Coverage Status](https://coveralls.io/repos/github/kibitan/masking/badge.svg?branch=master)](https://coveralls.io/github/kibitan/masking?branch=master)
5
8
  [![Maintainability](https://api.codeclimate.com/v1/badges/290b3005ecc193a3d138/maintainability)](https://codeclimate.com/github/kibitan/masking/maintainability)
6
9
  [![Gem Version](https://badge.fury.io/rb/masking.svg)](https://badge.fury.io/rb/masking)
@@ -15,11 +18,12 @@ gem install masking
15
18
 
16
19
  ## Requirement
17
20
 
18
- * Ruby 2.5/2.6
21
+ * Ruby 2.5/2.6/2.7(preview)
19
22
 
20
23
  ## Supported RDBMS
21
24
 
22
- * MySQL 5.7...(TBC)
25
+ * MySQL: 5.5<sup>[1](#footnote1)</sup>, 5.6, 5.7, 8.0
26
+ * MariaDB: 5.5, 10.0<sup>[2](#footnote2)</sup>, 10.1, 10.2, 10.3, 10.4
23
27
 
24
28
  ## Usage
25
29
 
@@ -35,7 +39,7 @@ gem install masking
35
39
  integer: 12345
36
40
  float: 123.45
37
41
  boolean: true
38
- null: null
42
+ null_column: null
39
43
  date: 2018-08-24
40
44
  time: 2018-08-24 15:54:06
41
45
  binary_or_blob: !binary | # Binary Data Language-Independent Type for YAML™ Version 1.1: http://yaml.org/type/binary.html
@@ -81,6 +85,7 @@ gem install masking
81
85
  $ masking -h
82
86
  Usage: masking [options]
83
87
  -c, --config=FILE_PATH specify config file. default: masking.yml
88
+ -v, --version version
84
89
  ```
85
90
 
86
91
  ## Use case of annonymized (production) database
@@ -118,30 +123,71 @@ You can also run `bin/console` for an interactive prompt that will allow you to
118
123
 
119
124
  To install this gem onto your local machine, run `bundle exec rake install`.
120
125
 
126
+ ### boot
127
+
128
+ ```bash
129
+ bundle exec exe/masking
130
+ ```
131
+
121
132
  ### Run test & rubocop & notes
122
133
 
123
134
  ```bash
124
135
  bundle exec rake
125
136
  ```
126
137
 
127
- #### Protip
138
+ #### acceptance test
139
+
140
+ ```bash
141
+ ./acceptance/run_test.sh
142
+ ```
143
+
144
+ available option via environment variable:
145
+
146
+ * `MYSQL_HOST`: database host(default: `localhost`)
147
+ * `MYSQL_USER`: mysql user name(default: `mysqluser`}
148
+ * `MYSQL_PASSWORD`: password for user(default: `password`)
149
+ * `MYSQL_DBNAME`: database name(default: `mydb`)
150
+
151
+ ##### with docker
128
152
 
129
- It's useful that set `rake` on [Git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks).
153
+ ```bash
154
+ docker-compose -f docker-compose.yml -f docker-compose/mysql80.yml run -e MYSQL_HOST=mysql80 app acceptance/run_test.sh
155
+ ```
156
+
157
+ or
130
158
 
131
159
  ```bash
132
- touch .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit && cat << EOF > .git/hooks/pre-commit
133
- #!/usr/bin/env bash
134
- bundle exec rake
135
- EOF
160
+ docker-compose/acceptance_test.sh mysql80
136
161
  ```
137
162
 
163
+ The docker-compose file names for other database versions, specify that file.
164
+
165
+ * MySQL 8.0: [`docker-compose/mysql80.yml`](./docker-compose/mysql80.yml)
166
+ * MySQL 5.7: [`docker-compose/mysql57.yml`](./docker-compose/mysql57.yml)
167
+ * MySQL 5.6: [`docker-compose/mysql56.yml`](./docker-compose/mysql56.yml)
168
+ * MySQL 5.5<sup>[1](#footnote1)</sup>: [`docker-compose/mysql55.yml`](./docker-compose/mysql55.yml)
169
+ * MariaDB 10.4: [`docker-compose/mariadb104.yml`](./docker-compose/mariadb104.yml)
170
+ * MariaDB 10.3: [`docker-compose/mariadb103.yml`](./docker-compose/mariadb103.yml)
171
+ * MariaDB 10.2: [`docker-compose/mariadb102.yml`](./docker-compose/mariadb102.yml)
172
+ * MariaDB 10.1: [`docker-compose/mariadb101.yml`](./docker-compose/mariadb101.yml)
173
+ * MariaDB 10.0<sup>[2](#footnote2)</sup>: [`docker-compose/mariadb100.yml`](./docker-compose/mariadb100.yml)
174
+ * MariaDB 5.5: [`docker-compose/mariadb55.yml`](./docker-compose/mariadb55.yml)
175
+
138
176
  #### [Markdown lint](https://github.com/markdownlint/markdownlint)
139
177
 
140
178
  ```bash
141
179
  bundle exec mdl *.md
142
180
  ```
143
181
 
144
- ### Profiling
182
+ ## Development with Docker
183
+
184
+ ```bash
185
+ docker build . -t masking
186
+ echo "sample stdout" | docker run -i masking
187
+ docker run masking -v
188
+ ```
189
+
190
+ ## Profiling
145
191
 
146
192
  use `bin/masking_profile`
147
193
 
@@ -181,7 +227,6 @@ Depend on only pure language standard libraries, no external libraries. (except
181
227
  * Pluguable/customizable for a mask way e.g. integrate with [Faker](https://github.com/stympy/faker)
182
228
  * Compatible with other RDBMS e.g. PostgreSQL, Oracle, SQL Server
183
229
  * Parse the schema type information and validate target columns value
184
- * Integration test with real database
185
230
  * Performance optimization
186
231
  * Write in streaming process
187
232
  * rewrite by another language?
@@ -199,3 +244,7 @@ The gem is available as open source under the terms of the [MIT License](https:/
199
244
  ## Code of Conduct
200
245
 
201
246
  Everyone interacting in the Masking project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/kibitan/masking/blob/master/CODE_OF_CONDUCT.md).
247
+
248
+ <a name="footnote1">1</a>: <small> MySQL 5.5 is already not supported by [official](https://www.mysql.com/support/supportedplatforms/database.html)</small>
249
+
250
+ <a name="footnote2">2</a>: <small> MariaDB 10.0 is already not supported by [official](https://mariadb.org/about/maintenance-policy/)</small>
@@ -0,0 +1,33 @@
1
+ *************************** 1. row ***************************
2
+ id: 1
3
+ string: anonymized string
4
+ email: anonymized+1@example.com
5
+ integer: 12345
6
+ float: 123.45
7
+ boolean: 1
8
+ null: NULL
9
+ date: 2018-08-24
10
+ time: 2018-08-24 15:54:06
11
+ binary_or_blob: \x92
12
+ *************************** 2. row ***************************
13
+ id: 2
14
+ string: anonymized string
15
+ email: anonymized+2@example.com
16
+ integer: 12345
17
+ float: 123.45
18
+ boolean: 1
19
+ null: NULL
20
+ date: 2018-08-24
21
+ time: 2018-08-24 15:54:06
22
+ binary_or_blob: \x92\x92
23
+ *************************** 3. row ***************************
24
+ id: 3
25
+ string: anonymized string
26
+ email: anonymized+3@example.com
27
+ integer: 12345
28
+ float: 123.45
29
+ boolean: 1
30
+ null: NULL
31
+ date: 2018-08-24
32
+ time: 2018-08-24 15:54:06
33
+ binary_or_blob: NULL
@@ -0,0 +1,59 @@
1
+ -- MySQL dump 10.13 Distrib 5.7.27, for osx10.14 (x86_64)
2
+ --
3
+ -- Host: localhost Database: sample
4
+ -- ------------------------------------------------------
5
+ -- Server version 5.7.27
6
+
7
+ /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
8
+ /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
9
+ /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
10
+ /*!40101 SET NAMES utf8 */;
11
+ /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
12
+ /*!40103 SET TIME_ZONE='+00:00' */;
13
+ /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
14
+ /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
15
+ /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
16
+ /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
17
+
18
+ --
19
+ -- Table structure for table `users`
20
+ --
21
+
22
+ DROP TABLE IF EXISTS `users`;
23
+ /*!40101 SET @saved_cs_client = @@character_set_client */;
24
+ /*!40101 SET character_set_client = utf8 */;
25
+ CREATE TABLE `users` (
26
+ `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
27
+ `string` varchar(20) NOT NULL DEFAULT '',
28
+ `email` varchar(200) NOT NULL DEFAULT '',
29
+ `integer` int(11) DEFAULT NULL,
30
+ `float` float DEFAULT NULL,
31
+ `boolean` tinyint(1) DEFAULT NULL,
32
+ `null` int(11) DEFAULT NULL,
33
+ `date` date DEFAULT NULL,
34
+ `time` timestamp NULL DEFAULT NULL,
35
+ `binary_or_blob` binary(11) DEFAULT NULL,
36
+ PRIMARY KEY (`id`)
37
+ ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
38
+ /*!40101 SET character_set_client = @saved_cs_client */;
39
+
40
+ --
41
+ -- Dumping data for table `users`
42
+ --
43
+
44
+ LOCK TABLES `users` WRITE;
45
+ /*!40000 ALTER TABLE `users` DISABLE KEYS */;
46
+ INSERT INTO `users` (`id`, `string`, `email`, `integer`, `float`, `boolean`, `null`, `date`, `time`, `binary_or_blob`) VALUES (1,'example@exa','test@example.com',1245,2.1,1,-321,NULL,NULL,_binary '\\x92\0\0\0\0\0\0\0'),(2,'あいうえお','invalid@email',0,-23.4422,0,321,NULL,NULL,_binary '\\x92\\x92\0\0\0'),(3,'+-l;a*&^%$','chikahiro@test.com',-1,21.2321,NULL,-231321,'2019-10-31','2019-10-31 16:27:21',NULL);
47
+ /*!40000 ALTER TABLE `users` ENABLE KEYS */;
48
+ UNLOCK TABLES;
49
+ /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
50
+
51
+ /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
52
+ /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
53
+ /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
54
+ /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
55
+ /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
56
+ /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
57
+ /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
58
+
59
+ -- Dump completed on 2019-10-31 18:19:32
@@ -0,0 +1,15 @@
1
+ users:
2
+ string: anonymized string
3
+ email: anonymized+%{n}@example.com
4
+ integer: 12345
5
+ float: 123.45
6
+ boolean: true
7
+ 'null': NULL
8
+ date: 2018-08-24
9
+ time: 2018-08-24 15:54:06
10
+ ## TODO: something not working well with binary...
11
+ # binary_or_blob: !binary |
12
+ # R0lGODlhDAAMAIQAAP//9/X17unp5WZmZgAAAOfn515eXvPz7Y6OjuDg4J+fn5
13
+ # OTk6enp56enmlpaWNjY6Ojo4SEhP/++f/++f/++f/++f/++f/++f/++f/++f/+
14
+ # +f/++f/++f/++f/++f/++SH+Dk1hZGUgd2l0aCBHSU1QACwAAAAADAAMAAAFLC
15
+ # AgjoEwnuNAFOhpEMTRiggcz4BNJHrv/zCFcLiwMWYNG84BwwEeECcgggoBADs=
@@ -0,0 +1,25 @@
1
+ #!/bin/sh
2
+
3
+ set -Ceu -o pipefail
4
+ # set -vx # for debug
5
+
6
+ MYSQL_HOST=${MYSQL_HOST:-localhost}
7
+ MYSQL_USER=${MYSQL_USER:-mysqluser}
8
+ MYSQL_PASSWORD=${MYSQL_PASSWORD:-password}
9
+ MYSQL_DBNAME=${MYSQL_DBNAME:-mydb}
10
+
11
+ FILEDIR="$( cd "$( dirname "$0" )" && pwd )"
12
+
13
+ ## clear tmp file
14
+ rm "$FILEDIR"/tmp/* || echo 'no tmp file'
15
+
16
+ ## import database
17
+ mysql -h "$MYSQL_HOST" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DBNAME" < "$FILEDIR/import_dumpfile.sql"
18
+
19
+ ## masking
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
+ mysql -h "$MYSQL_HOST" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DBNAME" < "$FILEDIR/tmp/masking_dumpfile.sql"
22
+
23
+ ## compare
24
+ 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/tmp/query_result.txt" "$FILEDIR/expected_query_result.txt" && echo 'test passed!'
@@ -0,0 +1,6 @@
1
+ version: '3.7'
2
+
3
+ services:
4
+ app:
5
+ build: .
6
+ stdin_open: true
@@ -0,0 +1,11 @@
1
+ version: '3.7'
2
+
3
+ services:
4
+ app:
5
+ build: .
6
+ stdin_open: true
7
+ volumes:
8
+ - .:/app
9
+ tmpfs:
10
+ - /app/tmp
11
+ - /app/vendor
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -Ceu -o pipefail
4
+ #set -vx # for debug
5
+
6
+ MYSQL_VERSION=${1:-mysql80}
7
+ DOCKER_COMPOSE_FILE=${2:-docker-compose.yml}
8
+ docker-compose -f "$DOCKER_COMPOSE_FILE" -f "docker-compose/$MYSQL_VERSION.yml" run -e "MYSQL_HOST=$MYSQL_VERSION" app acceptance/run_test.sh
@@ -0,0 +1,17 @@
1
+ version: '3.7'
2
+
3
+ services:
4
+ app:
5
+ build:
6
+ target: with-mysql-client
7
+ depends_on:
8
+ - mariadb100
9
+ entrypoint: docker-compose/wait-for-mysql.sh mariadb100
10
+
11
+ mariadb100:
12
+ image: mariadb:10.0
13
+ environment:
14
+ MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
15
+ MYSQL_USER: mysqluser
16
+ MYSQL_PASSWORD: password
17
+ MYSQL_DATABASE: mydb
@@ -0,0 +1,17 @@
1
+ version: '3.7'
2
+
3
+ services:
4
+ app:
5
+ build:
6
+ target: with-mysql-client
7
+ depends_on:
8
+ - mariadb101
9
+ entrypoint: docker-compose/wait-for-mysql.sh mariadb101
10
+
11
+ mariadb101:
12
+ image: mariadb:10.1
13
+ environment:
14
+ MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
15
+ MYSQL_USER: mysqluser
16
+ MYSQL_PASSWORD: password
17
+ MYSQL_DATABASE: mydb
@@ -0,0 +1,17 @@
1
+ version: '3.7'
2
+
3
+ services:
4
+ app:
5
+ build:
6
+ target: with-mysql-client
7
+ depends_on:
8
+ - mariadb102
9
+ entrypoint: docker-compose/wait-for-mysql.sh mariadb102
10
+
11
+ mariadb102:
12
+ image: mariadb:10.2
13
+ environment:
14
+ MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
15
+ MYSQL_USER: mysqluser
16
+ MYSQL_PASSWORD: password
17
+ MYSQL_DATABASE: mydb
@@ -0,0 +1,17 @@
1
+ version: '3.7'
2
+
3
+ services:
4
+ app:
5
+ build:
6
+ target: with-mysql-client
7
+ depends_on:
8
+ - mariadb103
9
+ entrypoint: docker-compose/wait-for-mysql.sh mariadb103
10
+
11
+ mariadb103:
12
+ image: mariadb:10.3
13
+ environment:
14
+ MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
15
+ MYSQL_USER: mysqluser
16
+ MYSQL_PASSWORD: password
17
+ MYSQL_DATABASE: mydb
@@ -0,0 +1,17 @@
1
+ version: '3.7'
2
+
3
+ services:
4
+ app:
5
+ build:
6
+ target: with-mysql-client
7
+ depends_on:
8
+ - mariadb104
9
+ entrypoint: docker-compose/wait-for-mysql.sh mariadb104
10
+
11
+ mariadb104:
12
+ image: mariadb:10.4
13
+ environment:
14
+ MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
15
+ MYSQL_USER: mysqluser
16
+ MYSQL_PASSWORD: password
17
+ MYSQL_DATABASE: mydb
@@ -0,0 +1,17 @@
1
+ version: '3.7'
2
+
3
+ services:
4
+ app:
5
+ build:
6
+ target: with-mysql-client
7
+ depends_on:
8
+ - mariadb55
9
+ entrypoint: docker-compose/wait-for-mysql.sh mariadb55
10
+
11
+ mariadb55:
12
+ image: mariadb:5.5
13
+ environment:
14
+ MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
15
+ MYSQL_USER: mysqluser
16
+ MYSQL_PASSWORD: password
17
+ MYSQL_DATABASE: mydb
@@ -0,0 +1,17 @@
1
+ version: '3.7'
2
+
3
+ services:
4
+ app:
5
+ build:
6
+ target: with-mysql-client
7
+ depends_on:
8
+ - mysql55
9
+ entrypoint: docker-compose/wait-for-mysql.sh mysql55
10
+
11
+ mysql55:
12
+ image: mysql:5.5
13
+ environment:
14
+ MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
15
+ MYSQL_USER: mysqluser
16
+ MYSQL_PASSWORD: password
17
+ MYSQL_DATABASE: mydb
@@ -0,0 +1,17 @@
1
+ version: '3.7'
2
+
3
+ services:
4
+ app:
5
+ build:
6
+ target: with-mysql-client
7
+ depends_on:
8
+ - mysql56
9
+ entrypoint: docker-compose/wait-for-mysql.sh mysql56
10
+
11
+ mysql56:
12
+ image: mysql:5.6
13
+ environment:
14
+ MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
15
+ MYSQL_USER: mysqluser
16
+ MYSQL_PASSWORD: password
17
+ MYSQL_DATABASE: mydb
@@ -0,0 +1,17 @@
1
+ version: '3.7'
2
+
3
+ services:
4
+ app:
5
+ build:
6
+ target: with-mysql-client
7
+ depends_on:
8
+ - mysql57
9
+ entrypoint: docker-compose/wait-for-mysql.sh mysql57
10
+
11
+ mysql57:
12
+ image: mysql:5.7
13
+ environment:
14
+ MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
15
+ MYSQL_USER: mysqluser
16
+ MYSQL_PASSWORD: password
17
+ MYSQL_DATABASE: mydb
@@ -0,0 +1,19 @@
1
+ version: '3.7'
2
+
3
+ services:
4
+ app:
5
+ build:
6
+ target: with-mysql-client
7
+ depends_on:
8
+ - mysql80
9
+ entrypoint: docker-compose/wait-for-mysql.sh mysql80
10
+
11
+ mysql80:
12
+ image: mysql:8.0
13
+ # fix for: ERROR 1045 (28000): Plugin caching_sha2_password could not be loaded:
14
+ command: --default-authentication-plugin=mysql_native_password
15
+ environment:
16
+ MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
17
+ MYSQL_USER: mysqluser
18
+ MYSQL_PASSWORD: password
19
+ MYSQL_DATABASE: mydb
@@ -0,0 +1,19 @@
1
+ #!/bin/sh
2
+ # inspited from Control startup and shutdown order in Compose | Docker Documentation: https://docs.docker.com/compose/startup-order/
3
+
4
+ set -e
5
+
6
+ MYSQL_USER=${MYSQL_USER:-mysqluser}
7
+ MYSQL_PASSWORD=${MYSQL_PASSWORD:-password}
8
+
9
+ MYSQL_HOST="$1"
10
+ shift
11
+ cmd=$*
12
+
13
+ until mysql -h "$MYSQL_HOST" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" -e 'exit'; do
14
+ >&2 echo "mysql is unavailable - sleeping"
15
+ sleep 1
16
+ done
17
+
18
+ >&2 echo "mysql is up - executing command"
19
+ exec $cmd
@@ -1,6 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ lib = File.expand_path('../lib', __dir__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+
4
7
  require 'masking'
5
8
  require 'masking/cli'
6
9
 
@@ -28,6 +28,7 @@ module Masking
28
28
  parser.banner = 'Usage: masking [options]'
29
29
 
30
30
  define_config_option(parser)
31
+ define_version_option(parser)
31
32
  end
32
33
  end
33
34
 
@@ -38,5 +39,12 @@ module Masking
38
39
  end
39
40
  end
40
41
  end
42
+
43
+ def define_version_option(parser)
44
+ parser.on('-v', '--version', 'version') do
45
+ puts Masking::VERSION
46
+ exit(true)
47
+ end
48
+ end
41
49
  end
42
50
  end
@@ -4,3 +4,7 @@ Masking::Error::ConfigFileIsNotFile:
4
4
  "ERROR: config file (<%= config_file_path %>) is not file"
5
5
  Masking::Error::ConfigFileIsNotValidYaml:
6
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?"
@@ -44,6 +44,8 @@ module Masking
44
44
  @tables ||= data.each_with_object({}) do |kv, r|
45
45
  r[kv[0].to_sym] = Table.new(kv[0], columns: kv[1])
46
46
  end
47
+ rescue Masking::Config::TargetColumns::Column::ColumnNameIsNil
48
+ raise Masking::Error::ConfigFileContainsNullAsColumnName
47
49
  end
48
50
  end
49
51
  end
@@ -10,6 +10,8 @@ module Masking
10
10
  attr_accessor :index
11
11
 
12
12
  def initialize(name, table_name:, method_value:)
13
+ raise ColumnNameIsNil if name.nil?
14
+
13
15
  @name = name.to_sym
14
16
  @table_name = table_name.to_sym
15
17
  @method_value = method_value
@@ -27,6 +29,7 @@ module Masking
27
29
  private
28
30
 
29
31
  attr_reader :method
32
+ class ColumnNameIsNil < StandardError; end
30
33
  end
31
34
  end
32
35
  end
@@ -1,9 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Global Errors in Masking library
3
4
  module Masking
4
5
  class Error < StandardError
5
6
  class ConfigFileDoesNotExist < Error; end
6
7
  class ConfigFileIsNotFile < Error; end
7
8
  class ConfigFileIsNotValidYaml < Error; end
9
+ class ConfigFileContainsNullAsColumnName < Error; end
10
+ class InsertStatementParseError < Error; end
8
11
  end
9
12
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'masking/errors'
3
4
  require 'masking/insert_statement/sql_builder'
4
5
 
5
6
  module Masking
@@ -10,6 +11,8 @@ module Masking
10
11
  @raw_statement = raw_statement
11
12
 
12
13
  PARSE_REGEXP.match(raw_statement).tap do |match_data|
14
+ raise Error::InsertStatementParseError if match_data.nil?
15
+
13
16
  @table = match_data[:table]
14
17
  @columns_section = match_data[:columns_section]
15
18
  @values_section = match_data[:values_section]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Masking
4
- VERSION = '0.0.3'
4
+ VERSION = '1.0.0'
5
5
  end
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
 
26
26
  spec.required_ruby_version = '>= 2.5'
27
27
 
28
- spec.add_development_dependency 'bundler', '~> 1.16'
28
+ spec.add_development_dependency 'bundler', '~> 2.0'
29
29
  spec.add_development_dependency 'rake', '~> 10.0'
30
30
  spec.add_development_dependency 'rake-notes'
31
31
  spec.add_development_dependency 'ruby-prof'
@@ -7,7 +7,7 @@ users:
7
7
  integer: 12345
8
8
  float: 123.45
9
9
  boolean: true
10
- null: null
10
+ null_column: null
11
11
  date: 2018-08-24
12
12
  time: 2018-08-24 15:54:06
13
13
  binary_or_blob: !binary |
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: 0.0.3
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chikahiro Tokoro
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-07-07 00:00:00.000000000 Z
11
+ date: 2019-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.16'
19
+ version: '2.0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.16'
26
+ version: '2.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -187,24 +187,49 @@ executables:
187
187
  extensions: []
188
188
  extra_rdoc_files: []
189
189
  files:
190
+ - ".circleci/config.yml"
190
191
  - ".codeclimate.yml"
192
+ - ".dockerignore"
193
+ - ".github/workflows/acceptance_test_mariadb.yml"
194
+ - ".github/workflows/acceptance_test_mysql.yml"
195
+ - ".github/workflows/check_changelog.yml"
191
196
  - ".gitignore"
192
197
  - ".mdlrc"
193
198
  - ".rubocop.yml"
194
199
  - ".ruby-version"
195
- - ".travis.yml"
196
200
  - CHANGELOG.md
197
201
  - CODE_OF_CONDUCT.md
202
+ - Dockerfile
198
203
  - Gemfile
199
204
  - Gemfile.lock
200
205
  - LICENSE.txt
201
206
  - README.md
202
207
  - Rakefile
208
+ - acceptance/expected_query_result.txt
209
+ - acceptance/import_dumpfile.sql
210
+ - acceptance/masking.yml
211
+ - acceptance/run_test.sh
212
+ - acceptance/tmp/.keep
203
213
  - bin/benchmark.rb
204
214
  - bin/console
205
215
  - bin/masking_profile
206
216
  - bin/setup
207
217
  - config/.keep
218
+ - coverage/.keep
219
+ - docker-compose-ci.yml
220
+ - docker-compose.yml
221
+ - docker-compose/acceptance_test.sh
222
+ - docker-compose/mariadb100.yml
223
+ - docker-compose/mariadb101.yml
224
+ - docker-compose/mariadb102.yml
225
+ - docker-compose/mariadb103.yml
226
+ - docker-compose/mariadb104.yml
227
+ - docker-compose/mariadb55.yml
228
+ - docker-compose/mysql55.yml
229
+ - docker-compose/mysql56.yml
230
+ - docker-compose/mysql57.yml
231
+ - docker-compose/mysql80.yml
232
+ - docker-compose/wait-for-mysql.sh
208
233
  - exe/masking
209
234
  - lib/masking.rb
210
235
  - lib/masking/cli.rb
@@ -253,7 +278,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
253
278
  - !ruby/object:Gem::Version
254
279
  version: '0'
255
280
  requirements: []
256
- rubygems_version: 3.0.1
281
+ rubygems_version: 3.0.3
257
282
  signing_key:
258
283
  specification_version: 4
259
284
  summary: Command line tool for anonymizing databese records
@@ -1,9 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.5.3
5
- - 2.6.0
6
- before_install: gem install bundler -v 1.17.3
7
-
8
- script:
9
- - bundle exec rspec