hiera-eyaml 1.1.4 → 1.3.1

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 (52) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +7 -0
  3. data/Gemfile.lock +28 -0
  4. data/PLUGINS.md +4 -0
  5. data/README.md +51 -41
  6. data/bin/eyaml +9 -357
  7. data/features/decrypts.feature +44 -0
  8. data/features/edit.feature +54 -0
  9. data/features/encrypts.feature +26 -0
  10. data/features/keys.feature +13 -0
  11. data/features/outputs.feature +30 -0
  12. data/features/plugin.feature +35 -0
  13. data/features/plugin_api.feature +16 -0
  14. data/features/puppet.feature +15 -0
  15. data/features/sandbox/convert_decrypted_values_to_uppercase.sh +2 -0
  16. data/features/sandbox/keys/private_key.pkcs7.pem +27 -0
  17. data/features/sandbox/keys/public_key.pkcs7.pem +18 -0
  18. data/features/sandbox/pipe_string.sh +5 -0
  19. data/features/sandbox/puppet/environments/local/test.eyaml +3 -0
  20. data/features/sandbox/puppet/hiera.yaml +17 -0
  21. data/features/sandbox/puppet/manifests/init.pp +3 -0
  22. data/features/sandbox/puppet/modules/test/manifests/init.pp +18 -0
  23. data/features/sandbox/puppet/puppet.conf +6 -0
  24. data/features/sandbox/supply_password.sh +7 -0
  25. data/features/sandbox/test_input.bin +0 -0
  26. data/features/sandbox/test_input.encrypted.txt +1 -0
  27. data/features/sandbox/test_input.txt +3 -0
  28. data/features/sandbox/test_input.yaml +114 -0
  29. data/features/step_definitions/environment_overrides.rb +3 -0
  30. data/features/support/env.rb +26 -0
  31. data/features/support/setup_sandbox.rb +21 -0
  32. data/features/valid_encryption.feature +12 -0
  33. data/hiera-eyaml.gemspec +1 -1
  34. data/lib/hiera/backend/eyaml.rb +19 -0
  35. data/lib/hiera/backend/eyaml/CLI.rb +110 -0
  36. data/lib/hiera/backend/eyaml/actions/createkeys_action.rb +24 -0
  37. data/lib/hiera/backend/eyaml/actions/decrypt_action.rb +67 -0
  38. data/lib/hiera/backend/eyaml/actions/edit_action.rb +47 -0
  39. data/lib/hiera/backend/eyaml/actions/encrypt_action.rb +80 -0
  40. data/lib/hiera/backend/eyaml/encryptor.rb +71 -0
  41. data/lib/hiera/backend/eyaml/encryptors/pkcs7.rb +99 -0
  42. data/lib/hiera/backend/eyaml/options.rb +32 -0
  43. data/lib/hiera/backend/eyaml/plugins.rb +65 -0
  44. data/lib/hiera/backend/eyaml/utils.rb +83 -0
  45. data/lib/hiera/backend/eyaml_backend.rb +108 -113
  46. data/sublime_text/README.md +16 -0
  47. data/sublime_text/eyaml.sublime-package +0 -0
  48. data/sublime_text/eyaml.syntax_definition.json +288 -0
  49. data/{bin → tools}/regem.sh +1 -1
  50. metadata +71 -7
  51. data/keys/.keepme +0 -0
  52. data/lib/hiera/backend/version.rb +0 -7
data/.gitignore CHANGED
@@ -3,3 +3,5 @@
3
3
  *.gradle
