def main(): """Run the application.""" if DEBUG: pid = os.getpid() log_filename = 'rbssh-%s.log' % pid if DEBUG_LOGDIR: log_path = os.path.join(DEBUG_LOGDIR, log_filename) else: log_path = log_filename logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)-18s %(levelname)-8s ' '%(message)s', datefmt='%m-%d %H:%M', filename=log_path, filemode='w') logging.debug('%s' % sys.argv) logging.debug('PID %s' % pid) ch = logging.StreamHandler() ch.setLevel(logging.INFO) ch.setFormatter(logging.Formatter('%(message)s')) ch.addFilter(logging.Filter('root')) logging.getLogger('').addHandler(ch) path, port, command = parse_options(sys.argv[1:]) if '://' not in path: path = 'ssh://' + path username, hostname = SCMTool.get_auth_from_uri(path, options.username) if username is None: username = getpass.getuser() logging.debug('!!! %s, %s, %s' % (hostname, username, command)) client = SSHClient(namespace=options.local_site_name) client.set_missing_host_key_policy(paramiko.WarningPolicy()) attempts = 0 password = None key = client.get_user_key() while True: try: client.connect(hostname, port, username=username, password=password, pkey=key, allow_agent=options.allow_agent) break except paramiko.AuthenticationException as e: if attempts == 3 or not sys.stdin.isatty(): logging.error('Too many authentication failures for %s' % username) sys.exit(1) attempts += 1 password = getpass.getpass("%s@%s's password: " % (username, hostname)) except paramiko.SSHException as e: logging.error('Error connecting to server: %s' % e) sys.exit(1) except Exception as e: logging.error('Unknown exception during connect: %s (%s)' % (e, type(e))) sys.exit(1) transport = client.get_transport() channel = transport.open_session() if sys.platform in ('cygwin', 'win32'): logging.debug('!!! Using WindowsHandler') handler = WindowsHandler(channel) else: logging.debug('!!! Using PosixHandler') handler = PosixHandler(channel) if options.subsystem == 'sftp': logging.debug('!!! Invoking sftp subsystem') channel.invoke_subsystem('sftp') handler.transfer() elif command: logging.debug('!!! Sending command %s' % command) channel.exec_command(' '.join(command)) handler.transfer() else: logging.debug('!!! Opening shell') channel.get_pty() channel.invoke_shell() handler.shell() logging.debug('!!! Done') status = channel.recv_exit_status() client.close() return status
def main(): """Run the application.""" os.environ.setdefault(str('DJANGO_SETTINGS_MODULE'), str('reviewboard.settings')) if DEBUG: pid = os.getpid() log_filename = 'rbssh-%s.log' % pid if DEBUG_LOGDIR: log_path = os.path.join(DEBUG_LOGDIR, log_filename) else: log_path = log_filename logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)-18s %(levelname)-8s ' '%(message)s', datefmt='%m-%d %H:%M', filename=log_path, filemode='w') logging.debug('%s' % sys.argv) logging.debug('PID %s' % pid) initialize() ch = logging.StreamHandler() ch.setLevel(logging.INFO) ch.setFormatter(logging.Formatter('%(message)s')) ch.addFilter(logging.Filter('root')) logging.getLogger('').addHandler(ch) path, port, command = parse_options(sys.argv[1:]) if '://' not in path: path = 'ssh://' + path username, hostname = SCMTool.get_auth_from_uri(path, options.username) if username is None: username = getpass.getuser() logging.debug('!!! %s, %s, %s' % (hostname, username, command)) client = SSHClient(namespace=options.local_site_name) client.set_missing_host_key_policy(paramiko.WarningPolicy()) attempts = 0 password = None key = client.get_user_key() while True: try: client.connect(hostname, port, username=username, password=password, pkey=key, allow_agent=options.allow_agent) break except paramiko.AuthenticationException as e: if attempts == 3 or not sys.stdin.isatty(): logging.error('Too many authentication failures for %s' % username) sys.exit(1) attempts += 1 password = getpass.getpass("%s@%s's password: " % (username, hostname)) except paramiko.SSHException as e: logging.error('Error connecting to server: %s' % e) sys.exit(1) except Exception as e: logging.error('Unknown exception during connect: %s (%s)' % (e, type(e))) sys.exit(1) transport = client.get_transport() channel = transport.open_session() if sys.platform in ('cygwin', 'win32'): logging.debug('!!! Using WindowsHandler') handler = WindowsHandler(channel) else: logging.debug('!!! Using PosixHandler') handler = PosixHandler(channel) if options.subsystem == 'sftp': logging.debug('!!! Invoking sftp subsystem') channel.invoke_subsystem('sftp') handler.transfer() elif command: logging.debug('!!! Sending command %s' % command) channel.exec_command(' '.join(command)) handler.transfer() else: logging.debug('!!! Opening shell') channel.get_pty() channel.invoke_shell() handler.shell() logging.debug('!!! Done') status = channel.recv_exit_status() client.close() return status
def main(): """Run the application.""" # We don't want any warnings to end up impacting output. warnings.simplefilter('ignore') if DEBUG: pid = os.getpid() log_filename = 'rbssh-%s.log' % pid if DEBUG_LOGDIR: log_path = os.path.join(DEBUG_LOGDIR, log_filename) else: log_path = log_filename logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)-18s %(levelname)-8s ' '%(message)s', datefmt='%m-%d %H:%M', filename=log_path, filemode='w') debug('%s', sys.argv) debug('PID %s', pid) # Perform the bare minimum to initialize the Django/Review Board # environment. We're not calling Review Board's initialize() because # we want to completely minimize what we import and set up. if hasattr(django, 'setup'): django.setup() from reviewboard.scmtools.core import SCMTool from reviewboard.ssh.client import SSHClient ch = logging.StreamHandler() ch.setLevel(logging.INFO) ch.setFormatter(logging.Formatter('%(message)s')) ch.addFilter(logging.Filter('root')) logging.getLogger('').addHandler(ch) path, port, command = parse_options(sys.argv[1:]) if '://' not in path: path = 'ssh://' + path username, hostname = SCMTool.get_auth_from_uri(path, options.username) if username is None: username = getpass.getuser() client = SSHClient(namespace=options.local_site_name) client.set_missing_host_key_policy(paramiko.WarningPolicy()) if command: purpose = command else: purpose = 'interactive shell' debug('!!! SSH backend = %s', type(client.storage)) debug('!!! Preparing to connect to %s@%s for %s', username, hostname, purpose) attempts = 0 password = None key = client.get_user_key() while True: try: client.connect(hostname, port, username=username, password=password, pkey=key, allow_agent=options.allow_agent) break except paramiko.AuthenticationException as e: if attempts == 3 or not sys.stdin.isatty(): logging.error('Too many authentication failures for %s' % username) sys.exit(1) attempts += 1 password = getpass.getpass("%s@%s's password: " % (username, hostname)) except paramiko.SSHException as e: logging.error('Error connecting to server: %s' % e) sys.exit(1) except Exception as e: logging.error('Unknown exception during connect: %s (%s)' % (e, type(e))) sys.exit(1) transport = client.get_transport() channel = transport.open_session() if sys.platform in ('cygwin', 'win32'): debug('!!! Using WindowsHandler') handler = WindowsHandler(channel) else: debug('!!! Using PosixHandler') handler = PosixHandler(channel) if options.subsystem == 'sftp': debug('!!! Invoking sftp subsystem') channel.invoke_subsystem('sftp') handler.transfer() elif command: debug('!!! Sending command %s', command) channel.exec_command(' '.join(command)) handler.transfer() else: debug('!!! Opening shell') channel.get_pty() channel.invoke_shell() handler.shell() debug('!!! Done') status = channel.recv_exit_status() client.close() return status
def _check_can_test_ssh(self): """Check whether SSH-based tests can be run. This will check if the user's SSH keys are authorized by the local machine for authentication, and whether any system-wide tools are available. If SSH-based tests cannot be run, the current test will be flagged as skipped. """ # These tests are global across all unit tests using this class. if SCMTestCase._can_test_ssh is None: SCMTestCase.ssh_client = SSHClient() key = self.ssh_client.get_user_key() SCMTestCase._can_test_ssh = ( key is not None and self.ssh_client.is_key_authorized(key)) if not SCMTestCase._can_test_ssh: raise SkipTest( "Cannot perform SSH access tests. The local user's SSH " "public key must be in the %s file and SSH must be enabled." % os.path.join(self.ssh_client.storage.get_ssh_dir(), 'authorized_keys')) # These tests are local to all unit tests using the same executable. system_exes = self.ssh_required_system_exes if system_exes: user_key = SCMTestCase.ssh_client.get_user_key() exes_to_check = (set(system_exes) - set(SCMTestCase._ssh_system_exe_status.keys())) for system_exe in exes_to_check: # For safety, we'll do one connection per check, to avoid # one check impacting another. client = SSHClient() client.connect('localhost', pkey=user_key) try: stdout, stderr = client.exec_command('which %s' % system_exe)[1:] # It's important to read all stdout/stderr data before # waiting for status. stdout.read() stderr.read() code = stdout.channel.recv_exit_status() status = (code == 0) except Exception as e: logger.error( 'Unexpected error running `which %s` on ' 'localhost for SSH test: %s', system_exe, e) status = False finally: client.close() SCMTestCase._ssh_system_exe_status[system_exe] = status missing_exes = ', '.join( '"%s"' % _system_exe for _system_exe in system_exes if not SCMTestCase._ssh_system_exe_status[_system_exe]) if missing_exes: raise SkipTest( 'Cannot perform SSH access tests. %s must be ' 'available in the system path when executing ' 'commands locally over SSH. You may need to install the ' 'tool or make sure that the correct directory is in ' '~/.zshenv, ~/.profile, or another suitable file used ' 'in non-interactive sessions.' % missing_exes)