heirloom 0.11.0.beta.1 → 0.11.0.beta.2

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.
@@ -8,6 +8,7 @@
8
8
  * Updated catalog output to include s3 urls
9
9
  * Catalog output renamed Bucket Prefix to bucket_prefix
10
10
  * Catalog output renamed Region to region
11
+ * Add `rotate` command to allow for encryption key rotation
11
12
 
12
13
  ## 0.10.1 (02/28/2013):
13
14
 
data/README.md CHANGED
@@ -26,7 +26,7 @@ To get started, copy the sample below to ~/.heirloom.yml and update the specifie
26
26
 
27
27
  ```
28
28
  # default environment
29
- aws:
29
+ default:
30
30
  access_key: UPDATE_ME
31
31
  secret_key: UPDATE_ME
32
32
  metadata_region: us-west-1
@@ -9,6 +9,7 @@ require "heirloom/config"
9
9
  require "heirloom/destroyer"
10
10
  require "heirloom/directory"
11
11
  require "heirloom/downloader"
12
+ require "heirloom/exceptions"
12
13
  require "heirloom/logger"
13
14
  require "heirloom/uploader"
14
15
  require "heirloom/version"
@@ -1,16 +1,16 @@
1
- require 'heirloom/archive/lister.rb'
2
- require 'heirloom/archive/reader.rb'
1
+ require 'heirloom/archive/authorizer.rb'
3
2
  require 'heirloom/archive/builder.rb'
4
- require 'heirloom/archive/updater.rb'
5
- require 'heirloom/archive/uploader.rb'
3
+ require 'heirloom/archive/checker.rb'
4
+ require 'heirloom/archive/destroyer.rb'
6
5
  require 'heirloom/archive/downloader.rb'
6
+ require 'heirloom/archive/lister.rb'
7
+ require 'heirloom/archive/reader.rb'
7
8
  require 'heirloom/archive/setuper.rb'
8
9
  require 'heirloom/archive/teardowner.rb'
9
- require 'heirloom/archive/writer.rb'
10
- require 'heirloom/archive/authorizer.rb'
11
- require 'heirloom/archive/destroyer.rb'
10
+ require 'heirloom/archive/updater.rb'
11
+ require 'heirloom/archive/uploader.rb'
12
12
  require 'heirloom/archive/verifier.rb'
13
- require 'heirloom/archive/checker.rb'
13
+ require 'heirloom/archive/writer.rb'
14
14
 
15
15
  module Heirloom
16
16
 
@@ -79,6 +79,23 @@ module Heirloom
79
79
  reader.show.merge reader.object_acls
80
80
  end
81
81
 
82
+ def rotate(args)
83
+ temp_dir = Dir.mktmpdir
84
+ temp_file = Tempfile.new('archive.tar.gz')
85
+
86
+ unless download({ :output => temp_dir, :secret => args[:old_secret], :extract => true }.merge(args))
87
+ raise Heirloom::Exceptions::RotateFailed.new "Download failed - aborting rotation"
88
+ end
89
+ unless build({ :directory => temp_dir, :secret => args[:new_secret], :file => temp_file.path }.merge(args))
90
+ raise Heirloom::Exceptions::RotateFailed.new "Build failed - aborting rotation"
91
+ end
92
+ destroy
93
+ upload({ :file => temp_file.path, :secret => args[:new_secret] }.merge(args))
94
+ ensure
95
+ temp_file.close!
96
+ FileUtils.remove_entry temp_dir
97
+ end
98
+
82
99
  def list(limit=10)
83
100
  lister.list(limit)
84
101
  end
@@ -1,18 +1,20 @@
1
1
  require 'json'
2
2
  require 'trollop'
3
3
 
4
+ require 'heirloom/cli/formatter'
4
5
  require 'heirloom/cli/shared'
6
+
5
7
  require 'heirloom/cli/authorize'
6
8
  require 'heirloom/cli/catalog'
7
- require 'heirloom/cli/upload'
8
- require 'heirloom/cli/setup'
9
+ require 'heirloom/cli/destroy'
10
+ require 'heirloom/cli/download'
9
11
  require 'heirloom/cli/list'
12
+ require 'heirloom/cli/rotate'
13
+ require 'heirloom/cli/setup'
10
14
  require 'heirloom/cli/show'
11
15
  require 'heirloom/cli/tag'
12
- require 'heirloom/cli/download'
13
- require 'heirloom/cli/destroy'
14
16
  require 'heirloom/cli/teardown'
15
- require 'heirloom/cli/formatter'
17
+ require 'heirloom/cli/upload'
16
18
 
17
19
  module Heirloom
18
20
  module CLI
@@ -30,15 +32,17 @@ module Heirloom
30
32
  CLI::Download.new.download
31
33
  when 'list'
32
34
  CLI::List.new.list
35
+ when 'rotate'
36
+ CLI::Rotate.new.rotate
33
37
  when 'setup'
34
38
  CLI::Setup.new.setup
35
39
  when 'show'
36
40
  CLI::Show.new.show
41
+ when 'tag', 'update'
42
+ CLI::Tag.new.tag
37
43
  when 'teardown'
38
44
  CLI::Teardown.new.teardown
39
- when 'update', 'tag'
40
- CLI::Tag.new.tag
41
- when 'build', 'upload'
45
+ when 'upload', 'build'
42
46
  CLI::Upload.new.upload
43
47
  when '-v'
44
48
  puts Heirloom::VERSION
@@ -0,0 +1,82 @@
1
+ module Heirloom
2
+ module CLI
3
+ class Rotate
4
+
5
+ include Heirloom::CLI::Shared
6
+
7
+ def initialize
8
+ @opts = read_options
9
+ @logger = HeirloomLogger.new :log_level => @opts[:level]
10
+ @config = load_config :logger => @logger,
11
+ :opts => @opts
12
+
13
+ ensure_valid_options :provided => @opts,
14
+ :required => [:name, :id, :old_secret, :new_secret],
15
+ :config => @config
16
+
17
+ @catalog = Heirloom::Catalog.new :name => @opts[:name],
18
+ :config => @config
19
+
20
+ @archive = Archive.new :name => @opts[:name],
21
+ :config => @config,
22
+ :id => @opts[:id]
23
+
24
+ unless @opts[:bucket_prefix]
25
+ ensure_archive_exists :archive => @archive,
26
+ :config => @config
27
+ end
28
+
29
+ # Lookup upload regions, metadata region, and bucket_prefix from simpledb unless specified
30
+ @opts[:regions] ||= @catalog.regions
31
+ @opts[:region] ||= @catalog.regions.first
32
+ @opts[:bucket_prefix] ||= @catalog.bucket_prefix
33
+ end
34
+
35
+ def rotate
36
+ @archive.rotate @opts
37
+ rescue Heirloom::Exceptions::RotateFailed => e
38
+ @config.logger.error e.message
39
+ exit 1
40
+ end
41
+
42
+ private
43
+
44
+ def read_options
45
+ Trollop::options do
46
+ version Heirloom::VERSION
47
+ banner <<-EOS
48
+
49
+ Rotate keys for an Heirloom.
50
+
51
+ Will download the heirloom to temp directory, decrypt, encrypt, and upload, replacing original.
52
+
53
+ Usage:
54
+
55
+ heirloom rotate -n NAME -i ID --new-secret MY_NEW_SECRET --old-secret MY_OLD_SECRET
56
+
57
+ To rotate Heirloom without looking up details in SimpleDB, specify region (-r) and bucket_prefix (-b) options.
58
+
59
+ EOS
60
+ opt :bucket_prefix, "Bucket prefix of the Heirloom to download.", :type => :string
61
+ opt :help, "Display Help"
62
+ opt :id, "ID of the Heirloom to rotate.", :type => :string
63
+ opt :level, "Log level [debug|info|warn|error].", :type => :string,
64
+ :default => 'info'
65
+ opt :metadata_region, "AWS region to store Heirloom metadata.", :type => :string,
66
+ :default => 'us-west-1'
67
+ opt :name, "Name of Heirloom.", :type => :string
68
+ opt :region, "Region to download Heirloom.", :type => :string,
69
+ :default => 'us-west-1'
70
+ opt :new_secret, "New Secret for encrypted Heirloom.", :type => :string,
71
+ :short => :none
72
+ opt :old_secret, "Old secret for encrypted Heirloom.", :type => :string,
73
+ :short => :none
74
+ opt :aws_access_key, "AWS Access Key ID", :type => :string,
75
+ :short => :none
76
+ opt :aws_secret_key, "AWS Secret Access Key", :type => :string,
77
+ :short => :none
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -6,7 +6,7 @@ module Heirloom
6
6
 
7
7
  def initialize(args)
8
8
  @config = args[:config]
9
- @exclude = args[:exclude]
9
+ @exclude = args[:exclude] ||= []
10
10
  @path = args[:path]
11
11
  @file = args[:file]
12
12
  @logger = @config.logger
@@ -1,5 +1,6 @@
1
- module Stackster
1
+ module Heirloom
2
2
  module Exceptions
3
+
3
4
  class Base < RuntimeError
4
5
  attr_accessor :message
5
6
 
@@ -7,5 +8,9 @@ module Stackster
7
8
  @message = message
8
9
  end
9
10
  end
11
+
12
+ class RotateFailed < Base
13
+ end
14
+
10
15
  end
11
16
  end
@@ -1,3 +1,3 @@
1
1
  module Heirloom
2
- VERSION = "0.11.0.beta.1"
2
+ VERSION = "0.11.0.beta.2"
3
3
  end
@@ -3,7 +3,8 @@ require 'spec_helper'
3
3
  describe Heirloom do
4
4
 
5
5
  before do
6
- @config_mock = mock 'config'
6
+ @logger_mock = mock 'logger', :info => true, :debug => true, :error => true
7
+ @config_mock = mock 'config', :logger => @logger_mock
7
8
  @archive = Heirloom::Archive.new :config => @config_mock,
8
9
  :name => 'chef',
9
10
  :id => '123'
@@ -223,4 +224,83 @@ describe Heirloom do
223
224
  end
224
225
 
225
226
  end
227
+
228
+ context "rotate" do
229
+ before do
230
+
231
+ @tmp_dir = '/path/to/temp/dir'
232
+ Dir.stub(:mktmpdir).and_return @tmp_dir
233
+
234
+ @tmp_file = mock 'file'
235
+ @tmp_file.stub :path => '/path/to/tmp/file', :close! => true
236
+ Tempfile.stub :new => @tmp_file
237
+ FileUtils.stub :remove_entry => true
238
+
239
+ end
240
+
241
+ it "should rotate an archive by downloading and re-uploading" do
242
+
243
+ @archive.should_receive(:download).
244
+ with(hash_including(:output => @tmp_dir,
245
+ :secret => "oldpassword",
246
+ :extract => true)).
247
+ and_return true
248
+ @archive.should_receive(:build).
249
+ with(hash_including(:directory => @tmp_dir,
250
+ :secret => "newpassword",
251
+ :file => @tmp_file.path)).
252
+ and_return true
253
+ @archive.should_receive(:destroy).with(no_args)
254
+ @archive.should_receive(:upload).
255
+ with(hash_including(:secret => "newpassword",
256
+ :file => @tmp_file.path))
257
+
258
+ @archive.rotate({ :new_secret => "newpassword", :old_secret => "oldpassword" })
259
+ end
260
+
261
+ context "failing download" do
262
+
263
+ before do
264
+ @archive.stub :download => false, :build => true, :destroy => nil, :upload => true
265
+ end
266
+
267
+ it "should raise an exception when download fails" do
268
+ expect {
269
+ @archive.rotate({ :new_secret => "new", :old_secret => "old" })
270
+ }.to raise_error Heirloom::Exceptions::RotateFailed
271
+ end
272
+
273
+ it "should not destroy the file when download fails" do
274
+ @archive.should_not_receive(:destroy)
275
+ begin
276
+ @archive.rotate({ :new_secret => "new", :old_secret => "old" })
277
+ rescue Heirloom::Exceptions::RotateFailed
278
+ end
279
+ end
280
+
281
+ end
282
+
283
+ context "failing build" do
284
+
285
+ before do
286
+ @archive.stub :download => true, :build => false, :destroy => nil, :upload => true
287
+ end
288
+
289
+ it "should raise an exception when build fails" do
290
+ expect {
291
+ @archive.rotate({ :new_secret => "new", :old_secret => "old" })
292
+ }.to raise_error Heirloom::Exceptions::RotateFailed
293
+ end
294
+
295
+ it "should not destroy the file when build fails" do
296
+ @archive.should_not_receive(:destroy)
297
+ begin
298
+ @archive.rotate({ :new_secret => "new", :old_secret => "old" })
299
+ rescue Heirloom::Exceptions::RotateFailed
300
+ end
301
+ end
302
+
303
+ end
304
+
305
+ end
226
306
  end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+ require 'heirloom/cli'
3
+
4
+ describe Heirloom do
5
+
6
+ before do
7
+
8
+ options = { :name => 'archive_name',
9
+ :id => '1.0.0',
10
+ :bucket_prefix => 'bp',
11
+ :old_secret => 'oldpassword',
12
+ :new_secret => 'newpassword',
13
+ :aws_access_key => 'key',
14
+ :aws_secret_key => 'secret' }
15
+ Trollop.stub(:options).and_return options
16
+
17
+ catalog_stub = stub :regions => ['us-east-1', 'us-west-1']
18
+ Heirloom::Catalog.stub(:new).and_return catalog_stub
19
+
20
+ @archive_mock = mock 'archive'
21
+ Heirloom::Archive.stub(:new).and_return @archive_mock
22
+
23
+ end
24
+
25
+ it "should delegate to archive object" do
26
+
27
+ @archive_mock.should_receive :rotate
28
+
29
+ Heirloom::CLI::Rotate.new.rotate
30
+
31
+ end
32
+
33
+ it "should log and do a SystemExit when a rotate fails" do
34
+
35
+ @archive_mock.stub(:rotate).and_raise Heirloom::Exceptions::RotateFailed.new("failed")
36
+
37
+ @logger_mock = mock 'logger'
38
+ Heirloom::HeirloomLogger.stub :new => @logger_mock
39
+
40
+ @logger_mock.should_receive(:error).with "failed"
41
+ expect {
42
+ Heirloom::CLI::Rotate.new.rotate
43
+ }.to raise_error SystemExit
44
+
45
+ end
46
+
47
+ end
@@ -91,6 +91,23 @@ describe Heirloom::Directory do
91
91
  end
92
92
  end
93
93
 
94
+ context "parameter validation" do
95
+ before do
96
+ Dir.stub(:entries).and_return ['pack_me', 'dont_pack_me']
97
+ end
98
+
99
+ it "should not fail if exclude is nil" do
100
+ @directory = Heirloom::Directory.new :config => @config_mock,
101
+ :exclude => nil,
102
+ :path => '/dir',
103
+ :file => '/tmp/file.tar.gz'
104
+ @directory.stub(:`).and_return 'cmd output'
105
+ lambda {
106
+ @directory.build_artifact_from_directory(:exclude => nil)
107
+ }.should_not raise_error
108
+ end
109
+ end
110
+
94
111
  end
