crypt_keeper 0.22.0 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.travis.yml +5 -1
  4. data/Appraisals +6 -6
  5. data/README.md +8 -20
  6. data/Rakefile +7 -3
  7. data/crypt_keeper.gemspec +5 -5
  8. data/gemfiles/{activerecord_4_1.gemfile → activerecord_5_0.gemfile} +2 -2
  9. data/lib/crypt_keeper.rb +1 -2
  10. data/lib/crypt_keeper/helper.rb +0 -18
  11. data/lib/crypt_keeper/log_subscriber/mysql_aes.rb +7 -9
  12. data/lib/crypt_keeper/log_subscriber/postgres_pgp.rb +7 -9
  13. data/lib/crypt_keeper/model.rb +14 -20
  14. data/lib/crypt_keeper/provider/aes_new.rb +1 -1
  15. data/lib/crypt_keeper/provider/base.rb +21 -0
  16. data/lib/crypt_keeper/provider/mysql_aes_new.rb +1 -1
  17. data/lib/crypt_keeper/provider/postgres_pgp.rb +2 -2
  18. data/lib/crypt_keeper/provider/postgres_pgp_public_key.rb +1 -1
  19. data/lib/crypt_keeper/version.rb +1 -1
  20. data/spec/crypt_keeper/log_subscriber/mysql_aes_spec.rb +56 -0
  21. data/spec/crypt_keeper/log_subscriber/postgres_pgp_spec.rb +94 -0
  22. data/spec/crypt_keeper/model_spec.rb +172 -0
  23. data/spec/crypt_keeper/provider/aes_new_spec.rb +41 -0
  24. data/spec/crypt_keeper/provider/mysql_aes_new_spec.rb +50 -0
  25. data/spec/crypt_keeper/provider/postgres_pgp_public_key_spec.rb +66 -0
  26. data/spec/crypt_keeper/provider/postgres_pgp_spec.rb +66 -0
  27. data/spec/spec_helper.rb +0 -1
  28. data/spec/support/encryptors.rb +9 -3
  29. data/spec/support/logging.rb +92 -0
  30. metadata +37 -44
  31. data/gemfiles/activerecord_4_1.gemfile.lock +0 -120
  32. data/gemfiles/activerecord_4_2.gemfile.lock +0 -120
  33. data/lib/crypt_keeper/provider/aes.rb +0 -66
  34. data/lib/crypt_keeper/provider/mysql_aes.rb +0 -47
  35. data/spec/log_subscriber/mysql_aes_spec.rb +0 -73
  36. data/spec/log_subscriber/postgres_pgp_spec.rb +0 -123
  37. data/spec/model_spec.rb +0 -169
  38. data/spec/provider/aes_new_spec.rb +0 -45
  39. data/spec/provider/aes_spec.rb +0 -67
  40. data/spec/provider/mysql_aes_new_spec.rb +0 -54
  41. data/spec/provider/mysql_aes_spec.rb +0 -35
  42. data/spec/provider/postgres_pgp_public_key_spec.rb +0 -70
  43. data/spec/provider/postgres_pgp_spec.rb +0 -70
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3297d5e1a03266d6b1d74f5e9fee1fbba49dd295
4
- data.tar.gz: f7621fbc63a9e94341105919bc839d8917d3f37b
3
+ metadata.gz: e2c1586ce0dee73fb7513ac7c243426996af7947
4
+ data.tar.gz: 8bc44c1580209d54e3614c8ecfcf9c30108f97f7
5
5
  SHA512:
6
- metadata.gz: 2de5ef53aaa8f9d2e255f3c9b68c2996dae3eb2f49919ecceeb335fefbaaaa4ca98b1b0aa0ffb71aaf672ad2f7e0b6ed4edcbc721201f411cf6e8ba368984ab2
7
- data.tar.gz: 82a701bd3b4c2a56394fdb205ecc0e24bb856028d0ccdbc61867ae0184b76967de02de7ddd07927fd00e16a6ad0d670f2d5442fc37ad408152ccc5eac900b574
6
+ metadata.gz: 24ab4328521f6915fc2a516de9f84e1d25409e626c4299330093b112710a100a4c1978df64992e44a50b951f7f9f8eb7b30df6343c197449603f6f8e9df0507d
7
+ data.tar.gz: 298e14e3bc7c4136bb6638c0f64c1a7a02d4163a443cafa6d7fffd778fa24f29659c98933f6b5e798e6881175f5ef592946194967af3c36c9796d3f6dcf3c778
data/.gitignore CHANGED
@@ -3,7 +3,7 @@
3
3
  .bundle
