heirloom 0.5.0rc2 → 0.5.0rc3

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