heirloom 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ module Stackster
2
+ module Exceptions
3
+ class Base < RuntimeError
4
+ attr_accessor :message
5
+
6
+ def initialize(message="")
7
+ @message = message
8
+ end
9
+ end
10
+ end
11
+ end
@@ -9,48 +9,59 @@ module Heirloom
9
9
  end
10
10
 
11
11
  def upload_file(args)
12
- bucket = args[:bucket]
13
- file = args[:file]
14
- id = args[:id]
15
- key_name = args[:key_name]
16
- key_folder = args[:key_folder]
17
- name = args[:name]
12
+ bucket = args[:bucket]
13
+ file = args[:file]
14
+ id = args[:id]
15
+ key_name = args[:key_name]
16
+ key_folder = args[:key_folder]
17
+ name = args[:name]
18
18
  public_readable = args[:public_readable]
19
19
 
20
+ body = File.open file
20
21
  s3_bucket = s3.get_bucket bucket
21
22
 
22
23
  @logger.info "Uploading s3://#{bucket}/#{key_folder}/#{key_name}"
23
24
 
24
25
  s3_bucket.files.create :key => "#{key_folder}/#{key_name}",
25
- :body => File.open(file),
26
+ :body => body,
26
27
  :public => public_readable
28
+ @logger.warn "File is readable by entire Internet." if public_readable
27
29
 
28
- @logger.info "File is readable by the public internet." if public_readable
30
+ body.close
29
31
  end
30
32
 
31
33
  def add_endpoint_attributes(args)
32
- bucket = args[:bucket]
33
- id = args[:id]
34
- name = args[:name]
35
- domain = "heirloom_#{name}"
34
+ bucket = args[:bucket]
35
+ id = args[:id]
36
+ name = args[:name]
37
+ key_name = args[:key_name]
38
+
39
+ domain = "heirloom_#{name}"
36
40
  key_folder = name
37
- key_name = "#{id}.tar.gz"
41
+ endpoint = endpoints[@region]
38
42
 
39
- s3_endpoint = "s3://#{bucket}/#{key_folder}/#{key_name}"
40
- http_endpoint = "http://#{endpoints[@region]}/#{bucket}/#{key_folder}/#{key_name}"
41
- https_endpoint = "https://#{endpoints[@region]}/#{bucket}/#{key_folder}/#{key_name}"
43
+ path = "#{bucket}/#{key_folder}/#{key_name}"
42
44
 
43
- sdb.put_attributes domain, id, { "#{@region}-s3-url" => s3_endpoint }
44
- @logger.info "Adding attribute #{s3_endpoint}."
45
+ end_point_attributes(path).each_pair do |key, value|
46
+ add_endpoint_attribute domain, id, key, value
47
+ end
48
+ end
45
49
 
46
- sdb.put_attributes domain, id, { "#{@region}-http-url" => http_endpoint }
47
- @logger.debug "Adding attribute #{http_endpoint}."
50
+ private
48
51
 
49
- sdb.put_attributes domain, id, { "#{@region}-https-url" => https_endpoint }
50
- @logger.debug "Adding attribute #{https_endpoint}."
52
+ def end_point_attributes(path)
53
+ {
54
+ "#{@region}-s3-url" => "s3://#{path}",
55
+ "#{@region}-http-url" => "http://#{endpoints[@region]}/#{path}",
56
+ "#{@region}-https-url" => "https://#{endpoints[@region]}/#{path}"
57
+ }
51
58
  end
52
59
 
53
- private
60
+ def add_endpoint_attribute(domain, id, key, value)
61
+ sdb.put_attributes domain, id, { key => value }
62
+ @logger.debug "Adding tag #{key}."
63
+ @logger.debug "Adding tag #{value}."
64
+ end
54
65
 
55
66
  def endpoints
