heirloom 0.9.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|