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.
@@ -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
@@ -0,0 +1 @@
1
+ require 'aion_s3'
@@ -0,0 +1,8 @@
1
+ # This module provides utilities for compressing and encrypting data, as well as uploading
2
+ # compliance locked objects to AWS s3.
3
+ module AionS3
4
+ end
5
+
6
+ require 'aion_s3/packer'
7
+ require 'aion_s3/uploader'
8
+ require 'aion_s3/version'
@@ -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
@@ -0,0 +1,3 @@
1
+ module AionS3
2
+ VERSION = '1.0.0'
3
+ 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: []