masking 0.0.3 → 1.0.0

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