diff options
Diffstat (limited to 'cobbler')
-rw-r--r-- | cobbler/api.py | 56 | ||||
-rw-r--r-- | cobbler/modules/authn_configfile.py | 5 | ||||
-rw-r--r-- | cobbler/modules/authn_kerberos.py | 81 | ||||
-rw-r--r-- | cobbler/modules/authz_allowall.py | 2 | ||||
-rw-r--r-- | cobbler/remote.py | 27 | ||||
-rw-r--r-- | cobbler/settings.py | 1 |
6 files changed, 149 insertions, 23 deletions
diff --git a/cobbler/api.py b/cobbler/api.py index e6ef88b..6343035 100644 --- a/cobbler/api.py +++ b/cobbler/api.py @@ -24,6 +24,11 @@ import action_status import action_validate import sub_process import module_loader +import logging + +ERROR = 100 +INFO = 10 +DEBUG = 5 class BootAPI: @@ -37,10 +42,33 @@ class BootAPI: self.__dict__ = self.__shared_state if not BootAPI.has_loaded: + + + logger = logging.getLogger("cobbler.api") + logger.setLevel(logging.DEBUG) + ch = logging.FileHandler("/var/log/cobbler/cobbler.log") + ch.setLevel(logging.DEBUG) + formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") + ch.setFormatter(formatter) + logger.addHandler(ch) + BootAPI.has_loaded = True module_loader.load_modules() self._config = config.Config(self) self.deserialize() + self.logger = logger + self.logger.debug("API handle initialized") + + self.authn = self.get_module_from_file( + "authentication", + "module", + "authn_configfile" + ) + self.authz = self.get_module_from_file( + "authorization", + "module", + "authz_allowall" + ) def version(self): """ @@ -48,6 +76,7 @@ class BootAPI: Currently checks the RPM DB, which is not perfect. Will return "?" if not installed. """ + self.logger.debug("cobbler version") cmd = sub_process.Popen("/bin/rpm -q cobbler", stdout=sub_process.PIPE, shell=True) result = cmd.communicate()[0].replace("cobbler-","") if result.find("not installed") != -1: @@ -55,7 +84,6 @@ class BootAPI: tokens = result[:result.rfind("-")].split(".") return int(tokens[0]) + 0.1 * int(tokens[1]) + 0.001 * int(tokens[2]) - def clear(self): """ Forget about current list of profiles, distros, and systems @@ -99,12 +127,14 @@ class BootAPI: """ Return a blank, unconfigured system, unattached to a collection """ + self.logger.debug("new_system") return self._config.new_system(is_subobject=is_subobject) def new_distro(self,is_subobject=False): """ Create a blank, unconfigured distro, unattached to a collection. """ + self.logger.debug("new_distro") return self._config.new_distro(is_subobject=is_subobject) @@ -112,12 +142,14 @@ class BootAPI: """ Create a blank, unconfigured profile, unattached to a collection """ + self.logger.debug("new_profile") return self._config.new_profile(is_subobject=is_subobject) def new_repo(self,is_subobject=False): """ Create a blank, unconfigured repo, unattached to a collection """ + self.logger.debug("new_repo") return self._config.new_repo(is_subobject=is_subobject) def auto_add_repos(self): @@ -125,6 +157,7 @@ class BootAPI: Import any repos this server knows about and mirror them. Credit: Seth Vidal. """ + self.logger.debug("auto_add_repos") try: import yum except: @@ -164,6 +197,7 @@ class BootAPI: for human admins, who may, for instance, forget to properly set up their TFTP servers for PXE, etc. """ + self.logger.debug("check") check = action_check.BootCheck(self._config) return check.run() @@ -176,6 +210,7 @@ class BootAPI: is not available on all platforms and can not detect "future" kickstart format correctness. """ + self.logger.debug("validateks") validator = action_validate.Validate(self._config) return validator.run() @@ -186,6 +221,7 @@ class BootAPI: /tftpboot. Any operations done in the API that have not been saved with serialize() will NOT be synchronized with this command. """ + self.logger.debug("sync") sync = action_sync.BootSync(self._config) return sync.run() @@ -194,10 +230,12 @@ class BootAPI: Take the contents of /var/lib/cobbler/repos and update them -- or create the initial copy if no contents exist yet. """ + self.logger.debug("reposync") reposync = action_reposync.RepoSync(self._config) return reposync.run(name) def status(self,mode): + self.logger.debug("status") statusifier = action_status.BootStatusReport(self._config, mode) return statusifier.run() @@ -252,4 +290,20 @@ class BootAPI: """ return module_loader.get_modules_in_category(category) + def authenticate(self,user,password): + """ + (Remote) access control. + """ + self.logger.debug("authorize(%s)" % (user)) + rc = self.authn.authenticate(self,user,password) + self.logger.debug("authorize(%s)=%s" % (user,rc)) + return rc + + def authorize(self,user,resource,arg1=None,arg2=None): + """ + (Remote) access control. + """ + rc = self.authz.authorize(self,user,resource,arg1,arg2) + self.logger.debug("authorize(%s,%s)=%s" % (user,resource,rc)) + return rc diff --git a/cobbler/modules/authn_configfile.py b/cobbler/modules/authn_configfile.py index 5740efa..30637b7 100644 --- a/cobbler/modules/authn_configfile.py +++ b/cobbler/modules/authn_configfile.py @@ -52,7 +52,7 @@ def __parse_storage(): pass return results -def authenticate(username,password): +def authenticate(api_handle,username,password): """ Validate a username/password combo, returning True/False @@ -70,7 +70,4 @@ def authenticate(username,password): return False -if __name__ == "__main__": - print authenticate("cobbler","cobbler") - print authenticate("cobbler","bogus") diff --git a/cobbler/modules/authn_kerberos.py b/cobbler/modules/authn_kerberos.py new file mode 100644 index 0000000..7f85db6 --- /dev/null +++ b/cobbler/modules/authn_kerberos.py @@ -0,0 +1,81 @@ +""" +Authentication module that uses kerberos. + +Copyright 2007, Red Hat, Inc +Michael DeHaan <mdehaan@redhat.com> + +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. +""" + +# NOTE: this is not using 'straight up' kerberos in that we +# relay passwords through cobblerd for authentication, that may +# be done later. It does of course check against kerberos, +# however. + +# ALSO NOTE: we're calling out to a Perl program to make +# this work. You must install Authen::Simple::Kerberos +# from CPAN and the Kerberos libraries for this to work. +# See the Cobbler Wiki for more info. + +# ALSO ALSO NOTE: set kerberos_realm in /var/lib/cobbler/settings +# to something appropriate or this will never work. CASING +# MATTERS. example.com != EXAMPLE.COM. + +import distutils.sysconfig +import ConfigParser +import sys +import os +from rhpl.translate import _, N_, textdomain, utf8 +import md5 +import traceback +# since sub_process isn't available on older OS's +try: + import sub_process as subprocess +except: + import subprocess + +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(api_handle,username,password): + """ + Validate a username/password combo, returning True/False + Uses cobbler_auth_helper + """ + + realm = self.api.settings().kerberos_realm + api_handle.logger.debug("authenticating %s against %s" % (username,realm)) + + rc = subprocess.call([ + "/usr/bin/cobbler_auth_help", + "--method=kerberos", + "--username=%s" % username, + "--password=%s" % password, + "--realm=%s" % realm + ]) + print rc + if rc == 42: + api_handle.logger.debug("authenticated ok") + # authentication ok (FIXME: log) + return True + else: + api_handle.logger.debug("authentication failed") + # authentication failed + return False + + diff --git a/cobbler/modules/authz_allowall.py b/cobbler/modules/authz_allowall.py index 4125ed6..1b05630 100644 --- a/cobbler/modules/authz_allowall.py +++ b/cobbler/modules/authz_allowall.py @@ -32,7 +32,7 @@ def register(): """ return "authz" -def authorize(user,resource,arg1=None,arg2=None): +def authorize(api_handle,user,resource,arg1=None,arg2=None): """ Validate a user against a resource. """ diff --git a/cobbler/remote.py b/cobbler/remote.py index 081f8c8..e84827a 100644 --- a/cobbler/remote.py +++ b/cobbler/remote.py @@ -20,7 +20,6 @@ import os import SimpleXMLRPCServer from rhpl.translate import _, N_, textdomain, utf8 import xmlrpclib -import logging import random import base64 @@ -52,7 +51,7 @@ class CobblerXMLRPCInterface: def __init__(self,api,logger): self.api = api - self.logger = logger + self.logger = self.api.logger def __sorter(self,a,b): return cmp(a["name"],b["name"]) @@ -365,17 +364,6 @@ 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): """ @@ -435,7 +423,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. """ - return self.authn.authenticate(input_user,input_password) + return self.api.authenticate(input_user,input_password) def __validate_token(self,token): """ @@ -457,6 +445,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): raise CX(_("invalid token: %s" % token)) def check_access(self,token,resource,arg1=None,arg2=None): + self.logger.debug("check_access(%s, %s)" % (token,resource)) validated = self.__validate_token(token) return self.__authorize(token,resource,arg1,arg2) @@ -473,17 +462,18 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): method calls. The token will time out after a set interval if not used. Re-logging in permitted. """ + self.logger.debug("login (%s)" % login_user) if self.__validate_user(login_user,login_password): token = self.__make_token(login_user) - self.logger.info("login succeeded: %s" % login_user) + self.logger.debug("login succeeded: %s" % login_user) return token else: - self.logger.info("login failed: %s" % login_user) + self.logger.debug("login failed: %s" % login_user) raise CX(_("login failed: %s") % login_user) def __authorize(self,token,resource,arg1=None,arg2=None): user = self.__get_user_from_token(token) - if self.authz.authorize(user,resource,arg1,arg2): + if self.api.authorize(user,resource,arg1,arg2): return True else: raise CX(_("user does not have access to resource: %s") % resource) @@ -492,6 +482,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): """ Retires a token ahead of the timeout. """ + self.logger.debug("logout(%s)" % token) if self.token_cache.has_key(token): del self.token_cache[token] return True @@ -501,6 +492,7 @@ class CobblerReadWriteXMLRPCInterface(CobblerXMLRPCInterface): """ This is a demo function that does not return anything useful. """ + self.logger.debug("token_check(%s)" % token) self.__validate_token(token) return True @@ -830,3 +822,4 @@ class CobblerReadWriteXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer): self.allow_reuse_address = True SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self,args) + diff --git a/cobbler/settings.py b/cobbler/settings.py index 8f9527d..c1fe232 100644 --- a/cobbler/settings.py +++ b/cobbler/settings.py @@ -34,6 +34,7 @@ DEFAULTS = { "dnsmasq_bin" : "/usr/sbin/dnsmasq", "dnsmasq_conf" : "/etc/dnsmasq.conf", "httpd_bin" : "/usr/sbin/httpd", + "kerberos_realm" : "example.org", "kernel_options" : { "lang" : " ", "text" : None, |