diff options
-rwxr-xr-x | lib/puppet/network/authstore.rb | 82 | ||||
-rw-r--r-- | spec/unit/network/authstore.rb | 105 |
2 files changed, 106 insertions, 81 deletions
diff --git a/lib/puppet/network/authstore.rb b/lib/puppet/network/authstore.rb index 4707f36a5..ab31faec8 100755 --- a/lib/puppet/network/authstore.rb +++ b/lib/puppet/network/authstore.rb @@ -220,8 +220,6 @@ module Puppet # and we're called with a MatchData whose capture 1 is puppet # we'll return a pattern of puppet.reductivelabs.com def interpolate(match) - return self if @name == :ip - clone = dup clone.pattern = clone.pattern.reverse.collect do |p| p.gsub(/\$(\d)/) { |m| match[$1.to_i] } @@ -279,63 +277,41 @@ module Puppet # Parse our input pattern and figure out what kind of allowal # statement it is. The output of this is used for later matching. def parse(value) - case value - when /^(\d+\.){1,3}\*$/ # an ip address with a '*' at the end + # Use the IPAddr class to determine if we've got a + # valid IP address. + @length = Integer($1) if value =~ /\/(\d+)$/ + begin + @pattern = IPAddr.new(value) @name = :ip - match = $1 - match.sub!(".", '') - ary = value.split(".") - - mask = case ary.index(match) - when 0; 8 - when 1; 16 - when 2; 24 - else - raise AuthStoreError, "Invalid IP pattern %s" % value - end - - @length = mask - - ary.pop - while ary.length < 4 - ary.push("0") - end - - begin - @pattern = IPAddr.new(ary.join(".") + "/" + mask.to_s) - rescue ArgumentError => detail - raise AuthStoreError, "Invalid IP address pattern %s" % value - end - when /^([a-zA-Z][-\w]*\.)+[-\w]+$/ # a full hostname - # Change to /^([a-zA-Z][-\w]*\.)+[-\w]+\.?$/ for FQDN support - @name = :domain - @pattern = munge_name(value) - when /^\*(\.([a-zA-Z][-\w]*)){1,}$/ # *.domain.com - @name = :domain - @pattern = munge_name(value) - @pattern.pop # take off the '*' - @length = @pattern.length - when /\$\d+/ # a backreference pattern ala $1.reductivelabs.com or 192.168.0.$1 or $1.$2 - @name = :dynamic - @pattern = munge_name(value) - else - # Else, use the IPAddr class to determine if we've got a - # valid IP address. - if value =~ /\/(\d+)$/ - @length = Integer($1) - end - begin - @pattern = IPAddr.new(value) + rescue ArgumentError => detail + case value + when /^(\d+\.){1,3}\*$/ # an ip address with a '*' at the end @name = :ip - rescue ArgumentError => detail - # so nothing matched, let's match as an opaque value - # some sanity checks first - unless value =~ /^[a-zA-Z0-9][-a-zA-Z0-9_.@]*$/ - raise AuthStoreError, "Invalid pattern %s" % value + segments = value.split(".")[0..-2] + @length = 8*segments.length + begin + @pattern = IPAddr.new((segments+[0,0,0])[0,4].join(".") + "/" + @length.to_s) + rescue ArgumentError => detail + raise AuthStoreError, "Invalid IP address pattern %s" % value end + when /^([a-zA-Z0-9][-\w]*\.)+[-\w]+$/ # a full hostname + # Change to /^([a-zA-Z][-\w]*\.)+[-\w]+\.?$/ for FQDN support + @name = :domain + @pattern = munge_name(value) + when /^\*(\.([a-zA-Z][-\w]*)){1,}$/ # *.domain.com + @name = :domain + @pattern = munge_name(value) + @pattern.pop # take off the '*' + @length = @pattern.length + when /\$\d+/ # a backreference pattern ala $1.reductivelabs.com or 192.168.0.$1 or $1.$2 + @name = :dynamic + @pattern = munge_name(value) + when /^[a-zA-Z0-9][-a-zA-Z0-9_.@]*$/ @pattern = [value] @length = nil # force an exact match @name = :opaque + else + raise AuthStoreError, "Invalid pattern %s" % value end end end diff --git a/spec/unit/network/authstore.rb b/spec/unit/network/authstore.rb index 4da3714ae..55b2c7bbc 100644 --- a/spec/unit/network/authstore.rb +++ b/spec/unit/network/authstore.rb @@ -6,25 +6,46 @@ require 'puppet/network/authconfig' describe Puppet::Network::AuthStore::Declaration do - describe "when the pattern is simple numeric IP" do - before :each do - @ip = '100.101.99.98' - @declaration = Puppet::Network::AuthStore::Declaration.new(:allow,@ip) - end - it "should match the specified IP" do - @declaration.should be_match('www.testsite.org',@ip) + ['100.101.99.98','100.100.100.100','1.2.3.4','11.22.33.44'].each { |ip| + describe "when the pattern is a simple numeric IP such as #{ip}" do + before :each do + @declaration = Puppet::Network::AuthStore::Declaration.new(:allow,ip) + end + it "should match the specified IP" do + @declaration.should be_match('www.testsite.org',ip) + end + it "should not match other IPs" do + @declaration.should_not be_match('www.testsite.org','200.101.99.98') + end end - it "should not match other IPs" do - @declaration.should_not be_match('www.testsite.org','200.101.99.98') - end - end + + (1..3).each { |n| + describe "when the pattern is a IP mask with #{n} numeric segments and a *" do + before :each do + @ip_pattern = ip.split('.')[0,n].join('.')+'.*' + @declaration = Puppet::Network::AuthStore::Declaration.new(:allow,@ip_pattern) + end + it "should match an IP in the range" do + @declaration.should be_match('www.testsite.org',ip) + end + it "should not match other IPs" do + @declaration.should_not be_match('www.testsite.org','200.101.99.98') + end + it "should not match IPs that differ in the last non-wildcard segment" do + other = ip.split('.') + other[n-1].succ! + @declaration.should_not be_match('www.testsite.org',other.join('.')) + end + end + } + } describe "when the pattern is a numeric IP with a back reference" do before :each do @ip = '100.101.$1' @declaration = Puppet::Network::AuthStore::Declaration.new(:allow,@ip).interpolate('12.34'.match(/(.*)/)) end - it "should match an IP with the apropriate interpolation" do + it "should match an IP with the appropriate interpolation" do @declaration.should be_match('www.testsite.org',@ip.sub(/\$1/,'12.34')) end it "should not match other IPs" do @@ -32,20 +53,25 @@ describe Puppet::Network::AuthStore::Declaration do end end - describe "when the pattern is a PQDN" do - before :each do - @host = 'spirit.mars.nasa.gov' - @declaration = Puppet::Network::AuthStore::Declaration.new(:allow,@host) - end - it "should match the specified PQDN" do - pending "FQDN consensus" - @declaration.should be_match(@host,'200.101.99.98') - end - it "should not match a similar FQDN" do - pending "FQDN consensus" - @declaration.should_not be_match(@host+'.','200.101.99.98') - end - end + { + 'spirit.mars.nasa.gov' => 'a PQDN', + 'ratchet.2ndsiteinc.com' => 'a PQDN with digits', + 'a.c.ru' => 'a PQDN with short segments', + }.each {|pqdn,desc| + describe "when the pattern is #{desc}" do + before :each do + @host = pqdn + @declaration = Puppet::Network::AuthStore::Declaration.new(:allow,@host) + end + it "should match the specified PQDN" do + @declaration.should be_match(@host,'200.101.99.98') + end + it "should not match a similar FQDN" do + pending "FQDN consensus" + @declaration.should_not be_match(@host+'.','200.101.99.98') + end + end + } describe "when the pattern is a FQDN" do before :each do @@ -57,7 +83,6 @@ describe Puppet::Network::AuthStore::Declaration do @declaration.should be_match(@host,'200.101.99.98') end it "should not match a similar PQDN" do - #pending "FQDN consensus" @declaration.should_not be_match(@host[0..-2],'200.101.99.98') end end @@ -70,7 +95,31 @@ describe Puppet::Network::AuthStore::Declaration do @pattern = %{^/catalog/([^/]+)$} @declaration = Puppet::Network::AuthStore::Declaration.new(:allow,'$1') end - it "should match an IP with the apropriate interpolation" do + it "should match an IP with the appropriate interpolation" do + @declaration.interpolate(@item.match(@pattern)).should be_match(@host,'10.0.0.5') + end + end + + describe "when the pattern is an opaque string with a back reference and the matched data contains dots" do + before :each do + @host = 'admin.mgmt.nym1' + @item = "/catalog/#{@host}" + @pattern = %{^/catalog/([^/]+)$} + @declaration = Puppet::Network::AuthStore::Declaration.new(:allow,'$1') + end + it "should match a name with the appropriate interpolation" do + @declaration.interpolate(@item.match(@pattern)).should be_match(@host,'10.0.0.5') + end + end + + describe "when the pattern is an opaque string with a back reference and the matched data contains dots with an initial prefix that looks like an IP address" do + before :each do + @host = '01.admin.mgmt.nym1' + @item = "/catalog/#{@host}" + @pattern = %{^/catalog/([^/]+)$} + @declaration = Puppet::Network::AuthStore::Declaration.new(:allow,'$1') + end + it "should match a name with the appropriate interpolation" do @declaration.interpolate(@item.match(@pattern)).should be_match(@host,'10.0.0.5') end end |