From 58cae26af9b3a868041b52fc0dde6047faff73a3 Mon Sep 17 00:00:00 2001 From: Michael DeHaan Date: Tue, 4 Dec 2007 16:36:32 -0500 Subject: AuthN/AuthZ modules are now pluggable, http://127.0.0.1/cobbler/web now active for mod_python using AuthN/AuthZ, backend now also doing AuthZ. default AuthN mechanism is using /etc/cobbler/auth.conf for now, which needs to be replaced, should use htdigest data at minimum. --- Makefile | 4 + cobbler/api.py | 4 +- cobbler/module_loader.py | 12 ++- cobbler/modules/authn_configfile.py | 53 +++++++++ cobbler/modules/authz_allowall.py | 41 +++++++ cobbler/remote.py | 207 ++++++++++++------------------------ config/cobbler.conf | 6 +- config/modules.conf | 5 + scripts/index.py | 122 ++++++++++++++++----- 9 files changed, 283 insertions(+), 171 deletions(-) create mode 100644 cobbler/modules/authn_configfile.py create mode 100644 cobbler/modules/authz_allowall.py diff --git a/Makefile b/Makefile index 6e8ac88..8bef981 100644 --- a/Makefile +++ b/Makefile @@ -50,6 +50,10 @@ devinstall: chown -R apache /var/www/cgi-bin/cobbler chmod -R +x /var/www/cobbler/web +webtest: devinstall + /sbin/service cobblerd restart + /sbin/service httpd restart + sdist: clean messages updatewui python setup.py sdist diff --git a/cobbler/api.py b/cobbler/api.py index 50ad244..e6ef88b 100644 --- a/cobbler/api.py +++ b/cobbler/api.py @@ -238,13 +238,13 @@ class BootAPI: """ return module_loader.get_module_by_name(module_name) - def get_module_from_file(self,section,name): + def get_module_from_file(self,section,name,fallback=None): """ Looks in /etc/cobbler/modules.conf for a section called 'section' and a key called 'name', and then returns the module that corresponds to the value of that key. """ - return module_loader.get_module_from_file(section,name) + return module_loader.get_module_from_file(section,name,fallback) def get_modules_in_category(self,category): """ diff --git a/cobbler/module_loader.py b/cobbler/module_loader.py index dd1b757..aafe05f 100644 --- a/cobbler/module_loader.py +++ b/cobbler/module_loader.py @@ -73,9 +73,15 @@ def load_modules(module_path=mod_path, blacklist=None): def get_module_by_name(name): return MODULE_CACHE.get(name, None) -def get_module_from_file(category,field): - - value = cp.get("serializers",field) +def get_module_from_file(category,field,fallback_module_name=None): + + try: + value = cp.get("serializers",field) + except: + if fallback_module_name is not None: + value = fallback_module_name + else: + raise CX(_("Cannot find config file setting for: %s") % field) return MODULE_CACHE.get(value, None) def get_modules_in_category(category): diff --git a/cobbler/modules/authn_configfile.py b/cobbler/modules/authn_configfile.py new file mode 100644 index 0000000..afdd858 --- /dev/null +++ b/cobbler/modules/authn_configfile.py @@ -0,0 +1,53 @@ +""" +Authentication module that uses /etc/cobbler/auth.conf +Choice of authentication module is in /etc/cobbler/modules.conf + +Copyright 2007, Red Hat, Inc +Michael DeHaan + +This software may be freely redistributed under the terms of the GNU +general public license. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +""" + +import distutils.sysconfig +import ConfigParser +import sys +from rhpl.translate import _, N_, textdomain, utf8 + +plib = distutils.sysconfig.get_python_lib() +mod_path="%s/cobbler" % plib +sys.path.insert(0, mod_path) + +import cexceptions +import utils + + +def register(): + """ + The mandatory cobbler module registration hook. + """ + return "authn" + +def authenticate(username,password): + """ + Validate a username/password combo, returning True/False + """ + + config_parser = ConfigParser.ConfigParser() + auth_conf = open("/etc/cobbler/auth.conf") + config_parser.readfp(auth_conf) + auth_conf.close() + user_database = config_parser.items("xmlrpc_service_users") + for x in user_database: + (db_user,db_password) = x + db_user = db_user.strip() + db_password = db_password.strip() + if db_user == username and db_password == password and db_password.lower() != "disabled": + return True + return False + + diff --git a/cobbler/modules/authz_allowall.py b/cobbler/modules/authz_allowall.py new file mode 100644 index 0000000..4125ed6 --- /dev/null +++ b/cobbler/modules/authz_allowall.py @@ -0,0 +1,41 @@ +""" +Authorization module that allows everything, which is the default +for new cobbler installs. + +Copyright 2007, Red Hat, Inc +Michael DeHaan + +This software may be freely redistributed under the terms of the GNU +general public license. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +""" + +import distutils.sysconfig +import ConfigParser +import sys +from rhpl.translate import _, N_, textdomain, utf8 + +plib = distutils.sysconfig.get_python_lib() +mod_path="%s/cobbler" % plib +sys.path.insert(0, mod_path) + +import cexceptions +import utils + + +def register(): + """ + The mandatory cobbler module registration hook. + """ + return "authz" + +def authorize(user,resource,arg1=None,arg2=None): + """ + Validate a user against a resource. + """ + return True + + diff --git a/cobbler/remote.py b/cobbler/remote.py index b6e6a04..dcc01d1 100644 --- a/cobbler/remote.py +++ b/cobbler/remote.py @@ -21,7 +21,6 @@ import SimpleXMLRPCServer from rhpl.translate import _, N_, textdomain, utf8 import xmlrpclib import logging -import ConfigParser import random import base64 @@ -33,14 +32,6 @@ import item_profile import item_system import item_repo -config_parser = ConfigParser.ConfigParser() -auth_conf = open("/etc/cobbler/auth.conf") -config_parser.readfp(auth_conf) -auth_conf.close() - -user_database = config_parser.items("xmlrpc_service_users") - - # FIXME: make configurable? TOKEN_TIMEOUT = 60*60 # 60 minutes OBJECT_TIMEOUT = 60*60 # 60 minutes @@ -374,6 +365,17 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): self.token_cache = {} self.object_cache = {} random.seed(time.time()) + self.authn = self.api.get_module_from_file( + "authentication", + "module", + "authn_configfile" + ) + self.authz = self.api.get_module_from_file( + "authorization", + "module", + "authz_allowall" + ) + def __next_id(self,retry=0): """ @@ -394,12 +396,12 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): urandom.close() return b64 - def __make_token(self): + def __make_token(self,user): """ Returns a new random token. """ b64 = self.__get_random(25) - self.token_cache[b64] = time.time() + self.token_cache[b64] = (time.time(), user) return b64 def __invalidate_expired_objects(self): @@ -420,12 +422,12 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): """ timenow = time.time() for token in self.token_cache.keys(): - tokentime = self.token_cache[token] + (tokentime, user) = self.token_cache[token] if (timenow > tokentime + TOKEN_TIMEOUT): self.logger.debug("expiring token: %s" % token) del self.token_cache[token] - def __validate_user(self,user,password): + def __validate_user(self,input_user,input_password): """ Returns whether this user/pass combo should be given access to the cobbler read-write API. @@ -433,14 +435,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): FIXME: currently looks for users in /etc/cobbler/auth.conf Would be very nice to allow for PAM and/or just Kerberos. """ - for x in user_database: - (db_user,db_password) = x - db_user = db_user.strip() - db_password = db_password.strip() - if db_user == user and db_password == password and db_password.lower() != "disabled": - return True - else: - return False + return self.authn.authenticate(input_user,input_password) def __validate_token(self,token): """ @@ -454,26 +449,44 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): self.__invalidate_expired_tokens() self.__invalidate_expired_objects() if self.token_cache.has_key(token): - self.token_cache[token] = time.time() # update to prevent timeout + user = self.__get_user_from_token(token) + self.token_cache[token] = (time.time(), user) # update to prevent timeout return True else: self.logger.debug("invalid token: %s" % token) raise CX(_("invalid token: %s" % token)) - def login(self,user,password): + def check_access(self,token,resource): + validated = self.__validate_token(token) + return self.__authorize(token,resource) + + def __get_user_from_token(self,token): + if not self.token_cache.has_key(token): + raise CX(_("invalid token: %s") % token) + else: + return self.token_cache[token][1] + + def login(self,login_user,login_password): """ Takes a username and password, validates it, and if successful returns a random login token which must be used on subsequent method calls. The token will time out after a set interval if not used. Re-logging in permitted. """ - if self.__validate_user(user,password): - token = self.__make_token() - self.logger.info("login succeeded: %s" % user) + if self.__validate_user(login_user,login_password): + token = self.__make_token(login_user) + self.logger.info("login succeeded: %s" % login_user) return token else: - self.logger.info("login failed: %s" % user) - raise CX(_("login failed: %s") % user) + self.logger.info("login failed: %s" % login_user) + raise CX(_("login failed: %s") % login_user) + + def __authorize(self,token,resource): + user = self.__get_user_from_token(token) + if self.authz.authorize(user,resource): + return True + else: + raise CX(_("user does not have access to resource: %s") % resource) def logout(self,token): """ @@ -523,7 +536,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): remote.modify_distro(distro_id, 'initrd', '/foo/initrd.img', token) remote.save_distro(distro_id, token) """ - self.__validate_token(token) + self.check_access(token,"new_distro") return self.__store_object(item_distro.Distro(self.api._config)) def new_profile(self,token): @@ -531,17 +544,10 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): Creates a new (unconfigured) profile object. See the documentation for new_distro as it works exactly the same. """ - self.__validate_token(token) + + self.check_access(token,"new_profile") return self.__store_object(item_profile.Profile(self.api._config)) - def new_subprofile(self,token): - """ - Creates a new (unconfigured) subprofile object. See the documentation - for new_distro as it works exactly the same. - """ - self.__validate_token(token) - return self.__store_object(item_profile.Profile(self.api._config, is_subobject=True)) - def new_subprofile(self,token): """ A subprofile is a profile that inherits directly from another profile, @@ -551,7 +557,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): were regular profiles. The same XMLRPC API methods work on them as profiles also. """ - self.__validate_token(token) + self.check_access(token,"new_subprofile") return self.__store_object(item_profile.Profile(self.api._config,is_subobject=True)) def new_system(self,token): @@ -559,7 +565,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): Creates a new (unconfigured) system object. See the documentation for new_distro as it works exactly the same. """ - self.__validate_token(token) + self.check_access(token,"new_system") return self.__store_object(item_system.System(self.api._config)) def new_repo(self,token): @@ -567,7 +573,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): Creates a new (unconfigured) repo object. See the documentation for new_distro as it works exactly the same. """ - self.__validate_token(token) + self.check_access(token,"new_repo") return self.__store_object(item_repo.Repo(self.api._config)) def get_distro_handle(self,name,token): @@ -576,7 +582,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): object id that can be passed in to modify_distro() or save_distro() commands. Raises an exception if no object can be matched. """ - self.__validate_token(token) + self.check_access(token,"get_distro_handle") self._refresh() found = self.api.distros().find(name) return self.__store_object(found) @@ -587,7 +593,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): object id that can be passed in to modify_profile() or save_profile() commands. Raises an exception if no object can be matched. """ - self.__validate_token(token) + self.check_access(token,"get_profile_handle") self._refresh() found = self.api.profiles().find(name) return self.__store_object(found) @@ -598,7 +604,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): object id that can be passed in to modify_system() or save_system() commands. Raises an exception if no object can be matched. """ - self.__validate_token(token) + self.check_access(token,"get_system_handle") self._refresh() found = self.api.systems().find(name) return self.__store_object(found) @@ -609,7 +615,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): object id that can be passed in to modify_repo() or save_pro() commands. Raises an exception if no object can be matched. """ - self.__validate_token(token) + self.check_access(token,"get_repo_handle") self._refresh() found = self.api.repos().find(name) return self.__store_object(found) @@ -618,7 +624,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): """ Saves a newly created or modified distro object to disk. """ - self.__validate_token(token) + self.check_access(token,"save_distro") obj = self.__get_object(object_id) return self.api.distros().add(obj,with_copy=True) @@ -626,7 +632,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): """ Saves a newly created or modified profile object to disk. """ - self.__validate_token(token) + self.check_access(token,"save_profile") obj = self.__get_object(object_id) return self.api.profiles().add(obj,with_copy=True) @@ -634,7 +640,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): """ Saves a newly created or modified system object to disk. """ - self.__validate_token(token) + self.check_access(token,"save_system") obj = self.__get_object(object_id) return self.api.systems().add(obj,with_copy=True) @@ -642,7 +648,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): """ Saves a newly created or modified repo object to disk. """ - self.__validate_token(token) + self.check_access(token,"save_repo") obj = self.__get_object(object_id) return self.api.repos().add(obj,with_copy=True) @@ -660,7 +666,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): Allows modification of certain attributes on newly created or existing distro object handle. """ - self.__validate_token(token) + self.check_access(token, "modify_distro", attribute, arg) obj = self.__get_object(object_id) return self.__call_method(obj, attribute, arg) @@ -669,7 +675,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): Allows modification of certain attributes on newly created or existing profile object handle. """ - self.__validate_token(token) + self.check_access(token, "modify_profile", attribute, arg) obj = self.__get_object(object_id) return self.__call_method(obj, attribute, arg) @@ -678,7 +684,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): Allows modification of certain attributes on newly created or existing system object handle. """ - self.__validate_token(token) + self.check_access(token, "modify_system", attribute, arg) obj = self.__get_object(object_id) return self.__call_method(obj, attribute, arg) @@ -687,7 +693,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): Allows modification of certain attributes on newly created or existing repo object handle. """ - self.__validate_token(token) + self.check_access(token, "modify_repo", attribute, arg) obj = self.__get_object(object_id) return self.__call_method(obj, attribute, arg) @@ -696,7 +702,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): Deletes a distro from a collection. Note that this just requires the name of the distro, not a handle. """ - self.__validate_token(token) + self.check_access(token, "distro_remove", name) rc = self.api._config.distros().remove(name) return rc @@ -705,7 +711,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): Deletes a profile from a collection. Note that this just requires the name of the profile, not a handle. """ - self.__validate_token(token) + self.check_access(token, "profile_remove", name) rc = self.api._config.profiles().remove(name) return rc @@ -714,7 +720,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): Deletes a system from a collection. Note that this just requires the name of the system, not a handle. """ - self.__validate_token(token) + self.check_access(token, "system_remove", name) rc = self.api._config.systems().remove(name) return rc @@ -723,7 +729,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): Deletes a repo from a collection. Note that this just requires the name of the repo, not a handle. """ - self.__validate_token(token) + self.check_access(token, "repo_remove", name) rc = self.api._config.repos().remove(name) return rc @@ -738,7 +744,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): Future versions of cobbler may understand how to do a cascade sync on object edits making explicit calls to sync redundant. """ - self.__validate_token(token) + self.check_access(token, sync) return self.api.sync() def reposync(self,repos=[],token=None): @@ -747,7 +753,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): reposync is very slow and probably should not be used through the XMLRPC API, setting up reposync on nightly cron is better. """ - self.__validate_token(token) + self.check_access(token, "reposync", repos) return self.api.reposync(repos) def import_tree(self,mirror_url,mirror_name,network_root=None,token=None): @@ -757,14 +763,14 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): It would be better to use the CLI. See documentation in api.py. This command may be removed from the API in a future release. """ - self.__validate_token(token) + self.check_access(token, "import_tree") return self.api.import_tree(mirror_url,mirror_name,network_root) def get_kickstart_templates(self,token): """ Returns all of the kickstarts that are in use by the system. """ - self.__validate_token(token) + self.check_access(token, "get_kickstart_templates") files = {} for x in self.api.profiles(): if x.kickstart is not None and x.kickstart != "" and x.kickstart != "<>": @@ -784,7 +790,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): Also if living in /etc/cobbler the file must be a kickstart file. """ - self.__validate_token(token) + self.check_access(token,"read_or_write_kickstart_templates",kickstart_file,is_read) if kickstart_file.find("..") != -1 or not kickstart_file.startswith("/"): raise CX(_("tainted file location")) @@ -812,8 +818,8 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): -# ********************************************************************************* -# ********************************************************************************* +# ********************************************************************* +# ********************************************************************* class CobblerReadWriteXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer): """ @@ -824,76 +830,3 @@ class CobblerReadWriteXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer): self.allow_reuse_address = True SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self,args) -# ********************************************************************************* -# ********************************************************************************* - -if __name__ == "__main__": - - # note: this demo requires that - # (A) /etc/cobbler/auth.conf has a "testuser/llamas2007" account - # (B) xmlrpc_rw_enabled is turned on /var/lib/cobbler/settings - # (C) cobblerd is running (and restarted if changing any of the above) - # (D) apache is configured as a reverse proxy (see cobbler.conf in /etc/httpd/conf.d) - # this demo does not use SSL yet -- it /should/ and /can/. - - my_uri = "http://127.0.0.1/cobbler_api_rw" - remote = xmlrpclib.Server(my_uri) - - testuser = "admin" - testpass = "mooses9" - - token = remote.login(testuser,testpass) - print token - - # just to make things "work" - os.system("touch /tmp/vmlinuz") - os.system("touch /tmp/initrd.img") - os.system("touch /tmp/fake.ks") - - # now add a distro - distro_id = remote.new_distro(token) - remote.modify_distro(distro_id, 'name', 'example-distro',token) - remote.modify_distro(distro_id, 'kernel', '/tmp/vmlinuz',token) - remote.modify_distro(distro_id, 'initrd', '/tmp/initrd.img',token) - remote.save_distro(distro_id,token) - - # now add a repository (that's not really mirroring anything useful) - repo_id = remote.new_repo(token) - remote.modify_repo(repo_id, 'name', 'example-repo', token) - remote.modify_repo(repo_id, 'mirror', 'rsync://mirror.example.org/foo', token) - remote.save_repo(repo_id, token) - - # now add a profile - profile_id = remote.new_profile(token) - remote.modify_profile(profile_id, 'name', 'example-profile', token) - remote.modify_profile(profile_id, 'distro', 'example-distro', token) - remote.modify_profile(profile_id, 'kickstart', '/tmp/fake.ks', token) - remote.modify_profile(profile_id, 'repos', ['example-repo'], token) - remote.save_profile(profile_id, token) - - # now add a system - system_id = remote.new_system(token) - remote.modify_system(system_id, 'name', 'example-system', token) - remote.modify_system(system_id, 'profile', 'example-profile', token) - remote.save_system(system_id, token) - - print remote.get_distros() - print remote.get_profiles() - print remote.get_systems() - print remote.get_repos() - - print remote.get_system("AA:BB:AA:BB:AA:BB",True) # flattened - - # now simulate hitting a "sync" button in a WebUI - print remote.sync(token) - - # the following code just tests a failed connection: - #remote = CobblerReadWriteXMLRPCInterface(api,logger) - #try: - # token = remote.login("exampleuser2","examplepass") - #except: - # token = "fake_token" - #print token - #rc = remote.test(token) - #print "test result: %s" % rc - # print "cache: %s" % remote.token_cache diff --git a/config/cobbler.conf b/config/cobbler.conf index 422420d..77bfe84 100644 --- a/config/cobbler.conf +++ b/config/cobbler.conf @@ -39,14 +39,14 @@ BrowserMatch "MSIE" AuthDigestEnableQueryStringHack=On AuthName Cobbler Require valid-user SetHandler mod_python - PythonAccessHandler index + PythonAuthenHandler index - PythonAuthZHandler index + #PythonAccessHandler index + #PythonAuthZHandler index PythonHandler mod_python.publisher # disable in production PythonDebug on - PythonAutoReload on diff --git a/config/modules.conf b/config/modules.conf index fbe710c..2d60d21 100644 --- a/config/modules.conf +++ b/config/modules.conf @@ -5,3 +5,8 @@ profile = serializer_yaml system = serializer_yaml repo = serializer_yaml +[authentication] +module = authn_configfile + +[authorization] +module = authn_allowall diff --git a/scripts/index.py b/scripts/index.py index 9076d6d..fc528df 100755 --- a/scripts/index.py +++ b/scripts/index.py @@ -13,60 +13,130 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. """ -# TO DO: -# connect backend authn via cobbler XMLRPC (non-RW) API -# connect backend authz via cobbler XMLRPC (RW) API +# still TODO: # serve up Web UI through this interface, via tokens in headers -# make REST interface for read/write commands (also?) from mod_python import apache +from mod_python import Session +import xmlrpclib + +XMLRPC_SERVER = "http://127.0.0.1/cobbler_api_rw" + +#======================================= + +class ServerProxy(xmlrpclib.ServerProxy): + + """ + Establishes a connection from the mod_python + web interface to cobblerd, which incidentally + is also being proxied by Apache. + """ + + def __init__(self, url=None): + xmlrpclib.ServerProxy.__init__(self, url, allow_none=True) + +xmlrpc_server = ServerProxy(XMLRPC_SERVER) + +#======================================= def __get_user(req): + """ + What user are we logged in as? + """ req.add_common_vars() env_vars = req.subprocess_env.copy() return env_vars["REMOTE_USER"] +def __get_session(req): + """ + Get/Create the Apache Session Object + FIXME: any reason to not use MemorySession? + """ + if not hasattr(req,"session"): + req.session = Session.MemorySession(req) + return req.session + +#====================================================== + def index(req): - user = __get_user(req) - path = req.uri - return "Hello, %s, %s" % (user, path) + + """ + Right now, index serves everything. + + Hitting this URL means we've already cleared authn/authz + but we still need to use the token for all remote requests. + + FIXME: deal with query strings and defer to CobblerWeb.py + """ + + my_user = __get_user(req) + my_uri = req.uri + + sess = __get_session(req) + token = sess['cobbler_token'] + + return "it seems to be all good: %s" % token + +#====================================================== def hello(req): + + """ + This is just another example for the publisher handler. + """ + user = __get_user(req) path = req.uri return "We are in hello(%s)" % path -def authenhandler(req): +#====================================================== - pw = req.get_basic_auth_pw() - user = req.user +def authenhandler(req): - # FIXME: poll cobbler_api (not rw) here to check - # check_authn(user,pass) -> T/F + """ + Validates that username/password are a valid combination, but does + not check access levels. + """ - apache.log_error("authenticate handler called") + my_pw = req.get_basic_auth_pw() + my_user = req.user + my_uri = req.uri - if user == "admin" and pw == "cobbler": - return apache.OK - else: + apache.log_error("authenhandler called: %s" % my_user) + try: + token = xmlrpc_server.login(my_user,my_pw) + except: return apache.HTTP_UNAUTHORIZED -def accesshandler(req): - uri = req.uri + try: + ok = xmlrpc_server.check_access(token,my_uri) + except: + return apache.HTTP_FORBIDDEN + - apache.log_error("accesshandler uri: %s" % (uri)) + sess=__get_session(req) + sess['cobbler_token'] = token + sess.save() - # FIXME: poll cobbler_api (not rw) here to check - # check_access(user,uri) -> T/F + return apache.OK + +#====================================================== + +def accesshandler(req): + + """ + Not using this + """ - if uri.find("hello") != -1: - return apache.HTTP_FORBIDDEN return apache.OK +#====================================================== + def authenzhandler(req): - # we really don't need this because of the accesshandler. - # add in later if we find we /DO/ need it - return apache.OK + """ + Not using this + """ + return apache.OK -- cgit