aion-s3 1.0.0

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