summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrice Figureau <brice-puppet@daysofwonder.com>2009-03-30 20:24:53 +0200
committerBrice Figureau <brice-puppet@daysofwonder.com>2009-04-23 20:52:03 +0200
commitaac996ed17e0ec72c5098b1225eb159aae4901fc (patch)
tree7cd8ae0baaad9a486581d6ec67f6d63a2fb5bfa6
parent72e28aeccc36092e7edf9dc25e44acdb08fa5e79 (diff)
downloadpuppet-aac996ed17e0ec72c5098b1225eb159aae4901fc.tar.gz
puppet-aac996ed17e0ec72c5098b1225eb159aae4901fc.tar.xz
puppet-aac996ed17e0ec72c5098b1225eb159aae4901fc.zip
Add environment support in the REST authorization layer
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 <brice-puppet@daysofwonder.com>
-rw-r--r--conf/auth.conf2
-rw-r--r--lib/puppet/network/authconfig.rb9
-rw-r--r--lib/puppet/network/rest_authconfig.rb2
-rwxr-xr-xlib/puppet/network/rights.rb28
-rwxr-xr-xspec/unit/network/authconfig.rb23
-rwxr-xr-xspec/unit/network/rest_authconfig.rb5
-rwxr-xr-xspec/unit/network/rights.rb31
7 files changed, 78 insertions, 22 deletions
diff --git a/conf/auth.conf b/conf/auth.conf
index 1c037901d..784acc980 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 f78cdc621..3e0807ad1 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 58708e120..e3fd51753 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 6b2082cdb..7f4bed7f6 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 d891fe45a..186d30ce3 100755
--- 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 1f98f4082..ea5a82cce 100755
--- 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 6e918124f..97094f8e5 100755
--- 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...