heirloom 0.5.0rc2 → 0.5.0rc3

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.
Files changed (40) hide show
  1. data/CHANGELOG +10 -2
  2. data/lib/heirloom.rb +1 -1
  3. data/lib/heirloom/archive.rb +1 -5
  4. data/lib/heirloom/archive/builder.rb +16 -13
  5. data/lib/heirloom/archive/downloader.rb +27 -19
  6. data/lib/heirloom/archive/writer.rb +52 -0
  7. data/lib/heirloom/cipher.rb +2 -0
  8. data/lib/heirloom/cipher/data.rb +33 -0
  9. data/lib/heirloom/cipher/file.rb +41 -0
  10. data/lib/heirloom/cli/authorize.rb +4 -2
  11. data/lib/heirloom/cli/build.rb +17 -12
  12. data/lib/heirloom/cli/destroy.rb +5 -3
  13. data/lib/heirloom/cli/download.rb +15 -10
  14. data/lib/heirloom/cli/list.rb +7 -5
  15. data/lib/heirloom/cli/shared.rb +14 -4
  16. data/lib/heirloom/cli/show.rb +6 -4
  17. data/lib/heirloom/cli/update.rb +4 -2
  18. data/lib/heirloom/config.rb +1 -1
  19. data/lib/heirloom/directory/directory.rb +23 -8
  20. data/lib/heirloom/directory/git_directory.rb +10 -1
  21. data/lib/heirloom/version.rb +1 -1
  22. data/spec/archive/builder_spec.rb +55 -50
  23. data/spec/archive/downloader_spec.rb +91 -37
  24. data/spec/archive/writer_spec.rb +51 -0
  25. data/spec/archive_spec.rb +0 -11
  26. data/spec/aws/simpledb_spec.rb +2 -2
  27. data/spec/cipher/data_spec.rb +56 -0
  28. data/spec/cipher/file_spec.rb +27 -0
  29. data/spec/cli/build_spec.rb +3 -3
  30. data/spec/cli/download_spec.rb +4 -2
  31. data/spec/cli/shared_spec.rb +12 -5
  32. data/spec/config_spec.rb +2 -2
  33. data/spec/directory/directory_spec.rb +39 -10
  34. data/spec/directory/git_directory_spec.rb +29 -15
  35. metadata +23 -20
  36. data/lib/heirloom/archive/extracter.rb +0 -38
  37. data/lib/heirloom/misc.rb +0 -1
  38. data/lib/heirloom/misc/tmp.rb +0 -12
  39. data/spec/archive/extracter_spec.rb +0 -21
  40. data/spec/misc/tmp_spec.rb +0 -19
data/CHANGELOG CHANGED
@@ -1,13 +1,21 @@
1
1
  ## v0.5.0:
2
2
 
3
- * Added check to verify domain exists for all cmds except build
3
+ * Verify domain exists for all cmds except build & download
4
4
  * Removing requirement to check simpledb on download.
5
- * Adding requirement base_prefix on download.
5
+ * Adding requirement for base_prefix on download.
6
6
  * Fix error when .heirloom.yml does not exist.
7
7
  * Refactor cli option validation
8
8
  * Refactor cli specs
9
9
  * Add -x to download to extract heirloom to given output path
10
10
  * Verify -o specified in download is a directory
11
+ * Requiring -d for builds (will no longer default to .)
12
+ * Remove new lines from values of git comments
13
+ * Verify directory given at build is a directory
14
+ * Support archiving directories outside the cwd.
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 Creds
18
+ * Adding encrypted attribute by default
11
19
 
12
20
  ## v0.4.0:
13
21
 
@@ -1,10 +1,10 @@
1
- require "heirloom/misc"
2
1
  require "heirloom/config"
3
2
  require "heirloom/acl"
4
3
  require "heirloom/aws"
5
4
  require "heirloom/logger"
6
5
  require "heirloom/archive"
7
6
  require "heirloom/directory"
7
+ require "heirloom/cipher"
8
8
  require "heirloom/uploader"
9
9
  require "heirloom/downloader"
10
10
  require "heirloom/destroyer"
@@ -4,7 +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/extracter.rb'
7
+ require 'heirloom/archive/writer.rb'
8
8
  require 'heirloom/archive/authorizer.rb'
9
9
  require 'heirloom/archive/destroyer.rb'
10
10
  require 'heirloom/archive/verifier.rb'
@@ -68,10 +68,6 @@ module Heirloom
68
68
  lister.list(limit)
69
69
  end
70
70
 
71
- def cleanup
72
- builder.cleanup
73
- end
74
-
75
71
  def regions
76
72
  reader.regions
77
73
  end
@@ -18,12 +18,15 @@ module Heirloom
18
18
 
19
19
  def build(args)
