Exemplo n.º 1
0
    def test_avatarAdaptsToRestrictedExecOnlySession(self):
        # When Conch tries to adapt the SSH server avatar to ISession, it
        # adapts to a RestrictedExecOnlySession. This means that a
        # RestrictedExecOnlySession handles any requests to execute a command.
        session = ISession(self.avatar)
        self.assertTrue(
            isinstance(session, RestrictedExecOnlySession),
            "ISession(avatar) doesn't adapt to ExecOnlySession. "
            "Got %r instead." % (session, ))
        self.assertEqual(get_BZR_PLUGIN_PATH_for_subprocess(),
                         session.environment['BZR_PLUGIN_PATH'])
        self.assertEqual('*****@*****.**' % self.avatar.username,
                         session.environment['BZR_EMAIL'])

        executable, arguments = session.getCommandToRun(
            'bzr serve --inet --directory=/ --allow-writes')
        interpreter = '%s/bin/py' % config.root
        self.assertEqual(interpreter, executable)
        self.assertEqual([
            interpreter,
            get_bzr_path(), 'lp-serve', '--inet',
            str(self.avatar.user_id)
        ], list(arguments))
        self.assertRaises(ForbiddenCommand, session.getCommandToRun,
                          'rm -rf /')
Exemplo n.º 2
0
 def launch(self):
     # Following the logic in TacFile. Specifically, if you configure sftp
     # to not run (and thus bzr+ssh) then we don't want to run the forking
     # service.
     if not self.should_launch:
         return
     from lp.codehosting import get_bzr_path
     command = [
         config.root + '/bin/py',
         get_bzr_path(),
         'launchpad-forking-service',
         '--path',
         config.codehosting.forking_daemon_socket,
     ]
     env = dict(os.environ)
     env['BZR_PLUGIN_PATH'] = config.root + '/bzrplugins'
     logfile = self.logfile
     if logfile == '-':
         # This process uses a different logging infrastructure from the
         # rest of the Launchpad code. As such, it cannot trivially use '-'
         # as the logfile. So we just ignore this setting.
         pass
     else:
         env['BZR_LOG'] = logfile
     process = subprocess.Popen(command, env=env, stdin=subprocess.PIPE)
     self.addCleanup(stop_process, process)
     process.stdin.close()
Exemplo n.º 3
0
    def test_avatarAdaptsToRestrictedExecOnlySession(self):
        # When Conch tries to adapt the SSH server avatar to ISession, it
        # adapts to a RestrictedExecOnlySession. This means that a
        # RestrictedExecOnlySession handles any requests to execute a command.
        session = ISession(self.avatar)
        self.failUnless(
            isinstance(session, RestrictedExecOnlySession),
            "ISession(avatar) doesn't adapt to ExecOnlySession. "
            "Got %r instead." % (session,))
        self.assertEqual(
            get_BZR_PLUGIN_PATH_for_subprocess(),
            session.environment['BZR_PLUGIN_PATH'])
        self.assertEqual(
            '*****@*****.**' % self.avatar.username,
            session.environment['BZR_EMAIL'])

        executable, arguments = session.getCommandToRun(
            'bzr serve --inet --directory=/ --allow-writes')
        interpreter = '%s/bin/py' % config.root
        self.assertEqual(interpreter, executable)
        self.assertEqual(
            [interpreter, get_bzr_path(), 'lp-serve',
             '--inet', str(self.avatar.user_id)],
            list(arguments))
        self.assertRaises(
            ForbiddenCommand, session.getCommandToRun, 'rm -rf /')
