With the help of the new auth.conf directive 'environment',
any ACL can now be restricted to a specific environment.
Omission of the directive means that the ACL will apply
to all the defined environment.

Signed-off-by: Brice Figureau <[email protected]>
---
 conf/auth.conf                        |    2 ++
 lib/puppet/network/authconfig.rb      |    9 +++++++--
 lib/puppet/network/rest_authconfig.rb |    2 +-
 lib/puppet/network/rights.rb          |   28 +++++++++++++++-------------
 spec/unit/network/authconfig.rb       |   23 +++++++++++++++++++++++
 spec/unit/network/rest_authconfig.rb  |    5 +++--
 spec/unit/network/rights.rb           |   31 +++++++++++++++++++++++++++----
 7 files changed, 78 insertions(+), 22 deletions(-)

diff --git a/conf/auth.conf b/conf/auth.conf
index 1c03790..784acc9 100644
--- a/conf/auth.conf
+++ b/conf/auth.conf
@@ -9,6 +9,7 @@
 # Path syntax (the one used below):
 # ---------------------------------
 # path /path/to/resource
+# [environment envlist]
 # [method methodlist]
 # allow [host|ip|*]
 # deny [host|ip]
@@ -21,6 +22,7 @@
 # This one is differenciated from the path one by a '~'
 # 
 # path ~ regex
+# [environment envlist]
 # [method methodlist]
 # allow [host|ip|*]
 # deny [host|ip]
diff --git a/lib/puppet/network/authconfig.rb b/lib/puppet/network/authconfig.rb
index f78cdc6..3e0807a 100644
--- a/lib/puppet/network/authconfig.rb
+++ b/lib/puppet/network/authconfig.rb
@@ -112,7 +112,7 @@ module Puppet
                             end
                             name.chomp!
                             right = newrights.newright(name, count)
-                        when /^\s*(allow|deny|method)\s+(.+)$/
+                        when /^\s*(allow|deny|method|environment)\s+(.+)$/
                             parse_right_directive(right, $1, $2, count)
                         else
                             raise ConfigurationError, "Invalid line %s: %s" % 
[count, line]
@@ -150,7 +150,12 @@ module Puppet
                 unless right.acl_type == :regex
                     raise ConfigurationError, "'method' directive not allowed 
in namespace ACL at line %s of %s" % [count, @config]
                 end
-                modify_right(right, :restrict_method, value, "allowing method 
%s access", count)
+                modify_right(right, :restrict_method, value, "allowing 
'method' %s", count)
+            when "environment"
+                unless right.acl_type == :regex
+                    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)
             else
                 raise ConfigurationError,
                     "Invalid argument '%s' at line %s" % [var, count]
diff --git a/lib/puppet/network/rest_authconfig.rb 
b/lib/puppet/network/rest_authconfig.rb
index 58708e1..e3fd517 100644
--- a/lib/puppet/network/rest_authconfig.rb
+++ b/lib/puppet/network/rest_authconfig.rb
@@ -25,7 +25,7 @@ module Puppet
         # check wether this request is allowed in our ACL
         def allowed?(request)
             read()
-            return @rights.allowed?(build_uri(request), request.node, 
request.ip, request.method)
+            return @rights.allowed?(build_uri(request), request.node, 
request.ip, request.method, request.environment)
         end
 
         def initialize(file = nil, parsenow = true)
diff --git a/lib/puppet/network/rights.rb b/lib/puppet/network/rights.rb
index 6b2082c..7f4bed7 100755
--- a/lib/puppet/network/rights.rb
+++ b/lib/puppet/network/rights.rb
@@ -8,7 +8,7 @@ class Puppet::Network::Rights
 
     # We basically just proxy directly to our rights.  Each Right stores
     # its own auth abilities.
-    [:allow, :deny].each do |method|
+    [:allow, :deny, :restrict_method, :restrict_environment].each do |method|
         define_method(method) do |name, *args|
             if obj = self[name]
                 obj.send(method, *args)
@@ -18,16 +18,6 @@ class Puppet::Network::Rights
         end
     end
 
-    # this method is used to add a new allowed +method+ to +name+
-    # method applies only to path rights
-    def restrict_method(name, *args)
-        if right = self[name]
-            right.restrict_method(*args)
-        else
-            raise ArgumentError, "'%s' right is not allowing method 
specification" % name
-        end
-    end
-
     def allowed?(name, *args)
         res = :nomatch
         right = @rights.find do |acl|
@@ -99,7 +89,7 @@ class Puppet::Network::Rights
     # A right.
     class Right < Puppet::Network::AuthStore
         attr_accessor :name, :key, :acl_type, :line
-        attr_accessor :methods, :length
+        attr_accessor :methods, :environment
 
         ALL = [:save, :destroy, :find, :search]
 
@@ -107,8 +97,10 @@ class Puppet::Network::Rights
 
         def initialize(name, line)
             @methods = []
+            @environment = []
             @name = name
             @line = line || 0
+
             case name
             when Symbol
                 @acl_type = :name
@@ -148,8 +140,9 @@ class Puppet::Network::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, method = nil, match = nil)
+        def allowed?(name, ip, method = nil, environment = nil, match = nil)
             return :dunno if acl_type == :regex and not 