4
4
  keys/*.pem
5
5
  pkg/
6
+ tmp/
7
+ .DS_Store
data/Gemfile CHANGED
@@ -3,3 +3,10 @@ source 'https://rubygems.org/'
3
3
  gem 'highline'
4
4
  gem 'trollop'
5
5
 
6
+ group :development do
7
+ gem "aruba"
8
+ gem "hiera-eyaml-plaintext"
9
+ gem "puppet"
10
+ end
11
+
12
+
data/Gemfile.lock CHANGED
@@ -1,12 +1,40 @@
1
1
  GEM
2
2
  remote: https://rubygems.org/
3
3
  specs:
4
+ aruba (0.5.3)
5
+ childprocess (>= 0.3.6)
6
+ cucumber (>= 1.1.1)
7
+ rspec-expectations (>= 2.7.0)
8
+ builder (3.2.2)
9
+ childprocess (0.3.9)
10
+ ffi (~> 1.0, >= 1.0.11)
11
+ cucumber (1.3.5)
12
+ builder (>= 2.1.2)
13
+ diff-lcs (>= 1.1.3)
14
+ gherkin (~> 2.12.0)
15
+ multi_json (~> 1.7.5)
16
+ multi_test (>= 0.0.2)
17
+ diff-lcs (1.2.4)
18
+ ffi (1.9.0)
19
+ gherkin (2.12.0)
20
+ multi_json (~> 1.3)
21
+ hiera-eyaml (1.2.0)
22
+ highline (>= 1.6.19)
23
+ trollop (>= 2.0)
24
+ hiera-eyaml-plaintext (0.1)
25
+ hiera-eyaml (>= 1.2.0)
4
26
  highline (1.6.19)
27
+ multi_json (1.7.8)
28
+ multi_test (0.0.2)
29
+ rspec-expectations (2.14.0)
30
+ diff-lcs (>= 1.1.3, < 2.0)
5
31
  trollop (2.0)
6
32
 
7
33
  PLATFORMS
8
34
  ruby
9
35
 
10
36
  DEPENDENCIES
37
+ aruba
38
+ hiera-eyaml-plaintext
11
39
  highline
12
40
  trollop
data/PLUGINS.md ADDED
@@ -0,0 +1,4 @@
1
+ PLUGINS
2
+ =======
3
+
4
+ Take a look at the skeleton project hiera-eyaml-plaintext, for a bare-bones demo plugin that you can copy and make into your own encryption plugin for hiera-eyaml.
data/README.md CHANGED
@@ -6,16 +6,17 @@ within yaml type files to be used by Puppet.
6
6
 
7
7
  More info can be found [in this corresponding post](http://themettlemonkey.wordpress.com/2013/07/15/hiera-eyaml-per-value-encrypted-backend-for-hiera-and-puppet/).
8
8
 
9
- The Hiera eYaml backend uses yaml formatted files with the .eyaml extension. Simply wrap your
10
- encrypted string with ENC[] and place it in an eyaml file. You can mix your plain values
11
- in as well or separate them into different files.
9
+ The Hiera eYaml backend uses yaml formatted files with the .eyaml extension. Simply prefix your
10
+ encrypted string with the encryption method (PKCS7,) wrap it with ENC[] and place it in an eyaml file. You can mix your plain values in as well or separate them into different files.
11
+
12
+ Example:
12
13
 
13
14
  <pre>
14
15
  ---
15
16
  plain-property: You can see me
16
17
 
17
18
  encrypted-property: >
18
- ENC[Y22exl+OvjDe+drmik2XEeD3VQtl1uZJXFFF2NnrMXDWx0csyqLB/2NOWefv
19
+ ENC[PKCS7,Y22exl+OvjDe+drmik2XEeD3VQtl1uZJXFFF2NnrMXDWx0csyqLB/2NOWefv
19
20
  NBTZfOlPvMlAesyr4bUY4I5XeVbVk38XKxeriH69EFAD4CahIZlC8lkE/uDh
20
21
  jJGQfh052eonkungHIcuGKY/5sEbbZl/qufjAtp/ufor15VBJtsXt17tXP4y
21
22
  l5ZP119Fwq8xiREGOL0lVvFYJz2hZc1ppPCNG5lwuLnTekXN/OazNYpf4CMd
@@ -23,10 +24,7 @@ encrypted-property: >
23
24
  IZGeunzwhqfmEtGiqpvJJQ5wVRdzJVpTnANBA5qxeA==]
24
25
  </pre>
25
26
 
26
- eYaml also supports encrypted values within arrays, hashes, nested arrays and nested hashes
27
- (see below for examples)
28
-
29
- N.B. when using the multi-line string syntax (i.e. >) **don't wrap encrypted strings with "" or ''**
27
+ eYaml supports multiple encryption types, and encrypted values can occur within arrays, hashes, nested arrays and nested hashes
30
28
 
31
29
  Setup
32
30
  =====
@@ -37,47 +35,58 @@ Setup
37
35
 
38
36
  ### Generate keys
39
37
 
40
- The first step is to create a pair of keys on the Puppet master
38
+ The first step is to create a pair of keys:
41
39
 
42
40
  $ eyaml -c
43
41
 
44
- This creates a public and private key with default names in the default location. (/etc/hiera/keys directory)
42
+ This creates a public and private key with default names in the default location. (./keys)
45
43
 
46
44
  ### Encryption
47
45
 
48
46
  To encrypt something, you only need the public_key, so distribute that to people creating hiera properties
49
47
 
50
- $ eyaml -e filename # Encrypt a file
51
- $ eyaml -e -s text # Encrypt some text
48
+ $ eyaml -e -f filename # Encrypt a file
49
+ $ eyaml -e -s 'hello there' # Encrypt a string
52
50
  $ eyaml -e -p # Encrypt a password (prompt for it)
53
51
 
54
- You can also specify the name of the value and the output style (block or string) so that you can
55
- redirect the output directly to a file:
52
+ ### Decryption
56
53
 
57
- $ eyaml -e -n my-secret -s "Secret Text" -o block
54
+ To decrypt something, you need the public_key and the private_key.
58
55
 
59
- returns:
56
+ To test decryption you can also use the eyaml tool if you have both keys
60
57
 
61
- $ my-secret: >
62
- $ ENC[...
63
- $ .......
64
- $ ......]
58
+ $ eyaml -d -f filename # Decrypt a file
59
+ $ eyaml -d -s 'ENC[PKCS7,.....]' # Decrypt a string
65
60
 
66
- ### Decryption
61
+ ### EYaml files
67
62
 
68
- To decrypt something, you need the public_key and the private_key on the puppet master.
63
+ Once you have created a few eyaml files, with a mixture of encrypted and non-encrypted properties, you can edit the encrypted values in place, using the special edit mode of the eyaml utility
69
64
 
70
- To test decryption you can also use the eyaml tool if you have both keys
65
+ $ eyaml -i filename.eyaml # Edit an eyaml file in place
71
66
 
72
- $ eyaml -d filename # Decrypt a file (PEM format)
73
- $ eyaml -d -s SOME-ENCRYPTED-TEXT # Decrypt some text
67
+ Multiple Encryption Types
68
+ =========================
74
69
 
75
- Change the permissions so that the private key is only readable by the user that hiera (puppet) is
76
- running as.
70
+ hiera-eyaml backend is pluggable, so that further encryption types can be added as separate gems to the general mechanism which hiera-eyaml uses. Hiera-eyaml ships with one default mechanism of 'pkcs7', the encryption type widely used to sign smime email messages.
77
71
 
78
- ### Configure Hiera
72
+ Other encryption types (if the gems for them have been loaded) can be specified using the following formats:
79
73
 
80
- Next configure hiera.yaml to use the eyaml backend
74
+ <pre>
75
+ ENC[PKCS7,SOME_ENCRYPTED_VALUE] # a PKCS7 encrypted value
76
+ ENC[GPG,SOME_ENCRYPTED_VALUE] # a GPG encrypted value (hiera-eyaml-gpg)
77
+ ... etc ...
78
+ </pre>
79
+
80
+ When editing eyaml files, you will see that the unencrypted plaintext is marked in such a way as to identify the encryption method. This is so that the eyaml tool knows to encrypt it back using the correct method afterwards:
81
+
82
+ <pre>
83
+ some_key: DEC::PKCS7[very secret password]!
84
+ </pre>
85
+
86
+ Hiera
87
+ =====
88
+
89
+ To use eyaml with hiera and puppet, first configure hiera.yaml to use the eyaml backend
81
90
 
82
91
  <pre>
83
92
  ---
@@ -94,24 +103,20 @@ Next configure hiera.yaml to use the eyaml backend
94
103
  :eyaml:
95
104
  :datadir: '/etc/puppet/hieradata'
96
105
 
97
- # Optional. Default is /etc/hiera/keys/private_key.pem
98
- :private_key: /new/path/to/key/private_key.pem
106
+ # If using the pkcs7 encryptor (default)
107
+ :pkcs7_private_key: /path/to/private_key_file.pem
108
+ :pkcs7_public_key: /path/to/public_key_file.pem
99
109
 
100
- # Optional. Default is /etc/hiera/keys/public_key.pem
101
- :public_key: /new/path/to/key/public_key.pem
102
110
  </pre>
103
111
 
104
- ### YAML files
112
+ Then, edit your hiera yaml files (renaming them with the .eyaml extension), and insert your encrypted values:
105
113
 
106
- Once the value is encrypted, wrap it with ENC[] and place it in the .eyaml file.
107
-
108
- Usages:
109
114
  <pre>
110
115
  ---
111
116
  plain-property: You can see me
112
117
 
113
118
  cipher-property : >
114
- ENC[Y22exl+OvjDe+drmik2XEeD3VQtl1uZJXFFF2NnrMXDWx0csyqLB/2NOWefv
119
+ ENC[PKCS7,Y22exl+OvjDe+drmik2XEeD3VQtl1uZJXFFF2NnrMXDWx0csyqLB/2NOWefv
115
120
  NBTZfOlPvMlAesyr4bUY4I5XeVbVk38XKxeriH69EFAD4CahIZlC8lkE/uDh
116
121
  jJGQfh052eonkungHIcuGKY/5sEbbZl/qufjAtp/ufor15VBJtsXt17tXP4y
117
122
  l5ZP119Fwq8xiREGOL0lVvFYJz2hZc1ppPCNG5lwuLnTekXN/OazNYpf4CMd
@@ -125,7 +130,7 @@ environments:
125
130
  production:
126
131
  host: prod.org.com
127
132
  password: >
128
- ENC[Y22exl+OvjDe+drmik2XEeD3VQtl1uZJXFFF2NnrMXDWx0csyqLB/2NOWefv
133
+ ENC[PKCS7,Y22exl+OvjDe+drmik2XEeD3VQtl1uZJXFFF2NnrMXDWx0csyqLB/2NOWefv
129
134
  NBTZfOlPvMlAesyr4bUY4I5XeVbVk38XKxeriH69EFAD4CahIZlC8lkE/uDh
130
135
  jJGQfh052eonkungHIcuGKY/5sEbbZl/qufjAtp/ufor15VBJtsXt17tXP4y
131
136
  l5ZP119Fwq8xiREGOL0lVvFYJz2hZc1ppPCNG5lwuLnTekXN/OazNYpf4CMd
@@ -136,7 +141,7 @@ things:
136
141
  - thing 1
137
142
  - - nested thing 1.0
138
143
  - >
139
- ENC[Y22exl+OvjDe+drmik2XEeD3VQtl1uZJXFFF2NnrMXDWx0csyqLB/2NOWefv
144
+ ENC[PKCS7,Y22exl+OvjDe+drmik2XEeD3VQtl1uZJXFFF2NnrMXDWx0csyqLB/2NOWefv
140
145
  NBTZfOlPvMlAesyr4bUY4I5XeVbVk38XKxeriH69EFAD4CahIZlC8lkE/uDh
141
146
  jJGQfh052eonkungHIcuGKY/5sEbbZl/qufjAtp/ufor15VBJtsXt17tXP4y
142
147
  l5ZP119Fwq8xiREGOL0lVvFYJz2hZc1ppPCNG5lwuLnTekXN/OazNYpf4CMd
@@ -146,8 +151,13 @@ things:
146
151
  - nested thing 2.1
147
152
  </pre>
148
153
 
154
+ Notes
155
+ =====
156
+
157
+ If you do not specify an encryption method within ENC[] tags, it will be assumed to be PKCS7
158
+
149
159
  Authors
150
160
  =======
151
161
 
152
162
  - [Tom Poulton](http://github.com/TomPoulton) - Initial author. eyaml backend.
153
- - [Geoff Meakin](http://github.com/gtmtech) - Major contributor. eyaml command.
163
+ - [Geoff Meakin](http://github.com/gtmtech) - Major contributor. eyaml command.
data/bin/eyaml CHANGED
@@ -1,361 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'openssl'
4
- require 'base64'
5
- require 'trollop'
6
- require 'highline/import'
7
- require 'hiera/backend/version'
8
- require 'tempfile'
3
+ require 'rubygems'
4
+ require 'hiera/backend/eyaml/CLI'
5
+ require 'hiera/backend/eyaml/plugins'
6
+ require 'hiera/backend/eyaml/encryptors/pkcs7'
9
7
 
10
- ENCRYPTED_BLOCK = />\n( *)ENC\[([a-zA-Z0-9+\/ \n]+)\]/
11
- ENCRYPTED_STRING = /ENC\[([a-zA-Z0-9+\/]+)\]/
12
- DECRYPTED_BLOCK = />\n( *)ENC!\[(.+)\]!ENC/
13
- DECRYPTED_STRING = /ENC!\[(.+)\]!ENC/
8
+ # Register all plugins
9
+ Hiera::Backend::Eyaml::Encryptors::Pkcs7.register
10
+ Hiera::Backend::Eyaml::Plugins.find
14
11
 
15
- def ensure_key_dir_exists(key_file)
16
- key_dir = File.dirname(key_file)
17
-
18
- if !File.directory?(key_dir)
19
- Dir.mkdir(key_dir)
20
- puts "Created #{key_dir} dir for #{key_file}."
21
- end
22
- end
23
-
24
- def get_file_input(options)
25
- if options[:file]
26
- File.read options[:file]
27
- else
28
- STDIN.read
29
- end
30
- end
31
-
32
- def get_input(options)
33
- return options[:string] if options[:string]
34
-
35
- if options[:password]
36
- ask("Enter password: ") {|q| q.echo = "*" }
37
- end
38
-
39
- get_file_input(options)
40
- end
41
-
42
- def encrypt(public_key, plaintext)
43
- cipher = OpenSSL::Cipher::AES.new(256, :CBC)
44
- ciphertext_binary = OpenSSL::PKCS7::encrypt([public_key], plaintext, cipher, OpenSSL::PKCS7::BINARY).to_der
45
- Base64.encode64(ciphertext_binary).strip
46
- end
47
-
48
- def decrypt(public_key, private_key, ciphertext)
49
- ciphertext_decoded = Base64.decode64(ciphertext)
50
- pkcs7 = OpenSSL::PKCS7.new( ciphertext_decoded )
51
- pkcs7.decrypt(private_key, public_key)
52
- end
53
-
54
- def decrypt_eyaml(public_key, private_key, cipher_eyaml)
55
- # decrypt blocks first
56
- plain_block_eyaml = cipher_eyaml.gsub(ENCRYPTED_BLOCK) { |match|
57
- indentation = $1
58
- ciphertext = $2.gsub(/[ \n]/, '')
59
- plaintext = decrypt(public_key, private_key, ciphertext)
60
- ">\n"+indentation+"ENC![" + plaintext + "]!ENC"
61
- }
62
- # then decrypt strings
63
- plain_block_eyaml.gsub(ENCRYPTED_STRING) { |match|
64
- plaintext = decrypt(public_key, private_key, $1)
65
- "ENC![" + plaintext + "]!ENC"
66
- }
67
- end
68
-
69
- def encrypt_eyaml(public_key, plain_eyaml)
70
- # encrypt blocks
71
- cipher_block_eyaml = plain_eyaml.gsub(DECRYPTED_BLOCK) { |match|
72
- indentation = $1
73
- ciphertext = encrypt(public_key, $2).gsub(/\n/,"\n"+indentation)
74
- ">\n" + indentation + "ENC[" + ciphertext + "]"
75
- }
76
- # encrypt strings
77
- cipher_block_eyaml.gsub(DECRYPTED_STRING) { |match|
78
- ciphertext = encrypt(public_key, $1).gsub(/\n/,'')
79
- "ENC[" + ciphertext + "]"
80
- }
81
- end
82
-
83
- def shred(file, clean_size)
84
- [0xff, 0x55, 0xaa, 0x00].each do |byte|
85
- file.seek(0, IO::SEEK_SET)
86
- clean_size.times { file.print(byte.chr) }
87
- file.fsync
88
- end
89
- end
90
-
91
- options = Trollop::options do
92
-
93
- version "Hiera-eyaml version " + Hiera::Backend::Eyaml::VERSION.to_s
94
- banner <<-EOS
95
- Hiera-eyaml is a backend for Hiera which provides OpenSSL encryption/decryption for Hiera properties
96
-
97
- Usage:
98
- eyaml [options] [file-to-encrypt]
99
- EOS
100
-
101
- opt :createkeys, "Create public and private keys for use encrypting properties", :short => 'c'
102
- opt :encrypt, "Encrypt a string, password, file or stdin"
103
- opt :decrypt, "Decrypt a string, file or stdin"
104
- opt :eyaml, "Assume input is eyaml format"
105
- opt :edit, "Edit an encrypted file inplace, implies --eyaml"
106
- opt :password, "Encrypt a password entered on the terminal", :short => 'p'
107
- opt :string, "Encrypt a string provided on the command line", :short => 's', :type => :string
108
- opt :private_key, "Filename of the private_key", :type => :string, :default => "/etc/hiera/keys/private_key.pem"
109
- opt :public_key, "Filename of the public_key", :type => :string, :default => "/etc/hiera/keys/public_key.pem"
110
- opt :output, "Output mode to use when encrypting (examples, block or string)", :short => 'o', :type => :string, :default => "examples"
111
- opt :name, "Add the name for the eyaml key (example, myvar: )", :short => 'n', :type => :string
112
- end
113
-
114
- main_option_count = 0
115
- main_option_count += 1 if options[:createkeys]
116
- main_option_count += 1 if options[:encrypt]
117
- main_option_count += 1 if options[:decrypt]
118
- main_option_count += 1 if options[:edit]
119
-
120
- Trollop::die "You can only specify one main action" if main_option_count > 1
121
- Trollop::die "You cannot specify --password and --string" if options[:password] and options[:string]
122
-
123
- options[:file] = ARGV[0]
124
- if options[:file] and (options[:password] or options[:string])
125
- $stderr.puts "WARN: file supplied but will be shadowed by string or password"
126
- end
127
-
128
- if options[:createkeys]
129
-
130
- # Try to do equivalent of:
131
- # openssl req -x509 -nodes -days 100000 -newkey rsa:2048 -keyout privatekey.pem -out publickey.pem -subj '/'
132
-
133
- ensure_key_dir_exists(options[:private_key])
134
- ensure_key_dir_exists(options[:public_key])
135
-
136
- key = OpenSSL::PKey::RSA.new(2048)
137
- open( options[:private_key], "w" ) do |io|
138
- io.write(key.to_pem)
139
- end
140
-
141
- $stderr.puts "#{options[:private_key]} created."
142
-
143
- name = OpenSSL::X509::Name.parse("/")
144
- cert = OpenSSL::X509::Certificate.new()
145
- cert.serial = 0
146
- cert.version = 2
147
- cert.not_before = Time.now
148
- cert.not_after = Time.now + 50 * 365 * 24 * 60 * 60
149
- cert.public_key = key.public_key
150
-
151
- ef = OpenSSL::X509::ExtensionFactory.new
152
- ef.subject_certificate = cert
153
- ef.issuer_certificate = cert
154
- cert.extensions = [
155
- ef.create_extension("basicConstraints","CA:TRUE", true),
156
- ef.create_extension("subjectKeyIdentifier", "hash"),
157
- # ef.create_extension("keyUsage", "cRLSign,keyCertSign", true),
158
- ]
159
- cert.add_extension ef.create_extension("authorityKeyIdentifier",
160
- "keyid:always,issuer:always")
161
-
162
- cert.sign key, OpenSSL::Digest::SHA1.new
163
-
164
- open( options[:public_key], "w" ) do |io|
165
- io.write(cert.to_pem)
166
- end
167
- $stderr.puts "#{options[:public_key]} created."
168
- exit
169
- end
170
-
171
- if options[:eyaml]
172
-
173
- if options[:decrypt]
174
- # prepare to decrypt blocks
175
- private_key_pem = File.read( options[:private_key] )
176
- private_key = OpenSSL::PKey::RSA.new( private_key_pem )
177
-
178
- public_key_pem = File.read( options[:public_key] )
179
- public_key = OpenSSL::X509::Certificate.new( public_key_pem )
180
-
181
- eyaml = get_file_input options
182
- plain_eyaml = decrypt_eyaml(public_key, private_key, eyaml)
183
-
184
- puts plain_eyaml
185
- exit
186
- end
187
-
188
- if options[:encrypt]
189
- # prepare to encrypt blocks
190
- public_key_pem = File.read( options[:public_key] )
191
- public_key = OpenSSL::X509::Certificate.new( public_key_pem )
192
-
193
- eyaml = get_file_input options
194
- cipher_eyaml = encrypt_yaml(public_key, eyaml)
195
-
196
- puts eyaml
197
- exit
198
- end
199
-
200
- else
201
-
202
- if options[:encrypt]
203
- plaintext = get_input options
204
-
205
- if plaintext.nil? or plaintext.length == 0
206
- $stderr.puts "Specify a string or --file to encrypt something. See --help for more usage instructions."
207
- exit
208
- end
209
-
210
- public_key_pem = File.read( options[:public_key] )
211
- public_key = OpenSSL::X509::Certificate.new( public_key_pem )
212
-
213
- ciphertext_as_block = encrypt(public_key, plaintext)
214
- ciphertext_as_string = ciphertext_as_block.split("\n").join('')
215
-
216
- case options[:output]
217
- when "examples"
218
- if options[:name].nil?
219
- puts "string: ENC[#{ciphertext_as_string}]\n\nOR\n\n"
220
- puts "block: >"
221
- puts " ENC[" + ciphertext_as_block.gsub(/\n/, "\n ") + "]"
222
- else
223
- puts options[:name] + ": ENC[#{ciphertext_as_string}]\n\nOR\n\n"
224
- puts options[:name] +": >"
225
- puts " ENC[" + ciphertext_as_block.gsub(/\n/, "\n ") + "]"
226
- puts
227
- end
228
- when "block"
229
- if options[:name].nil?
230
- puts "ENC[" + ciphertext_as_block + "]"
231
- else
232
- puts options[:name] + ": >"
233
- puts " ENC[" + ciphertext_as_block.gsub(/\n/, "\n ") + "]"
234
- puts
235
- end
236
- when "string"
237
- if options[:name].nil?
238
- puts "ENC[#{ciphertext_as_string}]"
239
- else
240
- puts options[:name] + ": ENC[#{ciphertext_as_string}]"
241
- puts
242
- end
243
- else
244
- $stderr.puts "Unknown output option: " + options[:output]
245
- exit 1
246
- end
247
- exit
248
-
249
- end
250
-
251
- if options[:decrypt]
252
-
253
- ciphertext = get_input options
254
- if ciphertext.nil? or ciphertext.length == 0
255
- $stderr.puts "Specify a string or --file to decrypt something. See --help for more usage instructions."
256
- exit 1
257
- end
258
-
259
- if ciphertext.start_with? "ENC["
260
-
261
- ciphertext = ciphertext[4..-2]
262
-
263
- private_key_pem = File.read( options[:private_key] )
264
- private_key = OpenSSL::PKey::RSA.new( private_key_pem )
265
-
266
- public_key_pem = File.read( options[:public_key] )
267
- public_key = OpenSSL::X509::Certificate.new( public_key_pem )
268
-
269
- plaintext = decrypt(public_key, private_key, ciphertext)
270
- puts "#{plaintext}"
271
- exit
272
-
273
- else
274
-
275
- $stderr.puts "Ciphertext is not an eyaml encrypted string (Does not start with ENC[...])"
276
- exit 1
277
-
278
- end
279
-
280
- exit
281
-
282
- end
283
- end
284
-
285
-
286
- if options[:edit]
287
- $stderr.puts "Launching edit mode"
288
- # prepare to edit blocks
289
- private_key_pem = File.read( options[:private_key] )
290
- private_key = OpenSSL::PKey::RSA.new( private_key_pem )
291
-
292
- public_key_pem = File.read( options[:public_key] )
293
- public_key = OpenSSL::X509::Certificate.new( public_key_pem )
294
-
295
- original_eyaml = File.read( options[:file] )
296
- original_size = original_eyaml.length
297
- plain_eyaml = decrypt_eyaml(public_key, private_key, original_eyaml)
298
-
299
- # write temp file
300
- plain_file = Tempfile.open('eyaml_edit')
301
- plain_file.puts plain_eyaml
302
- plain_file.flush
303
-
304
- # open editor
305
- $editor = ENV['EDITOR']
306
- if $editor == nil
307
- %w{/usr/bin/sensible-editor /usr/bin/editor /usr/bin/vim /usr/bin/vi}.each do |editor|
308
- if FileTest.executable?(editor)
309
- $editor = editor
310
- break
311
- end
312
- end
313
- end
314
- $stderr.puts "Opening decrypted file for editing in " + $editor
315
- system($editor, plain_file.path)
316
- status = $?
317
-
318
- throw "Process has not exited!?" unless status.exited?
319
-
320
- unless status.exitstatus == 0
321
- $syserr.puts "Editor did not exit successfully (exit code #{status.exitstatus}), aborting"
322
- exit 1
323
- end
324
-
325
- # some editors do not write new content in place, but instead
326
- # make a new file and more it in the old file's place.
327
- begin
328
- reopened_plain_file = File.open(plain_file.path, "r+")
329
- rescue Exception => e
330
- STDERR.puts e
331
- exit 1
332
- end
333
- new_eyaml = reopened_plain_file.read
334
-
335
- # make sure nothing is left on disk
336
- new_size = new_eyaml.length
337
- old_size = plain_eyaml.length
338
- clear_size = (new_size > old_size) ? new_size : old_size
339
- shred(plain_file, clear_size)
340
- plain_file.close true
341
- shred(reopened_plain_file, clear_size)
342
- reopened_plain_file.close
343
-
344
- if new_eyaml.length == 0
345
- $stderr.puts "Replacement content is empty, aborting"
346
- exit 1
347
- end
348
-
349
- if (new_eyaml == plain_eyaml)
350
- $stderr.puts "No changes made, aborting"
351
- exit 1
352
- end
353
-
354
- # re-encrypt the file again, currently we re-encrypt indiscriminately
355
- cipher_eyaml = encrypt_eyaml(public_key, new_eyaml)
356
-
357
- File.open(options[:file], 'w') { |file|
358
- file.write(cipher_eyaml)
359
- }
360
- exit
361
- end
12
+ Hiera::Backend::Eyaml::CLI.parse
13
+ Hiera::Backend::Eyaml::CLI.execute