95
112
 
96
113
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heirloom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0.beta.1
4
+ version: 0.11.0.beta.2
5
5
  prerelease: 7
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-10 00:00:00.000000000 Z
12
+ date: 2013-04-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -150,6 +150,7 @@ files:
150
150
  - lib/heirloom/cli/formatter/catalog.rb
151
151
  - lib/heirloom/cli/formatter/show.rb
152
152
  - lib/heirloom/cli/list.rb
153
+ - lib/heirloom/cli/rotate.rb
153
154
  - lib/heirloom/cli/setup.rb
154
155
  - lib/heirloom/cli/shared.rb
155
156
  - lib/heirloom/cli/show.rb
@@ -204,6 +205,7 @@ files:
204
205
  - spec/cli/formatter/catalog_spec.rb
205
206
  - spec/cli/formatter/show_spec.rb
206
207
  - spec/cli/list_spec.rb
208
+ - spec/cli/rotate_spec.rb
207
209
  - spec/cli/setup_spec.rb
208
210
  - spec/cli/shared_spec.rb
209
211
  - spec/cli/show_spec.rb
@@ -233,7 +235,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
233
235
  version: '0'
234
236
  segments:
235
237
  - 0
236
- hash: -822415306799597358
238
+ hash: -211146683438990673
237
239
  required_rubygems_version: !ruby/object:Gem::Requirement
238
240
  none: false
239
241
  requirements:
@@ -280,6 +282,7 @@ test_files:
280
282
  - spec/cli/formatter/catalog_spec.rb
281
283
  - spec/cli/formatter/show_spec.rb
282
284
  - spec/cli/list_spec.rb
285
+ - spec/cli/rotate_spec.rb
283
286
  - spec/cli/setup_spec.rb
284
287
  - spec/cli/shared_spec.rb
285
288
  - spec/cli/show_spec.rb