active_storage_encryption 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +12 -0
- data/.github/workflows/ci.yml +75 -0
- data/.gitignore +14 -0
- data/.ruby-version +1 -0
- data/.standard.yml +1 -0
- data/Appraisals +2 -0
- data/Gemfile +9 -0
- data/README.md +2 -0
- data/active_storage_encryption.gemspec +47 -0
- data/gemfiles/rails_7.gemfile +1 -0
- data/gemfiles/rails_7.gemfile.lock +78 -1
- data/gemfiles/rails_8.gemfile +1 -0
- data/gemfiles/rails_8.gemfile.lock +78 -1
- data/lib/active_storage/service/encrypted_gcs_service.rb +10 -0
- data/lib/active_storage_encryption/encrypted_blob_proxy_controller.rb +1 -1
- data/lib/active_storage_encryption/encrypted_gcs_service.rb +158 -0
- data/lib/active_storage_encryption/engine.rb +4 -0
- data/lib/active_storage_encryption/overrides.rb +33 -5
- data/lib/active_storage_encryption/private_url_policy.rb +1 -1
- data/lib/active_storage_encryption/version.rb +1 -1
- data/lib/active_storage_encryption.rb +1 -0
- data/lib/generators/add_encryption_key_to_active_storage_blobs.rb.erb +9 -0
- data/lib/generators/install_generator.rb +25 -0
- data/test/dummy/app/assets/images/.keep +0 -0
- data/test/dummy/app/controllers/concerns/.keep +0 -0
- data/test/dummy/app/models/concerns/.keep +0 -0
- data/test/dummy/app/models/user.rb +5 -0
- data/test/dummy/config/environments/test.rb +2 -0
- data/test/dummy/config/storage.yml +3 -0
- data/test/dummy/db/migrate/20250428093315_create_users.rb +7 -0
- data/test/dummy/db/schema.rb +6 -3
- data/test/dummy/lib/assets/.keep +0 -0
- data/test/dummy/log/.keep +0 -0
- data/test/integration/.keep +0 -0
- data/test/lib/encrypted_gcs_service_test.rb +201 -0
- data/test/lib/encrypted_s3_service_test.rb +4 -1
- data/test/lib/overrides_test.rb +349 -0
- metadata +52 -127
- data/test/dummy/log/development.log +0 -304
- data/test/dummy/log/test.log +0 -66969
- data/test/dummy/storage/0a/mt/0amtaps713liftrtbxt9h998epz4 +0 -0
- data/test/dummy/storage/0b/93/0b93pygovuunam1a3ovzwmrbuw2x +0 -0
- data/test/dummy/storage/0m/3s/0m3s7r3nboblijr1jxlnvm3p3l4b +0 -0
- data/test/dummy/storage/0o/9s/0o9s4ctbpu757qh7ucyony0itek4 +0 -0
- data/test/dummy/storage/1e/q6/1eq646og0wazgfw7bwjqz2uem0g4 +0 -0
- data/test/dummy/storage/1n/o3/1no30cpwrm727bm6arvb7zxagdg1 +0 -0
- data/test/dummy/storage/1x/6w/1x6wsoq3pew17reztwax78lrr3hc +0 -0
- data/test/dummy/storage/28/de/28deswrv89c9f2tk7dz1l5uovd4r +0 -0
- data/test/dummy/storage/2h/sd/2hsd1mh20c6os2nzyoicfyymhwev +0 -0
- data/test/dummy/storage/2t/ni/2tnidhdk4c6cj0tnw3jiw88dgs4g +0 -0
- data/test/dummy/storage/2v/e0/2ve0555nluisy2el5cf4txzgae3j +0 -0
- data/test/dummy/storage/2z/c5/2zc5mj8g0o9l7mfnim0vs4v48xd6 +0 -0
- data/test/dummy/storage/34/xc/34xc9hk74dm9227d6mhgfcfxl4ue +0 -0
- data/test/dummy/storage/3z/0t/3z0tnve7ivrq0qyrvfhfzztjhjqs +0 -0
- data/test/dummy/storage/49/14/4914188q1dptpw4po91cp54f32bg +0 -0
- data/test/dummy/storage/4c/74/4c7412lfz0pm2ocg6u01h67bnsch +0 -0
- data/test/dummy/storage/52/qf/52qfbgjlf3gor3agsyrt09t19o55 +0 -0
- data/test/dummy/storage/57/go/57gok1uc4ebc3ugrjrje4lpe1ram +0 -0
- data/test/dummy/storage/5f/dv/5fdvt6tu1mkyajbz4hbxbw6fpt9w +0 -0
- data/test/dummy/storage/5x/b7/5xb7zzi66fi5f6yrn09pq4ogb9wo +0 -0
- data/test/dummy/storage/6m/vr/6mvr1fr5it125tm4vahjw6bv9wkz +0 -0
- data/test/dummy/storage/7b/hb/7bhbdxqn67lape1f49jqfktcei4n +0 -0
- data/test/dummy/storage/7n/4v/7n4vpm1q14y4qffc4jj78m036gtw +0 -0
- data/test/dummy/storage/7q/ku/7qkufbjwbbqwnf89uciosleixnew +0 -0
- data/test/dummy/storage/8l/5v/8l5vb4o02hx46s5qohfn5to945p3 +0 -0
- data/test/dummy/storage/8q/pu/8qpun3f8vzl7auxajvqyq8f48ngw +0 -0
- data/test/dummy/storage/8w/ag/8wag4ptmox207h7mobamk0tcebwx +0 -0
- data/test/dummy/storage/8w/v8/8wv8lrhsw4s2r6guh1csd3jd89ii +0 -0
- data/test/dummy/storage/9b/c6/9bc6wlpfnqdywpnxgeoin3w9b5ch +0 -0
- data/test/dummy/storage/9l/wk/9lwkt21k5iburdaitbwliw7krtwt +0 -0
- data/test/dummy/storage/9p/0v/9p0vgfw3l2854k7so3rp33rmyh7p +0 -0
- data/test/dummy/storage/9r/sy/9rsya3r6syft34qz24g1h4u4qq44 +0 -0
- data/test/dummy/storage/9s/es/9seslusr46xjf3mfzq10hkp13kc1 +0 -0
- data/test/dummy/storage/9t/nv/9tnvn5v52fkvurpgszf4gco78t5h +0 -0
- data/test/dummy/storage/9u/to/9utokgxyu6xyovandu7pjhogoaqp +0 -0
- data/test/dummy/storage/9w/a4/9wa4c20p4dvm1cd5thnv9f7ei13w +0 -0
- data/test/dummy/storage/at/kg/atkgs5gwz2xdv9lvqftsg6p7gcpu +0 -0
- data/test/dummy/storage/at/qo/atqomgf3rpb2f6e1tq1yn2xqzojv +0 -0
- data/test/dummy/storage/ba/lq/balqtije6kf82ht4lr70ajaae9kc +0 -0
- data/test/dummy/storage/bf/i1/bfi1ij9rygr6lkx1r0lhgi8o5smx +0 -0
- data/test/dummy/storage/bg/ye/bgyenotrv3aj6lk88edwv0c41pfj +0 -0
- data/test/dummy/storage/bu/xe/buxed4b1l78kcax53fa37awm9ywk +0 -0
- data/test/dummy/storage/d2/c1/d2c11nhikb474oq3q7so0xbhukvj +0 -0
- data/test/dummy/storage/development.sqlite3 +0 -0
- data/test/dummy/storage/dk/hy/dkhybxn2o27a8xgvfhsxpgqxa1zf +0 -0
- data/test/dummy/storage/e7/2n/e72nz5cz3wf6qvh4dw4qfnw6ucog +0 -0
- data/test/dummy/storage/eo/4q/eo4qn68m7al0ehhe0s23ycuzkjto +0 -0
- data/test/dummy/storage/ew/8s/ew8sejdsx8ddmrzkvfa37ebz1ts1 +0 -0
- data/test/dummy/storage/f8/q1/f8q1kpg2tou8ru0afj8d2gy6ym5p +0 -0
- data/test/dummy/storage/fr/55/fr558uhp1k93jzhb4butyi2ry51t +0 -0
- data/test/dummy/storage/g4/nh/g4nhx1zxbeiegqpgn8ppsl1yhm0t +0 -0
- data/test/dummy/storage/gg/r5/ggr51egxhqfh4w5eluzs47qceb76 +0 -0
- data/test/dummy/storage/gh/ua/ghuaagralqmjy8rkbwmuv3010lvs +0 -0
- data/test/dummy/storage/gx/uh/gxuhmf52ufli3m7ng8irp8ghxa1v +0 -0
- data/test/dummy/storage/h0/m1/h0m1emy251xus1d9qh6u25dzy18o +0 -0
- data/test/dummy/storage/hh/kc/hhkc2q8paptyvhw2m5hlwylhtfo5 +0 -0
- data/test/dummy/storage/hq/0q/hq0q04kr6qzrp0qaee8rehcp2tzx +0 -0
- data/test/dummy/storage/ii/g1/iig1ge3fsjitai4g2fkq4qt369wh +0 -0
- data/test/dummy/storage/io/f0/iof0mv7w8qjd6m826g52pzyxedet +0 -0
- data/test/dummy/storage/jk/2i/jk2ifmx6ac35ubk3esufnm6bn1m1 +0 -0
- data/test/dummy/storage/jw/4t/jw4trdeyfkw3j8z70xcnr9a7gqe5 +0 -0
- data/test/dummy/storage/ke/k2/kek24leksglm1rs2a78mfmot0p3s +0 -0
- data/test/dummy/storage/kh/6d/kh6doaxxwxiyes0yqz2dmmpajkzv +0 -0
- data/test/dummy/storage/kj/7n/kj7nookjhisagd80z8hlv3wn50am +0 -0
- data/test/dummy/storage/kq/lf/kqlf5udtrgrk4v55qodxyt6i68p8 +0 -0
- data/test/dummy/storage/ky/33/ky334jbo8eb08pj9qbe919iz91mh +0 -0
- data/test/dummy/storage/lt/zw/ltzw4lur2bheit1273ogpfzhv7j1 +0 -0
- data/test/dummy/storage/m2/ve/m2vejmyttn1ium81dopppom6vum6 +0 -0
- data/test/dummy/storage/m8/d4/m8d4r9iauedq8wlpvnx1f3ou0jwg +0 -0
- data/test/dummy/storage/m9/ee/m9eetioklzatyff94gq0vn1cga1n +0 -0
- data/test/dummy/storage/ma/v0/mav084zvmyoh1a8i7dcwqy2aaoi9 +0 -0
- data/test/dummy/storage/mg/pa/mgpauiu02i28j3poef65k3q0gfpw +0 -0
- data/test/dummy/storage/mm/8g/mm8gp5evncb1ol1lj2jlmra2ixij +0 -0
- data/test/dummy/storage/mm/d2/mmd21x8c1amgnidzw0wowiwug4g3 +0 -0
- data/test/dummy/storage/n2/qr/n2qro0y9heko9cwxlf10wiqiipsw +0 -0
- data/test/dummy/storage/n8/b7/n8b7b7qgu6jtw577dnn10jrrmszs +0 -0
- data/test/dummy/storage/n8/p2/n8p2ine0qqhphn09kqtxco4y7g0a +0 -0
- data/test/dummy/storage/nk/vh/nkvhgk7snpdy2ak6k02htxx9swp7 +0 -0
- data/test/dummy/storage/nn/s0/nns0nggo0x645ytco52adnsi4myp +0 -0
- data/test/dummy/storage/nu/kz/nukzl7cckkzh68i7kyjkm9mzw7c0 +0 -0
- data/test/dummy/storage/nv/8v/nv8vyoghcde1yr1bjpsw4327qt7s +0 -0
- data/test/dummy/storage/of/on/ofonhf1gs26k3dpj6o7b0ktzfowh +0 -0
- data/test/dummy/storage/pl/pf/plpfs59hvdoogj9gdweqta36csqn +0 -0
- data/test/dummy/storage/q5/g5/q5g55ekmscu10pzfw6q4syigt81g +0 -0
- data/test/dummy/storage/q5/kc/q5kcr9twyb9v4mh31pay0t7nkuwu +0 -0
- data/test/dummy/storage/qa/xd/qaxdngi74r52ahqg1pz8hjddeajc +0 -0
- data/test/dummy/storage/r7/5v/r75vadn34ak53vinylgnfdl1s8rt +0 -0
- data/test/dummy/storage/rj/rg/rjrghnyzyvxpkjw1a57mrloz72x1 +0 -0
- data/test/dummy/storage/se/h7/seh7eorfoanpp6de62pubv7kyu1a +0 -0
- data/test/dummy/storage/sj/i1/sji1oj12soz2fcjcoz0gejvzo8to +0 -0
- data/test/dummy/storage/sn/2r/sn2rku9thay4hbcbt926an69maku +0 -0
- data/test/dummy/storage/sw/jm/swjmbmxou3tnarcirxc6gdycxh91 +0 -0
- data/test/dummy/storage/sz/mq/szmqlydvpgqaw7p3v0wh444wtcif +0 -0
- data/test/dummy/storage/test.sqlite3 +0 -0
- data/test/dummy/storage/tg/by/tgbyrdvg94ivhhy2z59e8l9fod10 +0 -0
- data/test/dummy/storage/u5/vm/u5vmz08tuayqggd436et8fiaeml1 +0 -0
- data/test/dummy/storage/u6/pf/u6pf4yky0vbmvid3fa3lm4lre68g +0 -0
- data/test/dummy/storage/ub/ql/ubqlmlilt8ujgdpngcm1zae41kgy +0 -0
- data/test/dummy/storage/un/29/un29e9khqism72ag27ojccmn5sds +0 -0
- data/test/dummy/storage/ux/ns/uxnsvuk4rr1p67n1oq6tmraz0gaw +0 -0
- data/test/dummy/storage/v1/qo/v1qor0zxg3lctk9mbwyos3oag9gj +0 -0
- data/test/dummy/storage/v8/ok/v8okmd7374w1obna13a7anllx2vu +0 -0
- data/test/dummy/storage/vd/tf/vdtfmz2ctis3dr1r35do9bow2xj5 +0 -0
- data/test/dummy/storage/vo/dg/vodgq1inccnujjt3auber7tt8w8o +0 -0
- data/test/dummy/storage/vp/oe/vpoeiq00tf9pk0jcjlccomkju1zc +0 -0
- data/test/dummy/storage/vu/kg/vukgoj6qf96bhealui2yaeyn4n72 +0 -0
- data/test/dummy/storage/w7/2z/w72zoqu7v6v6jp0tpy671dcbvpow +0 -0
- data/test/dummy/storage/wa/3f/wa3fncsnozc6n4xfu32gw34geqcd +0 -0
- data/test/dummy/storage/wy/ix/wyixbqx3f6a4agb8bjhrtpblpaua +0 -0
- data/test/dummy/storage/xd/st/xdsttma3tqt7mex0vhp1vsm3dq16 +0 -0
- data/test/dummy/storage/xv/ej/xvejm2e064bnpunx3nmktaqs0x90 +0 -0
- data/test/dummy/storage/xx/py/xxpyyodssq2xmp57qrtvuw0wchwk +0 -0
- data/test/dummy/storage/xz/ik/xzikejc5sohi3zexa93s9xmg4jst +0 -0
- data/test/dummy/storage/y4/g8/y4g8teo86blcv0zysa2d2jawvk6i +0 -0
- data/test/dummy/storage/y9/58/y958xli6aoktx1ehuyjc1k8dcbzv +0 -0
- data/test/dummy/storage/yj/lw/yjlw8bf70iujb16deja8ae43rqbc +0 -0
- data/test/dummy/storage/z3/qy/z3qyb9avbucwhxa8909rpfued0y5 +0 -0
- data/test/dummy/storage/zr/wu/zrwudcg4kgo7r0jemszuzok8grqp +0 -0
- data/test/dummy/tmp/local_secret.txt +0 -1
@@ -0,0 +1,349 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "test_helper"
|
4
|
+
|
5
|
+
class ActiveStorageEncryption::OverridesTest < ActiveSupport::TestCase
|
6
|
+
include ActiveJob::TestHelper
|
7
|
+
|
8
|
+
setup do
|
9
|
+
ActiveStorage::Current.url_options = {
|
10
|
+
host: "www.example.com",
|
11
|
+
protocol: "https"
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_encryption_key_is_set_on_encrypted_service_before_saving
|
16
|
+
blob = ActiveStorage::Blob.create!(
|
17
|
+
key: "yoyo",
|
18
|
+
filename: "test.txt",
|
19
|
+
byte_size: 10,
|
20
|
+
checksum: "abab",
|
21
|
+
metadata: {"identified" => true},
|
22
|
+
content_type: "text/plain",
|
23
|
+
encryption_key: "blabla",
|
24
|
+
service_name: "encrypted_disk"
|
25
|
+
)
|
26
|
+
|
27
|
+
assert blob.valid?
|
28
|
+
blob.encryption_key = nil
|
29
|
+
refute blob.valid?
|
30
|
+
assert_equal ["Encryption key must be present for this service"], blob.errors.full_messages
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_attach_download_and_destroy_with_encryption_works
|
34
|
+
user = User.create!
|
35
|
+
with_uploadable_random_file do |file|
|
36
|
+
user.file.attach(io: file, filename: "test.txt")
|
37
|
+
end
|
38
|
+
assert user.file.url.include?("/active-storage-encryption/blob/")
|
39
|
+
assert user.file.blob.encryption_key
|
40
|
+
with_uploadable_random_file do |file|
|
41
|
+
assert_equal file.size, user.file.blob.byte_size
|
42
|
+
end
|
43
|
+
with_uploadable_random_file do |file|
|
44
|
+
assert_equal file.read, user.file.download
|
45
|
+
end
|
46
|
+
user.file.destroy
|
47
|
+
user.reload
|
48
|
+
refute user.file.attached?
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_generate_random_encryption_key_is_long_enough
|
52
|
+
key = ActiveStorage::Blob.generate_random_encryption_key
|
53
|
+
assert_equal 48, key.size
|
54
|
+
assert_equal Encoding::BINARY, key.encoding
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_service_encrypted
|
58
|
+
blob = ActiveStorage::Blob.create!(service_name: :encrypted_disk, checksum: "yoyo", encryption_key: "haha", filename: "test", key: "hahahaha", byte_size: 50)
|
59
|
+
assert blob.service_encrypted?
|
60
|
+
blob_2 = ActiveStorage::Blob.create!(service_name: :test, checksum: "yoyo", filename: "test", key: "ok", byte_size: 50)
|
61
|
+
refute blob_2.service_encrypted?
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_create_before_direct_upload_works_with_encryption_and_without
|
65
|
+
blob = with_uploadable_random_file do |file|
|
66
|
+
ActiveStorage::Blob.create_before_direct_upload!(
|
67
|
+
filename: "test_upload",
|
68
|
+
byte_size: file.size,
|
69
|
+
checksum: "something",
|
70
|
+
metadata: {"identified" => true},
|
71
|
+
service_name: "encrypted_disk"
|
72
|
+
)
|
73
|
+
end
|
74
|
+
assert_raises ActiveStorage::FileNotFoundError do
|
75
|
+
blob.download
|
76
|
+
end
|
77
|
+
|
78
|
+
assert blob.service_encrypted?
|
79
|
+
assert blob.encryption_key
|
80
|
+
|
81
|
+
blob_2 = with_uploadable_random_file do |file|
|
82
|
+
ActiveStorage::Blob.create_before_direct_upload!(
|
83
|
+
filename: "test_upload_2",
|
84
|
+
byte_size: file.size,
|
85
|
+
checksum: "something",
|
86
|
+
metadata: {"identified" => true},
|
87
|
+
service_name: "test"
|
88
|
+
)
|
89
|
+
end
|
90
|
+
refute blob_2.service_encrypted?
|
91
|
+
refute blob_2.encryption_key
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_create_and_upload_works_with_encryption_and_without
|
95
|
+
encrypted_blob = with_uploadable_random_file do |file|
|
96
|
+
ActiveStorage::Blob.create_and_upload!(
|
97
|
+
io: file,
|
98
|
+
filename: "test_upload",
|
99
|
+
metadata: {"identified" => true},
|
100
|
+
service_name: "encrypted_disk"
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
104
|
+
assert encrypted_blob.service_encrypted?
|
105
|
+
assert encrypted_blob.url.include?("/active-storage-encryption/blob/")
|
106
|
+
assert encrypted_blob.encryption_key
|
107
|
+
with_uploadable_random_file do |file|
|
108
|
+
assert_equal file.size, encrypted_blob.byte_size
|
109
|
+
end
|
110
|
+
with_uploadable_random_file do |file|
|
111
|
+
assert_equal file.read, encrypted_blob.download
|
112
|
+
end
|
113
|
+
|
114
|
+
unencrypted_blob = with_uploadable_random_file do |file|
|
115
|
+
ActiveStorage::Blob.create_and_upload!(
|
116
|
+
io: file,
|
117
|
+
filename: "test_upload_2",
|
118
|
+
metadata: {"identified" => true},
|
119
|
+
service_name: "test"
|
120
|
+
)
|
121
|
+
end
|
122
|
+
|
123
|
+
refute unencrypted_blob.service_encrypted?
|
124
|
+
assert unencrypted_blob.url.include?("/rails/active_storage/disk/")
|
125
|
+
refute unencrypted_blob.encryption_key
|
126
|
+
with_uploadable_random_file do |file|
|
127
|
+
assert_equal file.size, unencrypted_blob.byte_size
|
128
|
+
end
|
129
|
+
with_uploadable_random_file do |file|
|
130
|
+
assert_equal file.read, unencrypted_blob.download
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_open_temp_reads_the_content_of_the_blob_with_encryption_and_without
|
135
|
+
encrypted_blob = with_uploadable_random_file do |file|
|
136
|
+
ActiveStorage::Blob.create_and_upload!(
|
137
|
+
io: file,
|
138
|
+
filename: "test_upload",
|
139
|
+
metadata: {"identified" => true},
|
140
|
+
service_name: "encrypted_disk"
|
141
|
+
)
|
142
|
+
end
|
143
|
+
|
144
|
+
with_uploadable_random_file do |file|
|
145
|
+
encrypted_blob.open do |b|
|
146
|
+
assert_equal file.read, b.read
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
unencrypted_blob = with_uploadable_random_file do |file|
|
151
|
+
ActiveStorage::Blob.create_and_upload!(
|
152
|
+
io: file,
|
153
|
+
filename: "test_upload_2",
|
154
|
+
metadata: {"identified" => true},
|
155
|
+
service_name: "test"
|
156
|
+
)
|
157
|
+
end
|
158
|
+
|
159
|
+
with_uploadable_random_file do |file|
|
160
|
+
unencrypted_blob.open do |b|
|
161
|
+
assert_equal file.read, b.read
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_can_download_a_chunk_with_encryption_and_without
|
167
|
+
encrypted_blob = with_uploadable_random_file do |file|
|
168
|
+
ActiveStorage::Blob.create_and_upload!(
|
169
|
+
io: file,
|
170
|
+
filename: "test_upload",
|
171
|
+
metadata: {"identified" => true},
|
172
|
+
service_name: "encrypted_disk"
|
173
|
+
)
|
174
|
+
end
|
175
|
+
|
176
|
+
chunk = encrypted_blob.download_chunk(0..5.bytes)
|
177
|
+
with_uploadable_random_file do |file|
|
178
|
+
assert_equal chunk, file.read(6)
|
179
|
+
end
|
180
|
+
|
181
|
+
unencrypted_blob = with_uploadable_random_file do |file|
|
182
|
+
ActiveStorage::Blob.create_and_upload!(
|
183
|
+
io: file,
|
184
|
+
filename: "test_upload_2",
|
185
|
+
metadata: {"identified" => true},
|
186
|
+
service_name: "test"
|
187
|
+
)
|
188
|
+
end
|
189
|
+
|
190
|
+
chunk = unencrypted_blob.download_chunk(0..5.bytes)
|
191
|
+
with_uploadable_random_file do |file|
|
192
|
+
assert_equal chunk, file.read(6)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_serializable_hash_works_with_encryption_and_without
|
197
|
+
encrypted_blob = with_uploadable_random_file do |file|
|
198
|
+
ActiveStorage::Blob.create_and_upload!(
|
199
|
+
io: file,
|
200
|
+
filename: "test_upload",
|
201
|
+
metadata: {"identified" => true},
|
202
|
+
service_name: "encrypted_disk"
|
203
|
+
)
|
204
|
+
end
|
205
|
+
encrypted_blob_hash = {
|
206
|
+
"id" => encrypted_blob.id,
|
207
|
+
"key" => encrypted_blob.key,
|
208
|
+
"filename" => encrypted_blob.filename,
|
209
|
+
"content_type" => encrypted_blob.content_type,
|
210
|
+
"metadata" => encrypted_blob.metadata,
|
211
|
+
"service_name" => encrypted_blob.service_name,
|
212
|
+
"byte_size" => encrypted_blob.byte_size,
|
213
|
+
"checksum" => encrypted_blob.checksum,
|
214
|
+
"created_at" => encrypted_blob.created_at
|
215
|
+
}
|
216
|
+
assert_equal encrypted_blob_hash.sort, encrypted_blob.serializable_hash.sort
|
217
|
+
|
218
|
+
unencrypted_blob = with_uploadable_random_file do |file|
|
219
|
+
ActiveStorage::Blob.create_and_upload!(
|
220
|
+
io: file,
|
221
|
+
filename: "test_upload_2",
|
222
|
+
metadata: {"identified" => true},
|
223
|
+
service_name: "encrypted_disk"
|
224
|
+
)
|
225
|
+
end
|
226
|
+
unencrypted_blob_hash = {
|
227
|
+
"id" => unencrypted_blob.id,
|
228
|
+
"key" => unencrypted_blob.key,
|
229
|
+
"filename" => unencrypted_blob.filename,
|
230
|
+
"content_type" => encrypted_blob.content_type,
|
231
|
+
"metadata" => unencrypted_blob.metadata,
|
232
|
+
"service_name" => unencrypted_blob.service_name,
|
233
|
+
"byte_size" => unencrypted_blob.byte_size,
|
234
|
+
"checksum" => unencrypted_blob.checksum,
|
235
|
+
"created_at" => unencrypted_blob.created_at
|
236
|
+
}
|
237
|
+
assert_equal unencrypted_blob_hash, unencrypted_blob.serializable_hash
|
238
|
+
end
|
239
|
+
|
240
|
+
def test_instance_compose_works_with_encryption_and_without
|
241
|
+
rng = Random.new(Minitest.seed)
|
242
|
+
|
243
|
+
encrypted_blob_1 = with_uploadable_random_file do |file|
|
244
|
+
ActiveStorage::Blob.create_and_upload!(
|
245
|
+
io: file, filename: "test_upload", metadata: {"identified" => true},
|
246
|
+
service_name: "encrypted_disk"
|
247
|
+
)
|
248
|
+
end
|
249
|
+
encrypted_blob_2 = with_uploadable_random_file do |file|
|
250
|
+
ActiveStorage::Blob.create_and_upload!(
|
251
|
+
io: file, filename: "test_upload_2", metadata: {"identified" => true},
|
252
|
+
service_name: "encrypted_disk"
|
253
|
+
)
|
254
|
+
end
|
255
|
+
new_encrypted_blob = ActiveStorage::Blob.create_before_direct_upload!(
|
256
|
+
key: "new_blob_key", filename: "combined_test_upload",
|
257
|
+
metadata: {"identified" => true}, content_type: "plain/text",
|
258
|
+
checksum: "okok",
|
259
|
+
byte_size: encrypted_blob_1.byte_size + encrypted_blob_2.byte_size,
|
260
|
+
encryption_key: rng.bytes(68),
|
261
|
+
service_name: "encrypted_disk"
|
262
|
+
)
|
263
|
+
new_encrypted_blob.compose([encrypted_blob_1.key, encrypted_blob_2.key], source_encryption_keys: [encrypted_blob_1.encryption_key, encrypted_blob_2.encryption_key])
|
264
|
+
with_uploadable_random_file do |file|
|
265
|
+
assert_equal file.read * 2, new_encrypted_blob.download
|
266
|
+
end
|
267
|
+
|
268
|
+
unencrypted_blob_1 = with_uploadable_random_file do |file|
|
269
|
+
ActiveStorage::Blob.create_and_upload!(
|
270
|
+
io: file, filename: "test_upload_3", metadata: {"identified" => true},
|
271
|
+
service_name: "test"
|
272
|
+
)
|
273
|
+
end
|
274
|
+
unencrypted_blob_2 = with_uploadable_random_file do |file|
|
275
|
+
ActiveStorage::Blob.create_and_upload!(
|
276
|
+
io: file, filename: "test_upload_4", metadata: {"identified" => true},
|
277
|
+
service_name: "test"
|
278
|
+
)
|
279
|
+
end
|
280
|
+
new_unencrypted_blob = ActiveStorage::Blob.create_before_direct_upload!(
|
281
|
+
key: "new_blob_key_2", filename: "combined_test_upload",
|
282
|
+
metadata: {"identified" => true}, content_type: "plain/text",
|
283
|
+
checksum: "okok",
|
284
|
+
byte_size: unencrypted_blob_1.byte_size + unencrypted_blob_2.byte_size
|
285
|
+
)
|
286
|
+
new_unencrypted_blob.compose([unencrypted_blob_1.key, unencrypted_blob_2.key])
|
287
|
+
with_uploadable_random_file do |file|
|
288
|
+
assert_equal file.read * 2, new_unencrypted_blob.download
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
def test_class_compose_works_with_and_without_encryption
|
293
|
+
rng = Random.new(Minitest.seed)
|
294
|
+
|
295
|
+
encrypted_blob_1 = with_uploadable_random_file do |file|
|
296
|
+
ActiveStorage::Blob.create_and_upload!(
|
297
|
+
io: file, filename: "test_upload", metadata: {"identified" => true},
|
298
|
+
service_name: "encrypted_disk"
|
299
|
+
)
|
300
|
+
end
|
301
|
+
encrypted_blob_2 = with_uploadable_random_file do |file|
|
302
|
+
ActiveStorage::Blob.create_and_upload!(
|
303
|
+
io: file, filename: "test_upload_2", metadata: {"identified" => true},
|
304
|
+
service_name: "encrypted_disk"
|
305
|
+
)
|
306
|
+
end
|
307
|
+
new_enc_blob = ActiveStorage::Blob.compose(
|
308
|
+
[encrypted_blob_1, encrypted_blob_2],
|
309
|
+
content_type: "text/plain",
|
310
|
+
filename: "composed_blob",
|
311
|
+
metadata: {"identified" => true},
|
312
|
+
key: "new_enc_blob",
|
313
|
+
service_name: "encrypted_disk",
|
314
|
+
encryption_key: rng.bytes(68)
|
315
|
+
)
|
316
|
+
with_uploadable_random_file do |file|
|
317
|
+
assert_equal file.read * 2, new_enc_blob.download
|
318
|
+
end
|
319
|
+
|
320
|
+
unencrypted_blob_1 = with_uploadable_random_file do |file|
|
321
|
+
ActiveStorage::Blob.create_and_upload!(
|
322
|
+
io: file, filename: "test_upload_3", metadata: {"identified" => true},
|
323
|
+
service_name: "test"
|
324
|
+
)
|
325
|
+
end
|
326
|
+
unencrypted_blob_2 = with_uploadable_random_file do |file|
|
327
|
+
ActiveStorage::Blob.create_and_upload!(
|
328
|
+
io: file, filename: "test_upload_4", metadata: {"identified" => true},
|
329
|
+
service_name: "test"
|
330
|
+
)
|
331
|
+
end
|
332
|
+
new_unencrypted_blob = ActiveStorage::Blob.compose(
|
333
|
+
[unencrypted_blob_1, unencrypted_blob_2],
|
334
|
+
key: "new_unencblob_key_2", filename: "combined_test_upload_2",
|
335
|
+
metadata: {"identified" => true}, service_name: "test"
|
336
|
+
)
|
337
|
+
with_uploadable_random_file do |file|
|
338
|
+
assert_equal file.read * 2, new_unencrypted_blob.download
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
private
|
343
|
+
|
344
|
+
def with_uploadable_random_file(size = 128, &blk)
|
345
|
+
rng = Random.new(Minitest.seed)
|
346
|
+
plaintext_upload_bytes = rng.bytes(size)
|
347
|
+
StringIO.open(plaintext_upload_bytes, "rb", &blk)
|
348
|
+
end
|
349
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_storage_encryption
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
8
8
|
- Sebastian van Hesteren
|
9
|
-
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2025-
|
11
|
+
date: 2025-05-02 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rails
|
@@ -95,6 +94,20 @@ dependencies:
|
|
95
94
|
- - ">="
|
96
95
|
- !ruby/object:Gem::Version
|
97
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: google-cloud-storage
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
98
111
|
- !ruby/object:Gem::Dependency
|
99
112
|
name: sqlite3
|
100
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -165,6 +178,20 @@ dependencies:
|
|
165
178
|
- - ">="
|
166
179
|
- !ruby/object:Gem::Version
|
167
180
|
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: pry
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
168
195
|
description: Adds customer-supplied encryption keys to storage services.
|
169
196
|
email:
|
170
197
|
- me@julik.nl
|
@@ -172,10 +199,17 @@ executables: []
|
|
172
199
|
extensions: []
|
173
200
|
extra_rdoc_files: []
|
174
201
|
files:
|
202
|
+
- ".github/dependabot.yml"
|
203
|
+
- ".github/workflows/ci.yml"
|
204
|
+
- ".gitignore"
|
205
|
+
- ".ruby-version"
|
206
|
+
- ".standard.yml"
|
175
207
|
- Appraisals
|
208
|
+
- Gemfile
|
176
209
|
- MIT-LICENSE
|
177
210
|
- README.md
|
178
211
|
- Rakefile
|
212
|
+
- active_storage_encryption.gemspec
|
179
213
|
- bin/rails
|
180
214
|
- bin/rubocop
|
181
215
|
- config/initializers/active_storage_encryption.rb
|
@@ -185,6 +219,7 @@ files:
|
|
185
219
|
- gemfiles/rails_8.gemfile
|
186
220
|
- gemfiles/rails_8.gemfile.lock
|
187
221
|
- lib/active_storage/service/encrypted_disk_service.rb
|
222
|
+
- lib/active_storage/service/encrypted_gcs_service.rb
|
188
223
|
- lib/active_storage/service/encrypted_mirror_service.rb
|
189
224
|
- lib/active_storage/service/encrypted_s3_service.rb
|
190
225
|
- lib/active_storage_encryption.rb
|
@@ -193,6 +228,7 @@ files:
|
|
193
228
|
- lib/active_storage_encryption/encrypted_disk_service.rb
|
194
229
|
- lib/active_storage_encryption/encrypted_disk_service/v1_scheme.rb
|
195
230
|
- lib/active_storage_encryption/encrypted_disk_service/v2_scheme.rb
|
231
|
+
- lib/active_storage_encryption/encrypted_gcs_service.rb
|
196
232
|
- lib/active_storage_encryption/encrypted_mirror_service.rb
|
197
233
|
- lib/active_storage_encryption/encrypted_s3_service.rb
|
198
234
|
- lib/active_storage_encryption/engine.rb
|
@@ -200,13 +236,19 @@ files:
|
|
200
236
|
- lib/active_storage_encryption/private_url_policy.rb
|
201
237
|
- lib/active_storage_encryption/resumable_gcs_upload.rb
|
202
238
|
- lib/active_storage_encryption/version.rb
|
239
|
+
- lib/generators/add_encryption_key_to_active_storage_blobs.rb.erb
|
240
|
+
- lib/generators/install_generator.rb
|
203
241
|
- lib/tasks/active_storage_encryption_tasks.rake
|
204
242
|
- test/active_storage_encryption_test.rb
|
205
243
|
- test/dummy/Rakefile
|
244
|
+
- test/dummy/app/assets/images/.keep
|
206
245
|
- test/dummy/app/assets/stylesheets/application.css
|
207
246
|
- test/dummy/app/controllers/application_controller.rb
|
247
|
+
- test/dummy/app/controllers/concerns/.keep
|
208
248
|
- test/dummy/app/helpers/application_helper.rb
|
209
249
|
- test/dummy/app/models/application_record.rb
|
250
|
+
- test/dummy/app/models/concerns/.keep
|
251
|
+
- test/dummy/app/models/user.rb
|
210
252
|
- test/dummy/app/views/layouts/application.html.erb
|
211
253
|
- test/dummy/app/views/pwa/manifest.json.erb
|
212
254
|
- test/dummy/app/views/pwa/service-worker.js
|
@@ -233,139 +275,24 @@ files:
|
|
233
275
|
- test/dummy/config/storage.yml
|
234
276
|
- test/dummy/db/migrate/20250304023851_create_active_storage_tables.active_storage.rb
|
235
277
|
- test/dummy/db/migrate/20250304023853_add_blob_encryption_key_column.rb
|
278
|
+
- test/dummy/db/migrate/20250428093315_create_users.rb
|
236
279
|
- test/dummy/db/schema.rb
|
237
|
-
- test/dummy/
|
238
|
-
- test/dummy/log
|
280
|
+
- test/dummy/lib/assets/.keep
|
281
|
+
- test/dummy/log/.keep
|
239
282
|
- test/dummy/public/404.html
|
240
283
|
- test/dummy/public/406-unsupported-browser.html
|
241
284
|
- test/dummy/public/422.html
|
242
285
|
- test/dummy/public/500.html
|
243
286
|
- test/dummy/public/icon.png
|
244
287
|
- test/dummy/public/icon.svg
|
245
|
-
- test/
|
246
|
-
- test/dummy/storage/0b/93/0b93pygovuunam1a3ovzwmrbuw2x
|
247
|
-
- test/dummy/storage/0m/3s/0m3s7r3nboblijr1jxlnvm3p3l4b
|
248
|
-
- test/dummy/storage/0o/9s/0o9s4ctbpu757qh7ucyony0itek4
|
249
|
-
- test/dummy/storage/1e/q6/1eq646og0wazgfw7bwjqz2uem0g4
|
250
|
-
- test/dummy/storage/1n/o3/1no30cpwrm727bm6arvb7zxagdg1
|
251
|
-
- test/dummy/storage/1x/6w/1x6wsoq3pew17reztwax78lrr3hc
|
252
|
-
- test/dummy/storage/28/de/28deswrv89c9f2tk7dz1l5uovd4r
|
253
|
-
- test/dummy/storage/2h/sd/2hsd1mh20c6os2nzyoicfyymhwev
|
254
|
-
- test/dummy/storage/2t/ni/2tnidhdk4c6cj0tnw3jiw88dgs4g
|
255
|
-
- test/dummy/storage/2v/e0/2ve0555nluisy2el5cf4txzgae3j
|
256
|
-
- test/dummy/storage/2z/c5/2zc5mj8g0o9l7mfnim0vs4v48xd6
|
257
|
-
- test/dummy/storage/34/xc/34xc9hk74dm9227d6mhgfcfxl4ue
|
258
|
-
- test/dummy/storage/3z/0t/3z0tnve7ivrq0qyrvfhfzztjhjqs
|
259
|
-
- test/dummy/storage/49/14/4914188q1dptpw4po91cp54f32bg
|
260
|
-
- test/dummy/storage/4c/74/4c7412lfz0pm2ocg6u01h67bnsch
|
261
|
-
- test/dummy/storage/52/qf/52qfbgjlf3gor3agsyrt09t19o55
|
262
|
-
- test/dummy/storage/57/go/57gok1uc4ebc3ugrjrje4lpe1ram
|
263
|
-
- test/dummy/storage/5f/dv/5fdvt6tu1mkyajbz4hbxbw6fpt9w
|
264
|
-
- test/dummy/storage/5x/b7/5xb7zzi66fi5f6yrn09pq4ogb9wo
|
265
|
-
- test/dummy/storage/6m/vr/6mvr1fr5it125tm4vahjw6bv9wkz
|
266
|
-
- test/dummy/storage/7b/hb/7bhbdxqn67lape1f49jqfktcei4n
|
267
|
-
- test/dummy/storage/7n/4v/7n4vpm1q14y4qffc4jj78m036gtw
|
268
|
-
- test/dummy/storage/7q/ku/7qkufbjwbbqwnf89uciosleixnew
|
269
|
-
- test/dummy/storage/8l/5v/8l5vb4o02hx46s5qohfn5to945p3
|
270
|
-
- test/dummy/storage/8q/pu/8qpun3f8vzl7auxajvqyq8f48ngw
|
271
|
-
- test/dummy/storage/8w/ag/8wag4ptmox207h7mobamk0tcebwx
|
272
|
-
- test/dummy/storage/8w/v8/8wv8lrhsw4s2r6guh1csd3jd89ii
|
273
|
-
- test/dummy/storage/9b/c6/9bc6wlpfnqdywpnxgeoin3w9b5ch
|
274
|
-
- test/dummy/storage/9l/wk/9lwkt21k5iburdaitbwliw7krtwt
|
275
|
-
- test/dummy/storage/9p/0v/9p0vgfw3l2854k7so3rp33rmyh7p
|
276
|
-
- test/dummy/storage/9r/sy/9rsya3r6syft34qz24g1h4u4qq44
|
277
|
-
- test/dummy/storage/9s/es/9seslusr46xjf3mfzq10hkp13kc1
|
278
|
-
- test/dummy/storage/9t/nv/9tnvn5v52fkvurpgszf4gco78t5h
|
279
|
-
- test/dummy/storage/9u/to/9utokgxyu6xyovandu7pjhogoaqp
|
280
|
-
- test/dummy/storage/9w/a4/9wa4c20p4dvm1cd5thnv9f7ei13w
|
281
|
-
- test/dummy/storage/at/kg/atkgs5gwz2xdv9lvqftsg6p7gcpu
|
282
|
-
- test/dummy/storage/at/qo/atqomgf3rpb2f6e1tq1yn2xqzojv
|
283
|
-
- test/dummy/storage/ba/lq/balqtije6kf82ht4lr70ajaae9kc
|
284
|
-
- test/dummy/storage/bf/i1/bfi1ij9rygr6lkx1r0lhgi8o5smx
|
285
|
-
- test/dummy/storage/bg/ye/bgyenotrv3aj6lk88edwv0c41pfj
|
286
|
-
- test/dummy/storage/bu/xe/buxed4b1l78kcax53fa37awm9ywk
|
287
|
-
- test/dummy/storage/d2/c1/d2c11nhikb474oq3q7so0xbhukvj
|
288
|
-
- test/dummy/storage/development.sqlite3
|
289
|
-
- test/dummy/storage/dk/hy/dkhybxn2o27a8xgvfhsxpgqxa1zf
|
290
|
-
- test/dummy/storage/e7/2n/e72nz5cz3wf6qvh4dw4qfnw6ucog
|
291
|
-
- test/dummy/storage/eo/4q/eo4qn68m7al0ehhe0s23ycuzkjto
|
292
|
-
- test/dummy/storage/ew/8s/ew8sejdsx8ddmrzkvfa37ebz1ts1
|
293
|
-
- test/dummy/storage/f8/q1/f8q1kpg2tou8ru0afj8d2gy6ym5p
|
294
|
-
- test/dummy/storage/fr/55/fr558uhp1k93jzhb4butyi2ry51t
|
295
|
-
- test/dummy/storage/g4/nh/g4nhx1zxbeiegqpgn8ppsl1yhm0t
|
296
|
-
- test/dummy/storage/gg/r5/ggr51egxhqfh4w5eluzs47qceb76
|
297
|
-
- test/dummy/storage/gh/ua/ghuaagralqmjy8rkbwmuv3010lvs
|
298
|
-
- test/dummy/storage/gx/uh/gxuhmf52ufli3m7ng8irp8ghxa1v
|
299
|
-
- test/dummy/storage/h0/m1/h0m1emy251xus1d9qh6u25dzy18o
|
300
|
-
- test/dummy/storage/hh/kc/hhkc2q8paptyvhw2m5hlwylhtfo5
|
301
|
-
- test/dummy/storage/hq/0q/hq0q04kr6qzrp0qaee8rehcp2tzx
|
302
|
-
- test/dummy/storage/ii/g1/iig1ge3fsjitai4g2fkq4qt369wh
|
303
|
-
- test/dummy/storage/io/f0/iof0mv7w8qjd6m826g52pzyxedet
|
304
|
-
- test/dummy/storage/jk/2i/jk2ifmx6ac35ubk3esufnm6bn1m1
|
305
|
-
- test/dummy/storage/jw/4t/jw4trdeyfkw3j8z70xcnr9a7gqe5
|
306
|
-
- test/dummy/storage/ke/k2/kek24leksglm1rs2a78mfmot0p3s
|
307
|
-
- test/dummy/storage/kh/6d/kh6doaxxwxiyes0yqz2dmmpajkzv
|
308
|
-
- test/dummy/storage/kj/7n/kj7nookjhisagd80z8hlv3wn50am
|
309
|
-
- test/dummy/storage/kq/lf/kqlf5udtrgrk4v55qodxyt6i68p8
|
310
|
-
- test/dummy/storage/ky/33/ky334jbo8eb08pj9qbe919iz91mh
|
311
|
-
- test/dummy/storage/lt/zw/ltzw4lur2bheit1273ogpfzhv7j1
|
312
|
-
- test/dummy/storage/m2/ve/m2vejmyttn1ium81dopppom6vum6
|
313
|
-
- test/dummy/storage/m8/d4/m8d4r9iauedq8wlpvnx1f3ou0jwg
|
314
|
-
- test/dummy/storage/m9/ee/m9eetioklzatyff94gq0vn1cga1n
|
315
|
-
- test/dummy/storage/ma/v0/mav084zvmyoh1a8i7dcwqy2aaoi9
|
316
|
-
- test/dummy/storage/mg/pa/mgpauiu02i28j3poef65k3q0gfpw
|
317
|
-
- test/dummy/storage/mm/8g/mm8gp5evncb1ol1lj2jlmra2ixij
|
318
|
-
- test/dummy/storage/mm/d2/mmd21x8c1amgnidzw0wowiwug4g3
|
319
|
-
- test/dummy/storage/n2/qr/n2qro0y9heko9cwxlf10wiqiipsw
|
320
|
-
- test/dummy/storage/n8/b7/n8b7b7qgu6jtw577dnn10jrrmszs
|
321
|
-
- test/dummy/storage/n8/p2/n8p2ine0qqhphn09kqtxco4y7g0a
|
322
|
-
- test/dummy/storage/nk/vh/nkvhgk7snpdy2ak6k02htxx9swp7
|
323
|
-
- test/dummy/storage/nn/s0/nns0nggo0x645ytco52adnsi4myp
|
324
|
-
- test/dummy/storage/nu/kz/nukzl7cckkzh68i7kyjkm9mzw7c0
|
325
|
-
- test/dummy/storage/nv/8v/nv8vyoghcde1yr1bjpsw4327qt7s
|
326
|
-
- test/dummy/storage/of/on/ofonhf1gs26k3dpj6o7b0ktzfowh
|
327
|
-
- test/dummy/storage/pl/pf/plpfs59hvdoogj9gdweqta36csqn
|
328
|
-
- test/dummy/storage/q5/g5/q5g55ekmscu10pzfw6q4syigt81g
|
329
|
-
- test/dummy/storage/q5/kc/q5kcr9twyb9v4mh31pay0t7nkuwu
|
330
|
-
- test/dummy/storage/qa/xd/qaxdngi74r52ahqg1pz8hjddeajc
|
331
|
-
- test/dummy/storage/r7/5v/r75vadn34ak53vinylgnfdl1s8rt
|
332
|
-
- test/dummy/storage/rj/rg/rjrghnyzyvxpkjw1a57mrloz72x1
|
333
|
-
- test/dummy/storage/se/h7/seh7eorfoanpp6de62pubv7kyu1a
|
334
|
-
- test/dummy/storage/sj/i1/sji1oj12soz2fcjcoz0gejvzo8to
|
335
|
-
- test/dummy/storage/sn/2r/sn2rku9thay4hbcbt926an69maku
|
336
|
-
- test/dummy/storage/sw/jm/swjmbmxou3tnarcirxc6gdycxh91
|
337
|
-
- test/dummy/storage/sz/mq/szmqlydvpgqaw7p3v0wh444wtcif
|
338
|
-
- test/dummy/storage/test.sqlite3
|
339
|
-
- test/dummy/storage/tg/by/tgbyrdvg94ivhhy2z59e8l9fod10
|
340
|
-
- test/dummy/storage/u5/vm/u5vmz08tuayqggd436et8fiaeml1
|
341
|
-
- test/dummy/storage/u6/pf/u6pf4yky0vbmvid3fa3lm4lre68g
|
342
|
-
- test/dummy/storage/ub/ql/ubqlmlilt8ujgdpngcm1zae41kgy
|
343
|
-
- test/dummy/storage/un/29/un29e9khqism72ag27ojccmn5sds
|
344
|
-
- test/dummy/storage/ux/ns/uxnsvuk4rr1p67n1oq6tmraz0gaw
|
345
|
-
- test/dummy/storage/v1/qo/v1qor0zxg3lctk9mbwyos3oag9gj
|
346
|
-
- test/dummy/storage/v8/ok/v8okmd7374w1obna13a7anllx2vu
|
347
|
-
- test/dummy/storage/vd/tf/vdtfmz2ctis3dr1r35do9bow2xj5
|
348
|
-
- test/dummy/storage/vo/dg/vodgq1inccnujjt3auber7tt8w8o
|
349
|
-
- test/dummy/storage/vp/oe/vpoeiq00tf9pk0jcjlccomkju1zc
|
350
|
-
- test/dummy/storage/vu/kg/vukgoj6qf96bhealui2yaeyn4n72
|
351
|
-
- test/dummy/storage/w7/2z/w72zoqu7v6v6jp0tpy671dcbvpow
|
352
|
-
- test/dummy/storage/wa/3f/wa3fncsnozc6n4xfu32gw34geqcd
|
353
|
-
- test/dummy/storage/wy/ix/wyixbqx3f6a4agb8bjhrtpblpaua
|
354
|
-
- test/dummy/storage/xd/st/xdsttma3tqt7mex0vhp1vsm3dq16
|
355
|
-
- test/dummy/storage/xv/ej/xvejm2e064bnpunx3nmktaqs0x90
|
356
|
-
- test/dummy/storage/xx/py/xxpyyodssq2xmp57qrtvuw0wchwk
|
357
|
-
- test/dummy/storage/xz/ik/xzikejc5sohi3zexa93s9xmg4jst
|
358
|
-
- test/dummy/storage/y4/g8/y4g8teo86blcv0zysa2d2jawvk6i
|
359
|
-
- test/dummy/storage/y9/58/y958xli6aoktx1ehuyjc1k8dcbzv
|
360
|
-
- test/dummy/storage/yj/lw/yjlw8bf70iujb16deja8ae43rqbc
|
361
|
-
- test/dummy/storage/z3/qy/z3qyb9avbucwhxa8909rpfued0y5
|
362
|
-
- test/dummy/storage/zr/wu/zrwudcg4kgo7r0jemszuzok8grqp
|
363
|
-
- test/dummy/tmp/local_secret.txt
|
288
|
+
- test/integration/.keep
|
364
289
|
- test/integration/encrypted_blob_proxy_controller_test.rb
|
365
290
|
- test/integration/encrypted_blobs_controller_test.rb
|
366
291
|
- test/lib/encrypted_disk_service_test.rb
|
292
|
+
- test/lib/encrypted_gcs_service_test.rb
|
367
293
|
- test/lib/encrypted_mirror_service_test.rb
|
368
294
|
- test/lib/encrypted_s3_service_test.rb
|
295
|
+
- test/lib/overrides_test.rb
|
369
296
|
- test/test_helper.rb
|
370
297
|
homepage: https://github.com/cheddar-me/active_storage_encryption
|
371
298
|
licenses:
|
@@ -375,7 +302,6 @@ metadata:
|
|
375
302
|
homepage_uri: https://github.com/cheddar-me/active_storage_encryption
|
376
303
|
source_code_uri: https://github.com/cheddar-me/active_storage_encryption
|
377
304
|
changelog_uri: https://github.com/cheddar-me/active_storage_encryption/blob/main/CHANGELOG.md
|
378
|
-
post_install_message:
|
379
305
|
rdoc_options: []
|
380
306
|
require_paths:
|
381
307
|
- lib
|
@@ -390,8 +316,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
390
316
|
- !ruby/object:Gem::Version
|
391
317
|
version: '0'
|
392
318
|
requirements: []
|
393
|
-
rubygems_version: 3.
|
394
|
-
signing_key:
|
319
|
+
rubygems_version: 3.6.6
|
395
320
|
specification_version: 4
|
396
321
|
summary: Customer-supplied encryption key support for ActiveStorage blobs.
|
397
322
|
test_files: []
|