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.
- data/.gitignore +2 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +28 -0
- data/PLUGINS.md +4 -0
- data/README.md +51 -41
- data/bin/eyaml +9 -357
- data/features/decrypts.feature +44 -0
- data/features/edit.feature +54 -0
- data/features/encrypts.feature +26 -0
- data/features/keys.feature +13 -0
- data/features/outputs.feature +30 -0
- data/features/plugin.feature +35 -0
- data/features/plugin_api.feature +16 -0
- data/features/puppet.feature +15 -0
- data/features/sandbox/convert_decrypted_values_to_uppercase.sh +2 -0
- data/features/sandbox/keys/private_key.pkcs7.pem +27 -0
- data/features/sandbox/keys/public_key.pkcs7.pem +18 -0
- data/features/sandbox/pipe_string.sh +5 -0
- data/features/sandbox/puppet/environments/local/test.eyaml +3 -0
- data/features/sandbox/puppet/hiera.yaml +17 -0
- data/features/sandbox/puppet/manifests/init.pp +3 -0
- data/features/sandbox/puppet/modules/test/manifests/init.pp +18 -0
- data/features/sandbox/puppet/puppet.conf +6 -0
- data/features/sandbox/supply_password.sh +7 -0
- data/features/sandbox/test_input.bin +0 -0
- data/features/sandbox/test_input.encrypted.txt +1 -0
- data/features/sandbox/test_input.txt +3 -0
- data/features/sandbox/test_input.yaml +114 -0
- data/features/step_definitions/environment_overrides.rb +3 -0
- data/features/support/env.rb +26 -0
- data/features/support/setup_sandbox.rb +21 -0
- data/features/valid_encryption.feature +12 -0
- data/hiera-eyaml.gemspec +1 -1
- data/lib/hiera/backend/eyaml.rb +19 -0
- data/lib/hiera/backend/eyaml/CLI.rb +110 -0
- data/lib/hiera/backend/eyaml/actions/createkeys_action.rb +24 -0
- data/lib/hiera/backend/eyaml/actions/decrypt_action.rb +67 -0
- data/lib/hiera/backend/eyaml/actions/edit_action.rb +47 -0
- data/lib/hiera/backend/eyaml/actions/encrypt_action.rb +80 -0
- data/lib/hiera/backend/eyaml/encryptor.rb +71 -0
- data/lib/hiera/backend/eyaml/encryptors/pkcs7.rb +99 -0
- data/lib/hiera/backend/eyaml/options.rb +32 -0
- data/lib/hiera/backend/eyaml/plugins.rb +65 -0
- data/lib/hiera/backend/eyaml/utils.rb +83 -0
- data/lib/hiera/backend/eyaml_backend.rb +108 -113
- data/sublime_text/README.md +16 -0
- data/sublime_text/eyaml.sublime-package +0 -0
- data/sublime_text/eyaml.syntax_definition.json +288 -0
- data/{bin → tools}/regem.sh +1 -1
- metadata +71 -7
- data/keys/.keepme +0 -0
- data/lib/hiera/backend/version.rb +0 -7
data/Gemfile
CHANGED
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
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
|
|
10
|
-
encrypted string with ENC[] and place it in an eyaml file. You can mix your plain values
|
|
11
|
-
|
|
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
|
|
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
|
|
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. (
|
|
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
|
|
51
|
-
$ eyaml -e -s
|
|
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
|
-
|
|
55
|
-
redirect the output directly to a file:
|
|
52
|
+
### Decryption
|
|
56
53
|
|
|
57
|
-
|
|
54
|
+
To decrypt something, you need the public_key and the private_key.
|
|
58
55
|
|
|
59
|
-
|
|
56
|
+
To test decryption you can also use the eyaml tool if you have both keys
|
|
60
57
|
|
|
61
|
-
$
|
|
62
|
-
$
|
|
63
|
-
$ .......
|
|
64
|
-
$ ......]
|
|
58
|
+
$ eyaml -d -f filename # Decrypt a file
|
|
59
|
+
$ eyaml -d -s 'ENC[PKCS7,.....]' # Decrypt a string
|
|
65
60
|
|
|
66
|
-
###
|
|
61
|
+
### EYaml files
|
|
67
62
|
|
|
68
|
-
|
|
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
|
-
|
|
65
|
+
$ eyaml -i filename.eyaml # Edit an eyaml file in place
|
|
71
66
|
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
Multiple Encryption Types
|
|
68
|
+
=========================
|
|
74
69
|
|
|
75
|
-
|
|
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
|
-
|
|
72
|
+
Other encryption types (if the gems for them have been loaded) can be specified using the following formats:
|
|
79
73
|
|
|
80
|
-
|
|
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
|
-
#
|
|
98
|
-
:
|
|
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
|
-
|
|
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 '
|
|
4
|
-
require '
|
|
5
|
-
require '
|
|
6
|
-
require '
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
16
|
-
|
|
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
|