def test_login_gssapi_principal_needs_keytab(requests_session):
    """Login with gssapi method raises if principal is provided without keytab."""
    hub_url = "https://hub.example.com/myapp/endpoint"

    conf = PyConfigParser()
    conf.load_from_dict(
        {
            "HUB_URL": hub_url,
            "AUTH_METHOD": "gssapi",
            "KRB_PRINCIPAL": "*****@*****.**",
        }
    )

    transport = FakeTransport()
    logger = mock.Mock()
    proxy = HubProxy(conf, transport=transport, logger=logger)

    proxy._login(force=True)

    # This is pretty dumb: login() swallows all exceptions (probably for no good reason).
    # The only hint there was a problem is a DEBUG log message, so we detect the error
    # that way.
    logger.debug.assert_called_with(
        "Failed to create new session: Cannot specify a principal without a keytab"
    )
Example #2
0
    def run_task(self, task_info):
        TaskClass = self.task_container[task_info["method"]]

        # add *task_manager* attribute to foreground tasks
        if TaskClass.foreground:
            # TODO:
            TaskClass.task_manager = self
            hub = self.hub
        else:
            # create a new session for the task
            hub = HubProxy(self.conf, client_type="worker")

        task = TaskClass(hub, self.conf, task_info["id"], task_info["args"])

        # redirect stdout and stderr
        thread = kobo.worker.logger.LoggingThread(hub, task_info["id"])
        sys.stdout = kobo.worker.logger.LoggingIO(open(os.devnull, "w"), thread)
        sys.stderr = sys.stdout
        thread.start()

        failed = False
        try:
            task.run()
        except ShutdownException:
            thread.stop()
            if TaskClass.foreground and TaskClass.exclusive:
                # close task (shutdown-worker and similar control tasks) and raise
                hub.worker.close_task(task.task_id, task.result)
                raise
            # interrupt otherwise
            hub.worker.interrupt_tasks([task.task_id])
            return
        except KeyboardInterrupt:
            thread.stop()
            # interrupt otherwise
            hub.worker.interrupt_tasks([task.task_id])
            return
        except SystemExit as ex:
            if len(ex.args) > 0 and ex.args[0] != 0:
                sys.stdout.write("\nProgram has exited with return code '%s'." % ex.args[0])
                failed = True
        except FailTaskException as ex:
            failed = True
        except:
            message = "ERROR: %s\n" % kobo.tback.get_exception()
            message += "See traceback.log for details (admin only).\n"
            hub.upload_task_log(StringIO(message), task.task_id, "error.log")
            hub.upload_task_log(StringIO(kobo.tback.Traceback().get_traceback()), task.task_id, "traceback.log", mode=0o600)
            failed = True
        finally:
            thread.stop()

        if failed:
            hub.worker.fail_task(task.task_id, task.result)
        else:
            hub.worker.close_task(task.task_id, task.result)
Example #3
0
def test_login_gssapi_krb_opts(requests_session):
    """Login with gssapi method prepares auth using correct gssapi parameters
    according to config."""

    hub_url = "https://hub.example.com/myapp/endpoint"
    login_url = "https://hub.example.com/myapp/auth/krb5login/"

    conf = PyConfigParser()
    conf.load_from_dict({
        "HUB_URL": hub_url,
        "AUTH_METHOD": "gssapi",
        "CA_CERT": "/some/ca-bundle.pem",
        "KRB_PRINCIPAL": "*****@*****.**",
        "KRB_SERVICE": "SVC",
        "KRB_REALM": "REALM.EXAMPLE.COM",
        "KRB_KEYTAB": "some-keytab",
        "KRB_CCACHE": "some-cache",
    })

    transport = FakeTransport()
    proxy = HubProxy(conf, transport=transport)

    mock_get = requests_session.return_value.get
    calls_before = len(mock_get.mock_calls)

    with mock.patch("requests_gssapi.HTTPSPNEGOAuth") as mock_auth:
        with mock.patch("gssapi.Credentials") as mock_creds:
            # Force a login
            proxy._login(force=True)

    get_call = mock_get.mock_calls[calls_before]

    # It should have prepared credentials with the details from config
    mock_creds.assert_called_once_with(
        name=gssapi.Name("*****@*****.**",
                         gssapi.NameType.kerberos_principal),
        store={
            "client_keytab": "some-keytab",
            "ccache": "FILE:some-cache"
        },
        usage="initiate",
    )

    # It should have prepared auth with those credentials and our configured
    # server principal
    mock_auth.assert_called_once_with(
        creds=mock_creds.return_value,
        target_name=gssapi.Name("SVC/[email protected]",
                                gssapi.NameType.kerberos_principal),
    )

    # It should have used the configured CA bundle when issuing the request
    assert get_call[2]["verify"] == "/some/ca-bundle.pem"
