heirloom 0.5.0rc3 → 0.5.0rc4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/CHANGELOG +11 -4
  2. data/README.md +3 -1
  3. data/heirloom.gemspec +3 -4
  4. data/lib/heirloom/archive.rb +15 -4
  5. data/lib/heirloom/archive/authorizer.rb +20 -3
  6. data/lib/heirloom/archive/builder.rb +2 -1
  7. data/lib/heirloom/archive/destroyer.rb +9 -2
  8. data/lib/heirloom/archive/setuper.rb +48 -0
  9. data/lib/heirloom/archive/verifier.rb +20 -10
  10. data/lib/heirloom/aws/s3.rb +7 -0
  11. data/lib/heirloom/cipher/data.rb +5 -2
  12. data/lib/heirloom/cipher/file.rb +1 -1
  13. data/lib/heirloom/cli.rb +14 -14
  14. data/lib/heirloom/cli/authorize.rb +3 -1
  15. data/lib/heirloom/cli/destroy.rb +1 -1
  16. data/lib/heirloom/cli/shared.rb +8 -9
  17. data/lib/heirloom/cli/{update.rb → tag.rb} +14 -9
  18. data/lib/heirloom/cli/{build.rb → upload.rb} +22 -25
  19. data/lib/heirloom/directory/directory.rb +2 -2
  20. data/lib/heirloom/uploader/s3.rb +2 -2
  21. data/lib/heirloom/version.rb +1 -1
  22. data/spec/archive/authorizer_spec.rb +14 -4
  23. data/spec/archive/builder_spec.rb +12 -5
  24. data/spec/archive/destroyer_spec.rb +24 -14
  25. data/spec/archive/setup_spec.rb +66 -0
  26. data/spec/archive/verifier_spec.rb +54 -22
  27. data/spec/archive/writer_spec.rb +2 -2
  28. data/spec/archive_spec.rb +3 -2
  29. data/spec/aws/s3_spec.rb +16 -0
  30. data/spec/cipher/data_spec.rb +3 -3
  31. data/spec/cipher/file_spec.rb +4 -3
  32. data/spec/cli/authorize_spec.rb +9 -2
  33. data/spec/cli/destroy_spec.rb +1 -1
  34. data/spec/cli/shared_spec.rb +2 -1
  35. data/spec/cli/{update_spec.rb → tag_spec.rb} +19 -13
  36. data/spec/cli/{build_spec.rb → upload_spec.rb} +26 -26
  37. data/spec/directory/directory_spec.rb +4 -2
  38. 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 base_prefix on download.
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 Creds
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
- Heirloom packages and distributes files to cloud storage services for deployment. Heirloom tracks metadata about those deployments, both about the file locations, as well as arbitrary metadata which can be set by an engineer or build process.
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
  ------------
@@ -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 'logger'
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
@@ -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 = args[:name]
19
- @id = args[: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 => 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
- accounts = args[:accounts]
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
- :bucket => bucket,
27
- :accounts => accounts
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
- bucket = "#{bucket_prefix}-#{region}"
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
@@ -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
@@ -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
@@ -18,7 +18,7 @@ module Heirloom
18
18
 
19
19
  @aes.encrypt
20
20
  @aes.iv = iv
21
- @aes.key = secret
21
+ @aes.key = Digest::SHA256.hexdigest secret
22
22
 
23
23
  # Need to refactor to be less complex
24
24
  # Additionally tests to do fully cover logic
@@ -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/build'
6
+ require 'heirloom/cli/upload'
7
7
  require 'heirloom/cli/list'
8
8
  require 'heirloom/cli/show'
9
- require 'heirloom/cli/update'
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|build|authorize|update|download|destroy] OPTIONS"
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
@@ -22,7 +22,9 @@ module Heirloom
22
22
  end
23
23
 
24
24
  def authorize
25
- @archive.authorize @opts[:accounts]
25
+ unless @archive.authorize @opts[:accounts]
26
+ exit 1
27
+ end
26
28
  end
27
29
 
28
30
  private
@@ -24,7 +24,7 @@ module Heirloom
24
24
  end
25
25
 
26
26
  def destroy
27
- @archive.destroy
27
+ @archive.destroy :keep_domain => false
28
28
  end
29
29
 
30
30
  private
@@ -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 != 32
19
- logger.error "Secret must be exactly 32 characters long."
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 << :aws_key unless config.access_key
31
- required << :aws_secret unless config.secret_key
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
- "Option '#{opt} (-#{opt[0]})' required but not specified."
37
- when []
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