hiera-eyaml 2.0.0 → 2.0.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.
- checksums.yaml +7 -7
- data/.gitignore +2 -0
- data/Gemfile.lock +2 -2
- data/README.md +21 -0
- data/hiera-eyaml.gemspec +3 -2
- data/lib/hiera/backend/eyaml.rb +3 -3
- data/lib/hiera/backend/eyaml/encryptors/pkcs7.rb +9 -5
- data/lib/hiera/backend/eyaml/options.rb +1 -1
- data/lib/hiera/backend/eyaml/parser/encrypted_tokens.rb +1 -1
- data/lib/hiera/backend/eyaml/subcommand.rb +23 -0
- data/lib/hiera/backend/eyaml/utils.rb +1 -1
- data/lib/hiera/backend/eyaml_backend.rb +89 -78
- metadata +52 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
5
|
-
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 848cae1bca737c5e047b25c5fc409f62e1d4df8d
|
4
|
+
data.tar.gz: 4c9fddfcdc14727770af712e2cbef650b1f1a0b4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a982f17533e5edae37c2579b320b6e94eaf15d4523dfa21e23d8e7b540bd7b461a09bac16e43d863c9ffa576f90417303fae25bd3ef7e4fd4b401195ae72b50f
|
7
|
+
data.tar.gz: 2453d8553a3c731033161ce7c8181d210912e20095882e426ae6f5e3b47c6e720d2e8fa6a51f61857cd23dc9384019bf6cee71761547a4b5479268c7107e7298
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -233,6 +233,27 @@ things:
|
|
233
233
|
- nested thing 2.1
|
234
234
|
```
|
235
235
|
|
236
|
+
Configuration file for eyaml
|
237
|
+
----------------------------
|
238
|
+
|
239
|
+
Default parameters for the eyaml command line tool can be provided by creating a configuration YAML file.
|
240
|
+
|
241
|
+
The location of the file defaults to `~/.eyaml/config.yaml` but can be overriden by setting `EYAML_CONFIG` environment variable.
|
242
|
+
|
243
|
+
The file takes any long form argument that you can provide on the command line. For example, to override the pkcs7 keys:
|
244
|
+
```yaml
|
245
|
+
---
|
246
|
+
pkcs7_private_key: '~/keys/eyaml/private_key.pkcs7.pem'
|
247
|
+
pkcs7_public_key: '~/keys/eyaml/public_key.pkcs7.pem'
|
248
|
+
```
|
249
|
+
|
250
|
+
Or to override to use GPG by default:
|
251
|
+
```yaml
|
252
|
+
---
|
253
|
+
encrypt_method: 'gpg'
|
254
|
+
gpg_gnupghome: '~/alternative_gnupghome'
|
255
|
+
gpg_recipients: 'sihil@example.com,gtmtech@example.com,tpoulton@example.com'
|
256
|
+
```
|
236
257
|
|
237
258
|
Pluggable Encryption
|
238
259
|
--------------------
|
data/hiera-eyaml.gemspec
CHANGED
@@ -17,6 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
|
-
gem.add_dependency('
|
21
|
-
gem.add_dependency('
|
20
|
+
gem.add_dependency('hiera', '>= 1.2.1')
|
21
|
+
gem.add_dependency('trollop', '>= 2.0')
|
22
|
+
gem.add_dependency('highline', '>= 1.6.19')
|
22
23
|
end
|
data/lib/hiera/backend/eyaml.rb
CHANGED
@@ -2,7 +2,7 @@ class Hiera
|
|
2
2
|
module Backend
|
3
3
|
module Eyaml
|
4
4
|
|
5
|
-
VERSION = "2.0.
|
5
|
+
VERSION = "2.0.1"
|
6
6
|
DESCRIPTION = "Hiera-eyaml is a backend for Hiera which provides OpenSSL encryption/decryption for Hiera properties"
|
7
7
|
|
8
8
|
class RecoverableError < StandardError
|
@@ -15,7 +15,7 @@ class Hiera
|
|
15
15
|
def self.subcommand
|
16
16
|
@@subcommand
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def self.default_encryption_scheme= new_encryption
|
20
20
|
@@default_encryption_scheme = new_encryption
|
21
21
|
end
|
@@ -41,7 +41,7 @@ class Hiera
|
|
41
41
|
def self.subcommands
|
42
42
|
@@subcommands
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
@@ -11,12 +11,15 @@ class Hiera
|
|
11
11
|
class Pkcs7 < Encryptor
|
12
12
|
|
13
13
|
self.options = {
|
14
|
-
:private_key => { :desc => "
|
14
|
+
:private_key => { :desc => "Path to private key",
|
15
15
|
:type => :string,
|
16
16
|
:default => "./keys/private_key.pkcs7.pem" },
|
17
|
-
:public_key => { :desc => "
|
17
|
+
:public_key => { :desc => "Path to public key",
|
18
18
|
:type => :string,
|
19
|
-
:default => "./keys/public_key.pkcs7.pem" }
|
19
|
+
:default => "./keys/public_key.pkcs7.pem" },
|
20
|
+
:subject => { :desc => "Subject to use for certificate when creating keys",
|
21
|
+
:type => :string,
|
22
|
+
:default => "/" },
|
20
23
|
}
|
21
24
|
|
22
25
|
self.tag = "PKCS7"
|
@@ -59,14 +62,15 @@ class Hiera
|
|
59
62
|
|
60
63
|
public_key = self.option :public_key
|
61
64
|
private_key = self.option :private_key
|
65
|
+
subject = self.option :subject
|
62
66
|
|
63
67
|
key = OpenSSL::PKey::RSA.new(2048)
|
64
68
|
Utils.ensure_key_dir_exists private_key
|
65
69
|
Utils.write_important_file :filename => private_key, :content => key.to_pem, :mode => 0600
|
66
70
|
|
67
|
-
name = OpenSSL::X509::Name.parse("/")
|
68
71
|
cert = OpenSSL::X509::Certificate.new()
|
69
|
-
cert.
|
72
|
+
cert.subject = OpenSSL::X509::Name.parse(subject)
|
73
|
+
cert.serial = 1
|
70
74
|
cert.version = 2
|
71
75
|
cert.not_before = Time.now
|
72
76
|
cert.not_after = if 1.size == 8 # 64bit
|
@@ -24,7 +24,7 @@ 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 sprintf "%18s %-18s =
|
27
|
+
Utils::debug sprintf "%18s %-18s = %18s %-18s", "(#{k.class.name})", k.to_s, "(#{v.class.name})", v.to_s
|
28
28
|
end
|
29
29
|
Utils::debug "--------------------------------"
|
30
30
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'base64'
|
2
|
+
require 'yaml'
|
2
3
|
# require 'hiera/backend/eyaml/subcommands/unknown_command'
|
3
4
|
|
4
5
|
class Hiera
|
@@ -29,10 +30,32 @@ class Hiera
|
|
29
30
|
:short => 'h'}
|
30
31
|
]
|
31
32
|
|
33
|
+
def self.load_config_file
|
34
|
+
config_file=ENV['EYAML_CONFIG'] || "#{ENV['HOME']}/.eyaml/config.yaml"
|
35
|
+
begin
|
36
|
+
config = YAML.load_file(config_file)
|
37
|
+
Utils::info "Loaded config from #{config_file}"
|
38
|
+
config
|
39
|
+
rescue Errno::ENOENT, IndexError
|
40
|
+
{}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
32
44
|
def self.all_options
|
33
45
|
options = @@global_options.dup
|
34
46
|
options += self.options if self.options
|
35
47
|
options += Plugins.options
|
48
|
+
# merge in defaults from configuration file
|
49
|
+
config_file = self.load_config_file
|
50
|
+
options.map!{ | opt|
|
51
|
+
key_name = "#{opt[:name]}"
|
52
|
+
if config_file.has_key? key_name
|
53
|
+
opt[:default] = config_file[key_name]
|
54
|
+
opt
|
55
|
+
else
|
56
|
+
opt
|
57
|
+
end
|
58
|
+
}
|
36
59
|
options
|
37
60
|
end
|
38
61
|
|
@@ -2,123 +2,134 @@ require 'hiera/backend/eyaml/encryptor'
|
|
2
2
|
require 'hiera/backend/eyaml/utils'
|
3
3
|
require 'hiera/backend/eyaml/options'
|
4
4
|
require 'hiera/backend/eyaml/parser/parser'
|
5
|
+
require 'hiera/filecache'
|
6
|
+
|
5
7
|
require 'yaml'
|
6
8
|
|
7
9
|
class Hiera
|
8
10
|
module Backend
|
9
11
|
class Eyaml_backend
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
+
attr_reader :extension
|
14
|
+
|
15
|
+
def initialize(cache = nil)
|
16
|
+
debug("Hiera eYAML backend starting")
|
17
|
+
|
18
|
+
@cache = cache || Filecache.new
|
19
|
+
@extension = Config[:eyaml][:extension] || "eyaml"
|
13
20
|
end
|
14
21
|
|
15
22
|
def lookup(key, scope, order_override, resolution_type)
|
16
|
-
|
17
|
-
debug("Lookup called for key #{key}")
|
18
23
|
answer = nil
|
19
24
|
|
20
|
-
|
21
|
-
eyaml_file = Backend.datafile(:eyaml, scope, source, @extension) || next
|
25
|
+
parse_options(scope)
|
22
26
|
|
23
|
-
|
27
|
+
debug("Looking up #{key} in eYAML backend")
|
24
28
|
|
25
|
-
|
29
|
+
Backend.datasources(scope, order_override) do |source|
|
30
|
+
debug("Looking for data source #{source}")
|
31
|
+
eyaml_file = Backend.datafile(:eyaml, scope, source, extension) || next
|
26
32
|
|
27
|
-
next
|
28
|
-
debug ("Data contains valid YAML")
|
33
|
+
next unless File.exists?(eyaml_file)
|
29
34
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
parsed_answer = parse_answer(key, data[key], scope)
|
34
|
-
|
35
|
-
begin
|
36
|
-
case resolution_type
|
37
|
-
when :array
|
38
|
-
debug("Appending answer array")
|
39
|
-
raise Exception, "Hiera type mismatch: expected Array and got #{parsed_answer.class}" unless parsed_answer.kind_of? Array or parsed_answer.kind_of? String
|
40
|
-
answer ||= []
|
41
|
-
answer << parsed_answer
|
42
|
-
when :hash
|
43
|
-
debug("Merging answer hash")
|
44
|
-
raise Exception, "Hiera type mismatch: expected Hash and got #{parsed_answer.class}" unless parsed_answer.kind_of? Hash
|
45
|
-
answer ||= {}
|
46
|
-
answer = Backend.merge_answer(parsed_answer,answer)
|
47
|
-
else
|
48
|
-
debug("Assigning answer variable")
|
49
|
-
answer = parsed_answer
|
50
|
-
break
|
51
|
-
end
|
52
|
-
rescue NoMethodError
|
53
|
-
raise Exception, "Resolution type is #{resolution_type} but parsed_answer is a #{parsed_answer.class}"
|
35
|
+
data = @cache.read(eyaml_file, Hash) do |data|
|
36
|
+
YAML.load(data) || {}
|
54
37
|
end
|
55
|
-
end
|
56
38
|
|
57
|
-
|
58
|
-
|
39
|
+
next if data.empty?
|
40
|
+
next unless data.include?(key)
|
59
41
|
|
60
|
-
|
61
|
-
|
62
|
-
#
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
42
|
+
# Extra logging that we found the key. This can be outputted
|
43
|
+
# multiple times if the resolution type is array or hash but that
|
44
|
+
# should be expected as the logging will then tell the user ALL the
|
45
|
+
# places where the key is found.
|
46
|
+
debug("Found #{key} in #{source}")
|
47
|
+
|
48
|
+
# for array resolution we just append to the array whatever
|
49
|
+
# we find, we then goes onto the next file and keep adding to
|
50
|
+
# the array
|
51
|
+
#
|
52
|
+
# for priority searches we break after the first found data item
|
53
|
+
new_answer = parse_answer(data[key], scope)
|
54
|
+
case resolution_type
|
55
|
+
when :array
|
56
|
+
raise Exception, "Hiera type mismatch: expected Array and got #{new_answer.class}" unless new_answer.kind_of? Array or new_answer.kind_of? String
|
57
|
+
answer ||= []
|
58
|
+
answer << new_answer
|
59
|
+
when :hash
|
60
|
+
raise Exception, "Hiera type mismatch: expected Hash and got #{new_answer.class}" unless new_answer.kind_of? Hash
|
61
|
+
answer ||= {}
|
62
|
+
answer = Backend.merge_answer(new_answer,answer)
|
63
|
+
else
|
64
|
+
answer = new_answer
|
65
|
+
break
|
71
66
|
end
|
72
|
-
answer
|
73
|
-
elsif data.is_a?(Array)
|
74
|
-
answer = []
|
75
|
-
data.each do |item|
|
76
|
-
answer << parse_answer(key, item, scope, extra_data)
|
77
|
-
end
|
78
|
-
answer
|
79
67
|
end
|
80
|
-
end
|
81
68
|
|
82
|
-
|
83
|
-
block_string.gsub(/[ \n]/, '')
|
69
|
+
return answer
|
84
70
|
end
|
85
71
|
|
86
|
-
|
87
|
-
|
88
|
-
if encrypted? value
|
72
|
+
private
|
89
73
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
config_value = Backend.parse_string(Config[:eyaml][config_key], scope)
|
94
|
-
debug "Setting: #{config_key} = #{config_value}"
|
95
|
-
Eyaml::Options[config_key] = config_value
|
96
|
-
end
|
74
|
+
def debug(message)
|
75
|
+
Hiera.debug("[eyaml_backend]: #{message}")
|
76
|
+
end
|
97
77
|
|
98
|
-
|
78
|
+
def decrypt(data)
|
79
|
+
if encrypted?(data)
|
80
|
+
debug("Attempting to decrypt")
|
99
81
|
|
100
82
|
parser = Eyaml::Parser::ParserFactory.hiera_backend_parser
|
101
|
-
tokens = parser.parse(
|
83
|
+
tokens = parser.parse(data)
|
102
84
|
decrypted = tokens.map{ |token| token.to_plain_text }
|
103
85
|
plaintext = decrypted.join
|
104
86
|
|
105
87
|
plaintext.chomp
|
106
|
-
|
107
88
|
else
|
108
|
-
|
89
|
+
data
|
109
90
|
end
|
110
91
|
end
|
111
92
|
|
112
|
-
def encrypted?(
|
113
|
-
|
93
|
+
def encrypted?(data)
|
94
|
+
/.*ENC\[.*?\]/ =~ data ? true : false
|
95
|
+
end
|
96
|
+
|
97
|
+
def parse_answer(data, scope, extra_data={})
|
98
|
+
if data.is_a?(Numeric) or data.is_a?(TrueClass) or data.is_a?(FalseClass)
|
99
|
+
return data
|
100
|
+
elsif data.is_a?(String)
|
101
|
+
return parse_string(data, scope, extra_data)
|
102
|
+
elsif data.is_a?(Hash)
|
103
|
+
answer = {}
|
104
|
+
data.each_pair do |key, val|
|
105
|
+
interpolated_key = Backend.parse_string(key, scope, extra_data)
|
106
|
+
answer[interpolated_key] = parse_answer(val, scope, extra_data)
|
107
|
+
end
|
108
|
+
|
109
|
+
return answer
|
110
|
+
elsif data.is_a?(Array)
|
111
|
+
answer = []
|
112
|
+
data.each do |item|
|
113
|
+
answer << parse_answer(item, scope, extra_data)
|
114
|
+
end
|
115
|
+
|
116
|
+
return answer
|
117
|
+
end
|
114
118
|
end
|
115
119
|
|
116
|
-
def
|
117
|
-
|
120
|
+
def parse_options(scope)
|
121
|
+
Config[:eyaml].each do |key, value|
|
122
|
+
parsed_value = Backend.parse_string(value, scope)
|
123
|
+
Eyaml::Options[key] = parsed_value
|
124
|
+
debug("Set option: #{key} = #{parsed_value}")
|
125
|
+
end
|
126
|
+
|
127
|
+
Eyaml::Options[:source] = "hiera"
|
118
128
|
end
|
119
129
|
|
120
|
-
def
|
121
|
-
|
130
|
+
def parse_string(data, scope, extra_data={})
|
131
|
+
decrypted_data = decrypt(data)
|
132
|
+
Backend.parse_string(decrypted_data, scope, extra_data)
|
122
133
|
end
|
123
134
|
end
|
124
135
|
end
|
metadata
CHANGED
@@ -1,50 +1,55 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: hiera-eyaml
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
|
-
authors:
|
6
|
+
authors:
|
7
7
|
- Tom Poulton
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
11
|
+
|
12
|
+
date: 2014-03-07 00:00:00 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: hiera
|
16
|
+
prerelease: false
|
17
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - ">="
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.2.1
|
20
22
|
type: :runtime
|
23
|
+
version_requirements: *id001
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: trollop
|
21
26
|
prerelease: false
|
22
|
-
|
23
|
-
requirements:
|
24
|
-
- -
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version:
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: highline
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - '>='
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 1.6.19
|
27
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: "2.0"
|
34
32
|
type: :runtime
|
33
|
+
version_requirements: *id002
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: highline
|
35
36
|
prerelease: false
|
36
|
-
|
37
|
-
requirements:
|
38
|
-
- -
|
39
|
-
- !ruby/object:Gem::Version
|
37
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
40
41
|
version: 1.6.19
|
42
|
+
type: :runtime
|
43
|
+
version_requirements: *id003
|
41
44
|
description: Hiera backend for decrypting encrypted yaml properties
|
42
45
|
email:
|
43
|
-
executables:
|
46
|
+
executables:
|
44
47
|
- eyaml
|
45
48
|
extensions: []
|
49
|
+
|
46
50
|
extra_rdoc_files: []
|
47
|
-
|
51
|
+
|
52
|
+
files:
|
48
53
|
- .gitignore
|
49
54
|
- .travis.yml
|
50
55
|
- Gemfile
|
@@ -81,27 +86,30 @@ files:
|
|
81
86
|
- sublime_text/eyaml.syntax_definition.json
|
82
87
|
- tools/regem.sh
|
83
88
|
homepage: http://github.com/TomPoulton/hiera-eyaml
|
84
|
-
licenses:
|
89
|
+
licenses:
|
85
90
|
- MIT
|
86
91
|
metadata: {}
|
92
|
+
|
87
93
|
post_install_message:
|
88
94
|
rdoc_options: []
|
89
|
-
|
95
|
+
|
96
|
+
require_paths:
|
90
97
|
- lib
|
91
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
-
requirements:
|
93
|
-
-
|
94
|
-
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
version: '0'
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- &id004
|
101
|
+
- ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: "0"
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- *id004
|
101
107
|
requirements: []
|
108
|
+
|
102
109
|
rubyforge_project:
|
103
|
-
rubygems_version: 2.0.
|
110
|
+
rubygems_version: 2.0.14
|
104
111
|
signing_key:
|
105
112
|
specification_version: 4
|
106
113
|
summary: OpenSSL Encryption backend for Hiera
|
107
114
|
test_files: []
|
115
|
+
|