4
4
  .config
5
5
  .yardoc
6
- Gemfile.lock
6
+ *emfile.lock
7
7
  InstalledFiles
8
8
  _yardoc
9
9
  coverage
@@ -6,9 +6,13 @@ rvm:
6
6
  - 2.3.1
7
7
 
8
8
  gemfile:
9
- - gemfiles/activerecord_4_1.gemfile
10
9
  - gemfiles/activerecord_4_2.gemfile
10
+ - gemfiles/activerecord_5_0.gemfile
11
11
 
12
+ matrix:
13
+ exclude:
14
+ - gemfile: gemfiles/activerecord_5_0.gemfile
15
+ rvm: 2.1.10
12
16
 
13
17
  addons:
14
18
  postgresql: 9.3
data/Appraisals CHANGED
@@ -1,9 +1,9 @@
1
- appraise "activerecord_4_1" do
2
- gem 'activerecord', '~> 4.1.0'
3
- gem 'activesupport', '~> 4.1.0'
1
+ appraise "activerecord_4_2" do
2
+ gem "activerecord", "~> 4.2.0"
3
+ gem "activesupport", "~> 4.2.0"
4
4
  end
5
5
 
6
- appraise "activerecord_4_2" do
7
- gem 'activerecord', '~> 4.2.0'
8
- gem 'activesupport', '~> 4.2.0'
6
+ appraise "activerecord_5_0" do
7
+ gem "activerecord", "~> 5.0.0"
8
+ gem "activesupport", "~> 5.0.0"
9
9
  end
data/README.md CHANGED
@@ -15,7 +15,7 @@ is a simple class that does 3 things.
15
15
  Note: Any options defined using `crypt_keeper` will be passed to `new` as a
16
16
  hash.
17
17
 