20
20
  @source = args[:directory] ||= '.'
21
+ @secret = args[:secret]
21
22
 
22
23
  directory = Directory.new :path => @source,
23
24
  :exclude => args[:exclude],
24
25
  :config => @config
25
26
 
26
- return false unless directory.build_artifact_from_directory
27
+ unless directory.build_artifact_from_directory :secret => @secret
28
+ return false
29
+ end
27
30
 
28
31
  @local_build = directory.local_build
29
32
 
@@ -36,11 +39,6 @@ module Heirloom
36
39
  @local_build
37
40
  end
38
41
 
39
- def cleanup
40
- @logger.info "Cleaning up local build #{@local_build}."
41
- File.delete @local_build
42
- end
43
-
44
42
  private
45
43
 
46
44
  def add_git_commit
@@ -49,14 +47,14 @@ module Heirloom
49
47
  if commit
50
48
  add_git_commit_to_artifact_record commit
51
49
  else
52
- @logger.warn "Could not find Git sha: #{@id}."
50
+ @logger.warn "Could not load Git sha '#{@id}' in '#{@source}'."
53
51
  end
54
52
  end
55
53
 
56
54
  def add_git_commit_to_artifact_record(commit)
57
55
  attributes = { 'sha' => @id,
58
56
  'abbreviated_sha' => commit.id_abbrev,
59
- 'message' => commit.message,
57
+ 'message' => commit.message.gsub("\n"," "),
60
58
  'author' => commit.author.name }
61
59
 
62
60
  attributes.each_pair do |k, v|
@@ -67,15 +65,16 @@ module Heirloom
67
65
  end
68
66
 
69
67
  def create_artifact_record
70
- attributes = { 'built_by' => "#{user}@#{hostname}",
71
- 'built_at' => Time.now.utc.iso8601,
72
- 'id' => @id }
68
+ attributes = { 'built_by' => "#{user}@#{hostname}",
69
+ 'built_at' => Time.now.utc.iso8601,
70
+ 'encrypted' => encrypted?,
71
+ 'id' => @id }
73
72
  @logger.info "Create artifact record #{@id}."
74
73
  sdb.put_attributes @domain, @id, attributes
75
74
  end
76
75
 
77
- def sdb
78
- @sdb ||= AWS::SimpleDB.new :config => @config
76
+ def encrypted?
77
+ @secret != nil
79
78
  end
80
79
 
81
80
  def user
@@ -86,5 +85,9 @@ module Heirloom
86
85
  Socket.gethostname
87
86
  end
88
87
 
88
+ def sdb
89
+ @sdb ||= AWS::SimpleDB.new :config => @config
90
+ end
91
+
89
92
  end
90
93
  end
@@ -2,8 +2,6 @@ module Heirloom
2
2
 
3
3
  class Downloader
4
4
 
5
- include Heirloom::Misc::Tmp
6
-
7
5
  def initialize(args)
8
6
  @config = args[:config]
9
7
  @name = args[:name]
@@ -12,31 +10,34 @@ module Heirloom
12
10
  end
13
11
 
14
12
  def download(args)
15
- region = args[:region]
16
- base_prefix = args[:base_prefix]
13
+ @region = args[:region]
14
+ @base_prefix = args[:base_prefix]
17
15
  extract = args[:extract]
16
+ secret = args[:secret]
18
17
  output = args[:output] ||= './'
19
18
 
19
+ @logger.info "Downloading s3://#{bucket}/#{key} from #{@region}."
20
+
20
21
  s3_downloader = Downloader::S3.new :config => @config,
21
22
  :logger => @logger,
22
- :region => region
23
+ :region => @region
23
24
 
24
- bucket = get_bucket :region => region, :base_prefix => base_prefix
25
+ raw_archive = s3_downloader.download_file :bucket => bucket,
26
+ :key => key
25
27
 
26
- @logger.info "Downloading s3://#{bucket}/#{key} from #{region}."
27
- archive = s3_downloader.download_file :bucket => bucket,
28
- :key => key
28
+ archive = cipher_data.decrypt_data :data => raw_archive,
29
+ :secret => secret
29
30
 
30
- if extract
31
- extracter = Extracter.new :config => @config
32
- extracter.extract :archive => archive, :output => output
33
- else
34
- output_file = File.join output, file
35
- @logger.info "Writing archive to '#{output_file}'."
36
- File.open(output_file, 'w') { |local_file| local_file.write archive }
37
- end
31
+ return false unless archive
32
+
33
+ return false unless writer.save_archive :archive => archive,
34
+ :output => output,
35
+ :file => file,
36
+ :extract => extract
38
37
 
39
38
  @logger.info "Download complete."
39
+
40
+ output
40
41
  end
41
42
 
42
43
  private