Exemplo n.º 4
0
 def setUp(self):
     bzr_path = get_bzr_path()
     BZR_PLUGIN_PATH = get_BZR_PLUGIN_PATH_for_subprocess()
     env = os.environ.copy()
     env['BZR_PLUGIN_PATH'] = BZR_PLUGIN_PATH
     # TODO: We probably want to use a random disk path for
     #       forking_daemon_socket, but we need to update config so that
     #       the CodeHosting service can find it.
     #       The main problem is that CodeHostingTac seems to start a tac
     #       server directly from the disk configs, and doesn't use the
     #       in-memory config. So we can't just override the memory
     #       settings, we have to somehow pass it a new config-on-disk to
     #       use.
     self.socket_path = config.codehosting.forking_daemon_socket
     command = [
         sys.executable, bzr_path, 'launchpad-forking-service', '--path',
         self.socket_path, '-Derror'
     ]
     process = subprocess.Popen(command,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE,
                                env=env)
     self.process = process
     stderr = []
     # The first line should be "Preloading" indicating it is ready
     stderr.append(process.stderr.readline())
     # The next line is the "Listening on socket" line
     stderr.append(process.stderr.readline())
     # Now it should be ready.  If there were any errors, let's check, and
     # report them.
     if (process.poll() is not None
             or not stderr[1].strip().startswith('Listening on socket')):
         if process.poll() is None:
             time.sleep(1)  # Give the traceback a chance to render.
             os.kill(process.pid, signal.SIGTERM)
             process.wait()
             self.process = None
         # Looks like there was a problem. We cannot use the "addDetail"
         # method because this class is not a TestCase and does not have
         # access to one.  It runs as part of a layer. A "print" is the
         # best we can do.  That should still be visible on buildbot, which
         # is where we have seen spurious failures so far.
         print
         print "stdout:"
         print process.stdout.read()
         print "-" * 70
         print "stderr:"
         print ''.join(stderr)
         print process.stderr.read()
         print "-" * 70
         raise RuntimeError(
             'Bzr server did not start correctly.  See stdout and stderr '
             'reported above. Command was "%s".  PYTHONPATH was "%s".  '
             'BZR_PLUGIN_PATH was "%s".' %
             (' '.join(command), env.get('PYTHONPATH'),
              env.get('BZR_PLUGIN_PATH')))