56
67
  {
@@ -0,0 +1 @@
1
+ require 'heirloom/utils/file'
@@ -0,0 +1,30 @@
1
+ module Heirloom
2
+ module Utils
3
+ module File
4
+
5
+ def which(cmd)
6
+ exts = pathext ? pathext.split(';') : ['']
7
+ path.split(path_separator).each do |path|
8
+ exts.each { |ext|
9
+ exe = "#{path}/#{cmd}#{ext}"
10
+ return exe if ::File.executable? exe
11
+ }
12
+ end
13
+ return nil
14
+ end
15
+
16
+ def path_separator
17
+ ::File::PATH_SEPARATOR
18
+ end
19
+
20
+ def path
21
+ ENV['PATH']
22
+ end
23
+
24
+ def pathext
25
+ ENV['PATHEXT']
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -1,3 +1,3 @@
1
1
  module Heirloom
2
- VERSION = "0.9.0"
2
+ VERSION = "0.10.0"
3
3
  end
data/spec/acl/s3_spec.rb CHANGED
@@ -29,7 +29,7 @@ describe Heirloom do
29
29
  with("bucket", "key-folder/key.tar.gz", {"Owner"=>{"DisplayName"=>"Brett", "ID"=>"123"}, "AccessControlList"=>[{"Grantee"=>{"EmailAddress"=>"acct1@test.com"}, "Permission"=>"READ"}, {"Grantee"=>{"EmailAddress"=>"acct2@test.com"}, "Permission"=>"READ"}, {"Grantee"=>{"DisplayName"=>"Brett", "ID"=>"123"}, "Permission"=>"FULL_CONTROL"}]})
30
30
 
31
31
  @s3.allow_read_access_from_accounts :bucket => 'bucket',
32
- :key_name => 'key',
32
+ :key_name => 'key.tar.gz',
33
33
  :key_folder => 'key-folder',
34
34
  :accounts => ['acct1@test.com', 'acct2@test.com']
35
35
  end
@@ -3,28 +3,40 @@ require 'spec_helper'
3
3
  describe Heirloom do
4
4
 
5
5
  before do
6
- @config_mock = double('config')
7
- @logger_mock = double('logger')
6
+ @config_mock = mock 'config'
7
+ @logger_mock = mock 'logger'
8
8
  @logger_mock.stub :info => true, :debug => true
9
9
  @config_mock.should_receive(:logger).and_return(@logger_mock)
10
10
  @authorizer = Heirloom::Authorizer.new :config => @config_mock,
11
11
  :name => 'tim',
12
- :id => '123'
12
+ :id => '123.tar.gz'
13
13
  end
14
14
 
15
15
  it "should authorize access to an archive in all regions" do
16
- reader = double
17
- s3_acl = double
18
- accounts = [ "test@a.com", "a@test.com", "test@test.co", "test@test.co.uk" ]
19
- @authorizer.should_receive(:reader).exactly(2).times.
20
- and_return(reader)
21
- reader.should_receive(:get_bucket).exactly(2).times.
16
+ s3_acl_mock = mock 's3 acl'
17
+ reader_mock = mock 'reader mock'
18
+ reader_mock.stub :key_name => '123.tar.gz'
19
+ reader_mock.should_receive(:get_bucket).exactly(2).times.
22
20
  and_return('the-bucket')
23
- Heirloom::ACL::S3.should_receive(:new).exactly(2).
24
- times.and_return(s3_acl)
25
- s3_acl.should_receive(:allow_read_access_from_accounts).
21
+
22
+ accounts = [ "test@a.com", "a@test.com", "test@test.co", "test@test.co.uk" ]
23
+
24
+ Heirloom::Reader.should_receive(:new).
25
+ with(:config => @config_mock,
26
+ :name => 'tim',
27
+ :id => '123.tar.gz').
28
+ and_return reader_mock
29
+ Heirloom::ACL::S3.should_receive(:new).
30
+ with(:config => @config_mock,
31
+ :region => 'us-west-1').
32
+ and_return s3_acl_mock
33
+ Heirloom::ACL::S3.should_receive(:new).
34
+ with(:config => @config_mock,
35
+ :region => 'us-west-2').
36
+ and_return s3_acl_mock
37
+ s3_acl_mock.should_receive(:allow_read_access_from_accounts).
26
38
  exactly(2).times.
27
- with(:key_name => '123',
39
+ with(:key_name => '123.tar.gz',
28
40
  :key_folder => 'tim',
29
41
  :bucket => 'the-bucket',
30
42
  :accounts => accounts)
@@ -17,7 +17,7 @@ describe Heirloom do
17
17
  @reader_mock.should_receive(:get_bucket).
18
18
  with(:region => 'us-west-1').
19
19
  and_return 'bucket-us-west-1'
20
-
20
+ @reader_mock.stub :key_name => '123.tar.gz'
21
21
 
22
22
  @s3_destroyer_mock = mock 's3 destroyer'
23
23
  Heirloom::Destroyer::S3.should_receive(:new).
@@ -85,7 +85,7 @@ describe Heirloom do
85
85
  before do
86
86
  @s3_downloader_mock.should_receive(:download_file).
87
87
  with(:bucket => 'bucket-us-west-1',
88
- :key => 'tim/123.tar.gz').
88
+ :key => 'tim/123.tar.gz.gpg').
89
89
  and_return 'encrypted_data'
90
90
  Heirloom::Cipher::Data.should_receive(:new).
91
91
  with(:config => @config_mock).
@@ -136,10 +136,10 @@ describe Heirloom do
136
136
  end
137
137
 
138
138
  it "should return false if the decrypt_data returns false" do
139
- @downloader.download(:region => 'us-west-1',
139
+ @downloader.download(:region => 'us-west-1',
140
140
  :bucket_prefix => 'bucket',
141
- :extract => false,
142
- :secret => 'badsecret').should be_false
141
+ :extract => false,
142
+ :secret => 'badsecret').should be_false
143
143
  end
144
144
 
145
145
  end
@@ -52,7 +52,7 @@ describe Heirloom do
52
52
  with("select * from `heirloom_tim` where itemName() = '123'").
53
53
  and_return( { '123' =>
54
54
  { 'us-west-1-s3-url' =>
55
- [ 's3://the-bucket/the-buck/the-key' ]
55
+ [ 's3://the-bucket/the-name/123.tar.gz' ]
56
56
  }
57
57
  } )
58
58
  @reader.get_bucket(:region => 'us-west-1').should == 'the-bucket'
@@ -80,10 +80,24 @@ describe Heirloom do
80
80
  with("select * from `heirloom_tim` where itemName() = '123'").
81
81
  and_return( { '123' =>
82
82
  { 'us-west-1-s3-url' =>
83
- ['s3://the-url/the-bucket/the-key']
83
+ ['s3://the-url/the-bucket/123.tar.gz']
84
84
  }
85
85
  } )
86
- @reader.get_key(:region => 'us-west-1').should == 'the-bucket/the-key'
86
+ @reader.get_key(:region => 'us-west-1').should == 'the-bucket/123.tar.gz'
87
+ end
88
+
89
+ it "should return the encrypted key name" do
90
+ @sdb_mock.should_receive(:select).
91
+ with("select * from `heirloom_tim` where itemName() = '123'").
92
+ and_return( { '123' => { 'encrypted' => [ 'true' ] } } )
93
+ @reader.key_name.should == '123.tar.gz.gpg'
94
+ end
95
+
96
+ it "should return the unencrypted key name" do
97
+ @sdb_mock.should_receive(:select).
98
+ with("select * from `heirloom_tim` where itemName() = '123'").
99
+ and_return( { '123' => { 'encrypted' => [ 'false' ] } } )
100
+ @reader.key_name.should == '123.tar.gz'
87
101
  end
88
102
 
89
103
  it "should return the regions the archive has been uploaded to" do
@@ -92,11 +106,11 @@ describe Heirloom do
92
106
  with("select * from `heirloom_tim` where itemName() = '123'").
93
107
  and_return( { '123' =>
94
108
  { 'us-west-1-s3-url' =>
95
- ['s3://the-url-us-west-1/the-bucket/the-key'],
109
+ ['s3://the-url-us-west-1/the-bucket/123.tar.gz'],
96
110
  'build_by' =>
97
111
  ['user'],
98
112
  'us-east-1-s3-url' =>
99
- ['s3://the-url-us-east-1/the-bucket/the-key']
113
+ ['s3://the-url-us-east-1/the-bucket/123.tar.gz']
100
114
  }
101
115
  } )
102
116
  @reader.regions.should == ['us-west-1', 'us-east-1']
@@ -3,38 +3,65 @@ require 'spec_helper'
3
3
  describe Heirloom do
4
4
 
5
5
  before do
6
- @config_mock = double 'config'
7
- @logger_mock = double 'logger'
8
- @config_mock.should_receive(:logger).and_return(@logger_mock)
6
+ @config_mock = mock 'config'
7
+ @logger_stub = stub 'logger', :info => true
8
+ @config_mock.stub :logger => @logger_stub
9
9
  @uploader = Heirloom::Uploader.new :config => @config_mock,
10
10
  :name => 'tim',
11
11
  :id => '123'
12
+ @s3_mock = mock 's3'
12
13
  end
13
14
 
14
15
  it "should upload a new archive" do
15
- s3_mock = mock 's3'
16
16
  Heirloom::Uploader::S3.should_receive(:new).
17
17
  with(:config => @config_mock,
18
- :logger => @logger_mock,
18
+ :logger => @logger_stub,
19
19
  :region => 'us-west-1').
20
- and_return s3_mock
21
- s3_mock.should_receive(:upload_file).
22
- with(:bucket => 'prefix-us-west-1',
23
- :file => '/tmp/file',
24
- :id => '123',
25
- :key_folder => 'tim',
26
- :key_name => "123.tar.gz",
27
- :name => 'tim',
28
- :public_readable => true)
29
- s3_mock.should_receive(:add_endpoint_attributes).
30
- with(:bucket => 'prefix-us-west-1',
31
- :id => '123',
32
- :name => 'tim')
33
- @logger_mock.should_receive(:info)
20
+ and_return @s3_mock
21
+ @s3_mock.should_receive(:upload_file).
22
+ with(:bucket => 'prefix-us-west-1',
23
+ :file => '/tmp/file',
24
+ :id => '123',
25
+ :key_folder => 'tim',
26
+ :key_name => "123.tar.gz",
27
+ :name => 'tim',
28
+ :public_readable => true)
29
+ @s3_mock.should_receive(:add_endpoint_attributes).
30
+ with(:bucket => 'prefix-us-west-1',
31
+ :id => '123',
32
+ :key_name => '123.tar.gz',
33
+ :name => 'tim')
34
34
  @uploader.upload :file => '/tmp/file',
35
35
  :bucket_prefix => 'prefix',
36
36
  :regions => ['us-west-1'],
37
- :public_readable => true
37
+ :public_readable => true,
38
+ :secret => nil
39
+ end
40
+
41
+ it "should upload a new archive with .gpg if secret provided" do
42
+ Heirloom::Uploader::S3.should_receive(:new).
43
+ with(:config => @config_mock,
44
+ :logger => @logger_stub,
45
+ :region => 'us-west-1').
46
+ and_return @s3_mock
47
+ @s3_mock.should_receive(:upload_file).
48
+ with(:bucket => 'prefix-us-west-1',
49
+ :file => '/tmp/file',
50
+ :id => '123',
51
+ :key_folder => 'tim',
52
+ :key_name => "123.tar.gz.gpg",
53
+ :name => 'tim',
54
+ :public_readable => true)
55
+ @s3_mock.should_receive(:add_endpoint_attributes).
56
+ with(:bucket => 'prefix-us-west-1',
57
+ :id => '123',
58
+ :key_name => '123.tar.gz.gpg',
59
+ :name => 'tim')
60
+ @uploader.upload :file => '/tmp/file',
61
+ :bucket_prefix => 'prefix',
62
+ :regions => ['us-west-1'],
63
+ :public_readable => true,
64
+ :secret => 'secret12'
38
65
  end
39
66
 
40
67
  end
@@ -2,54 +2,71 @@ require 'spec_helper'
2
2
 
3
3
  describe Heirloom do
4
4
  before do
5
+ @encrypted_file_mock = mock 'encrypted mock'
6
+ @decrypted_file_mock = mock 'decrypted mock'
7
+ @encrypted_file_mock.stub :path => '/tmp/enc'
8
+ @decrypted_file_mock.stub :path => '/tmp/dec',
9
+ :read => 'plaintext'
5
10
  @logger_mock = mock 'logger', :info => true
6
- @logger_mock.stub :info => true
11
+ @logger_mock.stub :info => true,
12
+ :debug => true
7
13
  @config_mock = mock 'config'
8
14
  @config_mock.stub :logger => @logger_mock
9
15
  @data = Heirloom::Cipher::Data.new :config => @config_mock
10
16
  end
11
17
 
12
- context "with secret given" do
13
- before do
14
- @aes_mock = mock 'aes'
15
- OpenSSL::Cipher::AES256.should_receive(:new).
16
- with(:CBC).and_return @aes_mock
17
- end
18
+ context "when succesful" do
19
+ context "with secret given" do
20
+ it "should decrypt the given data" do
21
+ @data.should_receive(:which).with('gpg').and_return true
22
+ Tempfile.should_receive(:new).with('archive.tar.gz.gpg').
23
+ and_return @encrypted_file_mock
24
+ Tempfile.should_receive(:new).with('archive.tar.gz').
25
+ and_return @decrypted_file_mock
26
+ ::File.should_receive(:open).
27
+ with(@encrypted_file_mock,'w')
28
+ $?.stub :success? => true
18
29
 
19
- it "should decrypt the given data" do
20
- @aes_mock.should_receive(:decrypt)
21
- @aes_mock.should_receive(:key=).with Digest::SHA256.hexdigest 'mysecret'
22
- @aes_mock.should_receive(:iv=).with 'firstsixteenchar'
23
- @aes_mock.should_receive(:update).with('crypteddata').and_return 'cleartext'
24
- @aes_mock.stub :final => 'final'
25
- @data.decrypt_data(:data => 'firstsixteencharcrypteddata',
26
- :secret => 'mysecret').
27
- should == 'cleartextfinal'
30
+ command = 'gpg --batch --yes --cipher-algo AES256 --passphrase password --output /tmp/dec /tmp/enc 2>&1'
31
+ @data.should_receive(:`).with(command).and_return true
32
+ @data.decrypt_data(:data => 'crypted',
33
+ :secret => 'password').should == 'plaintext'
34
+ end
28
35
  end
29
36
 
30
- it "should rescue bad key error and return false" do
31
- @logger_mock.should_receive(:error).
32
- with "Unable to decrypt Heirloom: 'OpenSSL::Cipher::CipherError'"
33
- @aes_mock.should_receive(:decrypt)
34
- @aes_mock.should_receive(:key=).with Digest::SHA256.hexdigest 'badsecret'
35
- @aes_mock.should_receive(:iv=).with 'firstsixteenchar'
36
- @aes_mock.should_receive(:update).with('crypteddata').and_return 'crap'
37
- @aes_mock.should_receive(:final).and_raise OpenSSL::Cipher::CipherError
38
- @data.decrypt_data(:data => 'firstsixteencharcrypteddata',
39
- :secret => 'badsecret').
40
- should be_false
37
+ context "no secret given" do
38
+ it "should return the data if no secret given" do
39
+ @data.decrypt_data(:data => 'plaintext',
40
+ :secret => nil).should == 'plaintext'
41
+ end
41
42
  end
42
-
43
43
  end
44
44
 
45
- context "no secret given" do
46
- before do
47
- @data = Heirloom::Cipher::Data.new :config => @config_mock
48
- end
45
+ context "when unsuccesful" do
46
+ context "with secret given" do
47
+ it "should return false if gpg not in path" do
48
+ @logger_mock.should_receive(:error)
49
+ @data.should_receive(:which).with('gpg').and_return false
50
+ @data.decrypt_data(:data => 'crypted',
51
+ :secret => 'password').should be_false
52
+ end
53
+
54
+ it "should return false if decrypted fails" do
55
+ @logger_mock.should_receive(:error)
56
+ @data.should_receive(:which).with('gpg').and_return true
57
+ Tempfile.should_receive(:new).with('archive.tar.gz.gpg').
58
+ and_return @encrypted_file_mock
59
+ Tempfile.should_receive(:new).with('archive.tar.gz').
60
+ and_return @decrypted_file_mock
61
+ ::File.should_receive(:open).
62
+ with(@encrypted_file_mock,'w')
63
+ $?.stub :success? => false
49
64
 
50
- it "should return the data if no secret given" do
51
- @data.decrypt_data(:data => 'plaintext',
52
- :secret => nil).should == 'plaintext'
65
+ command = 'gpg --batch --yes --cipher-algo AES256 --passphrase password --output /tmp/dec /tmp/enc 2>&1'
66
+ @data.should_receive(:`).with(command).and_return true
67
+ @data.decrypt_data(:data => 'crypted',
68
+ :secret => 'password').should be_false
69
+ end
53
70
  end
54
71
  end
55
72