+1 On Apr 19, 2009, at 11:38 AM, Brice Figureau wrote:
> > Introduces a new auth.conf directive (auth or authenticated) which > takes an argument (on,yes/off,no). > This can be used to restrict an ACL to only some state of > authentication of a REST request. > If no auth directive is given, both type of requests are used. > > Signed-off-by: Brice Figureau <[email protected]> > --- > lib/puppet/network/authconfig.rb | 7 +++++- > lib/puppet/network/rights.rb | 26 ++++++++++++++++++++---- > spec/unit/network/authconfig.rb | 34 +++++++++++++++++++++++++++++ > ++++ > spec/unit/network/rights.rb | 39 +++++++++++++++++++++++++++++ > ++++++-- > 4 files changed, 97 insertions(+), 9 deletions(-) > > diff --git a/lib/puppet/network/authconfig.rb b/lib/puppet/network/ > authconfig.rb > index 3e40c9d..41f8f1c 100644 > --- a/lib/puppet/network/authconfig.rb > +++ b/lib/puppet/network/authconfig.rb > @@ -111,7 +111,7 @@ module Puppet > end > name.chomp! > right = newrights.newright(name, count, > @file) > - when /^\s*(allow|deny|method|environment)\s+ > (.+)$/ > + when /^\s*(allow|deny|method|environment| > auth(?:enticated)?)\s+(.+)$/ > parse_right_directive(right, $1, $2, > count) > else > raise ConfigurationError, "Invalid line > %s: %s" % [count, line] > @@ -155,6 +155,11 @@ module Puppet > raise ConfigurationError, "'environment' > directive not allowed in namespace ACL at line %s of %s" % [count, > @config] > end > modify_right(right, :restrict_environment, value, > "adding environment %s", count) > + when /auth(?:enticated)?/ > + unless right.acl_type == :regex > + raise ConfigurationError, "'authenticated' > directive not allowed in namespace ACL at line %s of %s" % [count, > @config] > + end > + modify_right(right, :restrict_authenticated, value, > "adding authentication %s", count) > else > raise ConfigurationError, > "Invalid argument '%s' at line %s" % [var, count] > diff --git a/lib/puppet/network/rights.rb b/lib/puppet/network/ > rights.rb > index 75005d8..fc2d685 100755 > --- a/lib/puppet/network/rights.rb > +++ b/lib/puppet/network/rights.rb > @@ -14,7 +14,7 @@ class Rights > > # We basically just proxy directly to our rights. Each Right > stores > # its own auth abilities. > - [:allow, :deny, :restrict_method, :restrict_environment].each > do |method| > + > [:allow > , :deny > , :restrict_method > , :restrict_environment, :restrict_authenticated].each do |method| > define_method(method) do |name, *args| > if obj = self[name] > obj.send(method, *args) > @@ -27,7 +27,7 @@ class Rights > # Check that name is allowed or not > def allowed?(name, *args) > begin > - fail_on_deny(name, *args) > + fail_on_deny(name, :node => args[0], :ip => args[1]) > rescue AuthorizationError > return false > rescue ArgumentError > @@ -59,10 +59,12 @@ class Rights > > # if we end here, then that means we either didn't match > # or failed, in any case will throw an error to the outside > world > - if name =~ /^\// > + if name =~ /^\// or right > # we're a patch ACL, let's fail > msg = "%s access to %s [%s]" % [ (args[:node].nil? ? > args[:ip] : "#{args[:node]}(#{args[:ip]})"), name, args[:method] ] > > + msg += " authenticated " if args[:authenticated] > + > error = AuthorizationError.new("Forbidden request: " + > msg) > if right > error.file = right.file > @@ -121,7 +123,7 @@ class Rights > # A right. > class Right < Puppet::Network::AuthStore > attr_accessor :name, :key, :acl_type, :line, :file > - attr_accessor :methods, :environment > + attr_accessor :methods, :environment, :authentication > > ALL = [:save, :destroy, :find, :search] > > @@ -130,6 +132,7 @@ class Rights > def initialize(name, line, file) > @methods = [] > @environment = [] > + @authentication = nil > @name = name > @line = line || 0 > @file = file > @@ -173,9 +176,10 @@ class Rights > # if this right is too restrictive (ie we don't match this > access method) > # then return :dunno so that upper layers have a chance to > try another right > # tailored to the given method > - def allowed?(name, ip, args) > + def allowed?(name, ip, args = {}) > return :dunno if acl_type == :regex and not > @methods.include?(args[:method]) > return :dunno if acl_type == :regex and > @environment.size > 0 and not @environment.include? > (args[:environment]) > + return :dunno if acl_type == :regex and not > @authentication.nil? and args[:authenticated] != @authentication > > begin > # make sure any capture are replaced if needed > @@ -216,6 +220,18 @@ class Rights > @environment << env > end > > + def restrict_authenticated(authentication) > + case authentication > + when "yes", "on", "true", true > + authentication = true > + when "no", "off", "false", false > + authentication = false > + else > + raise ArgumentError, "'%s' incorrect authenticated > value: %s" % [name, authentication] > + end > + @authentication = authentication > + end > + > def match?(key) > # if we are a namespace compare directly > return self.key == namespace_to_key(key) if acl_type > == :name > diff --git a/spec/unit/network/authconfig.rb b/spec/unit/network/ > authconfig.rb > index 21af89b..f666523 100644 > --- a/spec/unit/network/authconfig.rb > +++ b/spec/unit/network/authconfig.rb > @@ -253,6 +253,40 @@ describe Puppet::Network::AuthConfig do > lambda { @authconfig.read }.should raise_error > end > > + it "should inform the current ACL if we get the 'auth' > directive" do > + acl = stub 'acl', :info > + acl.stubs(:acl_type).returns(:regex) > + > + @fd.stubs(:each).multiple_yields('path /certificates', > 'auth yes') > + @rights.stubs(:newright).with("/certificates", 1, > 'dummy').returns(acl) > + > + acl.expects(:restrict_authenticated).with('yes') > + > + @authconfig.read > + end > + > + it "should also allow the longest 'authenticated' > directive" do > + acl = stub 'acl', :info > + acl.stubs(:acl_type).returns(:regex) > + > + @fd.stubs(:each).multiple_yields('path /certificates', > 'authenticated yes') > + @rights.stubs(:newright).with("/certificates", 1, > 'dummy').returns(acl) > + > + acl.expects(:restrict_authenticated).with('yes') > + > + @authconfig.read > + end > + > + it "should raise an error if the 'auth' directive is used > in a right different than a path/regex one" do > + acl = stub 'acl', :info > + acl.stubs(:acl_type).returns(:regex) > + > + @fd.stubs(:each).multiple_yields('[puppetca]', 'auth > yes') > + @rights.stubs(:newright).with("puppetca", 1, > 'dummy').returns(acl) > + > + lambda { @authconfig.read }.should raise_error > + end > + > end > > end > diff --git a/spec/unit/network/rights.rb b/spec/unit/network/rights.rb > index be1db72..f98249a 100644 > --- a/spec/unit/network/rights.rb > +++ b/spec/unit/network/rights.rb > @@ -9,7 +9,7 @@ describe Puppet::Network::Rights do > @right = Puppet::Network::Rights.new > end > > - [:allow, :deny, :restrict_method, :restrict_environment].each > do |m| > + > [:allow > , :deny > , :restrict_method > , :restrict_environment, :restrict_authenticated].each do |m| > it "should have a #{m} method" do > @right.should respond_to(m) > end > @@ -150,9 +150,9 @@ describe Puppet::Network::Rights do > end > > it "should delegate to fail_on_deny" do > - @right.expects(:fail_on_deny).with("namespace", :args) > + @right.expects(:fail_on_deny).with("namespace", :node > => "host.domain.com", :ip => "127.0.0.1") > > - @right.allowed?("namespace", :args) > + @right.allowed?("namespace", "host.domain.com", > "127.0.0.1") > end > > it "should return true if fail_on_deny doesn't fail" do > @@ -397,6 +397,10 @@ describe Puppet::Network::Rights do > @acl.methods.should == Puppet::Network::Rights::Right::ALL > end > > + it "should allow all request authentication state by > default" do > + @acl.authentication.should be_nil > + end > + > it "should allow modification of the methods filters" do > @acl.restrict_method(:save) > > @@ -424,6 +428,22 @@ describe Puppet::Network::Rights do > @acl.environment.should == [:env] > end > > + ["on", "yes", "true", true].each do |auth| > + it "should allow filtering on authenticated requests > with '#{auth}'" do > + @acl.restrict_authenticated(auth) > + > + @acl.authentication.should be_true > + end > + end > + > + ["off", "no", "false", false].each do |auth| > + it "should allow filtering on unauthenticated requests > with '#{auth}'" do > + @acl.restrict_authenticated(auth) > + > + @acl.authentication.should be_false > + end > + end > + > describe "when checking right authorization" do > it "should return :dunno if this right is not restricted > to the given method" do > @acl.restrict_method(:destroy) > @@ -446,6 +466,19 @@ describe Puppet::Network::Rights do > @acl.allowed?("me","127.0.0.1", { :method > => :save, :environment => :development }).should == :dunno > end > > + it "should return :dunno if this right is not > restricted to the given request authentication state" do > + @acl.restrict_authenticated(true) > + > + @acl.allowed?("me","127.0.0.1", { :method > => :save, :authenticated => false }).should == :dunno > + end > + > + it "should return allow/deny if this right is > restricted to the given request authentication state" do > + @acl.restrict_authenticated(false) > + @acl.allow("127.0.0.1") > + > + @acl.allowed?("me","127.0.0.1", { :authenticated => > false }).should be_true > + end > + > it "should interpolate allow/deny patterns with the > given match" do > @acl.expects(:interpolate).with(:match) > > -- > 1.6.0.2 > > > > -- There is no expedient to which a man will not go to avoid the labor of thinking. --Thomas A. Edison --------------------------------------------------------------------- Luke Kanies | http://reductivelabs.com | http://madstop.com --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Puppet Developers" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/puppet-dev?hl=en -~----------~----~----~----~------~----~------~--~---