Example #4
0
    def __init__(self, conf, logger=None, **kwargs):
        kobo.log.LoggingBase.__init__(self, logger)
        self.conf = kobo.conf.PyConfigParser()

        # load default config
        default_config = os.path.abspath(
            os.path.join(os.path.dirname(__file__), "default.conf"))
        self.conf.load_from_file(default_config)

        # update data from another config
        if conf is not None:
            self.conf.load_from_conf(conf)

        # update data from kwargs
        self.conf.load_from_dict(kwargs)

        self.pid_dict = {}  # { task_id: pid }
        self.task_dict = {
        }  # { task_id: { task information obtained from self.hub.get_worker_tasks() } }

        self.locked = False  # if task manager is locked, it waits until tasks finish and exits

        self.task_container = TaskContainer()

        # self.hub (xml-rpc hub client) is created here
        self.hub = HubProxy(conf,
                            client_type="worker",
                            logger=self._logger,
                            **kwargs)
        # worker information obtained from hub
        self.worker_info = self.hub.worker.get_worker_info()
        self.update_worker_info()
Example #5
0
def test_login_gssapi(requests_session):
    """Login with gssapi method obtains session cookie via SPNEGO & krb5login."""

    hub_url = "https://example.com/myapp/endpoint"
    login_url = "https://example.com/myapp/auth/krb5login/"

    conf = PyConfigParser()
    conf.load_from_dict({
        "HUB_URL": hub_url,
        "AUTH_METHOD": "gssapi",
    })

    transport = FakeTransport()
    proxy = HubProxy(conf, transport=transport)

    # Proxy might have already done some calls during initialization.
    # We're trying to test login in isolation, so keep track of how many
    # mock calls there have been already.
    mock_get = requests_session.return_value.get
    calls_before = len(mock_get.mock_calls)

    # Force a login
    proxy._login(force=True)

    # Cookies should have been shared between session and transport
    assert requests_session.return_value.cookies is transport.cookiejar

    # Check the requests done
    calls = mock_get.mock_calls[calls_before:]

    assert calls[0][0] == ""
    call_args = calls[0][1]
    call_kwargs = calls[0][2]

    # It should have made a request to log in
    assert call_args == (login_url, )

    # It should have enabled SPNEGO auth.
    # More details about this object are verified in a separate test.
    assert "HTTPSPNEGOAuth" in str(type(call_kwargs["auth"]))

    # It should have verified the result
    assert calls[1][0] == "().raise_for_status"

    # And that's all
    assert len(calls) == 2
Example #6
0
def test_no_auto_logout(requests_session):
    """auto_logout argument warns of deprecation"""
    conf = PyConfigParser()
    conf.load_from_dict({"HUB_URL": 'https://example.com/hub'})

    transport = FakeTransport()
    with pytest.deprecated_call():
        HubProxy(conf, transport=transport, auto_logout=True)
