def _login(self, force=False, verbose=False): """Login to the hub. - self._hub instance is created in this method - session information is stored in a cookie in self._transport """ login_method_name = "_login_%s" % self._auth_method if not hasattr(self, login_method_name): raise ImproperlyConfigured("Unknown authentication method: %s" % self._auth_method) # create new self._hub instance (only once, when calling constructor) if self._hub is None: self._hub = xmlrpclib.ServerProxy("%s/%s/" % (self._hub_url, self._client_type), allow_none=True, transport=self._transport, verbose=verbose) if force or self._hub.auth.renew_session(): self._logger and self._logger.info("Creating new session...") try: # logout to delete current session information self._logout() except KeyboardInterrupt: raise except Exception as ex: self._logger and self._logger.error("Failed to log out: %s" % ex) try: login_method = getattr(self, login_method_name) login_method() self._logged_in = True except KeyboardInterrupt: raise except Exception as ex: self._logger and self._logger.debug("Failed to create new session: %s" % ex) else: self._logger and self._logger.info("New session created.")
def _login_gssapi(self): """Login using kerberos credentials (uses gssapi).""" login_url = urlparse.urljoin(self._hub_url, "auth/krb5login/") # read default values from settings principal = self._conf.get("KRB_PRINCIPAL") keytab = self._conf.get("KRB_KEYTAB") service = self._conf.get("KRB_SERVICE") realm = self._conf.get("KRB_REALM") ccache = self._conf.get("KRB_CCACHE") import requests import gssapi import requests_gssapi request_args = {} # NOTE behavior difference from hub proxy overall: # HubProxy by default DOES NOT verify https connections :( # See the constructor. It could be repeated here by defaulting verify to False, # but let's not do that, instead you must have an unbroken SSL setup to # use this auth method. if self._conf.get("CA_CERT"): request_args["verify"] = self._conf["CA_CERT"] server_name = self.get_server_principal(service=service, realm=realm) server_name = gssapi.Name(server_name, gssapi.NameType.kerberos_principal) auth_args = { "target_name": server_name, } if principal is not None: if keytab is None: raise ImproperlyConfigured( "Cannot specify a principal without a keytab") name = gssapi.Name(principal, gssapi.NameType.kerberos_principal) store = {"client_keytab": keytab} if ccache is not None: store["ccache"] = "FILE:" + ccache auth_args["creds"] = gssapi.Credentials(name=name, store=store, usage="initiate") # We only do one request, but a Session is used to allow requests to write # the new session ID into the cookiejar. with requests.Session() as s: s.cookies = self._transport.cookiejar response = s.get(login_url, auth=requests_gssapi.HTTPSPNEGOAuth(**auth_args), allow_redirects=False, **request_args) self._logger and self._logger.debug("Login response: %s %s", response, response.headers) response.raise_for_status()
def _login_krbv(self): """Login using kerberos credentials (uses python-krbV).""" # read default values from settings principal = self._conf.get("KRB_PRINCIPAL") keytab = self._conf.get("KRB_KEYTAB") service = self._conf.get("KRB_SERVICE") realm = self._conf.get("KRB_REALM") ccache = self._conf.get("KRB_CCACHE") proxyuser = self._conf.get("KRB_PROXYUSER") import krbV ctx = krbV.default_context() if ccache is not None: ccache = krbV.CCache(name='FILE:' + ccache, context=ctx) else: ccache = ctx.default_ccache() if principal is not None: if keytab is not None: cprinc = krbV.Principal(name=principal, context=ctx) keytab = krbV.Keytab(name=keytab, context=ctx) ccache.init(cprinc) ccache.init_creds_keytab(principal=cprinc, keytab=keytab) else: raise ImproperlyConfigured( "Cannot specify a principal without a keytab") else: # connect using existing credentials cprinc = ccache.principal() sprinc = krbV.Principal(name=self.get_server_principal(service=service, realm=realm), context=ctx) ac = krbV.AuthContext(context=ctx) ac.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE | krbV.KRB5_AUTH_CONTEXT_DO_TIME ac.rcache = ctx.default_rcache() # create and encode the authentication request try: ac, req = ctx.mk_req(server=sprinc, client=cprinc, auth_context=ac, ccache=ccache, options=krbV.AP_OPTS_MUTUAL_REQUIRED) except krbV.Krb5Error as ex: if getattr(ex, "err_code", None) == -1765328377: ex.message += ". Make sure you correctly set KRB_REALM (current value: %s)." % realm ex.args = (ex.err_code, ex.message) raise ex encode_func = base64.encodebytes if hasattr( base64, "encodebytes") else base64.encodestring req_enc = encode_func(req) self._hub.auth.login_krbv(req_enc)
value = self._get_value(get_next=False) result.append(value) return result def _get_tuple(self): """Get a tuple content.""" result = [] while True: self._get_token() self._skip_commas() if (self._tok_name, self._tok_value) == ("OP", ")"): break value = self._get_value(get_next=False) result.append(value) return tuple(result) # settings is created only if PROJECT_CONFIG_FILE is set if "PROJECT_CONFIG_FILE" in os.environ: try: settings = PyConfigParser() settings.load_from_file(os.environ.get("PROJECT_CONFIG_FILE")) except Exception: ex = sys.exc_info()[1] raise ImproperlyConfigured("Could not load config file: %s" % ex)
# -*- coding: utf-8 -*- import os from kobo.exceptions import ImproperlyConfigured from django.conf import settings for var in ["XMLRPC_METHODS", "TASK_DIR", "UPLOAD_DIR"]: if not hasattr(settings, var): raise ImproperlyConfigured("'%s' is missing in project settings. It must be set to run kobo.hub app." % var) for var in ["TASK_DIR", "UPLOAD_DIR"]: dir_path = getattr(settings, var) if not os.path.isdir(dir_path): try: os.makedirs(dir_path) except: raise ImproperlyConfigured("'%s' doesn't exist and can't be automatically created." % dir_path) elif not os.access(dir_path, os.R_OK | os.W_OK | os.X_OK): raise ImproperlyConfigured("Invalid permissions on '%s'." % dir_path) for var, value in [("MIDDLEWARE_CLASSES", "kobo.hub.middleware.WorkerMiddleware")]: if not hasattr(settings, var) or value not in getattr(settings, var, []): raise ImproperlyConfigured("'%s' in '%s' is missing in project settings. It must be set to run kobo.hub app." % (value, var))
def _login_gssapi_common(self, login_url, force_service, allow_redirects): """Common authentication logic for auth methods using gssapi. - if force_service is True, client always calculates a service principal up-front even if no KRB_SERVICE was set in config. Breaks OIDC since we are not actually doing gssapi with the kobo hub. - if allow_redirects is True, authentication is allowed to follow redirects. Required in the OIDC case. """ # read default values from settings principal = self._conf.get("KRB_PRINCIPAL") keytab = self._conf.get("KRB_KEYTAB") service = self._conf.get("KRB_SERVICE") realm = self._conf.get("KRB_REALM") ccache = self._conf.get("KRB_CCACHE") import requests import gssapi import requests_gssapi request_args = {} # NOTE behavior difference from hub proxy overall: # HubProxy by default DOES NOT verify https connections :( # See the constructor. It could be repeated here by defaulting verify to False, # but let's not do that, instead you must have an unbroken SSL setup to # use this auth method. if self._conf.get("CA_CERT"): request_args["verify"] = self._conf["CA_CERT"] auth_args = {"mutual_authentication": requests_gssapi.OPTIONAL} if service or force_service: if realm is None: # let gssapi select the correct realm (according to system configuration) if service is None: service = "HTTP" server_name = '%s@%s' % (service, self.get_hub_hostname()) server_name = gssapi.Name(server_name, gssapi.NameType.hostbased_service) else: server_name = self.get_server_principal(service=service, realm=realm) server_name = gssapi.Name(server_name, gssapi.NameType.kerberos_principal) auth_args["target_name"] = server_name if principal is not None: if keytab is None: raise ImproperlyConfigured( "Cannot specify a principal without a keytab") name = gssapi.Name(principal, gssapi.NameType.kerberos_principal) store = {"client_keytab": keytab} if ccache is not None: store["ccache"] = "FILE:" + ccache auth_args["creds"] = gssapi.Credentials(name=name, store=store, usage="initiate") # We only do one request, but a Session is used to allow requests to write # the new session ID into the cookiejar. with requests.Session() as s: s.cookies = self._transport.cookiejar response = s.get(login_url, auth=requests_gssapi.HTTPSPNEGOAuth(**auth_args), allow_redirects=allow_redirects, **request_args) self._logger and self._logger.debug("Login response: %s %s", response, response.headers) response.raise_for_status()
def _login_krbv(self): """Login using kerberos credentials (uses python-krbV).""" def get_server_principal(service=None, realm=None): """Convert hub url to kerberos principal.""" hostname = urlparse.urlparse(self._hub_url)[1] # remove port from hostname hostname = hostname.split(":")[0] if realm is None: # guess realm: last two parts from hostname realm = ".".join(hostname.split(".")[-2:]).upper() if service is None: service = "HTTP" return '%s/%s@%s' % (service, hostname, realm) # read default values from settings principal = self._conf.get("KRB_PRINCIPAL") keytab = self._conf.get("KRB_KEYTAB") service = self._conf.get("KRB_SERVICE") realm = self._conf.get("KRB_REALM") ccache = self._conf.get("KRB_CCACHE") proxyuser = self._conf.get("KRB_PROXYUSER") import krbV ctx = krbV.default_context() if ccache is not None: ccache = krbV.CCache(name='FILE:' + ccache, context=ctx) else: ccache = ctx.default_ccache() if principal is not None: if keytab is not None: cprinc = krbV.Principal(name=principal, context=ctx) keytab = krbV.Keytab(name=keytab, context=ctx) ccache.init(cprinc) ccache.init_creds_keytab(principal=cprinc, keytab=keytab) else: raise ImproperlyConfigured( "Cannot specify a principal without a keytab") else: # connect using existing credentials cprinc = ccache.principal() sprinc = krbV.Principal(name=get_server_principal(service=service, realm=realm), context=ctx) ac = krbV.AuthContext(context=ctx) ac.flags = krbV.KRB5_AUTH_CONTEXT_DO_SEQUENCE | krbV.KRB5_AUTH_CONTEXT_DO_TIME ac.rcache = ctx.default_rcache() # create and encode the authentication request try: ac, req = ctx.mk_req(server=sprinc, client=cprinc, auth_context=ac, ccache=ccache, options=krbV.AP_OPTS_MUTUAL_REQUIRED) except krbV.Krb5Error, ex: if getattr(ex, "err_code", None) == -1765328377: ex.message += ". Make sure you correctly set KRB_REALM (current value: %s)." % realm ex.args = (ex.err_code, ex.message) raise ex