@methods.include?(method)
+            return :dunno if acl_type == :regex and @environment.size > 0 and 
not @environment.include?(environment)
 
             if acl_type == :regex and match # make sure any capture are 
replaced
                 interpolate(match)
@@ -183,6 +176,15 @@ class Puppet::Network::Rights
             @methods << m
         end
 
+        def restrict_environment(env)
+            env = Puppet::Node::Environment.new(env)
+            if @environment.include?(env)
+                raise ArgumentError, "'%s' is already in the '%s' ACL" % [env, 
name]
+            end
+
+            @environment << env
+        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 d891fe4..186d30c 100644
--- a/spec/unit/network/authconfig.rb
+++ b/spec/unit/network/authconfig.rb
@@ -230,6 +230,29 @@ describe Puppet::Network::AuthConfig do
             lambda { @authconfig.read }.should raise_error
         end
 
+        it "should inform the current ACL if we get the 'environment' 
directive" do
+            acl = stub 'acl', :info
+            acl.stubs(:acl_type).returns(:regex)
+
+            @fd.stubs(:each).multiple_yields('path /certificates', 
'environment production,development')
+            @rights.stubs(:newright).with("/certificates", 1).returns(acl)
+
+            acl.expects(:restrict_environment).with('production')
+            acl.expects(:restrict_environment).with('development')
+
+            @authconfig.read
+        end
+
+        it "should raise an error if the 'environment' 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]', 'environment env')
+            @rights.stubs(:newright).with("puppetca", 1).returns(acl)
+
+            lambda { @authconfig.read }.should raise_error
+        end
+
     end
 
 end
diff --git a/spec/unit/network/rest_authconfig.rb 
b/spec/unit/network/rest_authconfig.rb
index 1f98f40..ea5a82c 100644
--- a/spec/unit/network/rest_authconfig.rb
+++ b/spec/unit/network/rest_authconfig.rb
@@ -16,7 +16,8 @@ describe Puppet::Network::RestAuthConfig do
         @acl = stub_everything 'rights'
         @authconfig.rights = @acl
 
-        @request = stub 'request', :indirection_name => "path", :key => 
"to/resource", :ip => "127.0.0.1", :node => "me", :method => :save
+        @request = stub 'request', :indirection_name => "path", :key => 
"to/resource", :ip => "127.0.0.1", 
+                                   :node => "me", :method => :save, 
:environment => :env
     end
 
     it "should use the puppet default rest authorization file" do
@@ -32,7 +33,7 @@ describe Puppet::Network::RestAuthConfig do
     end
 
     it "should ask for authorization to the ACL subsystem" do
-        @acl.expects(:allowed?).with("/path/to/resource", "me", "127.0.0.1", 
:save)
+        @acl.expects(:allowed?).with("/path/to/resource", "me", "127.0.0.1", 
:save, :env)
 
         @authconfig.allowed?(@request)
     end
diff --git a/spec/unit/network/rights.rb b/spec/unit/network/rights.rb
index 6e91812..97094f8 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].each do |m|
+    [:allow, :deny, :restrict_method, :restrict_environment].each do |m|
         it "should have a #{m} method" do
             @right.should respond_to(m)
         end
@@ -391,23 +391,46 @@ describe Puppet::Network::Rights do
             lambda { @acl.restrict_method(:save) }.should raise_error
         end
 
+        it "should allow setting an environment filters" do
+            
Puppet::Node::Environment.stubs(:new).with(:environment).returns(:env)
+
+            @acl.restrict_environment(:environment)
+
+            @acl.environment.should == [:env]
+        end
+
         describe "when checking right authorization" do
-            it "should return :dunno if this right doesn't apply" do
+            it "should return :dunno if this right is not restricted to the 
given method" do
                 @acl.restrict_method(:destroy)
 
                 @acl.allowed?("me","127.0.0.1", :save).should == :dunno
             end
 
+            it "should return allow/deny if this right is restricted to the 
given method" do
+                @acl.restrict_method(:save)
+                @acl.allow("127.0.0.1")
+
+                @acl.allowed?("me","127.0.0.1", :save).should be_true
+            end
+
+            it "should return :dunno if this right is not restricted to the 
given environment" do
+                Puppet::Node::Environment.stubs(:new).returns(:production)
+
+                @acl.restrict_environment(:production)
+
+                @acl.allowed?("me","127.0.0.1", :save, :development).should == 
:dunno
+            end
+
             it "should interpolate allow/deny patterns with the given match" do
                 @acl.expects(:interpolate).with(:match)
 
-                @acl.allowed?("me","127.0.0.1", :save, :match)
+                @acl.allowed?("me","127.0.0.1", :save, nil, :match)
             end
 
             it "should reset interpolation after the match" do
                 @acl.expects(:reset_interpolation)
 
-                @acl.allowed?("me","127.0.0.1", :save, :match)
+                @acl.allowed?("me","127.0.0.1", :save, nil, :match)
             end
 
             # mocha doesn't allow testing super...
-- 
1.6.0.2


--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to