Example #7
0
def test_proxies_to_xmlrpc(requests_session):
    """HubProxy proxies to underlying XML-RPC ServerProxy"""
    conf = PyConfigParser()
    conf.load_from_dict({"HUB_URL": 'https://example.com/hub'})

    transport = FakeTransport()
    proxy = HubProxy(conf, transport=transport)

    proxy.some_obj.some_method()

    # Last call should have invoked the method I requested
    (_, request_xml) = transport.fake_transport_calls[-1]
    assert b'some_obj.some_method' in request_xml
Example #8
0
    def run_task(self, task_info):
        TaskClass = self.task_container[task_info["method"]]

        # add *task_manager* attribute to foreground tasks
        if TaskClass.foreground:
            # TODO:
            TaskClass.task_manager = self
            hub = self.hub
        else:
            # create a new session for the task
            hub = HubProxy(self.conf, client_type="worker")

        task = TaskClass(hub, self.conf, task_info["id"], task_info["args"])

        # redirect stdout and stderr
        thread = kobo.worker.logger.LoggingThread(hub, task_info["id"])
        sys.stdout = kobo.worker.logger.LoggingIO(open(os.devnull, "w"), thread)
        sys.stderr = sys.stdout
        thread.start()

        failed = False
        try:
            task.run()
        except ShutdownException:
            thread.stop()
            if TaskClass.foreground and TaskClass.exclusive:
                # close task (shutdown-worker and similar control tasks) and raise
                hub.worker.close_task(task.task_id, task.result)
                raise
            # interrupt otherwise
            hub.worker.interrupt_tasks([task.task_id])
            return
        except KeyboardInterrupt:
            thread.stop()
            # interrupt otherwise
            hub.worker.interrupt_tasks([task.task_id])
            return
        except SystemExit, ex:
            if len(ex.args) > 0 and ex.args[0] != 0:
                sys.stdout.write("\nProgram has exited with return code '%s'." % ex.args[0])
                failed = True
Example #9
0
    def run_task(self, task_info):
        TaskClass = self.task_container[task_info["method"]]

        # add *task_manager* attribute to foreground tasks
        if TaskClass.foreground:
            # TODO:
            TaskClass.task_manager = self
            hub = self.hub
        else:
            # create a new session for the task
            hub = HubProxy(self.conf, client_type="worker")

        task = TaskClass(hub, self.conf, task_info["id"], task_info["args"])

        # redirect stdout and stderr
        thread = kobo.worker.logger.LoggingThread(hub,
                                                  task_info["id"],
                                                  logger=self)
        sys.stdout = kobo.worker.logger.LoggingIO(open(os.devnull, "w"),
                                                  thread)
        sys.stderr = sys.stdout
        thread.start()

        failed = False
        try:
            task.run()
        except ShutdownException:
            thread.stop()
            if TaskClass.foreground and TaskClass.exclusive:
                # close task (shutdown-worker and similar control tasks) and raise
                hub.worker.close_task(task.task_id, task.result)
                raise
            # interrupt otherwise
            hub.worker.interrupt_tasks([task.task_id])
            return
        except KeyboardInterrupt:
            thread.stop()
            # interrupt otherwise
            hub.worker.interrupt_tasks([task.task_id])
            return
        except SystemExit as ex:
            if len(ex.args) > 0 and ex.args[0] != 0:
                sys.stdout.write(
                    "\nProgram has exited with return code '%s'." % ex.args[0])
                failed = True
        except FailTaskException as ex:
            failed = True
        except:
            message = "ERROR: %s\n" % kobo.tback.get_exception()
            message += "See traceback.log for details (admin only).\n"
            hub.upload_task_log(BytesIO(message.encode()), task.task_id,
                                "error.log")
            hub.upload_task_log(BytesIO(
                kobo.tback.Traceback().get_traceback()),
                                task.task_id,
                                "traceback.log",
                                mode=0o600)
            failed = True
        finally:
            thread.stop()

        if failed:
            hub.worker.fail_task(task.task_id, task.result)
        else:
            hub.worker.close_task(task.task_id, task.result)