18
- You can see an AES example [here](https://github.com/jmazzi/crypt_keeper/blob/master/lib/crypt_keeper/provider/aes.rb).
18
+ You can see an AES example [here](https://github.com/jmazzi/crypt_keeper/blob/master/lib/crypt_keeper/provider/aes_new.rb).
19
19
 
20
20
  ## Why?
21
21
 
@@ -108,19 +108,6 @@ There are four supported encryptors: `aes_new`, `mysql_aes_new`, `postgres_pgp`,
108
108
  * Accepts a public and private_key. The private key is optional. If the private key is not present the ciphertext value is returned instead of the plaintext. This allows you to keep the private key off certain servers. Encryption is possible with only a public key. Any server that needs access to the plaintext will need the private key.
109
109
  * Passphrases are hashed by PostgresSQL itself using a [String2Key (S2K)](http://www.postgresql.org/docs/9.2/static/pgcrypto.html) algorithm. This is rather similar to crypt() algorithms — purposefully slow and with random salt — but it produces a full-length binary key.
110
110
 
111
- ## Deprecated Encryptors
112
- These encryptors are now deprecated and should be migrated from as soon as possible using the included `bin/crypt_keeper` script.
113
-
114
- * [AES Legacy](https://github.com/jmazzi/crypt_keeper/blob/master/lib/crypt_keeper/provider/aes.rb) *DEPRECATED*
115
- * Encryption is peformed using AES-256 via OpenSSL.
116
- * [How to migrate to AES New](https://github.com/jmazzi/crypt_keeper/wiki/AES-Legacy-Migration-Instructions)
117
-
118
- * [MySQL AES Legacy](https://github.com/jmazzi/crypt_keeper/blob/master/lib/crypt_keeper/provider/mysql_aes.rb) *DEPRECATED*
119
- * Encryption is peformed MySQL's native AES functions.
120
- * ActiveRecord logs are [automatically](https://github.com/jmazzi/crypt_keeper/blob/master/lib/crypt_keeper/log_subscriber/mysql_aes.rb)
121
- filtered for you to protect senitive data from being logged.
122
- * [How to migrate to MySQL AES New](https://github.com/jmazzi/crypt_keeper/wiki/MysqlAes-Legacy-Migration-Instructions)
123
-
124
111
  ## Searching
125
112
  Searching ciphertext is a complex problem that varies depending on the encryption algorithm you choose. All of the bundled providers include search support, but they have some caveats.
126
113
 
@@ -144,12 +131,13 @@ Model.where(something: 'blah').search_by_plaintext(:field, 'searchstring')
144
131
  ## Creating your own encryptor
145
132
 
146
133
  Creating your own encryptor is easy. All you have to do is create a class
147
- under the `CryptKeeper::Provider` namespace, like this:
134
+ under the `CryptKeeper::Provider` namespace, and inherit from the `Base` encryptor,
135
+ like this:
148
136
 
149
137
  ```ruby
150
138
  module CryptKeeper
151
139
  module Provider
152
- class MyEncryptor
140
+ class MyEncryptor < Base
153
141
  def initialize(options = {})
154
142
  end
155
143
 
@@ -175,11 +163,11 @@ end
175
163
 
176
164
  ## Requirements
177
165
 
178
- CryptKeeper has been tested against ActiveRecord 3.1, 3.2, 4.0, 4.1, 4.2 using ruby
179
- 1.9.3, 2.0.0 and 2.1.1
166
+ CryptKeeper has been tested against ActiveRecord 4.2 and 5.0 using Ruby
167
+ 2.1.10, 2.2.5 and 2.3.1.
180
168
 
181
- ActiveRecord 4.0 is supported starting with v0.11.0.
182
- ActiveRecord 4.1 is supported starting with v0.16.0.
169
+ ActiveRecord 4.2 is supported starting with v0.19.0.
170
+ ActiveRecord 5.0 is supported starting with v0.23.0.
183
171
 
184
172
  ## Installation
185
173
 
data/Rakefile CHANGED
@@ -1,9 +1,13 @@
1
1
  #!/usr/bin/env rake
2
2
  require "bundler/gem_tasks"
3
- require 'rspec/core/rake_task'
4
- require 'appraisal'
3
+ require "rspec/core/rake_task"
4
+ require "appraisal"
5
5
 
6
6
  RSpec::Core::RakeTask.new :spec
7
7
  Bundler::GemHelper.install_tasks
8
8
 
9
- task :default => [:spec]
9
+ if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"]
10
+ task default: :appraisal
11
+ else
12
+ task default: :spec
13
+ end
@@ -16,18 +16,18 @@ Gem::Specification.new do |gem|
16
16
  gem.require_paths = ["lib"]
17
17
  gem.version = CryptKeeper::VERSION
18
18
 
19
- gem.add_runtime_dependency 'activerecord', '>= 3.1', '< 4.3'
20
- gem.add_runtime_dependency 'activesupport', '>= 3.1', '< 4.3'
19
+ gem.add_runtime_dependency 'activerecord', '>= 4.2', '< 5.1'
20
+ gem.add_runtime_dependency 'activesupport', '>= 4.2', '< 5.1'
21
21
  gem.add_runtime_dependency 'aes', '~> 0.5.0'
22
22
  gem.add_runtime_dependency 'armor', '~> 0.0.2'
23
23
 
24
- gem.add_development_dependency 'rspec', '~> 2.14.0'
24
+ gem.add_development_dependency 'rspec', '~> 3.5.0'
25
25
  gem.add_development_dependency 'guard', '~> 2.6.1'
26
26
  gem.add_development_dependency 'guard-rspec', '~> 4.2.9'
27
27
  gem.add_development_dependency 'rake', '~> 10.3.1'
28
28
  gem.add_development_dependency 'rb-fsevent', '~> 0.9.1'
29
29
  gem.add_development_dependency 'coveralls'
30
- gem.add_development_dependency 'appraisal', '~> 1.0.0'
30
+ gem.add_development_dependency 'appraisal', '~> 2.1.0'
31
31
 
32
32
  if RUBY_PLATFORM == 'java'
33
33
  gem.add_development_dependency 'jruby-openssl', '~> 0.7.7'
@@ -36,7 +36,7 @@ Gem::Specification.new do |gem|
36
36
  gem.add_development_dependency 'activerecord-jdbcmysql-adapter'
37
37
  else
38
38
  gem.add_development_dependency 'sqlite3'
39
- gem.add_development_dependency 'pg', '~> 0.17.1'
39
+ gem.add_development_dependency 'pg', '~> 0.18.0'
40
40
  gem.add_development_dependency 'mysql2', '~> 0.3.11'
41
41
  end
42
42
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", "~> 4.1.0"
6
- gem "activesupport", "~> 4.1.0"
5
+ gem "activerecord", "~> 5.0.0"
6
+ gem "activesupport", "~> 5.0.0"
7
7
 
8
8
  gemspec :path => "../"
@@ -3,9 +3,8 @@ require 'active_record'
3
3
  require 'crypt_keeper/version'
4
4
  require 'crypt_keeper/model'
5
5
  require 'crypt_keeper/helper'
6
- require 'crypt_keeper/provider/aes'
6
+ require 'crypt_keeper/provider/base'
7
7
  require 'crypt_keeper/provider/aes_new'
8
- require 'crypt_keeper/provider/mysql_aes'
9
8
  require 'crypt_keeper/provider/mysql_aes_new'
10
9
  require 'crypt_keeper/provider/postgres_pgp'
11
10
  require 'crypt_keeper/provider/postgres_pgp_public_key'
@@ -17,23 +17,5 @@ module CryptKeeper
17
17
  ::Armor.digest(key, salt)
18
18
  end
19
19
  end
20
-
21
- module Serializer
22
- def dump(value)
23
- if value.blank? || CryptKeeper.stub_encryption?
24
- value
25
- else
26
- encrypt(value.to_s)
27
- end
28
- end
29
-
30
- def load(value)
31
- if value.blank? || CryptKeeper.stub_encryption?
32
- value
33
- else
34
- decrypt(value)
35
- end
36
- end
37
- end
38
20
  end
39
21
  end
@@ -4,14 +4,12 @@ require 'active_support/lazy_load_hooks'
4
4
  module CryptKeeper
5
5
  module LogSubscriber
6
6
  module MysqlAes
7
- extend ActiveSupport::Concern
8
-
9
- included do
10
- alias_method_chain :sql, :mysql_aes
11
- end
12
-
13
7
  # Public: Prevents sensitive data from being logged
14
- def sql_with_mysql_aes(event)
8
+ #
9
+ # event - An ActiveSupport::Notifications::Event
10
+ #
11
+ # Returns a boolean.
12
+ def sql(event)
15
13
  filter = /(aes_(encrypt|decrypt))\(.*\)/i
16
14
  payload = event.payload[:sql]
17
15
  .encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
@@ -22,12 +20,12 @@ module CryptKeeper
22
20
  "#{$1}([FILTERED])"
23
21
  end
24
22
 
25
- sql_without_mysql_aes(event)
23
+ super(event)
26
24
  end
27
25
  end
28
26
  end
29
27
  end
30
28
 
31
29
  ActiveSupport.on_load :crypt_keeper_mysql_aes_log do
32
- ActiveRecord::LogSubscriber.send :include, CryptKeeper::LogSubscriber::MysqlAes
30
+ ActiveRecord::LogSubscriber.prepend CryptKeeper::LogSubscriber::MysqlAes
33
31
  end
@@ -4,14 +4,12 @@ require 'active_support/lazy_load_hooks'
4
4
  module CryptKeeper
5
5
  module LogSubscriber
6
6
  module PostgresPgp
7
- extend ActiveSupport::Concern
8
-
9
- included do
10
- alias_method_chain :sql, :postgres_pgp
11
- end
12
-
13
7
  # Public: Prevents sensitive data from being logged
14
- def sql_with_postgres_pgp(event)
8
+ #
9
+ # event - An ActiveSupport::Notifications::Event
10
+ #
11
+ # Returns a boolean.
12
+ def sql(event)
15
13
  filter = /(\(*)pgp_(sym|pub)_(?<operation>decrypt|encrypt)(\(+.*\)+)/im
16
14
  payload = event.payload[:sql]
17
15
  .encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
@@ -22,12 +20,12 @@ module CryptKeeper
22
20
  "#{$~[:operation]}([FILTERED])"
23
21
  end
24
22
 
25
- sql_without_postgres_pgp(event)
23
+ super(event)
26
24
  end
27
25
  end
28
26
  end
29
27
  end
30
28
 
31
29
  ActiveSupport.on_load :crypt_keeper_postgres_pgp_log do
32
- ActiveRecord::LogSubscriber.send :include, CryptKeeper::LogSubscriber::PostgresPgp
30
+ ActiveRecord::LogSubscriber.prepend CryptKeeper::LogSubscriber::PostgresPgp
33
31
  end
@@ -68,24 +68,20 @@ module CryptKeeper
68
68
  end
69
69
 
70
70
  crypt_keeper_fields.each do |field|
71
- serialize field, encryptor_klass.new(crypt_keeper_options).
72
- extend(::CryptKeeper::Helper::Serializer)
71
+ serialize field, encryptor
73
72
  end
74
73
  end
75
74
 
76
75
  def search_by_plaintext(field, criteria)
77
76
  if crypt_keeper_fields.include?(field.to_sym)
78
- encryptor = encryptor_klass.new(crypt_keeper_options)
79
- encryptor.search(scoping_strategy, field.to_s, criteria)
77
+ encryptor.search(all, field.to_s, criteria)
80
78
  else
81
- raise "#{field} is not a crypt_keeper field"
79
+ raise ArgumentError, "#{field} is not a crypt_keeper field"
82
80
  end
83
81
  end
84
82
 
85
83
  # Public: Encrypt a table for the first time.
86
84
  def encrypt_table!
87
- enc = encryptor_klass.new(crypt_keeper_options)
88
-
89
85
  tmp_table = Class.new(ActiveRecord::Base).tap do |c|
90
86
  c.table_name = self.table_name
91
87
  c.inheritance_column = :type_disabled
@@ -94,7 +90,7 @@ module CryptKeeper
94
90
  transaction do
95
91
  tmp_table.find_each do |r|
96
92
  crypt_keeper_fields.each do |field|
97
- r.send("#{field}=", enc.encrypt(r[field])) if r[field].present?
93
+ r.send("#{field}=", encryptor.encrypt(r[field])) if r[field].present?
98
94
  end
99
95
 
100
96
  r.save!
@@ -104,13 +100,12 @@ module CryptKeeper
104
100
 
105
101
  # Public: Decrypt a table (reverse of encrypt_table!)
106
102
  def decrypt_table!
107
- enc = encryptor_klass.new(crypt_keeper_options)
108
103
  tmp_table = Class.new(ActiveRecord::Base).tap { |c| c.table_name = self.table_name }
109
104
 
110
105
  transaction do
111
106
  tmp_table.find_each do |r|
112
107
  crypt_keeper_fields.each do |field|
113
- r.send("#{field}=", enc.decrypt(r[field])) if r[field].present?
108
+ r.send("#{field}=", encryptor.decrypt(r[field])) if r[field].present?
114
109
  end
115
110
 
116
111
  r.save!
@@ -125,18 +120,17 @@ module CryptKeeper
125
120
  @encryptor_klass ||= "CryptKeeper::Provider::#{crypt_keeper_encryptor.to_s.camelize}".constantize
126
121
  end
127
122
 
128
- # Private: Ensure that the encryptor responds to new
129
- def ensure_valid_encryptor!
130
- unless defined?(encryptor_klass) && encryptor_klass.respond_to?(:new)
131
- raise "You must specify a valid encryptor `crypt_keeper :encryptor => :aes`"
132
- end
123
+ # Private: The encryptor instance.
124
+ def encryptor
125
+ @encryptor ||= encryptor_klass.new(crypt_keeper_options)
133
126
  end
134
127
 
135
- def scoping_strategy
136
- if ::ActiveRecord.respond_to?(:version) && ::ActiveRecord.version.segments[0] == 4
137
- all
138
- else
139
- scoped
128
+ # Private: Ensure we have a valid encryptor.
129
+ def ensure_valid_encryptor!
130
+ unless defined?(encryptor_klass) && encryptor_klass.respond_to?(:new) &&
131
+ %i(load dump).all? { |m| encryptor.respond_to?(m) }
132
+ raise ArgumentError, "You must specify a valid encryptor that implements " \
133
+ "the `load` and `dump` methods (you can inherit from CryptKeeper::Provider::Base). Example: `crypt_keeper :encryptor => :aes`"
140
134
  end
141
135
  end
142
136
  end
@@ -3,7 +3,7 @@ require 'armor'
3
3
 
4
4
  module CryptKeeper
5
5
  module Provider
6
- class AesNew
6
+ class AesNew < Base
7
7
  include CryptKeeper::Helper::DigestPassphrase
8
8
 
9
9
  # Public: The encryption key
@@ -0,0 +1,21 @@
1
+ module CryptKeeper
2
+ module Provider
3
+ class Base
4
+ def dump(value)
5
+ if value.blank? || CryptKeeper.stub_encryption?
6
+ value
7
+ else
8
+ encrypt(value.to_s)
9
+ end
10
+ end
11
+
12
+ def load(value)
13
+ if value.blank? || CryptKeeper.stub_encryption?
14
+ value
15
+ else
16
+ decrypt(value)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -2,7 +2,7 @@ require 'crypt_keeper/log_subscriber/mysql_aes'
2
2
 
3
3
  module CryptKeeper
4
4
  module Provider
5
- class MysqlAesNew
5
+ class MysqlAesNew < Base
6
6
  include CryptKeeper::Helper::SQL
7
7
  include CryptKeeper::Helper::DigestPassphrase
8
8
 
@@ -2,7 +2,7 @@ require 'crypt_keeper/log_subscriber/postgres_pgp'
2
2
 
3
3
  module CryptKeeper
4
4
  module Provider
5
- class PostgresPgp
5
+ class PostgresPgp < Base
6
6
  include CryptKeeper::Helper::SQL
7
7
 
8
8
  attr_accessor :key
@@ -36,7 +36,7 @@ module CryptKeeper
36
36
  end
37
37
 
38
38
  def search(records, field, criteria)
39
- records.where("(pgp_sym_decrypt(cast(#{field} AS bytea), ?) = ?)", key, criteria)
39
+ records.where("(pgp_sym_decrypt(cast(\"#{field}\" AS bytea), ?) = ?)", key, criteria)
40
40
  end
41
41
  end
42
42
  end
@@ -2,7 +2,7 @@ require 'crypt_keeper/log_subscriber/postgres_pgp'
2
2
 
3
3
  module CryptKeeper
4
4
  module Provider
5
- class PostgresPgpPublicKey
5
+ class PostgresPgpPublicKey < Base
6
6
  include CryptKeeper::Helper::SQL
7
7
 
8
8
  attr_accessor :key
@@ -1,3 +1,3 @@
1
1
  module CryptKeeper
2
- VERSION = "0.22.0"
2
+ VERSION = "1.0.0.beta1"
3
3
  end
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe CryptKeeper::LogSubscriber::MysqlAes do
4
+ before do
5
+ CryptKeeper.silence_logs = false
6
+ end
7
+
8
+ use_mysql
9
+
10
+ context "AES encryption" do
11
+ # Fire the ActiveSupport.on_load
12
+ before do
13
+ CryptKeeper::Provider::MysqlAesNew.new key: 'secret', salt: 'salt'
14
+ end
15
+
16
+ let(:input_query) do
17
+ "SELECT aes_encrypt('encrypt_value', 'encrypt_key'), aes_decrypt('decrypt_value', 'decrypt_key') FROM DUAL;"
18
+ end
19
+
20
+ let(:output_query) do
21
+ "SELECT aes_encrypt([FILTERED]) FROM DUAL;"
22
+ end
23
+
24
+ let(:input_search_query) do
25
+ "SELECT \"sensitive_data\".* FROM \"sensitive_data\" WHERE ((aes_decrypt('f'), 'tool') = 'blah')) AND secret = 'testing'"
26
+ end
27
+
28
+ let(:output_search_query) do
29
+ "SELECT \"sensitive_data\".* FROM \"sensitive_data\" WHERE ((aes_decrypt([FILTERED]) AND secret = 'testing'"
30
+ end
31
+
32
+ it "filters aes functions" do
33
+ should_log_scrubbed_query(input: input_query, output: output_query)
34
+ end
35
+
36
+ it "filters aes functions in lowercase" do
37
+ should_log_scrubbed_query(input: input_query.downcase, output: output_query.downcase.gsub(/filtered/, 'FILTERED'))
38
+ end
39
+
40
+ it "filters aes functions when searching" do
41
+ should_log_scrubbed_query(input: input_search_query, output: output_search_query)
42
+ end
43
+
44
+ it "forces string encodings" do
45
+ input_query = "SELECT aes_encrypt('hi \255', 'test') FROM DUAL;"
46
+
47
+ should_log_scrubbed_query(input: input_query, output: output_query)
48
+ end
49
+
50
+ it "skips logging if CryptKeeper.silence_logs is set" do
51
+ CryptKeeper.silence_logs = true
52
+
53
+ should_not_log_query(input_query)
54
+ end
55
+ end
56
+ end