@@ -49,9 +50,16 @@ module Heirloom
49
50
  "#{@name}/#{file}"
50
51
  end
51
52
 
52
- def get_bucket(args)
53
- "#{args[:base_prefix]}-#{args[:region]}"
53
+ def bucket
54
+ "#{@base_prefix}-#{@region}"
54
55
  end
55
56
 
57
+ def writer
58
+ @writer ||= Writer.new :config => @config
59
+ end
60
+
61
+ def cipher_data
62
+ @cipher_data ||= Cipher::Data.new :config => @config
63
+ end
56
64
  end
57
65
  end
@@ -0,0 +1,52 @@
1
+ module Heirloom
2
+ class Writer
3
+
4
+ def initialize(args)
5
+ @config = args[:config]
6
+ @logger = @config.logger
7
+ end
8
+
9
+ def save_archive(args)
10
+ @output = args[:output]
11
+ @file = args[:file]
12
+ @archive = args[:archive]
13
+ @extract = args[:extract]
14
+
15
+ @extract ? extract_archive : write_archive
16
+ end
17
+
18
+ private
19
+
20
+ def extract_archive
21
+ @tmp_archive = Tempfile.new('archive.tar.gz').path
22
+
23
+ create_tmp_archive
24
+ extract_tmp_archive
25
+ end
26
+
27
+ def write_archive
28
+ output_file = File.join @output, @file
29
+ @logger.info "Writing archive to '#{output_file}'."
30
+ File.open(output_file, 'w') { |local_file| local_file.write @archive }
31
+ end
32
+
33
+ def create_tmp_archive
34
+ File.open(@tmp_archive, 'w') { |local_file| local_file.write @archive }
35
+ end
36
+
37
+ def extract_tmp_archive
38
+ @logger.info "Extracting archive to '#{@output}'."
39
+ cmd = "tar xzf #{@tmp_archive} -C #{@output}"
40
+ @logger.debug "Executing '#{cmd}'."
41
+ `#{cmd}`
42
+ if $?.success?
43
+ @logger.debug "Archive succesfully extracted."
44
+ true
45
+ else
46
+ @logger.error "Error extracting archive."
47
+ false
48
+ end
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,2 @@
1
+ require 'heirloom/cipher/data'
2
+ require 'heirloom/cipher/file'
@@ -0,0 +1,33 @@
1
+ require 'openssl'
2
+
3
+ module Heirloom
4
+ module Cipher
5
+ class Data
6
+
7
+ def initialize(args)
8
+ @config = args[:config]
9
+ @logger = @config.logger
10
+ end
11
+
12
+ def decrypt_data(args)
13
+ data = args[:data]
14
+ secret = args[:secret]
15
+
16
+ return data unless secret
17
+
18
+ @logger.info "Secret provided. Decrypting archive."
19
+
20
+ @aes = OpenSSL::Cipher::AES256.new(:CBC)
21
+ @aes.decrypt
22
+ @aes.key = secret
23
+ @aes.iv = data.slice!(0,16)
24
+ begin
25
+ @aes.update(data) + @aes.final
26
+ rescue OpenSSL::Cipher::CipherError => e
27
+ @logger.error "Unable to decrypt archive: '#{e.message}'"
28
+ false
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,41 @@
1
+ require 'openssl'
2
+ require 'tempfile'
3
+
4
+ module Heirloom
5
+ module Cipher
6
+ class File
7
+
8
+ def initialize(args)
9
+ @config = args[:config]
10
+ @aes = OpenSSL::Cipher::AES256.new(:CBC)
11
+ end
12
+
13
+ def encrypt_file(args)
14
+ file = args[:file]
15
+ secret = args[:secret]
16
+ output = Tempfile.new('archive.tar.gz.enc')
17
+ iv = @aes.random_iv
18
+
19
+ @aes.encrypt
20
+ @aes.iv = iv
21
+ @aes.key = secret
22
+
23
+ # Need to refactor to be less complex
24
+ # Additionally tests to do fully cover logic
25
+ ::File.open(output,'w') do |enc|
26
+ enc << iv
27
+ ::File.open(file) do |f|
28
+ loop do
29
+ r = f.read(4096)
30
+ break unless r
31
+ enc << @aes.update(r)
32
+ end
33
+ end
34
+ enc << @aes.final
35
+ end
36
+ output.path
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -45,11 +45,13 @@ EOS
45
45
  :multi => true
46
46
  opt :help, "Display Help"
47
47
  opt :id, "ID of the archive to authorize.", :type => :string
48
- opt :key, "AWS Access Key", :type => :string
49
48
  opt :level, "Log level [debug|info|warn|error].", :type => :string,
50
49
  :default => 'info'
51
- opt :secret, "AWS Secret Access Key", :type => :string
52
50
  opt :name, "Name of archive.", :type => :string
