hiera-eyaml 1.3.8 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0794eaaca28f7702c08e251f54f938c06c7856fe
4
- data.tar.gz: 505eea5b6e2bc567f5587adabb3c0aaef8b701e2
3
+ metadata.gz: a8965f033228e9d0c47c6ec9e7b2a399b76ead46
4
+ data.tar.gz: 222599950c2668eb59e99f42ad0b19cf1693d0c1
5
5
  SHA512:
6
- metadata.gz: b995c5e993985e4d38c0b1dfe55c0767057311cf00c75b3d3ac12538dfe7d58a9343a949005f06ccb1d1ea10628ffea2bf13e770d3ea5dad1288e2e09ba30174
7
- data.tar.gz: b54b10584df24f60bf148bd62116e9c6b6426e67be16a4c95172b2e1776cd33a30b308dba0a17a7814ceac84268749a35737567147605714e63e85b7ac6f8fbd
6
+ metadata.gz: 8ed7968fd5f5cb756bebcdcf82c8e3cc7c2284feb0e10d37e68e03f09daf1935f4fe71c48868b4119fe5b8240661a61c92f13f4bbc2066333508bef6b0b39621
7
+ data.tar.gz: a586ad0604541e2639c1e20f3fd1d72ac2099df0f57c962350536e43f0a97265456412a926651ca20592bbef1cd5a259488136ad12eaafe1de74924e1e2d6ec7
data/.gitignore CHANGED
@@ -5,3 +5,4 @@ keys/*.pem
5
5
  pkg/
6
6
  tmp/
7
7
  .DS_Store
8
+ .rvmrc
data/Gemfile.lock CHANGED
@@ -19,9 +19,9 @@ GEM
19
19
  ffi (1.9.3)
20
20
  gherkin (2.12.2)
21
21
  multi_json (~> 1.3)
22
- hiera (1.2.1)
22
+ hiera (1.3.0)
23
23
  json_pure
24
- hiera-eyaml-plaintext (0.5)
24
+ hiera-eyaml-plaintext (0.6)
25
25
  highline (1.6.20)
26
26
  json_pure (1.8.1)
27
27
  multi_json (1.8.2)
data/README.md CHANGED
@@ -6,6 +6,7 @@ Hiera eyaml
6
6
  hiera-eyaml is a backend for Hiera that provides per-value encryption of sensitive data within yaml files
7
7
  to be used by Puppet.
8
8
 
9
+ :new: *v2.0 - commandline tool syntax has changed, see below for details*
9
10
 
10
11
  Advantages over hiera-gpg
11
12
  -------------------------
@@ -46,7 +47,7 @@ encrypted-property: >
46
47
  IZGeunzwhqfmEtGiqpvJJQ5wVRdzJVpTnANBA5qxeA==]
47
48
  ```
48
49
 
49
- To edit this you can use the command `eyaml -i important.eyaml` which will decrypt the file, fire up an editor with
50
+ To edit this you can use the command `eyaml edit important.eyaml` which will decrypt the file, fire up an editor with
50
51
  the decrypted values and re-encrypt any edited values when you exit the editor. This tool makes editing your encrypted
51
52
  files as simple as clear text files.
52
53
 
@@ -62,7 +63,7 @@ Setup
62
63
 
63
64
  The first step is to create a pair of keys:
64
65
 
65
- $ eyaml -c
66
+ $ eyaml createkeys
66
67
 
67
68
  This creates a public and private key with default names in the default location. (./keys)
68
69
 
@@ -90,13 +91,13 @@ The permissions for this folder should allow the puppet user (normally 'puppet')
90
91
 
91
92
  To encrypt something, you only need the public_key, so distribute that to people creating hiera properties
92
93
 
93
- $ eyaml -e -f filename # Encrypt a file
94
- $ eyaml -e -s 'hello there' # Encrypt a string
95
- $ eyaml -e -p # Encrypt a password (prompt for it)
94
+ $ eyaml encrypt -f filename # Encrypt a file
95
+ $ eyaml encrypt -s 'hello there' # Encrypt a string
96
+ $ eyaml encrypt -p # Encrypt a password (prompt for it)
96
97
 
97
98
  Use the -l parameter to pass in a label for the encrypted value,
98
99
 
99
- $ eyaml -e -l 'some_easy_to_use_label' -s 'yourSecretString' --pkcs7-private-key /etc/puppet/secure/keys/private_key.pkcs7.pem --pkcs7-public-key /etc/puppet/secure/keys/public_key.pkcs7.pem
100
+ $ eyaml encrypt -l 'some_easy_to_use_label' -s 'yourSecretString'
100
101
 
101
102
 
102
103
  ### Decryption
@@ -105,8 +106,8 @@ To decrypt something, you need the public_key and the private_key.
105
106
 
106
107
  To test decryption you can also use the eyaml tool if you have both keys
107
108
 
108
- $ eyaml -d -f filename # Decrypt a file
109
- $ eyaml -d -s 'ENC[PKCS7,.....]' # Decrypt a string
109
+ $ eyaml decrypt -f filename # Decrypt a file
110
+ $ eyaml decrypt -s 'ENC[PKCS7,.....]' # Decrypt a string
110
111
 
111
112
  ### Editing eyaml files
112
113
 
@@ -115,7 +116,7 @@ you can edit the encrypted values in place, using the special edit mode of the e
115
116
  mode opens a decrypted copy of the eyaml file in your `$EDITOR` and will encrypt and modified values
116
117
  when you exit the editor.
117
118
 
118
- $ eyaml -i filename.eyaml # Edit an eyaml file in place
119
+ $ eyaml edit filename.eyaml # Edit an eyaml file in place
119
120
 
120
121
  When editing eyaml files, you will see that the unencrypted plaintext is marked to allow the eyaml tool to
121
122
  identify each encrypted block, along with the encryption method. This is used to make sure that the block
@@ -312,4 +313,4 @@ Authors
312
313
  - [Tom Poulton](http://github.com/TomPoulton) - Initial author. eyaml backend.
313
314
  - [Geoff Meakin](http://github.com/gtmtech) - Major contributor. eyaml command, tests, CI
314
315
  - [Simon Hildrew](http://github.com/sihil) - Contributor. eyaml edit sub command.
315
- - [Robert Fielding](http://github.com/rooprob) - Contributor. eyaml recrypt sub command.
316
+ - [Robert Fielding](http://github.com/rooprob) - Contributor. eyaml recrypt sub command.
@@ -2,11 +2,20 @@ class Hiera
2
2
  module Backend
3
3
  module Eyaml
4
4
 
5
+ VERSION = "2.0.0"
6
+ DESCRIPTION = "Hiera-eyaml is a backend for Hiera which provides OpenSSL encryption/decryption for Hiera properties"
7
+
5
8
  class RecoverableError < StandardError
6
9
  end
7
10
 
8
- VERSION = "1.3.8"
11
+ def self.subcommand= command
12
+ @@subcommand = command
13
+ end
9
14
 
15
+ def self.subcommand
16
+ @@subcommand
17
+ end
18
+
10
19
  def self.default_encryption_scheme= new_encryption
11
20
  @@default_encryption_scheme = new_encryption
12
21
  end
@@ -16,6 +25,23 @@ class Hiera
16
25
  @@default_encryption_scheme
17
26
  end
18
27
 
28
+ def self.verbosity_level= new_verbosity_level
29
+ @@debug_level = new_verbosity_level
30
+ end
31
+
32
+ def self.verbosity_level
33
+ @@debug_level ||= 1
34
+ @@debug_level
35
+ end
36
+
37
+ def self.subcommands= commands
38
+ @@subcommands = commands
39
+ end
40
+
41
+ def self.subcommands
42
+ @@subcommands
43
+ end
44
+
19
45
  end
20
46
  end
21
47
  end
@@ -1,13 +1,9 @@
1
1
  require 'trollop'
2
2
  require 'hiera/backend/eyaml'
3
3
  require 'hiera/backend/eyaml/utils'
4
- require 'hiera/backend/eyaml/actions/createkeys_action'
5
- require 'hiera/backend/eyaml/actions/decrypt_action'
6
- require 'hiera/backend/eyaml/actions/encrypt_action'
7
- require 'hiera/backend/eyaml/actions/recrypt_action'
8
- require 'hiera/backend/eyaml/actions/edit_action'
9
4
  require 'hiera/backend/eyaml/plugins'
10
5
  require 'hiera/backend/eyaml/options'
6
+ require 'hiera/backend/eyaml/subcommand'
11
7
 
12
8
  class Hiera
13
9
  module Backend
@@ -16,87 +12,27 @@ class Hiera
16
12
 
17
13
  def self.parse
18
14
 
19
- options = Trollop::options do
20
-
21
- version "Hiera-eyaml version " + Hiera::Backend::Eyaml::VERSION.to_s
22
- banner <<-EOS
23
- Hiera-eyaml is a backend for Hiera which provides OpenSSL encryption/decryption for Hiera properties
24
-
25
- Usage:
26
- eyaml [options]
27
- eyaml -i file.eyaml # edit a file
28
- eyaml -e -s some-string # encrypt a string
29
- eyaml -e -p # encrypt a password
30
- eyaml -e -f file.txt # encrypt a file
31
- cat file.txt | eyaml -e # encrypt a file on a pipe
32
-
33
- Options:
34
- EOS
35
-
36
- opt :createkeys, "Create public and private keys for use encrypting properties", :short => 'c'
37
- opt :decrypt, "Decrypt something", :short => 'd'
38
- opt :encrypt, "Encrypt something", :short => 'e'
39
- opt :recrypt, "Recrypt something", :short => 'r', :type => :string
40
- opt :edit, "Decrypt, Edit, and Reencrypt", :short => 'i', :type => :string
41
- opt :eyaml, "Source input is an eyaml file", :short => 'y', :type => :string
42
- opt :password, "Source input is a password entered on the terminal", :short => 'p'
43
- opt :string, "Source input is a string provided as an argument", :short => 's', :type => :string
44
- opt :file, "Source input is a file", :short => 'f', :type => :string
45
- opt :stdin, "Source input is taken from stdin", :short => :none
46
- opt :encrypt_method, "Override default encryption and decryption method (default is PKCS7)", :short => 'n', :default => "pkcs7"
47
- opt :output, "Output format of final result (examples, block, string)", :type => :string, :short => 'o', :default => "examples"
48
- opt :label, "Apply a label to the encrypted result", :short => 'l', :type => :string
49
- opt :debug, "Be more verbose", :short => :none
50
- opt :quiet, "Be less verbose", :short => :none
51
-
52
- Hiera::Backend::Eyaml::Plugins.options.each do |name, option|
53
- opt name, option[:desc], :type => option[:type], :short => option[:short], :default => option[:default]
54
- end
55
-
15
+ Utils.require_dir 'hiera/backend/eyaml/subcommands'
16
+ Eyaml.subcommands = Utils.find_all_subclasses_of({ :parent_class => Hiera::Backend::Eyaml::Subcommands }).collect {|classname| Utils.snakecase classname}
17
+
18
+ Eyaml.subcommand = ARGV.shift
19
+ subcommand = case Eyaml.subcommand
20
+ when nil
21
+ ARGV.delete_if {true}
22
+ "unknown_command"
23
+ when /^\-/
24
+ ARGV.delete_if {true}
25
+ "help"
26
+ else
27
+ Eyaml.subcommand
56
28
  end
57
29
 
58
- actions = [:createkeys, :decrypt, :recrypt, :encrypt, :edit].collect {|x| x if options[x]}.compact
59
- sources = [:edit, :recrypt, :eyaml, :password, :string, :file, :stdin].collect {|x| x if options[x]}.compact
60
- # sources << :stdin if STDIN
30
+ command_class = Subcommand.find subcommand
61
31
 
62
- Trollop::die "You can only specify one of (#{actions.join(', ')})" if actions.count > 1
63
- Trollop::die "You can only specify one of (#{sources.join(', ')})" if sources.count > 1
64
- Trollop::die "Creating keys does not require a source to encrypt/decrypt" if actions.first == :createkeys and sources.count > 0
32
+ options = command_class.parse
33
+ options[:executor] = command_class
65
34
 
66
- options[:source] = sources.first
67
- options[:action] = actions.first
68
- options[:source] = :not_applicable if options[:action] == :createkeys
69
-
70
- Trollop::die "Nothing to do" if options[:source].nil? or options[:action].nil?
71
-
72
- options[:input_data] = case options[:source]
73
- when :stdin
74
- STDIN.read
75
- when :password
76
- Utils.read_password
77
- when :string
78
- options[:string]
79
- when :file
80
- File.read options[:file]
81
- when :eyaml
82
- File.read options[:eyaml]
83
- when :stdin
84
- STDIN.read
85
- else
86
- if options[:edit]
87
- options[:eyaml] = options[:edit]
88
- options[:source] = :eyaml
89
- File.read options[:edit]
90
- elsif options[:recrypt]
91
- options[:eyaml] = options[:recrypt]
92
- options[:source] = :eyaml
93
- File.read options[:recrypt]
94
- else
95
- nil
96
- end
97
- end
98
-
99
- Eyaml.default_encryption_scheme = options[:encrypt_method].upcase if options[:encrypt_method]
35
+ options = command_class.validate options
100
36
  Eyaml::Options.set options
101
37
  Eyaml::Options.debug
102
38
 
@@ -104,11 +40,14 @@ Options:
104
40
 
105
41
  def self.execute
106
42
 
107
- action = Eyaml::Options[:action]
108
- action_class = Module.const_get('Hiera').const_get('Backend').const_get('Eyaml').const_get('Actions').const_get("#{Utils.camelcase action.to_s}Action")
109
-
110
- return_value = action_class.execute
111
- puts return_value unless return_value.nil?
43
+ executor = Eyaml::Options[:executor]
44
+ begin
45
+ result = executor.execute
46
+ puts result unless result.nil?
47
+ rescue Exception => e
48
+ Utils.warn e.message
49
+ Utils.info e.backtrace.inspect
50
+ end
112
51
 
113
52
  end
114
53
 
@@ -0,0 +1,21 @@
1
+ require 'rubygems'
2
+
3
+ class Hiera
4
+ module Backend
5
+ module Eyaml
6
+ class Commands
7
+
8
+ @@commands = []
9
+
10
+ def self.register
11
+
12
+ end
13
+
14
+ def self.commands
15
+ @@commands
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,4 +1,5 @@
1
1
  require 'base64'
2
+ require 'hiera/backend/eyaml/utils'
2
3
 
3
4
  class Hiera
4
5
  module Backend
@@ -15,7 +16,7 @@ class Hiera
15
16
  encryption_scheme = Eyaml.default_encryption_scheme if encryption_scheme.nil?
16
17
  require "hiera/backend/eyaml/encryptors/#{encryption_scheme.downcase}"
17
18
  encryptor_module = Module.const_get('Hiera').const_get('Backend').const_get('Eyaml').const_get('Encryptors')
18
- encryptor_class = self.find_closest_class :parent_class => encryptor_module, :class_name => encryption_scheme
19
+ encryptor_class = Utils.find_closest_class :parent_class => encryptor_module, :class_name => encryption_scheme
19
20
  raise StandardError, "Could not find hiera-eyaml encryptor: #{encryption_scheme}. Try gem install hiera-eyaml-#{encryption_scheme.downcase} ?" if encryptor_class.nil?
20
21
  encryptor_class
21
22
  end
@@ -50,23 +51,8 @@ class Hiera
50
51
  Eyaml::Options[ "#{plugin_classname}_#{name}" ] || self.options[ "#{plugin_classname}_#{name}" ]
51
52
  end
52
53
 
53
- def self.find_closest_class args
54
- parent_class = args[ :parent_class ]
55
- class_name = args[ :class_name ]
56
- constants = parent_class.constants
57
- candidates = []
58
- constants.each do | candidate |
59
- candidates << candidate.to_s if candidate.to_s.downcase == class_name.downcase
60
- end
61
- if candidates.count > 0
62
- parent_class.const_get candidates.first
63
- else
64
- nil
65
- end
66
- end
67
-
68
54
  def self.hiera?
69
- "hiera".eql? Eyaml::Options[:source]
55
+ Utils::hiera?
70
56
  end
71
57
 
72
58
  def self.format_message msg
@@ -74,19 +60,15 @@ class Hiera
74
60
  end
75
61
 
76
62
  def self.debug msg
77
- if self.hiera?
78
- Hiera.debug format_message msg
79
- else
80
- Utils::debug format_message msg
81
- end
63
+ Utils::debug :from => plugin_classname, :msg => msg
64
+ end
65
+
66
+ def self.info msg
67
+ Utils::info :from => plugin_classname, :msg => msg
82
68
  end
83
69
 
84
70
  def self.warn msg
85
- if self.hiera?
86
- Hiera.warn format_message msg
87
- else
88
- Utils::info format_message msg
89
- end
71
+ Utils::warn :from => plugin_classname, :msg => msg
90
72
  end
91
73
 
92
74
  end
@@ -24,9 +24,9 @@ class Hiera
24
24
  Utils::debug "Dump of eyaml tool options dict:"
25
25
  Utils::debug "--------------------------------"
26
26
  @@options.each do |k, v|
27
- Utils::debug "#{k.class.name}:#{k} = #{v.class.name}:#{v}"
27
+ Utils::debug sprintf "%18s %-18s = %-18s %-18s", "(#{k.class.name})", k.to_s, v.to_s, "(#{v.class.name})"
28
28
  end
29
- Utils::debug ""
29
+ Utils::debug "--------------------------------"
30
30
  end
31
31
 
32
32
  end
@@ -6,13 +6,16 @@ class Hiera
6
6
  class Plugins
7
7
 
8
8
  @@plugins = []
9
- @@options = {}
9
+ @@commands = []
10
+ @@options = []
10
11
 
11
12
  def self.register_options args
12
- options_hash = args[ :options ]
13
+ options = args[ :options ]
13
14
  plugin = args[ :plugin ]
14
- options_hash.each do |key, value|
15
- @@options.merge!({ "#{plugin}_#{key}" => value })
15
+ options.each do |name, option_hash|
16
+ new_option = {:name => "#{plugin}_#{name}"}
17
+ new_option.merge! option_hash
18
+ @@options << new_option
16
19
  end
17
20
  end
18
21
 
@@ -31,8 +34,6 @@ class Hiera
31
34
  specs.each do |spec|
32
35
  next if @@plugins.include? spec
33
36
 
34
- # If this gem depends on Vagrant, verify this is a valid release of
35
- # Vagrant for this gem to load into.
36
37
  dependency = spec.dependencies.find { |d| d.name == "hiera-eyaml" }
37
38
  next if dependency && !dependency.requirement.satisfied_by?( this_version )
38
39
 
@@ -59,6 +60,10 @@ class Hiera
59
60
  @@plugins
60
61
  end
61
62
 
63
+ def self.commands
64
+ @@commands
65
+ end
66
+
62
67
  end
63
68
  end
64
69
  end
@@ -0,0 +1,126 @@
1
+ require 'base64'
2
+ # require 'hiera/backend/eyaml/subcommands/unknown_command'
3
+
4
+ class Hiera
5
+ module Backend
6
+ module Eyaml
7
+
8
+ class Subcommand
9
+
10
+ class << self
11
+ attr_accessor :global_options, :options, :helptext
12
+ end
13
+
14
+ @@global_options = [
15
+ {:name => :encrypt_method,
16
+ :description => "Override default encryption and decryption method (default is PKCS7)",
17
+ :short => 'n',
18
+ :default => "pkcs7"},
19
+ {:name => :version,
20
+ :description => "Show version information"},
21
+ {:name => :verbose,
22
+ :description => "Be more verbose",
23
+ :short => 'v'},
24
+ {:name => :quiet,
25
+ :description => "Be less verbose",
26
+ :short => 'q'},
27
+ {:name => :help,
28
+ :description => "Information on how to use this command",
29
+ :short => 'h'}
30
+ ]
31
+
32
+ def self.all_options
33
+ options = @@global_options.dup
34
+ options += self.options if self.options
35
+ options += Plugins.options
36
+ options
37
+ end
38
+
39
+ def self.attach_option opt
40
+ self.suboptions += opt
41
+ end
42
+
43
+ def self.find commandname = "unknown_command"
44
+ begin
45
+ require "hiera/backend/eyaml/subcommands/#{commandname.downcase}"
46
+ rescue Exception => e
47
+ require "hiera/backend/eyaml/subcommands/unknown_command"
48
+ return Hiera::Backend::Eyaml::Subcommands::UnknownCommand
49
+ end
50
+ command_module = Module.const_get('Hiera').const_get('Backend').const_get('Eyaml').const_get('Subcommands')
51
+ command_class = Utils.find_closest_class :parent_class => command_module, :class_name => commandname
52
+ command_class || Hiera::Backend::Eyaml::Subcommands::UnknownCommand
53
+ end
54
+
55
+ def self.parse
56
+
57
+ me = self
58
+
59
+ options = Trollop::options do
60
+
61
+ version "Hiera-eyaml version " + Hiera::Backend::Eyaml::VERSION.to_s
62
+ banner ["eyaml #{me.prettyname}: #{me.description}", me.helptext, "Options:"].compact.join("\n\n")
63
+
64
+ me.all_options.each do |available_option|
65
+
66
+ skeleton = {:description => "",
67
+ :short => :none}
68
+
69
+ skeleton.merge! available_option
70
+ opt skeleton[:name],
71
+ skeleton[:desc] || skeleton[:description], #legacy plugins
72
+ :short => skeleton[:short],
73
+ :default => skeleton[:default],
74
+ :type => skeleton[:type]
75
+
76
+ end
77
+
78
+ stop_on Eyaml.subcommands
79
+
80
+ end
81
+
82
+ if options[:verbose]
83
+ Hiera::Backend::Eyaml.verbosity_level += 1
84
+ end
85
+
86
+ if options[:quiet]
87
+ Hiera::Backend::Eyaml.verbosity_level = 0
88
+ end
89
+
90
+ if options[:encrypt_method]
91
+ Hiera::Backend::Eyaml.default_encryption_scheme = options[:encrypt_method]
92
+ end
93
+
94
+ options
95
+
96
+ end
97
+
98
+ def self.validate args
99
+ args
100
+ end
101
+
102
+ def self.description
103
+ "no description"
104
+ end
105
+
106
+ def self.helptext
107
+ "Usage: eyaml #{self.prettyname} [options]"
108
+ end
109
+
110
+ def self.execute
111
+ raise StandardError, "This command is not implemented yet (#{self.to_s.split('::').last})"
112
+ end
113
+
114
+ def self.prettyname
115
+ Utils.snakecase self.to_s.split('::').last
116
+ end
117
+
118
+ def self.hidden?
119
+ false
120
+ end
121
+
122
+ end
123
+
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,29 @@
1
+ require 'hiera/backend/eyaml/subcommand'
2
+
3
+ class Hiera
4
+ module Backend
5
+ module Eyaml
6
+ module Subcommands
7
+
8
+ class Createkeys < Subcommand
9
+
10
+ def self.options
11
+ []
12
+ end
13
+
14
+ def self.description
15
+ "create a set of keys with which to encrypt/decrypt eyaml data"
16
+ end
17
+
18
+ def self.execute
19
+ encryptor = Encryptor.find Eyaml.default_encryption_scheme
20
+ encryptor.create_keys
21
+ nil
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,81 @@
1
+ require 'hiera/backend/eyaml'
2
+ require 'hiera/backend/eyaml/utils'
3
+ require 'hiera/backend/eyaml/options'
4
+ require 'hiera/backend/eyaml/parser/parser'
5
+ require 'hiera/backend/eyaml/subcommand'
6
+
7
+ class Hiera
8
+ module Backend
9
+ module Eyaml
10
+ module Subcommands
11
+
12
+ class Decrypt < Subcommand
13
+
14
+ def self.options
15
+ [{:name => :string,
16
+ :description => "Source input is a string provided as an argument",
17
+ :short => 's',
18
+ :type => :string},
19
+ {:name => :file,
20
+ :description => "Source input is a regular file",
21
+ :short => 'f',
22
+ :type => :string},
23
+ {:name => :eyaml,
24
+ :description => "Source input is an eyaml file",
25
+ :short => 'e',
26
+ :type => :string},
27
+ {:name => :stdin,
28
+ :description => "Source input is taken from stdin",
29
+ :short => :none}
30
+ ]
31
+ end
32
+
33
+ def self.description
34
+ "decrypt some data"
35
+ end
36
+
37
+ def self.validate options
38
+ sources = [:eyaml, :password, :string, :file, :stdin].collect {|x| x if options[x]}.compact
39
+ Trollop::die "You must specify a source" if sources.count.zero?
40
+ Trollop::die "You can only specify one of (#{sources.join(', ')})" if sources.count > 1
41
+ options[:source] = sources.first
42
+
43
+ options[:input_data] = case options[:source]
44
+ when :stdin
45
+ STDIN.read
46
+ when :string
47
+ options[:string]
48
+ when :file
49
+ File.read options[:file]
50
+ when :eyaml
51
+ File.read options[:eyaml]
52
+ end
53
+ options
54
+ end
55
+
56
+ def self.execute
57
+ parser = Parser::ParserFactory.encrypted_parser
58
+ tokens = parser.parse(Eyaml::Options[:input_data])
59
+ case Eyaml::Options[:source]
60
+ when :eyaml
61
+ decrypted = tokens.map{ |token| token.to_decrypted }
62
+ decrypted.join
63
+ else
64
+ decrypted = tokens.map{ |token|
65
+ case token.class.name
66
+ when /::EncToken$/
67
+ token.plain_text
68
+ else
69
+ token.match
70
+ end
71
+ }
72
+ decrypted.join
73
+ end
74
+ end
75
+
76
+ end
77
+
78
+ end
79
+ end
80
+ end
81
+ end
@@ -1,19 +1,37 @@
1
1
  require 'hiera/backend/eyaml/utils'
2
- require 'hiera/backend/eyaml/actions/decrypt_action'
3
- require 'hiera/backend/eyaml/actions/encrypt_action'
4
2
  require 'hiera/backend/eyaml/options'
5
3
  require 'hiera/backend/eyaml/parser/parser'
4
+ require 'hiera/backend/eyaml/subcommand'
6
5
  require 'highline/import'
7
6
 
8
7
  class Hiera
9
8
  module Backend
10
9
  module Eyaml
11
- module Actions
12
-
13
- class EditAction
10
+ module Subcommands
14
11
 
15
- def self.execute
12
+ class Edit < Subcommand
16
13
 
14
+ def self.options
15
+ []
16
+ end
17
+
18
+ def self.description
19
+ "edit an eyaml file"
20
+ end
21
+
22
+ def self.helptext
23
+ "Usage: eyaml edit [options] <some-eyaml-file>"
24
+ end
25
+
26
+ def self.validate options
27
+ Trollop::die "You must specify an eyaml file" if ARGV.empty?
28
+ options[:source] = :eyaml
29
+ options[:eyaml] = ARGV.shift
30
+ options[:input_data] = File.read options[:eyaml]
31
+ options
32
+ end
33
+
34
+ def self.execute
17
35
  encrypted_parser = Parser::ParserFactory.encrypted_parser
18
36
  tokens = encrypted_parser.parse Eyaml::Options[:input_data]
19
37
  decrypted_input = tokens.each_with_index.to_a.map{|(t,index)| t.to_decrypted :index => index}.join
@@ -30,7 +48,6 @@ class Hiera
30
48
 
31
49
  raise StandardError, "Editor #{editor} has not exited?" unless status.exited?
32
50
  raise StandardError, "Editor did not exit successfully (exit code #{status.exitstatus}), aborting" unless status.exitstatus == 0
33
-
34
51
  raise StandardError, "Edited file is blank" if edited_file.empty?
35
52
 
36
53
  if edited_file == decrypted_input
@@ -0,0 +1,100 @@
1
+ require 'hiera/backend/eyaml/options'
2
+ require 'hiera/backend/eyaml/parser/parser'
3
+ require 'hiera/backend/eyaml/parser/encrypted_tokens'
4
+ require 'hiera/backend/eyaml/subcommand'
5
+
6
+ class Hiera
7
+ module Backend
8
+ module Eyaml
9
+ module Subcommands
10
+
11
+ class Encrypt < Subcommand
12
+
13
+ def self.options
14
+ [{:name => :password,
15
+ :description => "Source input is a password entered on the terminal",
16
+ :short => 'p'},
17
+ {:name => :string,
18
+ :description => "Source input is a string provided as an argument",
19
+ :short => 's',
20
+ :type => :string},
21
+ {:name => :file,
22
+ :description => "Source input is a regular file",
23
+ :short => 'f',
24
+ :type => :string},
25
+ {:name => :stdin,
26
+ :description => "Source input is taken from stdin",
27
+ :short => :none},
28
+ {:name => :eyaml,
29
+ :description => "Source input is an eyaml file",
30
+ :short => 'e',
31
+ :type => :string},
32
+ {:name => :output,
33
+ :description => "Output format of final result (examples, block, string)",
34
+ :type => :string,
35
+ :short => 'o',
36
+ :default => "examples"},
37
+ {:name => :label,
38
+ :description => "Apply a label to the encrypted result",
39
+ :short => 'l',
40
+ :type => :string}
41
+ ]
42
+ end
43
+
44
+ def self.description
45
+ "encrypt some data"
46
+ end
47
+
48
+ def self.validate options
49
+ sources = [:password, :string, :file, :stdin, :eyaml].collect {|x| x if options[x]}.compact
50
+ Trollop::die "You must specify a source" if sources.count.zero?
51
+ Trollop::die "You can only specify one of (#{sources.join(', ')})" if sources.count > 1
52
+ options[:source] = sources.first
53
+
54
+ options[:input_data] = case options[:source]
55
+ when :password
56
+ Utils.read_password
57
+ when :string
58
+ options[:string]
59
+ when :file
60
+ File.read options[:file]
61
+ when :stdin
62
+ STDIN.read
63
+ when :eyaml
64
+ File.read options[:eyaml]
65
+ end
66
+ options
67
+
68
+ end
69
+
70
+ def self.execute
71
+ case Eyaml::Options[:source]
72
+ when :eyaml
73
+ parser = Parser::ParserFactory.decrypted_parser
74
+ tokens = parser.parse(Eyaml::Options[:input_data])
75
+ encrypted = tokens.map{ |token| token.to_encrypted }
76
+ encrypted.join
77
+ else
78
+ encryptor = Encryptor.find
79
+ ciphertext = encryptor.encode( encryptor.encrypt(Eyaml::Options[:input_data]) )
80
+ token = Parser::EncToken.new(:block, Eyaml::Options[:input_data], encryptor, ciphertext, nil, ' ')
81
+ case Eyaml::Options[:output]
82
+ when "block"
83
+ token.to_encrypted :label => Eyaml::Options[:label], :use_chevron => !Eyaml::Options[:label].nil?, :format => :block
84
+ when "string"
85
+ token.to_encrypted :label => Eyaml::Options[:label], :format => :string
86
+ when "examples"
87
+ string = token.to_encrypted :label => Eyaml::Options[:label] || 'string', :format => :string
88
+ block = token.to_encrypted :label => Eyaml::Options[:label] || 'block', :format => :block
89
+ "#{string}\n\nOR\n\n#{block}"
90
+ else
91
+ token.to_encrypted :format => :string
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,51 @@
1
+ require 'hiera/backend/eyaml/subcommand'
2
+ require 'hiera/backend/eyaml'
3
+
4
+ class Hiera
5
+ module Backend
6
+ module Eyaml
7
+ module Subcommands
8
+
9
+ class Help < Subcommand
10
+
11
+ def self.options
12
+ []
13
+ end
14
+
15
+ def self.description
16
+ "this page"
17
+ end
18
+
19
+ def self.execute
20
+
21
+ puts <<-EOS
22
+ Welcome to eyaml #{Eyaml::VERSION}
23
+
24
+ Usage:
25
+ eyaml subcommand [global-opts] [subcommand-opts]
26
+
27
+ Available subcommands:
28
+ #{Eyaml.subcommands.collect {|command|
29
+ command_class = Subcommands.const_get(Utils.camelcase command)
30
+ sprintf "%15s: %-65s", command.downcase, command_class.description unless command_class.hidden?
31
+ }.compact.join("\n")}
32
+
33
+ For more help on an individual command, use --help on that command
34
+
35
+ Installed Plugins:
36
+ #{Plugins.plugins.collect {|plugin|
37
+ "\t" + plugin.name.split("hiera-eyaml-").last
38
+ }.join("\n")}
39
+ EOS
40
+ end
41
+
42
+ def self.hidden?
43
+ true
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,30 +1,42 @@
1
- require 'hiera/backend/eyaml/utils'
2
- require 'hiera/backend/eyaml/actions/decrypt_action'
3
- require 'hiera/backend/eyaml/actions/encrypt_action'
1
+ require 'hiera/backend/eyaml/subcommand'
4
2
  require 'hiera/backend/eyaml/options'
5
3
  require 'hiera/backend/eyaml/parser/parser'
6
4
 
7
5
  class Hiera
8
6
  module Backend
9
7
  module Eyaml
10
- module Actions
8
+ module Subcommands
11
9
 
12
- class RecryptAction
10
+ class Recrypt < Subcommand
13
11
 
14
- def self.execute
12
+ def self.options
13
+ []
14
+ end
15
+
16
+ def self.description
17
+ "recrypt an eyaml file"
18
+ end
19
+
20
+ def self.helptext
21
+ "Usage: eyaml recrypt [options] <some-eyaml-file>"
22
+ end
23
+
24
+ def self.validate options
25
+ Trollop::die "You must specify an eyaml file" if ARGV.empty?
26
+ options[:source] = :eyaml
27
+ options[:eyaml] = ARGV.shift
28
+ options[:input_data] = File.read options[:eyaml]
29
+ options
30
+ end
31
+
32
+ def self.execute
15
33
 
16
34
  encrypted_parser = Parser::ParserFactory.encrypted_parser
17
35
  tokens = encrypted_parser.parse Eyaml::Options[:input_data]
18
36
  decrypted_input = tokens.each_with_index.to_a.map{|(t,index)| t.to_decrypted :index => index}.join
19
- decrypted_file = Utils.write_tempfile decrypted_input
20
-
21
- edited_file = File.read decrypted_file
22
- Utils.secure_file_delete :file => decrypted_file, :num_bytes => [edited_file.length, decrypted_input.length].max
23
-
24
- raise StandardError, "Edited file is blank" if edited_file.empty?
25
37
 
26
38
  decrypted_parser = Parser::ParserFactory.decrypted_parser
27
- edited_tokens = decrypted_parser.parse(edited_file)
39
+ edited_tokens = decrypted_parser.parse(decrypted_input)
28
40
 
29
41
  encrypted_output = edited_tokens.map{ |t| t.to_encrypted }.join
30
42
 
@@ -0,0 +1,48 @@
1
+ require 'hiera/backend/eyaml/subcommand'
2
+
3
+ class Hiera
4
+ module Backend
5
+ module Eyaml
6
+ module Subcommands
7
+
8
+ class UnknownCommand < Eyaml::Subcommand
9
+
10
+ class << self
11
+ attr_accessor :original_command
12
+ end
13
+
14
+ @@original_command = "unknown"
15
+
16
+ def self.options
17
+ []
18
+ end
19
+
20
+ def self.description
21
+ "Unknown command (#{@@original_command})"
22
+ end
23
+
24
+ def self.execute
25
+ subcommands = Eyaml.subcommands
26
+ puts <<-EOS
27
+ Unknown subcommand#{ ": " + Eyaml.subcommand if Eyaml.subcommand }
28
+
29
+ Usage: eyaml <subcommand>
30
+
31
+ Please use one of the following subcommands or help for more help:
32
+ #{Eyaml.subcommands.sort.collect {|command|
33
+ command_class = Subcommands.const_get(Utils.camelcase command)
34
+ command unless command_class.hidden?
35
+ }.compact.join(", ")}
36
+ EOS
37
+ end
38
+
39
+ def self.hidden?
40
+ true
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,47 @@
1
+ require 'hiera/backend/eyaml/subcommand'
2
+ require 'hiera/backend/eyaml'
3
+
4
+ class Hiera
5
+ module Backend
6
+ module Eyaml
7
+ module Subcommands
8
+
9
+ class Version < Subcommand
10
+
11
+ def self.options
12
+ []
13
+ end
14
+
15
+ def self.description
16
+ "show version information"
17
+ end
18
+
19
+ def self.execute
20
+ plugin_versions = {}
21
+
22
+ puts <<-EOS
23
+ Version info
24
+
25
+ hiera-eyaml (core): #{Eyaml::VERSION}
26
+ EOS
27
+
28
+ Plugins.plugins.each do |plugin|
29
+ plugin_shortname = plugin.name.split("hiera-eyaml-").last
30
+ plugin_version = begin
31
+ Encryptor.find(plugin_shortname)::VERSION.to_s
32
+ rescue
33
+ "unknown (is plugin compatible with eyaml 2.0+ ?)"
34
+ end
35
+ puts " hiera-eyaml-#{plugin_shortname} (gem): #{plugin_version}"
36
+ end
37
+
38
+ nil
39
+
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
@@ -25,6 +25,11 @@ class Hiera
25
25
  string.split('_').map{|e| e.capitalize}.join
26
26
  end
27
27
 
28
+ def self.snakecase string
29
+ return string if string !~ /[A-Z]/
30
+ string.split(/(?=[A-Z])/).collect {|x| x.downcase}.join("_")
31
+ end
32
+
28
33
  def self.find_editor
29
34
  editor = ENV['EDITOR']
30
35
  editor ||= %w{ /usr/bin/sensible-editor /usr/bin/editor /usr/bin/vim /usr/bin/vi }.collect {|e| e if FileTest.executable? e}.compact.first
@@ -46,7 +51,9 @@ class Hiera
46
51
  def self.write_tempfile data_to_write
47
52
  file = Tempfile.open('eyaml_edit')
48
53
  path = file.path
54
+ file.close!
49
55
 
56
+ file = File.open(path, "w")
50
57
  file.puts data_to_write
51
58
  file.close
52
59
 
@@ -80,12 +87,83 @@ class Hiera
80
87
 
81
88
  end
82
89
 
83
- def self.info message
84
- STDERR.puts message unless Eyaml::Options[:quiet]
90
+ def self.find_closest_class args
91
+ parent_class = args[ :parent_class ]
92
+ class_name = args[ :class_name ]
93
+ constants = parent_class.constants
94
+ candidates = []
95
+ constants.each do | candidate |
96
+ candidates << candidate.to_s if candidate.to_s.downcase == class_name.downcase
97
+ end
98
+ if candidates.count > 0
99
+ parent_class.const_get candidates.first
100
+ else
101
+ nil
102
+ end
103
+ end
104
+
105
+ def self.require_dir classdir
106
+ num_class_hierarchy_levels = self.to_s.split("::").count - 1
107
+ root_folder = File.dirname(__FILE__) + "/" + Array.new(num_class_hierarchy_levels).fill("..").join("/")
108
+ class_folder = root_folder + "/" + classdir
109
+ Dir[File.expand_path("#{class_folder}/*.rb")].uniq.each do |file|
110
+ # puts "Requiring file: #{file}"
111
+ require file
112
+ end
113
+ end
114
+
115
+ def self.find_all_subclasses_of args
116
+ parent_class = args[ :parent_class ]
117
+ constants = parent_class.constants
118
+ candidates = []
119
+ constants.each do | candidate |
120
+ candidates << candidate.to_s.split('::').last if parent_class.const_get(candidate).class.to_s == "Class"
121
+ end
122
+ candidates
123
+ end
124
+
125
+ def self.hiera?
126
+ "hiera".eql? Eyaml::Options[:source]
127
+ end
128
+
129
+ def self.structure_message messageinfo
130
+ message = {:from => "hiera-eyaml-core"}
131
+ case messageinfo.class.to_s
132
+ when 'Hash'
133
+ message.merge!(messageinfo)
134
+ else
135
+ message.merge!({:msg => messageinfo.to_s})
136
+ end
137
+ end
138
+
139
+ def self.warn messageinfo
140
+ message = self.structure_message messageinfo
141
+ message = "[#{message[:from]}] !!! #{message[:msg]}"
142
+ if self.hiera?
143
+ Hiera.warn format_message msg
144
+ else
145
+ STDERR.puts message
146
+ end
85
147
  end
86
148
 
87
- def self.debug message
88
- STDERR.puts message if Eyaml::Options[:debug]
149
+ def self.info messageinfo
150
+ message = self.structure_message messageinfo
151
+ message = "[#{message[:from]}] #{message[:msg]}"
152
+ if self.hiera?
153
+ Hiera.debug message if Eyaml.verbosity_level > 0
154
+ else
155
+ STDERR.puts message if Eyaml.verbosity_level > 0
156
+ end
157
+ end
158
+
159
+ def self.debug messageinfo
160
+ message = self.structure_message messageinfo
161
+ message = "[#{message[:from]}] #{message[:msg]}"
162
+ if self.hiera?
163
+ Hiera.debug message if Eyaml.verbosity_level > 1
164
+ else
165
+ STDERR.puts message if Eyaml.verbosity_level > 1
166
+ end
89
167
  end
90
168
 
91
169
  end
@@ -1,6 +1,6 @@
1
1
  require 'hiera/backend/eyaml/encryptor'
2
- require 'hiera/backend/eyaml/actions/decrypt_action'
3
2
  require 'hiera/backend/eyaml/utils'
3
+ require 'hiera/backend/eyaml/options'
4
4
  require 'hiera/backend/eyaml/parser/parser'
5
5
  require 'yaml'
6
6
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hiera-eyaml
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.8
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Poulton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-25 00:00:00.000000000 Z
11
+ date: 2013-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: trollop
@@ -57,11 +57,7 @@ files:
57
57
  - hiera-eyaml.gemspec
58
58
  - lib/hiera/backend/eyaml.rb
59
59
  - lib/hiera/backend/eyaml/CLI.rb
60
- - lib/hiera/backend/eyaml/actions/createkeys_action.rb
61
- - lib/hiera/backend/eyaml/actions/decrypt_action.rb
62
- - lib/hiera/backend/eyaml/actions/edit_action.rb
63
- - lib/hiera/backend/eyaml/actions/encrypt_action.rb
64
- - lib/hiera/backend/eyaml/actions/recrypt_action.rb
60
+ - lib/hiera/backend/eyaml/commands.rb
65
61
  - lib/hiera/backend/eyaml/encryptor.rb
66
62
  - lib/hiera/backend/eyaml/encryptors/pkcs7.rb
67
63
  - lib/hiera/backend/eyaml/options.rb
@@ -69,6 +65,15 @@ files:
69
65
  - lib/hiera/backend/eyaml/parser/parser.rb
70
66
  - lib/hiera/backend/eyaml/parser/token.rb
71
67
  - lib/hiera/backend/eyaml/plugins.rb
68
+ - lib/hiera/backend/eyaml/subcommand.rb
69
+ - lib/hiera/backend/eyaml/subcommands/createkeys.rb
70
+ - lib/hiera/backend/eyaml/subcommands/decrypt.rb
71
+ - lib/hiera/backend/eyaml/subcommands/edit.rb
72
+ - lib/hiera/backend/eyaml/subcommands/encrypt.rb
73
+ - lib/hiera/backend/eyaml/subcommands/help.rb
74
+ - lib/hiera/backend/eyaml/subcommands/recrypt.rb
75
+ - lib/hiera/backend/eyaml/subcommands/unknown_command.rb
76
+ - lib/hiera/backend/eyaml/subcommands/version.rb
72
77
  - lib/hiera/backend/eyaml/utils.rb
73
78
  - lib/hiera/backend/eyaml_backend.rb
74
79
  - sublime_text/README.md
@@ -1,24 +0,0 @@
1
- require 'hiera/backend/eyaml/utils'
2
- require 'hiera/backend/eyaml/options'
3
-
4
- class Hiera
5
- module Backend
6
- module Eyaml
7
- module Actions
8
-
9
- class CreatekeysAction
10
-
11
- def self.execute
12
-
13
- encryptor = Encryptor.find Eyaml.default_encryption_scheme
14
- encryptor.create_keys
15
- nil
16
-
17
- end
18
-
19
- end
20
-
21
- end
22
- end
23
- end
24
- end
@@ -1,39 +0,0 @@
1
- require 'hiera/backend/eyaml'
2
- require 'hiera/backend/eyaml/utils'
3
- require 'hiera/backend/eyaml/options'
4
- require 'hiera/backend/eyaml/parser/parser'
5
-
6
- class Hiera
7
- module Backend
8
- module Eyaml
9
- module Actions
10
-
11
- class DecryptAction
12
-
13
- def self.execute
14
- parser = Parser::ParserFactory.encrypted_parser
15
- tokens = parser.parse(Eyaml::Options[:input_data])
16
- case Eyaml::Options[:source]
17
- when :eyaml
18
- decrypted = tokens.map{ |token| token.to_decrypted }
19
- decrypted.join
20
- else
21
- decrypted = tokens.map{ |token|
22
- case token.class.name
23
- when /::EncToken$/
24
- token.plain_text
25
- else
26
- token.match
27
- end
28
- }
29
- decrypted.join
30
- end
31
-
32
- end
33
-
34
- end
35
-
36
- end
37
- end
38
- end
39
- end
@@ -1,41 +0,0 @@
1
- require 'hiera/backend/eyaml/options'
2
- require 'hiera/backend/eyaml/parser/parser'
3
- require 'hiera/backend/eyaml/parser/encrypted_tokens'
4
-
5
- class Hiera
6
- module Backend
7
- module Eyaml
8
- module Actions
9
- class EncryptAction
10
-
11
- def self.execute
12
- case Eyaml::Options[:source]
13
- when :eyaml
14
- parser = Parser::ParserFactory.decrypted_parser
15
- tokens = parser.parse(Eyaml::Options[:input_data])
16
- encrypted = tokens.map{ |token| token.to_encrypted }
17
- encrypted.join
18
- else
19
- encryptor = Encryptor.find
20
- ciphertext = encryptor.encode( encryptor.encrypt(Eyaml::Options[:input_data]) )
21
- token = Parser::EncToken.new(:block, Eyaml::Options[:input_data], encryptor, ciphertext, nil, ' ')
22
- case Eyaml::Options[:output]
23
- when "block"
24
- token.to_encrypted :label => Eyaml::Options[:label], :use_chevron => !Eyaml::Options[:label].nil?, :format => :block
25
- when "string"
26
- token.to_encrypted :label => Eyaml::Options[:label], :format => :string
27
- when "examples"
28
- string = token.to_encrypted :label => Eyaml::Options[:label] || 'string', :format => :string
29
- block = token.to_encrypted :label => Eyaml::Options[:label] || 'block', :format => :block
30
- "#{string}\n\nOR\n\n#{block}"
31
- else
32
- token.to_encrypted :format => :string
33
- end
34
- end
35
- end
36
-
37
- end
38
- end
39
- end
40
- end
41
- end