require 'puppet/util/loadedfile'
require 'puppet/network/rights'
module Puppet
class ConfigurationError < Puppet::Error; end
class Network::AuthConfig < Puppet::Util::LoadedFile
def self.main
unless defined? @main
@main = self.new()
end
@main
end
# Just proxy the setting methods to our rights stuff
[:allow, :deny].each do |method|
define_method(method) do |*args|
@rights.send(method, *args)
end
end
# Here we add a little bit of semantics. They can set auth on a whole
# namespace or on just a single method in the namespace.
def allowed?(request)
name = request.call.intern
namespace = request.handler.intern
method = request.method.intern
read()
if @rights.include?(name)
return @rights[name].allowed?(request.name, request.ip)
elsif @rights.include?(namespace)
return @rights[namespace].allowed?(request.name, request.ip)
else
return false
end
end
# Does the file exist? Puppetmasterd does not require it, but
# puppetd does.
def exists?
FileTest.exists?(@file)
end
def initialize(file = nil, parsenow = true)
@file ||= Puppet[:authconfig]
unless @file
raise Puppet::DevError, "No authconfig file defined"
end
return unless self.exists?
super(@file)
@rights = Puppet::Network::Rights.new
@configstamp = @configstatted = nil
@configtimeout = 60
if parsenow
read()
end
end
# Read the configuration file.
def read
return unless FileTest.exists?(@file)
if @configstamp
if @configtimeout and @configstatted
if Time.now - @configstatted > @configtimeout
@configstatted = Time.now
tmp = File.stat(@file).ctime
if tmp == @configstamp
return
else
Puppet.notice "%s vs %s" % [tmp, @configstamp]
end
else
return
end
else
Puppet.notice "%s and %s" % [@configtimeout, @configstatted]
end
end
parse()
@configstamp = File.stat(@file).ctime
@configstatted = Time.now
end
private
def parse
newrights = Puppet::Network::Rights.new
begin
File.open(@file) { |f|
right = nil
count = 1
f.each { |line|
case line
when /^\s*#/: next # skip comments
when /^\s*$/: next # skip blank lines
when /\[([\w.]+)\]/: # "namespace" or "namespace.method"
name = $1
if newrights.include?(name)
raise FileServerError, "%s is already set at %s" %
[newrights[name], name]
end
newrights.newright(name)
right = newrights[name]
when /^\s*(\w+)\s+(.+)$/:
var = $1
value = $2
case var
when "allow":
value.split(/\s*,\s*/).each { |val|
begin
right.info "allowing %s access" % val
right.allow(val)
rescue AuthStoreError => detail
raise ConfigurationError, "%s at line %s of %s" %
[detail.to_s, count, @config]
end
}
when "deny":
value.split(/\s*,\s*/).each { |val|
begin
right.info "denying %s access" % val
right.deny(val)
rescue AuthStoreError => detail
raise ConfigurationError, "%s at line %s of %s" %
[detail.to_s, count, @config]
end
}
else
raise ConfigurationError,
"Invalid argument '%s' at line %s" % [var, count]
end
else
raise ConfigurationError, "Invalid line %s: %s" % [count, line]
end
count += 1
}
}
rescue Errno::EACCES => detail
Puppet.err "Configuration error: Cannot read %s; cannot serve" % @file
#raise Puppet::Error, "Cannot read %s" % @config
rescue Errno::ENOENT => detail
Puppet.err "Configuration error: '%s' does not exit; cannot serve" %
@file
#raise Puppet::Error, "%s does not exit" % @config
#rescue FileServerError => detail
# Puppet.err "FileServer error: %s" % detail
end
# Verify each of the rights are valid.
# We let the check raise an error, so that it can raise an error
# pointing to the specific problem.
newrights.each { |name, right|
right.valid?
}
@rights = newrights
end
end
end
# $Id: authconfig.rb 2345 2007-03-22 15:40:28Z luke $
syntax highlighted by Code2HTML, v. 0.9.1