heirloom 0.5.0rc3 → 0.5.0rc4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +11 -4
- data/README.md +3 -1
- data/heirloom.gemspec +3 -4
- data/lib/heirloom/archive.rb +15 -4
- data/lib/heirloom/archive/authorizer.rb +20 -3
- data/lib/heirloom/archive/builder.rb +2 -1
- data/lib/heirloom/archive/destroyer.rb +9 -2
- data/lib/heirloom/archive/setuper.rb +48 -0
- data/lib/heirloom/archive/verifier.rb +20 -10
- data/lib/heirloom/aws/s3.rb +7 -0
- data/lib/heirloom/cipher/data.rb +5 -2
- data/lib/heirloom/cipher/file.rb +1 -1
- data/lib/heirloom/cli.rb +14 -14
- data/lib/heirloom/cli/authorize.rb +3 -1
- data/lib/heirloom/cli/destroy.rb +1 -1
- data/lib/heirloom/cli/shared.rb +8 -9
- data/lib/heirloom/cli/{update.rb → tag.rb} +14 -9
- data/lib/heirloom/cli/{build.rb → upload.rb} +22 -25
- data/lib/heirloom/directory/directory.rb +2 -2
- data/lib/heirloom/uploader/s3.rb +2 -2
- data/lib/heirloom/version.rb +1 -1
- data/spec/archive/authorizer_spec.rb +14 -4
- data/spec/archive/builder_spec.rb +12 -5
- data/spec/archive/destroyer_spec.rb +24 -14
- data/spec/archive/setup_spec.rb +66 -0
- data/spec/archive/verifier_spec.rb +54 -22
- data/spec/archive/writer_spec.rb +2 -2
- data/spec/archive_spec.rb +3 -2
- data/spec/aws/s3_spec.rb +16 -0
- data/spec/cipher/data_spec.rb +3 -3
- data/spec/cipher/file_spec.rb +4 -3
- data/spec/cli/authorize_spec.rb +9 -2
- data/spec/cli/destroy_spec.rb +1 -1
- data/spec/cli/shared_spec.rb +2 -1
- data/spec/cli/{update_spec.rb → tag_spec.rb} +19 -13
- data/spec/cli/{build_spec.rb → upload_spec.rb} +26 -26
- data/spec/directory/directory_spec.rb +4 -2
- metadata +26 -34
data/CHANGELOG
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
* Verify domain exists for all cmds except build & download
|
4
4
|
* Removing requirement to check simpledb on download.
|
5
|
-
* Adding requirement for
|
5
|
+
* Adding requirement for base on download.
|
6
6
|
* Fix error when .heirloom.yml does not exist.
|
7
7
|
* Refactor cli option validation
|
8
8
|
* Refactor cli specs
|
@@ -13,9 +13,16 @@
|
|
13
13
|
* Verify directory given at build is a directory
|
14
14
|
* Support archiving directories outside the cwd.
|
15
15
|
* Fixed bug in git repo verification on build.
|
16
|
-
* Added support for encryption
|
17
|
-
* Removed short name and changed long name for AWS CLI
|
18
|
-
* Adding encrypted attribute by default
|
16
|
+
* Added support for encryption.
|
17
|
+
* Removed short name and changed long name for AWS CLI creds.
|
18
|
+
* Adding encrypted attribute by default for all builds.
|
19
|
+
* Change base_prefix CLI option to base
|
20
|
+
* Changed subcommands build -> upload, update -> tag
|
21
|
+
* Changed tag option updated_value -> value
|
22
|
+
* On upload, Heirloom will attempt to create buckets which do not exist.
|
23
|
+
* Will not destroy the sdb domain when cleanin up old versions on upload.
|
24
|
+
* Hard coding gem versions
|
25
|
+
* Validating email addresses in authorize
|
19
26
|
|
20
27
|
## v0.4.0:
|
21
28
|
|
data/README.md
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
Heirloom
|
2
2
|
========
|
3
3
|
|
4
|
-
|
4
|
+
The goal of Heirloom is to securely and easily transport data to cloud hosted applciations.
|
5
|
+
|
6
|
+
Heirloom creates archives from directories. Their archives are versioned and hosted in geographic distributed locations. Heirloom tracks metadata about those archives, both about the archive locations, as well as arbitrary tags which can be set by an engineer or process. It supports encryption and authorization to allow for securely transporting sensitive data over cloud storage services.
|
5
7
|
|
6
8
|
Installation
|
7
9
|
------------
|
data/heirloom.gemspec
CHANGED
@@ -21,8 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
# specify any dependencies here; for example:
|
22
22
|
s.add_development_dependency "rspec"
|
23
23
|
|
24
|
-
s.add_runtime_dependency 'fog'
|
25
|
-
s.add_runtime_dependency 'grit'
|
26
|
-
s.add_runtime_dependency '
|
27
|
-
s.add_runtime_dependency 'trollop'
|
24
|
+
s.add_runtime_dependency 'fog', '~> 1.5.0'
|
25
|
+
s.add_runtime_dependency 'grit', '~> 2.5.0'
|
26
|
+
s.add_runtime_dependency 'trollop', '= 2.0'
|
28
27
|
end
|
data/lib/heirloom/archive.rb
CHANGED
@@ -4,6 +4,7 @@ require 'heirloom/archive/builder.rb'
|
|
4
4
|
require 'heirloom/archive/updater.rb'
|
5
5
|
require 'heirloom/archive/uploader.rb'
|
6
6
|
require 'heirloom/archive/downloader.rb'
|
7
|
+
require 'heirloom/archive/setuper.rb'
|
7
8
|
require 'heirloom/archive/writer.rb'
|
8
9
|
require 'heirloom/archive/authorizer.rb'
|
9
10
|
require 'heirloom/archive/destroyer.rb'
|
@@ -15,8 +16,8 @@ module Heirloom
|
|
15
16
|
|
16
17
|
def initialize(args)
|
17
18
|
@config = args[:config]
|
18
|
-
@name
|
19
|
-
@id
|
19
|
+
@name = args[:name]
|
20
|
+
@id = args[:id]
|
20
21
|
end
|
21
22
|
|
22
23
|
def authorize(accounts)
|
@@ -36,6 +37,10 @@ module Heirloom
|
|
36
37
|
downloader.download args
|
37
38
|
end
|
38
39
|
|
40
|
+
def setup(args)
|
41
|
+
setuper.setup args
|
42
|
+
end
|
43
|
+
|
39
44
|
def update(args)
|
40
45
|
updater.update args
|
41
46
|
end
|
@@ -56,8 +61,9 @@ module Heirloom
|
|
56
61
|
verifier.domain_exists?
|
57
62
|
end
|
58
63
|
|
59
|
-
def destroy
|
60
|
-
destroyer.destroy :regions
|
64
|
+
def destroy(args)
|
65
|
+
destroyer.destroy :regions => regions,
|
66
|
+
:keep_domain => args[:keep_domain]
|
61
67
|
end
|
62
68
|
|
63
69
|
def show
|
@@ -121,6 +127,11 @@ module Heirloom
|
|
121
127
|
:id => @id
|
122
128
|
end
|
123
129
|
|
130
|
+
def setuper
|
131
|
+
@setuper ||= Setuper.new :config => @config,
|
132
|
+
:name => @name
|
133
|
+
end
|
134
|
+
|
124
135
|
def verifier
|
125
136
|
@verifier ||= Verifier.new :config => @config,
|
126
137
|
:name => @name
|
@@ -10,8 +10,10 @@ module Heirloom
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def authorize(args)
|
13
|
+
@accounts = args[:accounts]
|
13
14
|
regions = args[:regions]
|
14
|
-
|
15
|
+
|
16
|
+
return false unless validate_format_of_accounts
|
15
17
|
|
16
18
|
@logger.info "Authorizing access to artifact."
|
17
19
|
|
@@ -23,15 +25,30 @@ module Heirloom
|
|
23
25
|
|
24
26
|
s3_acl.allow_read_access_from_accounts :key_name => @id,
|
25
27
|
:key_folder => @name,
|
26
|
-
:
|
27
|
-
:
|
28
|
+
:accounts => @accounts,
|
29
|
+
:bucket => bucket
|
28
30
|
end
|
29
31
|
|
30
32
|
@logger.info "Authorization complete."
|
33
|
+
true
|
31
34
|
end
|
32
35
|
|
33
36
|
private
|
34
37
|
|
38
|
+
def validate_format_of_accounts
|
39
|
+
@accounts.each do |account|
|
40
|
+
unless validate_email account
|
41
|
+
@logger.error "#{account} is not a valid email address."
|
42
|
+
return false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def validate_email email
|
48
|
+
email_pattern = (email =~ /^.*@.*\..*$/)
|
49
|
+
email_pattern.nil? ? false : true
|
50
|
+
end
|
51
|
+
|
35
52
|
def reader
|
36
53
|
@reader ||= Reader.new :config => @config,
|
37
54
|
:name => @name,
|
@@ -13,12 +13,12 @@ module Heirloom
|
|
13
13
|
@domain = "heirloom_#{@name}"
|
14
14
|
@id = args[:id]
|
15
15
|
@logger = @config.logger
|
16
|
-
sdb.create_domain @domain
|
17
16
|
end
|
18
17
|
|
19
18
|
def build(args)
|
20
19
|
@source = args[:directory] ||= '.'
|
21
20
|
@secret = args[:secret]
|
21
|
+
@base = args[:base]
|
22
22
|
|
23
23
|
directory = Directory.new :path => @source,
|
24
24
|
:exclude => args[:exclude],
|
@@ -68,6 +68,7 @@ module Heirloom
|
|
68
68
|
attributes = { 'built_by' => "#{user}@#{hostname}",
|
69
69
|
'built_at' => Time.now.utc.iso8601,
|
70
70
|
'encrypted' => encrypted?,
|
71
|
+
'base' => @base,
|
71
72
|
'id' => @id }
|
72
73
|
@logger.info "Create artifact record #{@id}."
|
73
74
|
sdb.put_attributes @domain, @id, attributes
|
@@ -12,6 +12,7 @@ module Heirloom
|
|
12
12
|
|
13
13
|
def destroy(args)
|
14
14
|
regions = args[:regions]
|
15
|
+
keep_domain = args[:keep_domain]
|
15
16
|
|
16
17
|
@logger.info "Destroying #{@name} - #{@id}"
|
17
18
|
|
@@ -34,6 +35,13 @@ module Heirloom
|
|
34
35
|
|
35
36
|
sdb.delete @domain, @id
|
36
37
|
|
38
|
+
destroy_domain unless keep_domain
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def destroy_domain
|
44
|
+
|
37
45
|
# Simple DB is eventually consisten
|
38
46
|
# Sleep for 3 sec for changes to reflect
|
39
47
|
Kernel.sleep 3
|
@@ -42,11 +50,10 @@ module Heirloom
|
|
42
50
|
@logger.info "Domain #{@domain} empty. Destroying."
|
43
51
|
sdb.delete_domain @domain
|
44
52
|
end
|
53
|
+
|
45
54
|
@logger.info "Destroy complete."
|
46
55
|
end
|
47
56
|
|
48
|
-
private
|
49
|
-
|
50
57
|
def sdb
|
51
58
|
@sdb ||= AWS::SimpleDB.new :config => @config
|
52
59
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Heirloom
|
2
|
+
|
3
|
+
class Setuper
|
4
|
+
|
5
|
+
def initialize(args)
|
6
|
+
@config = args[:config]
|
7
|
+
@name = args[:name]
|
8
|
+
@domain = "heirloom_#{@name}"
|
9
|
+
@logger = @config.logger
|
10
|
+
end
|
11
|
+
|
12
|
+
def setup(args)
|
13
|
+
@regions = args[:regions]
|
14
|
+
@bucket_prefix = args[:bucket_prefix]
|
15
|
+
create_buckets
|
16
|
+
create_domain
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def create_buckets
|
22
|
+
@regions.each do |region|
|
23
|
+
bucket = "#{@bucket_prefix}-#{region}"
|
24
|
+
|
25
|
+
unless verifier.bucket_exists? :region => region,
|
26
|
+
:bucket_prefix => @bucket_prefix
|
27
|
+
@logger.info "Creating bucket #{bucket} in #{region}."
|
28
|
+
s3 = AWS::S3.new :config => @config,
|
29
|
+
:region => region
|
30
|
+
s3.put_bucket bucket, region
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_domain
|
36
|
+
sdb.create_domain @domain unless verifier.domain_exists?
|
37
|
+
end
|
38
|
+
|
39
|
+
def verifier
|
40
|
+
@verifier ||= Verifier.new :config => @config,
|
41
|
+
:name => @name
|
42
|
+
end
|
43
|
+
|
44
|
+
def sdb
|
45
|
+
@sdb ||= AWS::SimpleDB.new :config => @config
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -14,23 +14,33 @@ module Heirloom
|
|
14
14
|
result = true
|
15
15
|
|
16
16
|
regions.each do |region|
|
17
|
-
|
18
|
-
|
19
|
-
s3 ||= AWS::S3.new :config => @config,
|
20
|
-
:region => region
|
21
|
-
|
22
|
-
if s3.get_bucket bucket
|
23
|
-
@logger.debug "#{bucket} exists in #{region}"
|
24
|
-
else
|
25
|
-
@logger.debug "#{bucket} in #{region} does not exist"
|
17
|
+
unless bucket_exists? :region => region,
|
18
|
+
:bucket_prefix => bucket_prefix
|
26
19
|
result = false
|
27
20
|
end
|
28
|
-
|
29
21
|
end
|
30
22
|
|
31
23
|
result
|
32
24
|
end
|
33
25
|
|
26
|
+
def bucket_exists?(args)
|
27
|
+
bucket_prefix = args[:bucket_prefix]
|
28
|
+
region = args[:region]
|
29
|
+
|
30
|
+
bucket = "#{bucket_prefix}-#{region}"
|
31
|
+
|
32
|
+
s3 ||= AWS::S3.new :config => @config,
|
33
|
+
:region => region
|
34
|
+
|
35
|
+
if s3.get_bucket bucket
|
36
|
+
@logger.debug "Bucket #{bucket} exists in #{region}"
|
37
|
+
true
|
38
|
+
else
|
39
|
+
@logger.debug "Bucket #{bucket} in #{region} does not exist"
|
40
|
+
false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
34
44
|
def domain_exists?
|
35
45
|
domain = "heirloom_#{@name}"
|
36
46
|
sdb.domain_exists? domain
|
data/lib/heirloom/aws/s3.rb
CHANGED
@@ -34,6 +34,13 @@ module Heirloom
|
|
34
34
|
@s3.put_object_acl(bucket, key, grants)
|
35
35
|
end
|
36
36
|
|
37
|
+
def put_bucket(bucket_name, region)
|
38
|
+
region = nil if region == 'us-east-1'
|
39
|
+
options = { 'LocationConstraint' => region,
|
40
|
+
'x-amz-acl' => 'private' }
|
41
|
+
@s3.put_bucket bucket_name, options
|
42
|
+
end
|
43
|
+
|
37
44
|
end
|
38
45
|
end
|
39
46
|
end
|
data/lib/heirloom/cipher/data.rb
CHANGED
@@ -13,17 +13,20 @@ module Heirloom
|
|
13
13
|
data = args[:data]
|
14
14
|
secret = args[:secret]
|
15
15
|
|
16
|
-
return data unless secret
|
16
|
+
return data unless args[:secret]
|
17
17
|
|
18
18
|
@logger.info "Secret provided. Decrypting archive."
|
19
19
|
|
20
20
|
@aes = OpenSSL::Cipher::AES256.new(:CBC)
|
21
21
|
@aes.decrypt
|
22
|
-
@aes.key = secret
|
22
|
+
@aes.key = Digest::SHA256.hexdigest secret
|
23
23
|
@aes.iv = data.slice!(0,16)
|
24
24
|
begin
|
25
25
|
@aes.update(data) + @aes.final
|
26
26
|
rescue OpenSSL::Cipher::CipherError => e
|
27
|
+
if e.message == 'wrong final block length'
|
28
|
+
@logger.error 'This archive does not appear to be encrypted.'
|
29
|
+
end
|
27
30
|
@logger.error "Unable to decrypt archive: '#{e.message}'"
|
28
31
|
false
|
29
32
|
end
|
data/lib/heirloom/cipher/file.rb
CHANGED
data/lib/heirloom/cli.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
require 'trollop'
|
2
1
|
require 'json'
|
2
|
+
require 'trollop'
|
3
3
|
|
4
4
|
require 'heirloom/cli/shared'
|
5
5
|
require 'heirloom/cli/authorize'
|
6
|
-
require 'heirloom/cli/
|
6
|
+
require 'heirloom/cli/upload'
|
7
7
|
require 'heirloom/cli/list'
|
8
8
|
require 'heirloom/cli/show'
|
9
|
-
require 'heirloom/cli/
|
9
|
+
require 'heirloom/cli/tag'
|
10
10
|
require 'heirloom/cli/download'
|
11
11
|
require 'heirloom/cli/destroy'
|
12
12
|
|
@@ -16,25 +16,25 @@ module Heirloom
|
|
16
16
|
cmd = ARGV.shift
|
17
17
|
|
18
18
|
case cmd
|
19
|
-
when 'list'
|
20
|
-
CLI::List.new.list
|
21
|
-
when 'show'
|
22
|
-
CLI::Show.new.show
|
23
|
-
when 'build'
|
24
|
-
CLI::Build.new.build
|
25
19
|
when 'authorize'
|
26
20
|
CLI::Authorize.new.authorize
|
27
|
-
when 'update'
|
28
|
-
CLI::Update.new.update
|
29
|
-
when 'download'
|
30
|
-
CLI::Download.new.download
|
31
21
|
when 'destroy', 'delete'
|
32
22
|
CLI::Destroy.new.destroy
|
23
|
+
when 'download'
|
24
|
+
CLI::Download.new.download
|
25
|
+
when 'list'
|
26
|
+
CLI::List.new.list
|
27
|
+
when 'show'
|
28
|
+
CLI::Show.new.show
|
29
|
+
when 'update', 'tag'
|
30
|
+
CLI::Tag.new.tag
|
31
|
+
when 'build', 'upload'
|
32
|
+
CLI::Upload.new.upload
|
33
33
|
when '-v'
|
34
34
|
puts Heirloom::VERSION
|
35
35
|
else
|
36
36
|
puts "Unkown command: '#{cmd}'." unless cmd == '-h'
|
37
|
-
puts "heirloom [list|show|
|
37
|
+
puts "heirloom [list|show|upload|authorize|tag|download|destroy] OPTIONS"
|
38
38
|
puts "Append -h for help on specific command."
|
39
39
|
end
|
40
40
|
end
|
data/lib/heirloom/cli/destroy.rb
CHANGED
data/lib/heirloom/cli/shared.rb
CHANGED
@@ -15,8 +15,8 @@ module Heirloom
|
|
15
15
|
config = args[:config]
|
16
16
|
secret = args[:secret]
|
17
17
|
logger = config.logger
|
18
|
-
if secret && secret.length
|
19
|
-
logger.error "Secret must be
|
18
|
+
if secret && secret.length < 8
|
19
|
+
logger.error "Secret must be at least 8 characters long."
|
20
20
|
exit 1
|
21
21
|
end
|
22
22
|
end
|
@@ -27,15 +27,14 @@ module Heirloom
|
|
27
27
|
config = args[:config]
|
28
28
|
logger = config.logger
|
29
29
|
|
30
|
-
required << :
|
31
|
-
required << :
|
30
|
+
required << :aws_access_key unless config.access_key
|
31
|
+
required << :aws_secret_key unless config.secret_key
|
32
32
|
|
33
|
-
missing_opts = required.map do |opt|
|
33
|
+
missing_opts = required.sort.map do |opt|
|
34
34
|
case provided[opt]
|
35
|
-
when nil
|
36
|
-
|
37
|
-
|
38
|
-
"Option '#{opt} (-#{opt[0]})' required but not specified."
|
35
|
+
when nil, []
|
36
|
+
pretty_opt = opt.to_s.gsub('_', '-')
|
37
|
+
"Option '#{pretty_opt}' required but not specified."
|
39
38
|
end
|
40
39
|
end
|
41
40
|
|