hiera-file 1.0.1 → 1.1.0
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/lib/hiera/backend/file_backend.rb +49 -13
- data/spec/unit/file_backend_spec.rb +53 -10
- metadata +2 -2
@@ -1,44 +1,80 @@
|
|
1
|
+
require 'hiera/config'
|
2
|
+
|
1
3
|
class Hiera
|
2
4
|
module Backend
|
3
5
|
class File_backend
|
4
6
|
def initialize
|
5
7
|
Hiera.debug("Hiera File backend starting")
|
8
|
+
|
9
|
+
if Hiera::Config.include?(:file) and Hiera::Config[:file].has_key? :interpolate
|
10
|
+
@interpolate = Hiera::Config[:file][:interpolate]
|
11
|
+
else
|
12
|
+
@interpolate = true
|
13
|
+
end
|
6
14
|
end
|
7
15
|
|
8
16
|
def lookup(key, scope, order_override, resolution_type)
|
9
17
|
answer = nil
|
10
18
|
|
11
|
-
Hiera.debug("Looking up #{key} in
|
19
|
+
Hiera.debug("Looking up #{key} in File backend")
|
12
20
|
|
13
21
|
Backend.datasources(scope, order_override) do |source|
|
14
22
|
Hiera.debug("Hiera File_backend: looking for data source '#{source}'")
|
15
23
|
|
16
24
|
datadir = Backend.datafile(:file, scope, source, "d") or next
|
17
25
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
abs_path = File.expand_path(File.join(abs_datadir, key))
|
23
|
-
unless abs_path.index(abs_datadir) == 0
|
24
|
-
raise Exception, "Hiera File backend: key lookup outside of datadir '#{key}'"
|
25
|
-
end
|
26
|
+
validate_key_lookup!(datadir, key)
|
27
|
+
|
28
|
+
path = File.join(datadir, key)
|
29
|
+
next unless File.exist?(path)
|
26
30
|
|
27
|
-
|
28
|
-
data = File.read(abs_path)
|
31
|
+
data = File.read(path)
|
29
32
|
|
30
33
|
case resolution_type
|
31
34
|
when :array
|
32
35
|
answer ||= []
|
33
|
-
answer <<
|
36
|
+
answer << parse_answer(data, scope)
|
34
37
|
else
|
35
|
-
answer =
|
38
|
+
answer = parse_answer(data, scope)
|
36
39
|
break
|
37
40
|
end
|
38
41
|
end
|
39
42
|
|
40
43
|
answer
|
41
44
|
end
|
45
|
+
|
46
|
+
# Ensure that looked up files are within the datadir to prevent directory traversal
|
47
|
+
#
|
48
|
+
# @param datadir [String] The directory being used for the lookup
|
49
|
+
# @param key [String] The key being looked up
|
50
|
+
#
|
51
|
+
# @todo Raise a SecurityError instead of an Exception
|
52
|
+
# @raise [Exception] If the path to the data file is outside of the datadir
|
53
|
+
def validate_key_lookup!(datadir, key)
|
54
|
+
|
55
|
+
# Expand the datadir and path, and ensure that the datadir contains
|
56
|
+
# the given key. If the expanded key is outside of the datadir then
|
57
|
+
# this is a directory traversal attack and should be aborted.
|
58
|
+
abs_datadir = File.expand_path(datadir)
|
59
|
+
abs_path = File.expand_path(File.join(abs_datadir, key))
|
60
|
+
unless abs_path.index(abs_datadir) == 0
|
61
|
+
raise Exception, "Hiera File backend: key lookup outside of datadir '#{key}'"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Parse the answer according to the chosen interpolation mode
|
66
|
+
#
|
67
|
+
# @param data [String] The value to parse
|
68
|
+
# @param scope [Hash] The variable scope to use for interpolation
|
69
|
+
#
|
70
|
+
# @return [String] The interpolated data
|
71
|
+
def parse_answer(data, scope)
|
72
|
+
if @interpolate
|
73
|
+
Backend.parse_answer(data, scope)
|
74
|
+
else
|
75
|
+
data
|
76
|
+
end
|
77
|
+
end
|
42
78
|
end
|
43
79
|
end
|
44
80
|
end
|
@@ -7,8 +7,9 @@ class Hiera
|
|
7
7
|
before do
|
8
8
|
Hiera.stubs(:debug)
|
9
9
|
Hiera.stubs(:warn)
|
10
|
-
end
|
11
10
|
|
11
|
+
Hiera::Config.load(:backends => :file)
|
12
|
+
end
|
12
13
|
|
13
14
|
describe "#initialize" do
|
14
15
|
it "should announce its creation" do # because other specs checks this
|
@@ -23,8 +24,6 @@ class Hiera
|
|
23
24
|
Backend.stubs(:datasources).multiple_yields(["one"], ["two"])
|
24
25
|
end
|
25
26
|
|
26
|
-
subject { File_backend.new }
|
27
|
-
|
28
27
|
it "should look for data in all sources" do
|
29
28
|
Backend.expects(:datafile).with(:file, {}, "one", "d")
|
30
29
|
Backend.expects(:datafile).with(:file, {}, "two", "d")
|
@@ -59,16 +58,60 @@ class Hiera
|
|
59
58
|
subject.lookup("key", {}, nil, :array).should == ['value one', 'value two']
|
60
59
|
end
|
61
60
|
|
62
|
-
|
63
|
-
|
61
|
+
describe "With interpolation" do
|
62
|
+
after do
|
63
|
+
Hiera::Config.load({:file => {}})
|
64
|
+
end
|
64
65
|
|
65
|
-
|
66
|
-
|
66
|
+
describe "explicitly enabled" do
|
67
|
+
before do
|
68
|
+
Hiera::Config.load({:file => {:interpolate => true}})
|
69
|
+
end
|
67
70
|
|
68
|
-
|
69
|
-
|
71
|
+
it "should parse the answer for scope variables" do
|
72
|
+
scope = {'scope_val' => 'v'}
|
73
|
+
|
74
|
+
Backend.expects(:datafile).with(:file, scope, "one", "d").returns("/datadir/one.d")
|
75
|
+
Backend.expects(:datafile).with(:file, scope, "two", "d").never
|
76
|
+
|
77
|
+
File.expects(:exist?).with("/datadir/one.d/key").returns true
|
78
|
+
File.expects(:read).with("/datadir/one.d/key").returns '%{scope_val}alue'
|
79
|
+
|
80
|
+
subject.lookup("key", scope, nil, :priority).should == 'value'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "set to default" do
|
85
|
+
it "should parse the answer for scope variables" do
|
86
|
+
scope = {'scope_val' => 'v'}
|
87
|
+
|
88
|
+
Backend.expects(:datafile).with(:file, scope, "one", "d").returns("/datadir/one.d")
|
89
|
+
Backend.expects(:datafile).with(:file, scope, "two", "d").never
|
90
|
+
|
91
|
+
File.expects(:exist?).with("/datadir/one.d/key").returns true
|
92
|
+
File.expects(:read).with("/datadir/one.d/key").returns '%{scope_val}alue'
|
93
|
+
|
94
|
+
subject.lookup("key", scope, nil, :priority).should == 'value'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "explicitly disabled" do
|
99
|
+
before do
|
100
|
+
Hiera::Config.load({:file => {:interpolate => false}})
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should not parse the answer for scope variables" do
|
104
|
+
scope = {'scope_val' => 'v'}
|
105
|
+
|
106
|
+
Backend.expects(:datafile).with(:file, scope, "one", "d").returns("/datadir/one.d")
|
107
|
+
Backend.expects(:datafile).with(:file, scope, "two", "d").never
|
108
|
+
|
109
|
+
File.expects(:exist?).with("/datadir/one.d/key").returns true
|
110
|
+
File.expects(:read).with("/datadir/one.d/key").returns '%{scope_val}alue'
|
70
111
|
|
71
|
-
|
112
|
+
subject.lookup("key", scope, nil, :priority).should == '%{scope_val}alue'
|
113
|
+
end
|
114
|
+
end
|
72
115
|
end
|
73
116
|
|
74
117
|
it "should prevent directory traversal attacks" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hiera-file
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-05-06 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: hiera
|