Ejemplo n.º 1
0
    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.")
Ejemplo n.º 2
0
    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()
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
            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)
Ejemplo n.º 5
0
# -*- 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))
Ejemplo n.º 6
0
    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()
Ejemplo n.º 7
0
    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