Exemplo n.º 5
0
 def setUp(self):
     bzr_path = get_bzr_path()
     BZR_PLUGIN_PATH = get_BZR_PLUGIN_PATH_for_subprocess()
     env = os.environ.copy()
     env['BZR_PLUGIN_PATH'] = BZR_PLUGIN_PATH
     # TODO: We probably want to use a random disk path for
     #       forking_daemon_socket, but we need to update config so that
     #       the CodeHosting service can find it.
     #       The main problem is that CodeHostingTac seems to start a tac
     #       server directly from the disk configs, and doesn't use the
     #       in-memory config. So we can't just override the memory
     #       settings, we have to somehow pass it a new config-on-disk to
     #       use.
     self.socket_path = config.codehosting.forking_daemon_socket
     command = [sys.executable, bzr_path, 'launchpad-forking-service',
                '--path', self.socket_path, '-Derror']
     process = subprocess.Popen(
         command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
     self.process = process
     stderr = []
     # The first line should be "Preloading" indicating it is ready
     stderr.append(process.stderr.readline())
     # The next line is the "Listening on socket" line
     stderr.append(process.stderr.readline())
     # Now it should be ready.  If there were any errors, let's check, and
     # report them.
     if (process.poll() is not None or
         not stderr[1].strip().startswith('Listening on socket')):
         if process.poll() is None:
             time.sleep(1)  # Give the traceback a chance to render.
             os.kill(process.pid, signal.SIGTERM)
             process.wait()
             self.process = None
         # Looks like there was a problem. We cannot use the "addDetail"
         # method because this class is not a TestCase and does not have
         # access to one.  It runs as part of a layer. A "print" is the
         # best we can do.  That should still be visible on buildbot, which
         # is where we have seen spurious failures so far.
         print
         print "stdout:"
         print process.stdout.read()
         print "-" * 70
         print "stderr:"
         print ''.join(stderr)
         print process.stderr.read()
         print "-" * 70
         raise RuntimeError(
             'Bzr server did not start correctly.  See stdout and stderr '
             'reported above. Command was "%s".  PYTHONPATH was "%s".  '
             'BZR_PLUGIN_PATH was "%s".' %
             (' '.join(command),
              env.get('PYTHONPATH'),
              env.get('BZR_PLUGIN_PATH')))
Exemplo n.º 6
0
    def start_bzr_subprocess(self, process_args, env_changes=None,
                             working_dir=None):
        """Start bzr in a subprocess for testing.

        Copied and modified from `bzrlib.tests.TestCase.start_bzr_subprocess`.
        This version removes some of the skipping stuff, some of the
        irrelevant comments (e.g. about win32) and uses Launchpad's own
        mechanisms for getting the path to 'bzr'.

        Comments starting with 'LAUNCHPAD' are comments about our
        modifications.
        """
        if env_changes is None:
            env_changes = {}
        env_changes['BZR_PLUGIN_PATH'] = get_BZR_PLUGIN_PATH_for_subprocess()
        old_env = {}

        def cleanup_environment():
            for env_var, value in env_changes.iteritems():
                old_env[env_var] = osutils.set_or_unset_env(env_var, value)

        def restore_environment():
            for env_var, value in old_env.iteritems():
                osutils.set_or_unset_env(env_var, value)

        cwd = None
        if working_dir is not None:
            cwd = osutils.getcwd()
            os.chdir(working_dir)

        # LAUNCHPAD: Because of buildout, we need to get a custom Python
        # binary, not sys.executable.
        python_path = self.get_python_path()
        # LAUNCHPAD: We can't use self.get_bzr_path(), since it'll find
        # lib/bzrlib, rather than the path to sourcecode/bzr/bzr.
        bzr_path = get_bzr_path()
        try:
            cleanup_environment()
            command = [python_path, bzr_path]
            command.extend(process_args)
            process = self._popen(
                command, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                stderr=subprocess.PIPE)
        finally:
            restore_environment()
            if cwd is not None:
                os.chdir(cwd)

        return process
Exemplo n.º 7
0
def lookup_command_template(command):
    """Map a command to a command template.

    :param command: Command requested by the user
    :return: Command template
    :raise ForbiddenCommand: Raised when command isn't allowed
    """
    python_command = "%(root)s/bin/py %(bzr)s" % {
        'root': config.root,
        'bzr': get_bzr_path(),
    }
    args = " lp-serve --inet %(user_id)s"
    command_template = python_command + args

    if command == 'bzr serve --inet --directory=/ --allow-writes':
        return command_template
    # At the moment, only bzr branch serving is allowed.
    raise ForbiddenCommand("Not allowed to execute %r." % (command, ))
Exemplo n.º 8
0
def lookup_command_template(command):
    """Map a command to a command template.

    :param command: Command requested by the user
    :return: Command template
    :raise ForbiddenCommand: Raised when command isn't allowed
    """
    python_command = "%(root)s/bin/py %(bzr)s" % {
            'root': config.root,
            'bzr': get_bzr_path(),
            }
    args = " lp-serve --inet %(user_id)s"
    command_template = python_command + args

    if command == 'bzr serve --inet --directory=/ --allow-writes':
        return command_template
    # At the moment, only bzr branch serving is allowed.
    raise ForbiddenCommand("Not allowed to execute %r." % (command,))
Exemplo n.º 9
0
    def get_bzr_path(self):
        """See `bzrlib.tests.TestCase.get_bzr_path`.

        We override this to return the 'bzr' executable from sourcecode.
        """
        return get_bzr_path()
Exemplo n.º 10
0
 def test_bzr(self):
     self.assertEqual(
         config.root + '/bin/py ' + get_bzr_path() +
         ' lp-serve --inet %(user_id)s',
         lookup_command_template(
             'bzr serve --inet --directory=/ --allow-writes'))
Exemplo n.º 11
0
    def get_bzr_path(self):
        """See `bzrlib.tests.TestCase.get_bzr_path`.

        We override this to return the 'bzr' executable from sourcecode.
        """
        return get_bzr_path()
Exemplo n.º 12
0
 def test_bzr(self):
     self.assertEquals(
         config.root + '/bin/py ' + get_bzr_path() +
         ' lp-serve --inet %(user_id)s',
         lookup_command_template(
             'bzr serve --inet --directory=/ --allow-writes'))