hiera-eyaml 1.1.4 → 1.3.1

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