aion-s3 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.
- checksums.yaml +7 -0
- data/lib/aion-s3.rb +1 -0
- data/lib/aion_s3.rb +8 -0
- data/lib/aion_s3/packer.rb +120 -0
- data/lib/aion_s3/uploader.rb +64 -0
- data/lib/aion_s3/version.rb +3 -0
- metadata +103 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0e2a5f113d1729577f5f289cd6d96acd4d530833fd6deffd840f0c54eae00ce7
|
4
|
+
data.tar.gz: 29fbc5075544c42f8269533ec46fcac2e38358bd3e524e11813d1ea59a96f5b1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 00cd42ac47c8339fcc2f4d1b640c42f055dc19ee95f30191cda8333843cc62797f82662600cbe2e65021e54b4cc201b6f69350e04b4ed709da97a0518843158a
|
7
|
+
data.tar.gz: dab3192475cc6c6e8cff389953b613ee0e2c2b03c06e7d1bd7f429cd6887325e99988e9d93a99f6f110a421672a7408e32c556b9281370662890a8fc22c01a3b
|
data/lib/aion-s3.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'aion_s3'
|
data/lib/aion_s3.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'zlib'
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
module AionS3
|
6
|
+
|
7
|
+
# A <code>Packer</code> is a utility for packing and unpacking data.
|
8
|
+
# Packing applies compression and encryption to provided data.
|
9
|
+
# Unpacking applies decryption and decompression to provided data.
|
10
|
+
#
|
11
|
+
# Encryption uses cipher +AES-256-CBC+. The key is generated via a password provided when the <code>Packer</code> is initialized.
|
12
|
+
# The password must be a string at least 20 chars long.
|
13
|
+
#
|
14
|
+
# It is *very* important that the password is randomly generated.
|
15
|
+
class Packer
|
16
|
+
|
17
|
+
# @return [String]
|
18
|
+
attr_reader :password
|
19
|
+
|
20
|
+
# Returns a new Packer object with a key based on the given +password+.
|
21
|
+
# If no password is provided, a random password will be generated
|
22
|
+
# The password can later be read via #password.
|
23
|
+
#
|
24
|
+
# @param [String] password
|
25
|
+
def initialize(password = nil)
|
26
|
+
password ||= Packer.random_password
|
27
|
+
if password and password.size < 32
|
28
|
+
raise ArgumentError, 'Provided password must be at least 32 characters'
|
29
|
+
end
|
30
|
+
@key = OpenSSL::Digest.digest('sha256', password)
|
31
|
+
@password = password.freeze
|
32
|
+
end
|
33
|
+
|
34
|
+
# Encrypts data with +AES-256-CBC+ and returns it as a binary encoded string.
|
35
|
+
#
|
36
|
+
# @param [String] data
|
37
|
+
# @return [String] a binary encoded string
|
38
|
+
def encrypt(data)
|
39
|
+
_data = data
|
40
|
+
cipher = OpenSSL::Cipher::AES.new(256, :cbc).encrypt
|
41
|
+
cipher.key = @key
|
42
|
+
cipher.random_iv + cipher.update(_data) + cipher.final
|
43
|
+
end
|
44
|
+
|
45
|
+
# Decrypts data that have been encrypted using #encrypt(data) and returns it as a binary encoded string.
|
46
|
+
#
|
47
|
+
# @param [String] data
|
48
|
+
# @return [String] a binary encoded string
|
49
|
+
def decrypt(data)
|
50
|
+
_data = data
|
51
|
+
decipher = OpenSSL::Cipher::AES.new(256, :cbc).decrypt
|
52
|
+
decipher.key = @key
|
53
|
+
decipher.iv = _data.byteslice(0,16)
|
54
|
+
decipher.update(_data.byteslice(16, _data.bytesize - 16)) + decipher.final
|
55
|
+
end
|
56
|
+
|
57
|
+
# Decompresses data with zlib and returns it a binary encoded string.
|
58
|
+
#
|
59
|
+
# @param [String] data
|
60
|
+
# @return [String] a binary encoded string
|
61
|
+
def deflate(data)
|
62
|
+
Zlib::Deflate.deflate(data, Zlib::BEST_COMPRESSION)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Compresses data with zlib and returns it a binary encoded string.
|
66
|
+
#
|
67
|
+
# @param [String] data
|
68
|
+
# @return [String] a binary encoded string
|
69
|
+
def inflate(data)
|
70
|
+
Zlib::Inflate.inflate(data)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Compresses and encrypts given data.
|
74
|
+
#
|
75
|
+
# *Note*
|
76
|
+
# The ruby string's local encoding will be lost when packed.
|
77
|
+
# unpack(data) will always return a string with binary encoding.
|
78
|
+
#
|
79
|
+
# Example:
|
80
|
+
#
|
81
|
+
# data = 'æøå' # utf8 encoded string
|
82
|
+
# str = unpack(pack(data))
|
83
|
+
#
|
84
|
+
# puts str.bytes == data.bytes
|
85
|
+
# puts str == data
|
86
|
+
# puts str.encoding == data.encoding
|
87
|
+
#
|
88
|
+
# Produces:
|
89
|
+
#
|
90
|
+
# true
|
91
|
+
# false
|
92
|
+
# false
|
93
|
+
#
|
94
|
+
# @param [String] data
|
95
|
+
# @return [String] a binary encoded string
|
96
|
+
def pack(data)
|
97
|
+
encrypt(deflate(data))
|
98
|
+
end
|
99
|
+
|
100
|
+
# Decrypts and decompresses given data.
|
101
|
+
#
|
102
|
+
# @param [Object] data
|
103
|
+
# @return [String] a binary encoded string
|
104
|
+
def unpack(data)
|
105
|
+
inflate(decrypt(data))
|
106
|
+
end
|
107
|
+
|
108
|
+
# Returns a base64 encoded string based on random bytes.
|
109
|
+
# The length will be <code>n * 2</code> characters.
|
110
|
+
#
|
111
|
+
# If +n+ is not defined, it will default to 24, which will generate a 32 character base64 encoded string.
|
112
|
+
#
|
113
|
+
# @param [Integer] n
|
114
|
+
# @return [String] a base64 encoded string
|
115
|
+
def self.random_password(n = 24)
|
116
|
+
SecureRandom.base64(n)
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'aws-sdk-s3'
|
2
|
+
|
3
|
+
module AionS3
|
4
|
+
|
5
|
+
# An <code>Uploader</code> is a utility for uploading data to s3.
|
6
|
+
# The Uploader supports compliance locking, where files are locked for update/deletion for a configured amount of time.
|
7
|
+
#
|
8
|
+
# The utility is a wrapper around <code>Aws::S3::Client</code>.
|
9
|
+
class Uploader
|
10
|
+
|
11
|
+
# @return [Aws::S3::Client]
|
12
|
+
attr_reader :client
|
13
|
+
|
14
|
+
# @param [String] bucket
|
15
|
+
# @param [Integer] lock_days
|
16
|
+
# @param [Hash] s3_options
|
17
|
+
def initialize(bucket, lock_days: 0, s3_options: {})
|
18
|
+
@client = Aws::S3::Client.new(s3_options)
|
19
|
+
@bucket = bucket
|
20
|
+
@lock_seconds = lock_days.to_i * 24 * 60 * 60
|
21
|
+
end
|
22
|
+
|
23
|
+
# Gets metadata from an object in s3.
|
24
|
+
#
|
25
|
+
# If a target is provided, the object data will be downloaded as well.
|
26
|
+
# +target+ must be a string with file path or an <code>IO</code> object.
|
27
|
+
#
|
28
|
+
# @param [String] key
|
29
|
+
# @param [String, IO] target
|
30
|
+
# @return [Aws::S3::Types::GetObjectOutput]
|
31
|
+
def get(key, target = nil)
|
32
|
+
@client.get_object(
|
33
|
+
bucket: @bucket,
|
34
|
+
key: key,
|
35
|
+
response_target: target
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Puts an object to s3.
|
40
|
+
#
|
41
|
+
# If <code>Uploader</code> was configured with lock_days > 0 a compliance lock will be put on the object.
|
42
|
+
#
|
43
|
+
# @param [String] key an urlsafe string
|
44
|
+
# @param [String, IO] body
|
45
|
+
# @return [Aws::S3::Types::PutObjectOutput]
|
46
|
+
def put(key, body)
|
47
|
+
options = {
|
48
|
+
bucket: @bucket,
|
49
|
+
key: key,
|
50
|
+
body: body,
|
51
|
+
}
|
52
|
+
|
53
|
+
if @lock_seconds > 0
|
54
|
+
options.reverse_merge!(
|
55
|
+
object_lock_mode: 'COMPLIANCE',
|
56
|
+
object_lock_retain_until_date: Time.now + @lock_seconds
|
57
|
+
)
|
58
|
+
end
|
59
|
+
|
60
|
+
@client.put_object(options)
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aion-s3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael Andersen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-11-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aws-sdk-s3
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.17.3
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.17.3
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 12.3.1
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 12.3.1
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 5.11.3
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 5.11.3
|
69
|
+
description: A tool for compressing, encrypting and uploading files to AWS S3
|
70
|
+
email: michael@aion.dk
|
71
|
+
executables: []
|
72
|
+
extensions: []
|
73
|
+
extra_rdoc_files: []
|
74
|
+
files:
|
75
|
+
- lib/aion-s3.rb
|
76
|
+
- lib/aion_s3.rb
|
77
|
+
- lib/aion_s3/packer.rb
|
78
|
+
- lib/aion_s3/uploader.rb
|
79
|
+
- lib/aion_s3/version.rb
|
80
|
+
homepage: https://github.com/aion-dk/aion-s3
|
81
|
+
licenses:
|
82
|
+
- MIT
|
83
|
+
metadata: {}
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubygems_version: 3.0.3
|
100
|
+
signing_key:
|
101
|
+
specification_version: 4
|
102
|
+
summary: Aion S3
|
103
|
+
test_files: []
|