From 2ce669c7f8aea6b66b2150798a5ef4d253b00a2e Mon Sep 17 00:00:00 2001 From: Jeff McCune Date: Wed, 7 Mar 2012 11:52:30 -0800 Subject: (#12357) Add validate_absolute_path() function This patch adds a new function to validate if a string is an absolute filesystem path or not. The intent of this is to make this functionality generic and reusable. Josh left a comment in another pull request I had: If node_installdir or $node_vardir is not defined, then we should raise an error, otherwise we may create a scheduled task to an untrusted directory. One solution to this comment is to validate the Puppet variable is an absolute path. Examples of this function look like: function_validate_absolute_path Using Puppet::Parser::Scope.new Garbage inputs validate_absolute_path(nil) should fail validate_absolute_path([nil]) should fail validate_absolute_path({"foo"=>"bar"}) should fail validate_absolute_path({}) should fail validate_absolute_path("") should fail relative paths validate_absolute_path("relative1") should fail validate_absolute_path(".") should fail validate_absolute_path("..") should fail validate_absolute_path("./foo") should fail validate_absolute_path("../foo") should fail validate_absolute_path("etc/puppetlabs/puppet") should fail validate_absolute_path("opt/puppet/bin") should fail absolute paths validate_absolute_path("C:/") should not fail validate_absolute_path("C:\\") should not fail validate_absolute_path("C:\\WINDOWS\\System32") should not fail validate_absolute_path("C:/windows/system32") should not fail validate_absolute_path("X:/foo/bar") should not fail validate_absolute_path("X:\\foo\\bar") should not fail validate_absolute_path("/var/tmp") should not fail validate_absolute_path("/var/lib/puppet") should not fail validate_absolute_path("/var/opt/../lib/puppet") should not fail validate_absolute_path("C:\\Program Files (x86)\\Puppet Labs\\Puppet Enterprise") should not fail validate_absolute_path("C:/Program Files (x86)/Puppet Labs/Puppet Enterprise") should not fail Finished in 0.05637 seconds 23 examples, 0 failures --- .../parser/functions/validate_absolute_path.rb | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 lib/puppet/parser/functions/validate_absolute_path.rb (limited to 'lib/puppet/parser/functions/validate_absolute_path.rb') diff --git a/lib/puppet/parser/functions/validate_absolute_path.rb b/lib/puppet/parser/functions/validate_absolute_path.rb new file mode 100644 index 0000000..46f86ec --- /dev/null +++ b/lib/puppet/parser/functions/validate_absolute_path.rb @@ -0,0 +1,38 @@ +module Puppet::Parser::Functions + newfunction(:validate_absolute_path, :doc => <<-'ENDHEREDOC') do |args| + Validate the string represents an absolute path in the filesystem. This function works + for windows and unix style paths. + + The following values will pass: + + $my_path = "C:/Program Files (x86)/Puppet Labs/Puppet" + validate_absolute_path($my_path) + $my_path2 = "/var/lib/puppet" + validate_absolute_path($my_path2) + + + The following values will fail, causing compilation to abort: + + validate_absolute_path(true) + validate_absolute_path([ 'var/lib/puppet', '/var/foo' ]) + validate_absolute_path([ '/var/lib/puppet', 'var/foo' ]) + $undefined = undef + validate_absolute_path($undefined) + + ENDHEREDOC + + require 'puppet/util' + + unless args.length > 0 then + raise Puppet::ParseError, ("validate_absolute_path(): wrong number of arguments (#{args.length}; must be > 0)") + end + + args.each do |arg| + # This logic was borrowed from + # [lib/puppet/file_serving/base.rb](https://github.com/puppetlabs/puppet/blob/master/lib/puppet/file_serving/base.rb) + unless Puppet::Util.absolute_path?(arg, :posix) or Puppet::Util.absolute_path?(arg, :windows) + raise Puppet::ParseError, ("#{arg.inspect} is not an absolute path.") + end + end + end +end -- cgit v1.2.3 From 31944c986345a135a3e68247c6d3e644ea369089 Mon Sep 17 00:00:00 2001 From: Jeff McCune Date: Mon, 12 Mar 2012 15:53:02 -0700 Subject: (#12357) Fix broken compatibility with Puppet 2.6 Without this patch, the previous change set to the validate_absolute_path() parser function contains Puppet 2.6 incompatible changes. stdlib 2.x is compatible with Puppet 2.6. These changes are a problem because we cannot introduce backwards incompatible changes in a minor release. This patch fixes the problem by back porting the implementation of the `Puppet::Util.absolute_path?` from 2.7.x to the function block itself. The function block tests to see if `Puppet::Util.absolute_path?` will respond and if not, falls back to the inline back ported implementation. The spec tests have been updated to simulate the behavior of Puppet 2.6 even when running with Puppet 2.7. --- .../parser/functions/validate_absolute_path.rb | 22 +++++- .../functions/validate_absolute_path_spec.rb | 87 ++++++++++++---------- 2 files changed, 67 insertions(+), 42 deletions(-) (limited to 'lib/puppet/parser/functions/validate_absolute_path.rb') diff --git a/lib/puppet/parser/functions/validate_absolute_path.rb b/lib/puppet/parser/functions/validate_absolute_path.rb index 46f86ec..fe27974 100644 --- a/lib/puppet/parser/functions/validate_absolute_path.rb +++ b/lib/puppet/parser/functions/validate_absolute_path.rb @@ -30,8 +30,26 @@ module Puppet::Parser::Functions args.each do |arg| # This logic was borrowed from # [lib/puppet/file_serving/base.rb](https://github.com/puppetlabs/puppet/blob/master/lib/puppet/file_serving/base.rb) - unless Puppet::Util.absolute_path?(arg, :posix) or Puppet::Util.absolute_path?(arg, :windows) - raise Puppet::ParseError, ("#{arg.inspect} is not an absolute path.") + + # Puppet 2.7 and beyond will have Puppet::Util.absolute_path? Fall back to a back-ported implementation otherwise. + if Puppet::Util.respond_to?(:absolute_path?) then + unless Puppet::Util.absolute_path?(arg, :posix) or Puppet::Util.absolute_path?(arg, :windows) + raise Puppet::ParseError, ("#{arg.inspect} is not an absolute path.") + end + else + # This code back-ported from 2.7.x's lib/puppet/util.rb Puppet::Util.absolute_path? + # Determine in a platform-specific way whether a path is absolute. This + # defaults to the local platform if none is specified. + # Escape once for the string literal, and once for the regex. + slash = '[\\\\/]' + name = '[^\\\\/]+' + regexes = { + :windows => %r!^(([A-Z]:#{slash})|(#{slash}#{slash}#{name}#{slash}#{name})|(#{slash}#{slash}\?#{slash}#{name}))!i, + :posix => %r!^/!, + } + + rval = (!!(arg =~ regexes[:posix])) || (!!(arg =~ regexes[:windows])) + rval or raise Puppet::ParseError, ("#{arg.inspect} is not an absolute path.") end end end diff --git a/spec/unit/puppet/parser/functions/validate_absolute_path_spec.rb b/spec/unit/puppet/parser/functions/validate_absolute_path_spec.rb index 2b44f50..1e0b5ac 100644 --- a/spec/unit/puppet/parser/functions/validate_absolute_path_spec.rb +++ b/spec/unit/puppet/parser/functions/validate_absolute_path_spec.rb @@ -5,34 +5,67 @@ describe Puppet::Parser::Functions.function(:validate_absolute_path) do Puppet::Parser::Functions.autoloader.loadall end - let(:scope) do - scope = Puppet::Parser::Scope.new - end - # The subject of these examplres is the method itself. subject do - scope.method :function_validate_absolute_path + Puppet::Parser::Scope.new.method :function_validate_absolute_path end - context 'Using Puppet::Parser::Scope.new' do + describe "Valid Paths" do + def self.valid_paths + %w{ + C:/ + C:\\ + C:\\WINDOWS\\System32 + C:/windows/system32 + X:/foo/bar + X:\\foo\\bar + /var/tmp + /var/lib/puppet + /var/opt/../lib/puppet + } + end - describe 'Garbage inputs' do - paths = [ + context "Without Puppet::Util.absolute_path? (e.g. Puppet <= 2.6)" do + before :each do + # The intent here is to mock Puppet to behave like Puppet 2.6 does. + # Puppet 2.6 does not have the absolute_path? method. This is only a + # convenience test, stdlib should be run with the Puppet 2.6.x in the + # $LOAD_PATH in addition to 2.7.x and master. + Puppet::Util.expects(:respond_to?).with(:absolute_path?).returns(false) + end + valid_paths.each do |path| + it "validate_absolute_path(#{path.inspect}) should not fail" do + expect { subject.call [path] }.not_to raise_error Puppet::ParseError + end + end + end + + context "Puppet without mocking" do + valid_paths.each do |path| + it "validate_absolute_path(#{path.inspect}) should not fail" do + expect { subject.call [path] }.not_to raise_error Puppet::ParseError + end + end + end + end + + describe 'Invalid paths' do + context 'Garbage inputs' do + [ nil, [ nil ], { 'foo' => 'bar' }, { }, '', - ] - - paths.each do |path| + ].each do |path| it "validate_absolute_path(#{path.inspect}) should fail" do expect { subject.call [path] }.to raise_error Puppet::ParseError end end end - describe 'relative paths' do - paths = %w{ + + context 'Relative paths' do + %w{ relative1 . .. @@ -40,37 +73,11 @@ describe Puppet::Parser::Functions.function(:validate_absolute_path) do ../foo etc/puppetlabs/puppet opt/puppet/bin - } - - paths.each do |path| + }.each do |path| it "validate_absolute_path(#{path.inspect}) should fail" do expect { subject.call [path] }.to raise_error Puppet::ParseError end end end - describe 'absolute paths' do - paths = %w{ - C:/ - C:\\ - C:\\WINDOWS\\System32 - C:/windows/system32 - X:/foo/bar - X:\\foo\\bar - /var/tmp - /var/lib/puppet - /var/opt/../lib/puppet - } - - paths = paths + [ - 'C:\\Program Files (x86)\\Puppet Labs\\Puppet Enterprise', - 'C:/Program Files (x86)/Puppet Labs/Puppet Enterprise', - ] - - paths.each do |path| - it "validate_absolute_path(#{path.inspect}) should not fail" do - expect { subject.call [path] }.not_to raise_error - end - end - end end end -- cgit v1.2.3