51
+ opt :aws_access_key, "AWS Access Key ID", :type => :string,
52
+ :short => :none
53
+ opt :aws_secret_key, "AWS Secret Access Key", :type => :string,
54
+ :short => :none
53
55
  end
54
56
  end
55
57
 
@@ -27,19 +27,22 @@ module Heirloom
27
27
  exit 1
28
28
  end
29
29
 
30
+ ensure_directory :path => @opts[:directory], :config => @config
31
+ ensure_valid_secret :secret => @opts[:secret], :config => @config
32
+
30
33
  @archive.destroy if @archive.exists?
31
34
 
32
35
  build = @archive.build :bucket_prefix => @opts[:base_prefix],
33
36
  :directory => @opts[:directory],
34
37
  :exclude => @opts[:exclude],
35
- :git => @opts[:git]
38
+ :git => @opts[:git],
39
+ :secret => @opts[:secret]
36
40
 
37
41
  if build
38
42
  @archive.upload :bucket_prefix => @opts[:base_prefix],
39
43
  :regions => @opts[:region],
40
44
  :public_readable => @opts[:public],
41
45
  :file => build
42
- @archive.cleanup
43
46
  else
44
47
  @logger.error "Build failed."
45
48
  exit 1
@@ -57,17 +60,15 @@ Build and upload a new archive.
57
60
 
58
61
  Usage:
59
62
 
60
- heirloom build -n NAME -i ID -b BASE_PREFIX -r REGION1 -r REGION2 [-d DIRECTORY_TO_BUILD] [-p] [-g] [-e DIRECTORY_TO_EXCLUDE] [-l LOG_LEVEL]
63
+ heirloom build -n NAME -i ID -b BASE_PREFIX -r REGION1 -r REGION2 -d DIRECTORY_TO_BUILD
61
64
 
62
65
  EOS
63
66
  opt :base_prefix, "Base bucket prefix which will be combined with region. \
64
- For example: -b 'test' -r 'us-west-1' will expect bucket 'test-us-west-1' to be present", :type => :string
65
- opt :directory, "Source directory of build.", :type => :string,
66
- :default => '.'
67
+ For example: -b 'test' -r 'us-west-1' will expect bucket 'test-us-west-1' \
68
+ to be present", :type => :string
69
+ opt :directory, "Source directory of build.", :type => :string
67
70
  opt :exclude, "File(s) or directorie(s) to exclude. \
68
- Can be specified multiple times.", :type => :string,
69
- :multi => true
70
- opt :key, "AWS Access Key ID", :type => :string
71
+ Can be specified multiple times.", :type => :string, :multi => true
71
72
  opt :git, "Read git commit information from directory and set as archive attributes."
72
73
  opt :help, "Display Help"
73
74
  opt :id, "ID for archive (when -g specified, assumed to be GIT sha).", :type => :string
@@ -75,9 +76,13 @@ Can be specified multiple times.", :type => :string,
75
76
  :default => 'info'
76
77
  opt :name, "Name of archive.", :type => :string
77
78
  opt :public, "Set this archive as public readable?"
78
- opt :region, "Region(s) to upload archive. Can be specified multiple times.", :type => :string,
79
- :multi => true
80
- opt :secret, "AWS Secret Access Key", :type => :string
79
+ opt :region, "Region(s) to upload archive. \
80
+ Can be specified multiple times.", :type => :string, :multi => true
81
+ opt :secret, "Encrypt the archive with given secret.", :type => :string
82
+ opt :aws_access_key, "AWS Access Key ID", :type => :string,
83
+ :short => :none
84
+ opt :aws_secret_key, "AWS Secret Access Key", :type => :string,
85
+ :short => :none
81
86
  end
82
87
  end
83
88
 
@@ -38,16 +38,18 @@ Destroy an archive.
38
38
 
39
39
  Usage:
40
40
 
41
- heirloom destroy -n NAME -i ID [-l LOG_LEVEL]
41
+ heirloom destroy -n NAME -i ID
42
42
 
43
43
  EOS
44
44
  opt :help, "Display Help"
45
45
  opt :id, "ID of the archive to display.", :type => :string
46
- opt :key, "AWS Access Key ID", :type => :string
47
46
  opt :level, "Log level [debug|info|warn|error].", :type => :string,
48
47
  :default => 'info'
49
48
  opt :name, "Name of archive.", :type => :string
50
- opt :secret, "AWS Secret Access Key", :type => :string
49
+ opt :aws_access_key, "AWS Access Key ID", :type => :string,
50
+ :short => :none
51
+ opt :aws_secret_key, "AWS Secret Access Key", :type => :string,
52
+ :short => :none
51
53
  end
52
54
  end
53
55
  end