heirloom 0.9.0 → 0.10.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.
- data/.rvmrc +1 -1
- data/CHANGELOG +7 -0
- data/README.md +1 -11
- data/lib/heirloom.rb +2 -0
- data/lib/heirloom/acl/s3.rb +8 -9
- data/lib/heirloom/archive/authorizer.rb +3 -1
- data/lib/heirloom/archive/destroyer.rb +3 -3
- data/lib/heirloom/archive/downloader.rb +4 -4
- data/lib/heirloom/archive/reader.rb +15 -5
- data/lib/heirloom/archive/uploader.rb +13 -9
- data/lib/heirloom/archive/writer.rb +2 -0
- data/lib/heirloom/cipher.rb +2 -0
- data/lib/heirloom/cipher/data.rb +37 -19
- data/lib/heirloom/cipher/file.rb +23 -22
- data/lib/heirloom/cipher/shared.rb +19 -0
- data/lib/heirloom/cli/upload.rb +2 -1
- data/lib/heirloom/directory/directory.rb +12 -1
- data/lib/heirloom/exceptions.rb +11 -0
- data/lib/heirloom/uploader/s3.rb +34 -23
- data/lib/heirloom/utils.rb +1 -0
- data/lib/heirloom/utils/file.rb +30 -0
- data/lib/heirloom/version.rb +1 -1
- data/spec/acl/s3_spec.rb +1 -1
- data/spec/archive/authorizer_spec.rb +25 -13
- data/spec/archive/destroyer_spec.rb +1 -1
- data/spec/archive/downloader_spec.rb +4 -4
- data/spec/archive/reader_spec.rb +19 -5
- data/spec/archive/uploader_spec.rb +47 -20
- data/spec/cipher/data_spec.rb +52 -35
- data/spec/cipher/file_spec.rb +23 -9
- data/spec/cli/upload_spec.rb +1 -0
- data/spec/directory/directory_spec.rb +36 -10
- data/spec/uploader/s3_spec.rb +64 -0
- data/spec/utils/file_spec.rb +30 -0
- metadata +22 -14
data/.rvmrc
CHANGED
@@ -1 +1 @@
|
|
1
|
-
rvm use ruby-1.9.3-
|
1
|
+
rvm use ruby-1.9.3-p327@heirloom --create
|
data/CHANGELOG
CHANGED
data/README.md
CHANGED
@@ -22,7 +22,7 @@ Install the gem
|
|
22
22
|
gem install heirloom --no-ri --no-rdoc
|
23
23
|
```
|
24
24
|
|
25
|
-
To get started copy the sample below
|
25
|
+
To get started, copy the sample below to ~/.heirloom.yml and update the specified fields.
|
26
26
|
|
27
27
|
```
|
28
28
|
aws:
|
@@ -31,16 +31,6 @@ aws:
|
|
31
31
|
metadata_region: us-west-1
|
32
32
|
```
|
33
33
|
|
34
|
-
Proxy Support
|
35
|
-
-------------
|
36
|
-
|
37
|
-
Heirloom supports accessing AWS API endpoint throught a proxy. This can be set via the http_proxy and https_proxy variables.
|
38
|
-
|
39
|
-
```
|
40
|
-
export http_proxy=http://1.2.3.4:80
|
41
|
-
export http_proxys=http://1.2.3.4:80
|
42
|
-
```
|
43
|
-
|
44
34
|
Documentation
|
45
35
|
-------------
|
46
36
|
|
data/lib/heirloom.rb
CHANGED
data/lib/heirloom/acl/s3.rb
CHANGED
@@ -11,20 +11,19 @@ module Heirloom
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def allow_read_access_from_accounts(args)
|
14
|
-
bucket
|
15
|
-
key_name
|
14
|
+
bucket = args[:bucket]
|
15
|
+
key_name = args[:key_name]
|
16
16
|
key_folder = args[:key_folder]
|
17
|
-
accounts
|
17
|
+
accounts = args[:accounts]
|
18
18
|
|
19
|
-
key
|
19
|
+
key = "#{key_folder}/#{key_name}"
|
20
20
|
|
21
21
|
current_acls = s3.get_bucket_acl bucket
|
22
|
+
name = current_acls['Owner']['Name']
|
23
|
+
id = current_acls['Owner']['ID']
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
grants = build_bucket_grants :id => id,
|
27
|
-
:name => name,
|
25
|
+
grants = build_bucket_grants :id => id,
|
26
|
+
:name => name,
|
28
27
|
:accounts => accounts
|
29
28
|
|
30
29
|
accounts.each do |a|
|
@@ -17,13 +17,15 @@ module Heirloom
|
|
17
17
|
|
18
18
|
@logger.info "Authorizing #{@accounts.join(', ')}."
|
19
19
|
|
20
|
+
key_name = reader.key_name
|
21
|
+
|
20
22
|
regions.each do |region|
|
21
23
|
bucket = reader.get_bucket :region => region
|
22
24
|
|
23
25
|
s3_acl = ACL::S3.new :config => @config,
|
24
26
|
:region => region
|
25
27
|
|
26
|
-
s3_acl.allow_read_access_from_accounts :key_name =>
|
28
|
+
s3_acl.allow_read_access_from_accounts :key_name => key_name,
|
27
29
|
:key_folder => @name,
|
28
30
|
:accounts => @accounts,
|
29
31
|
:bucket => bucket
|
@@ -18,15 +18,15 @@ module Heirloom
|
|
18
18
|
regions.each do |region|
|
19
19
|
bucket = reader.get_bucket :region => region
|
20
20
|
|
21
|
-
|
21
|
+
key_name = reader.key_name
|
22
22
|
|
23
23
|
if bucket
|
24
|
-
@logger.debug "Destroying 's3://#{bucket}/#{@name}/#{
|
24
|
+
@logger.debug "Destroying 's3://#{bucket}/#{@name}/#{key_name}'."
|
25
25
|
|
26
26
|
s3_destroyer = Destroyer::S3.new :config => @config,
|
27
27
|
:region => region
|
28
28
|
|
29
|
-
s3_destroyer.destroy_file :key_name =>
|
29
|
+
s3_destroyer.destroy_file :key_name => key_name,
|
30
30
|
:bucket => bucket,
|
31
31
|
:key_folder => @name
|
32
32
|
end
|
@@ -12,8 +12,8 @@ module Heirloom
|
|
12
12
|
def download(args)
|
13
13
|
@region = args[:region]
|
14
14
|
@bucket_prefix = args[:bucket_prefix]
|
15
|
+
@secret = args[:secret]
|
15
16
|
extract = args[:extract]
|
16
|
-
secret = args[:secret]
|
17
17
|
output = args[:output] ||= './'
|
18
18
|
|
19
19
|
@logger.info "Downloading s3://#{bucket}/#{key} from #{@region}."
|
@@ -28,7 +28,7 @@ module Heirloom
|
|
28
28
|
return false unless raw_archive
|
29
29
|
|
30
30
|
archive = cipher_data.decrypt_data :data => raw_archive,
|
31
|
-
:secret => secret
|
31
|
+
:secret => @secret
|
32
32
|
|
33
33
|
return false unless archive
|
34
34
|
|
@@ -44,12 +44,12 @@ module Heirloom
|
|
44
44
|
|
45
45
|
private
|
46
46
|
|
47
|
-
def file
|
47
|
+
def file
|
48
48
|
"#{@id}.tar.gz"
|
49
49
|
end
|
50
50
|
|
51
51
|
def key
|
52
|
-
"#{@name}/#{
|
52
|
+
@secret ? "#{@name}/#{@id}.tar.gz.gpg" : "#{@name}/#{@id}.tar.gz"
|
53
53
|
end
|
54
54
|
|
55
55
|
def bucket
|
@@ -4,9 +4,9 @@ module Heirloom
|
|
4
4
|
|
5
5
|
def initialize(args)
|
6
6
|
@config = args[:config]
|
7
|
-
@name
|
7
|
+
@name = args[:name]
|
8
|
+
@id = args[:id]
|
8
9
|
@domain = "heirloom_#{@name}"
|
9
|
-
@id = args[:id]
|
10
10
|
@logger = @config.logger
|
11
11
|
end
|
12
12
|
|
@@ -66,21 +66,31 @@ module Heirloom
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
+
def key_name
|
70
|
+
encrypted? ? "#{@id}.tar.gz.gpg" : "#{@id}.tar.gz"
|
71
|
+
end
|
72
|
+
|
69
73
|
private
|
70
74
|
|
75
|
+
def encrypted?
|
76
|
+
show['encrypted'] == 'true'
|
77
|
+
end
|
78
|
+
|
71
79
|
def domain_exists?
|
72
80
|
sdb.domain_exists? @domain
|
73
81
|
end
|
74
82
|
|
75
83
|
def get_url(args)
|
84
|
+
region = args[:region]
|
85
|
+
|
76
86
|
return nil unless exists?
|
77
|
-
@logger.debug "Looking for #{
|
78
|
-
url = "#{
|
87
|
+
@logger.debug "Looking for #{region} endpoint for #{@id}"
|
88
|
+
url = "#{region}-s3-url"
|
79
89
|
if show[url]
|
80
90
|
@logger.debug "Found #{url} for #{@id}."
|
81
91
|
show[url]
|
82
92
|
else
|
83
|
-
@logger.debug "#{
|
93
|
+
@logger.debug "#{region} endpoint for #{@id} not found."
|
84
94
|
nil
|
85
95
|
end
|
86
96
|
end
|
@@ -4,16 +4,19 @@ module Heirloom
|
|
4
4
|
|
5
5
|
def initialize(args)
|
6
6
|
@config = args[:config]
|
7
|
-
@name
|
8
|
-
@id
|
7
|
+
@name = args[:name]
|
8
|
+
@id = args[:id]
|
9
9
|
@logger = @config.logger
|
10
10
|
end
|
11
11
|
|
12
12
|
def upload(args)
|
13
|
-
heirloom_file
|
14
|
-
bucket_prefix
|
15
|
-
regions
|
13
|
+
heirloom_file = args[:file]
|
14
|
+
bucket_prefix = args[:bucket_prefix]
|
15
|
+
regions = args[:regions]
|
16
16
|
public_readable = args[:public_readable]
|
17
|
+
secret = args[:secret]
|
18
|
+
|
19
|
+
key_name = secret ? "#{@id}.tar.gz.gpg" : "#{@id}.tar.gz"
|
17
20
|
|
18
21
|
regions.each do |region|
|
19
22
|
bucket = "#{bucket_prefix}-#{region}"
|
@@ -26,13 +29,14 @@ module Heirloom
|
|
26
29
|
:file => heirloom_file,
|
27
30
|
:id => @id,
|
28
31
|
:key_folder => @name,
|
29
|
-
:key_name =>
|
32
|
+
:key_name => key_name,
|
30
33
|
:name => @name,
|
31
34
|
:public_readable => public_readable
|
32
35
|
|
33
|
-
s3_uploader.add_endpoint_attributes :bucket
|
34
|
-
:id
|
35
|
-
:name
|
36
|
+
s3_uploader.add_endpoint_attributes :bucket => bucket,
|
37
|
+
:id => @id,
|
38
|
+
:name => @name,
|
39
|
+
:key_name => key_name
|
36
40
|
end
|
37
41
|
@logger.info "Upload complete."
|
38
42
|
end
|
data/lib/heirloom/cipher.rb
CHANGED
data/lib/heirloom/cipher/data.rb
CHANGED
@@ -1,36 +1,54 @@
|
|
1
|
-
require '
|
1
|
+
require 'tempfile'
|
2
2
|
|
3
3
|
module Heirloom
|
4
4
|
module Cipher
|
5
5
|
class Data
|
6
6
|
|
7
|
+
include Heirloom::Cipher::Shared
|
8
|
+
|
7
9
|
def initialize(args)
|
8
10
|
@config = args[:config]
|
9
11
|
@logger = @config.logger
|
10
12
|
end
|
11
13
|
|
12
14
|
def decrypt_data(args)
|
13
|
-
data = args[:data]
|
14
|
-
secret = args[:secret]
|
15
|
-
|
16
|
-
return data unless args[:secret]
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
@
|
21
|
-
|
22
|
-
@
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
15
|
+
@data = args[:data]
|
16
|
+
@secret = args[:secret]
|
17
|
+
|
18
|
+
return @data unless args[:secret]
|
19
|
+
return false unless gpg_in_path?
|
20
|
+
|
21
|
+
@encrypted_file = Tempfile.new('archive.tar.gz.gpg')
|
22
|
+
@decrypted_file = Tempfile.new('archive.tar.gz')
|
23
|
+
|
24
|
+
::File.open(@encrypted_file, 'w') { |f| f.write @data }
|
25
|
+
|
26
|
+
decrypt
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def decrypt
|
32
|
+
@logger.info "Secret provided. Decrypting with: '#{command}'"
|
33
|
+
output = `#{command(@secret)}`
|
34
|
+
@logger.debug "Decryption output: '#{output}'"
|
35
|
+
|
36
|
+
if $?.success?
|
37
|
+
@decrypted_file.read
|
38
|
+
else
|
39
|
+
@logger.error "Decryption failed with output: '#{output}'"
|
31
40
|
false
|
32
41
|
end
|
33
42
|
end
|
43
|
+
|
44
|
+
def command(secret='XXXXXXXX')
|
45
|
+
"gpg --batch --yes --cipher-algo AES256 --passphrase #{secret} --output #{@decrypted_file.path} #{@encrypted_file.path} 2>&1"
|
46
|
+
end
|
47
|
+
|
48
|
+
def logger
|
49
|
+
@logger
|
50
|
+
end
|
51
|
+
|
34
52
|
end
|
35
53
|
end
|
36
54
|
end
|
data/lib/heirloom/cipher/file.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'openssl'
|
2
1
|
require 'tempfile'
|
3
2
|
require 'fileutils'
|
4
3
|
|
@@ -6,45 +5,47 @@ module Heirloom
|
|
6
5
|
module Cipher
|
7
6
|
class File
|
8
7
|
|
8
|
+
include Heirloom::Cipher::Shared
|
9
|
+
|
9
10
|
def initialize(args)
|
10
11
|
@config = args[:config]
|
11
|
-
@
|
12
|
+
@logger = @config.logger
|
12
13
|
end
|
13
14
|
|
14
15
|
def encrypt_file(args)
|
15
16
|
@file = args[:file]
|
17
|
+
@secret = args[:secret]
|
16
18
|
@encrypted_file = Tempfile.new('archive.tar.gz.enc')
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
@aes.encrypt
|
21
|
-
@aes.iv = iv
|
22
|
-
@aes.key = Digest::SHA256.hexdigest secret
|
23
|
-
|
24
|
-
# Need to refactor to be less complex
|
25
|
-
# Additionally tests to do fully cover logic
|
26
|
-
::File.open(@encrypted_file,'w') do |enc|
|
27
|
-
enc << iv
|
28
|
-
::File.open(@file) do |f|
|
29
|
-
loop do
|
30
|
-
r = f.read(4096)
|
31
|
-
break unless r
|
32
|
-
enc << @aes.update(r)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
enc << @aes.final
|
36
|
-
end
|
19
|
+
|
20
|
+
return false unless gpg_in_path?
|
21
|
+
return false unless encrypt
|
37
22
|
|
38
23
|
replace_file
|
39
24
|
end
|
40
25
|
|
41
26
|
private
|
42
27
|
|
28
|
+
def encrypt
|
29
|
+
@logger.info "Encrypting with: '#{command}'"
|
30
|
+
output = `#{command(@secret)}`
|
31
|
+
@logger.debug "Encryption output: '#{output}'"
|
32
|
+
@logger.error "Encryption failed with output: '#{output}'" unless $?.success?
|
33
|
+
$?.success?
|
34
|
+
end
|
35
|
+
|
36
|
+
def command(secret="XXXXXXXX")
|
37
|
+
"gpg --batch --yes -c --cipher-algo AES256 --passphrase #{secret} --output #{@encrypted_file.path} #{@file} 2>&1"
|
38
|
+
end
|
39
|
+
|
43
40
|
def replace_file
|
44
41
|
FileUtils.mv @encrypted_file.path, @file
|
45
42
|
@encrypted_file.close!
|
46
43
|
end
|
47
44
|
|
45
|
+
def logger
|
46
|
+
@logger
|
47
|
+
end
|
48
|
+
|
48
49
|
end
|
49
50
|
end
|
50
51
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module Heirloom
|
4
|
+
module Cipher
|
5
|
+
module Shared
|
6
|
+
|
7
|
+
include Heirloom::Utils::File
|
8
|
+
|
9
|
+
def gpg_in_path?
|
10
|
+
unless which('gpg')
|
11
|
+
@logger.error "gpg not found in path."
|
12
|
+
return false
|
13
|
+
end
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/heirloom/cli/upload.rb
CHANGED
@@ -2,6 +2,8 @@ module Heirloom
|
|
2
2
|
|
3
3
|
class Directory
|
4
4
|
|
5
|
+
include Heirloom::Utils::File
|
6
|
+
|
5
7
|
def initialize(args)
|
6
8
|
@config = args[:config]
|
7
9
|
@exclude = args[:exclude]
|
@@ -25,6 +27,7 @@ module Heirloom
|
|
25
27
|
private
|
26
28
|
|
27
29
|
def build_archive
|
30
|
+
return false unless tar_in_path?
|
28
31
|
command = "cd #{@path} && tar czf #{@file} #{files_to_pack}"
|
29
32
|
@logger.info "Archiving with: `#{command}`"
|
30
33
|
output = `#{command}`
|
@@ -39,8 +42,16 @@ module Heirloom
|
|
39
42
|
:secret => @secret
|
40
43
|
end
|
41
44
|
|
45
|
+
def tar_in_path?
|
46
|
+
unless which('tar')
|
47
|
+
@logger.error "tar not found in path."
|
48
|
+
return false
|
49
|
+
end
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
42
53
|
def files_to_pack
|
43
|
-
(Dir.entries(@path) - ['.', '..'] - @exclude).map do |file|
|
54
|
+
@files_to_pack ||= (Dir.entries(@path) - ['.', '..'] - @exclude).map do |file|
|
44
55
|
"'#{file}'"
|
45
56
|
end.join(' ')
|
46
57
|
end
|