diff --git a/conf/auth.conf b/conf/auth.conf index cb202a989..ba389c076 100644 --- a/conf/auth.conf +++ b/conf/auth.conf @@ -1,99 +1,100 @@ # This is an example auth.conf file, it mimics the puppetmasterd defaults # # The ACL are checked in order of appearance in this file. # # Supported syntax: # This file supports two different syntax depending on how # you want to express the ACL. # # Path syntax (the one used below): # --------------------------------- # path /path/to/resource # [environment envlist] # [method methodlist] # [auth[enthicated] {yes|no|on|off|any}] # allow [host|ip|*] # deny [host|ip] # # The path is matched as a prefix. That is /file match at # the same time /file_metadat and /file_content. # # Regex syntax: # ------------- # This one is differenciated from the path one by a '~' # # path ~ regex # [environment envlist] # [method methodlist] # [auth[enthicated] {yes|no|on|off|any}] # allow [host|ip|*] # deny [host|ip] # # The regex syntax is the same as ruby ones. # # Ex: # path ~ .pp$ # will match every resource ending in .pp (manifests files for instance) # # path ~ ^/path/to/resource # is essentially equivalent to path /path/to/resource # # environment:: restrict an ACL to a specific set of environments # method:: restrict an ACL to a specific set of methods # auth:: restrict an ACL to an authenticated or unauthenticated request # the default when unspecified is to restrict the ACL to authenticated requests # (ie exactly as if auth yes was present). # ### Authenticated ACL - those applies only when the client ### has a valid certificate and is thus authenticated # allow nodes to retrieve their own catalog (ie their configuration) path ~ ^/catalog/([^/]+)$ method find allow $1 # allow nodes to retrieve their own node definition path ~ ^/node/([^/]+)$ method find allow $1 # allow all nodes to access the certificates services path /certificate_revocation_list/ca method find allow * # allow all nodes to store their reports path /report method save allow * # inconditionnally allow access to all files services # which means in practice that fileserver.conf will # still be used path /file allow * ### Unauthenticated ACL, for clients for which the current master doesn't -### have a valid certificate +### have a valid certificate; we allow authenticated users, too, because +### there isn't a great harm in letting that request through. # allow access to the master CA path /certificate/ca -auth no +auth any method find allow * path /certificate/ -auth no +auth any method find allow * path /certificate_request -auth no +auth any method find, save allow * # this one is not stricly necessary, but it has the merit # to show the default policy which is deny everything else path / auth any diff --git a/lib/puppet/network/rest_authconfig.rb b/lib/puppet/network/rest_authconfig.rb index 7dcc81ef4..3f5c008dd 100644 --- a/lib/puppet/network/rest_authconfig.rb +++ b/lib/puppet/network/rest_authconfig.rb @@ -1,94 +1,96 @@ require 'puppet/network/authconfig' module Puppet class Network::RestAuthConfig < Network::AuthConfig extend MonitorMixin attr_accessor :rights DEFAULT_ACL = [ { :acl => "~ ^\/catalog\/([^\/]+)$", :method => :find, :allow => '$1', :authenticated => true }, { :acl => "~ ^\/node\/([^\/]+)$", :method => :find, :allow => '$1', :authenticated => true }, # this one will allow all file access, and thus delegate # to fileserver.conf { :acl => "/file" }, { :acl => "/certificate_revocation_list/ca", :method => :find, :authenticated => true }, { :acl => "/report", :method => :save, :authenticated => true }, - { :acl => "/certificate/ca", :method => :find, :authenticated => false }, - { :acl => "/certificate/", :method => :find, :authenticated => false }, - { :acl => "/certificate_request", :method => [:find, :save], :authenticated => false }, + # These allow `auth any`, because if you can do them anonymously you + # should probably also be able to do them when trusted. + { :acl => "/certificate/ca", :method => :find, :authenticated => nil }, + { :acl => "/certificate/", :method => :find, :authenticated => nil }, + { :acl => "/certificate_request", :method => [:find, :save], :authenticated => nil }, { :acl => "/status", :method => [:find], :authenticated => true }, ] def self.main synchronize do add_acl = @main.nil? super @main.insert_default_acl if add_acl and !@main.exists? end @main end def allowed?(request) Puppet.deprecation_warning "allowed? should not be called for REST authorization - use check_authorization instead" check_authorization(request) end # check wether this request is allowed in our ACL # raise an Puppet::Network::AuthorizedError if the request # is denied. def check_authorization(indirection, method, key, params) read # we're splitting the request in part because # fail_on_deny could as well be called in the XMLRPC context # with a ClientRequest. if authorization_failure_exception = @rights.is_request_forbidden_and_why?(indirection, method, key, params) Puppet.warning("Denying access: #{authorization_failure_exception}") raise authorization_failure_exception end end def initialize(file = nil, parsenow = true) super(file || Puppet[:rest_authconfig], parsenow) # if we didn't read a file (ie it doesn't exist) # make sure we can create some default rights @rights ||= Puppet::Network::Rights.new end def parse super() insert_default_acl end # force regular ACLs to be present def insert_default_acl DEFAULT_ACL.each do |acl| unless rights[acl[:acl]] Puppet.info "Inserting default '#{acl[:acl]}'(#{acl[:authenticated] ? "auth" : "non-auth"}) ACL because #{( !exists? ? "#{Puppet[:rest_authconfig]} doesn't exist" : "none were found in '#{@file}'")}" mk_acl(acl) end end # queue an empty (ie deny all) right for every other path # actually this is not strictly necessary as the rights system # denies not explicitely allowed paths unless rights["/"] rights.newright("/") rights.restrict_authenticated("/", :any) end end def mk_acl(acl) @rights.newright(acl[:acl]) @rights.allow(acl[:acl], acl[:allow] || "*") if method = acl[:method] method = [method] unless method.is_a?(Array) method.each { |m| @rights.restrict_method(acl[:acl], m) } end @rights.restrict_authenticated(acl[:acl], acl[:authenticated]) unless acl[:authenticated].nil? end end end