Beispiel #1
0
def test_run_cmd_silent(docker_env, caplog):
    caplog.set_level(logging.DEBUG)
    gateway_ip, gateway_port = docker_env.get_host_ip_port('gateway')

    gateway_session = SSHSession(host=gateway_ip,
                                 port=gateway_port,
                                 username='******',
                                 password='******').open()

    # run command and check full command is logged
    text = 'text with public and private data'
    cmd = "echo '%s'" % text
    assert gateway_session.run_cmd(cmd).output == text
    assert cmd in caplog.text

    # check nothing is logged when silent is True
    text = 'another text with public and private data'
    cmd = "echo '%s'" % text
    assert gateway_session.run_cmd(cmd, silent=True).output == text
    assert cmd not in caplog.text

    # check data is concealed when silent is a list
    text = 'a third text with public and private data'
    cmd = "echo '%s'" % text
    assert gateway_session.run_cmd(cmd, silent=['third',
                                                'private data']).output == text
    assert cmd not in caplog.text
    assert 'a XXXXXXX text with public and XXXXXXX' in caplog.text

    # check data is concealed when silent is a list with regexp
    text = 'another text   to   test    regexp'
    cmd = "echo '%s'" % text
    assert gateway_session.run_cmd(cmd, silent=['\s+']).output == text
    assert cmd not in caplog.text
    assert 'anotherXXXXXXXtextXXXXXXXtoXXXXXXXtestXXXXXXXregexp' in caplog.text
Beispiel #2
0
def test_ssh_connection_error(docker_env):
    gateway_ip, gateway_port = docker_env.get_host_ip_port('gateway')

    # open first ssh session to gateway
    gateway_session1 = SSHSession(host=gateway_ip,
                                  port=gateway_port,
                                  username='******',
                                  password='******').open()

    # modify password from session 1
    gateway_session1.run_cmd('echo "user1:newpassword" | sudo -S chpasswd')

    # try to open 2nd session
    with pytest.raises(exception.ConnectionError) as excinfo:
        SSHSession(host=gateway_ip,
                   port=gateway_port,
                   username='******',
                   password='******').open()
    assert type(excinfo.value.__cause__
                ) == paramiko.ssh_exception.AuthenticationException

    # set back correct password from session 1
    gateway_session1.run_cmd('echo "user1:password1" | sudo -S chpasswd')

    # try again to open 2nd session
    gateway_session2 = SSHSession(host=gateway_ip,
                                  port=gateway_port,
                                  username='******',
                                  password='******').open()
    assert gateway_session2.is_active()
Beispiel #3
0
def test_active_close_session(docker_env):
    gateway_ip, gateway_port = docker_env.get_host_ip_port('gateway')

    gateway_session = SSHSession(host=gateway_ip,
                                 port=gateway_port,
                                 username='******',
                                 password='******').open()
    assert gateway_session.is_active()

    # open an already active session should be harmless
    gateway_session.open()
    assert gateway_session.is_active()

    remotehost_ip, remotehost_port = docker_env.get_host_ip_port('remotehost')
    remotehost_session = gateway_session.get_remote_session(
        host=tests_util.get_host_ip(),
        port=remotehost_port,
        username='******',
        password='******')
    assert remotehost_session.is_active()

    # check that gateway session is well closed
    gateway_session.close()
    assert not gateway_session.is_active()
    # remote session is also automatically closed
    assert not remotehost_session.is_active()

    # closing a closed session does nothing
    gateway_session.close()

    # running command on an inactive session raise a SSHException
    with pytest.raises(exception.SSHException):
        gateway_session.run_cmd('ls')
Beispiel #4
0
def create_new_cert_on_host(host_session: SSHSession, certificate_file: CertificateFile, ca_cert: str, ca_key: str):
    try:
        ca_cert_file_path = '/tmp/ca.cert.pem'

        ca_key_file_path = '/tmp/ca.key.pem'
        host_session.run_cmd(f'echo "{ca_cert}" > {ca_cert_file_path}; echo "{ca_key}" > {ca_key_file_path} ')
        host_session.run_cmd(f'openssl x509 -in {ca_cert_file_path} -out {certificate_file.file_path}.new -days 365  \
                                -signkey {ca_key_file_path} -sha256')

    except Exception as e:
        print("Could not create new certificate file")
        raise e
Beispiel #5
0
def test_exists(docker_env):
    gateway_ip, gateway_port = docker_env.get_host_ip_port('gateway')

    gateway_session = SSHSession(host=gateway_ip,
                                 port=gateway_port,
                                 username='******',
                                 password='******').open()

    assert not gateway_session.exists('/home/user1/non_existing_file')

    gateway_session.run_cmd('touch /home/user1/existing_file')
    assert gateway_session.exists('/home/user1/existing_file')

    gateway_session.run_cmd('rm /home/user1/existing_file')
    assert not gateway_session.exists('/home/user1/existing_file')

    # create file visible only by user2
    gateway_session.run_cmd([
        'sudo mkdir /etc/user2_private_dir',
        'sudo touch /etc/user2_private_dir/existing_file',
        'sudo chown user2:user2 /etc/user2_private_dir',
        'sudo chmod 600 /etc/user2_private_dir'
    ])

    # check it is not visible by user1 by default
    assert not gateway_session.exists('/etc/user2_private_dir/existing_file')

    # check it is readable with root access
    assert gateway_session.exists('/etc/user2_private_dir/existing_file',
                                  use_sudo=True)

    # cleanup
    gateway_session.run_cmd('sudo rm -rf /etc/user2_private_dir')
Beispiel #6
0
def test_active_close_session(docker_env):
    gateway_ip, gateway_port = docker_env.get_host_ip_port()

    gateway_session = SSHSession(host=gateway_ip,
                                 port=gateway_port,
                                 username='******',
                                 password='******').open()
    assert gateway_session.is_active()

    # open an already active session should be harmless
    gateway_session.open()
    assert gateway_session.is_active()

    remotehost_session = gateway_session.get_remote_session(
        host='remotehost', port=22, username='******', password='******')
    assert remotehost_session.is_active()

    # check that gateway session is well closed
    gateway_session.close()
    assert not gateway_session.is_active()
    # remote session is also automatically closed
    assert not remotehost_session.is_active()

    # closing a closed session does nothing
    gateway_session.close()

    # running command on an inactive session will automatically open the session
    assert gateway_session.run_cmd('ls').exit_code == 0
Beispiel #7
0
def test_run_cmd_sudo(docker_env):
    gateway_ip, gateway_port = docker_env.get_host_ip_port('gateway')

    gateway_session = SSHSession(host=gateway_ip,
                                 port=gateway_port,
                                 username='******',
                                 password='******').open()

    # run command as user2
    assert gateway_session.run_cmd('whoami',
                                   username='******').output == 'user2'

    # run bash builtins commands with sudo (here command 'source')
    gateway_session.file(remote_path='/home/user2/ssh_setenv',
                         use_sudo=True,
                         owner='user2',
                         content='MY_VAR=variable_set')
    gateway_session.run_cmd('source /home/user2/ssh_setenv', username='******')
Beispiel #8
0
def test_input_data(docker_env):
    gateway_ip, gateway_port = docker_env.get_host_ip_port('gateway')

    gateway_session = SSHSession(host=gateway_ip,
                                 port=gateway_port,
                                 username='******',
                                 password='******').open()

    commands = [
        'read -p "Requesting user input value?" my_var', 'echo $my_var'
    ]

    # without input given, command will hang until timeout is reached
    with pytest.raises(exception.TimeoutError):
        gateway_session.run_cmd(commands, timeout=5)

    # with input given, command should run correctly and return the value entered
    assert gateway_session.get_cmd_output(commands,
                                          input_data={
                                              'Requesting user input value':
                                              'dummy_value'
                                          }).split()[-1] == "dummy_value"
def respaldo_ssh(hostname, ip, cisco_os, username, password, enable_password):

    try:
        ruta = os.getcwd()
        with open(
                ruta + "/full backup manual/respaldo_" + hostname + "_" +
                datetime.now().strftime("%d%m%Y_%H%M"), "w") as file:
            if cisco_os == "nxos":
                ssh_session = SSHSession(ip, username,
                                         password=password).open()
                for comando in commands_nxos:
                    resultado = ssh_session.run_cmd(comando)
                    file.write(resultado.output)
                ssh_session.close()
            elif cisco_os == "iosxe":
                ssh_session = SSHSession(ip, username,
                                         password=password).open()
                for comando in commands_iosxe:
                    resultado = ssh_session.run_cmd(comando)
                    file.write(resultado.output)
                ssh_session.close()
            elif cisco_os == "junos":
                ssh_session = SSHSession(ip,
                                         username,
                                         password=password,
                                         timeout=10).open()
                for comando in commands_junos:
                    resultado = ssh_session.run_cmd(comando)
                    file.write(resultado.output)
                ssh_session.close()

    except Exception as e:
        print(e)
        return ("fallido")

    return ("realizado")
Beispiel #10
0
def test_run_cmd_success_exit_code(docker_env):
    gateway_ip, gateway_port = docker_env.get_host_ip_port('gateway')

    gateway_session = SSHSession(host=gateway_ip,
                                 port=gateway_port,
                                 username='******',
                                 password='******').open()

    # check invalid type for parameter
    with pytest.raises(TypeError):
        gateway_session.run_cmd('hostname', success_exit_code={'key': 'value'})

    # valid command with custom success exit code should raise RunCmdError
    with pytest.raises(exception.RunCmdError) as exc_info:
        gateway_session.run_cmd('hostname', success_exit_code=3)
    assert exc_info.value.exit_code == 0
    assert exc_info.value.success_exit_code == [3]

    # dummy command should not raise error as exit code 127 is valid too
    # and test also that list is supported
    gateway_session.run_cmd('dummy commmand', success_exit_code=[0, 127])
    gateway_session.run_cmd('hostname', success_exit_code=[0, 127])
Beispiel #11
0
def test_run_cmd_retry(docker_env):
    gateway_ip, gateway_port = docker_env.get_host_ip_port('gateway')

    gateway_session = SSHSession(host=gateway_ip,
                                 port=gateway_port,
                                 username='******',
                                 password='******').open()

    with pytest.raises(exception.RunCmdError) as exc_info:
        gateway_session.run_cmd('dummy commmand', retry=2, retry_interval=1)
    assert exc_info.value.runs_nb == 3

    # prepare command that append a character in file at each new run
    temporary_filename1 = util.id_generator(size=7)
    cmd = "echo -n 'p' >> {0} && grep 'pppp' {0}".format(temporary_filename1)

    # command should still raise exception after 2 retries(=3 runs) as we except 4 p
    with pytest.raises(exception.RunCmdError) as exc_info:
        gateway_session.run_cmd(cmd, retry=2, retry_interval=1)
    assert exc_info.value.runs_nb == 3

    # same command should work fine with 3 retries(=4 runs)
    temporary_filename2 = util.id_generator(size=8)
    cmd = cmd.replace(temporary_filename1, temporary_filename2)
    result = gateway_session.run_cmd(cmd, retry=3, retry_interval=1)

    # by default no history kept
    assert len(result.result_list) == 0

    # check history is kept when requested
    temporary_filename3 = util.id_generator(size=8)
    cmd = cmd.replace(temporary_filename2, temporary_filename3)
    result = gateway_session.run_cmd(cmd,
                                     retry=3,
                                     retry_interval=1,
                                     keep_retry_history=True)
    assert len(result.result_list) == 4
Beispiel #12
0
def test_run_cmd_interrupt_remote_command(docker_env, monkeypatch, caplog):
    caplog.set_level(logging.DEBUG)
    """Test behavior of run_cmd when user hit Contrl-C while a command is being executed remotely"""
    gateway_ip, gateway_port = docker_env.get_host_ip_port('gateway')
    gateway_session = SSHSession(host=gateway_ip,
                                 port=gateway_port,
                                 username='******',
                                 password='******').open()

    mock_input = '__builtin__.raw_input' if util.PY2 else 'builtins.input'

    # 1. if user request to interrupt remote command
    with pytest.raises(KeyboardInterrupt):
        # raise KeyboardInterrupt while command is running
        with mock.patch('select.select',
                        side_effect=KeyboardInterrupt('Fake Ctrl-C')):
            # request to terminate remote command simulating the user entering "Y" in the terminal
            monkeypatch.setattr(mock_input, lambda x: "Y")
            gateway_session.run_cmd('sleep 30')

    # check command is no longer running on remote host
    assert gateway_session.get_exit_code(
        'ps aux | grep -v grep | grep "sleep 30"') == 1

    # 2. user request to NOT interrupt remote command
    with pytest.raises(KeyboardInterrupt):
        # raise KeyboardInterrupt while command is running
        with mock.patch('select.select',
                        side_effect=KeyboardInterrupt('Fake Ctrl-C')):
            # request to terminate remote command simulating the user entering "N" in the terminal
            monkeypatch.setattr(mock_input, lambda x: "N")
            gateway_session.run_cmd('sleep 40')

    # check command is still running on remote host
    assert gateway_session.get_exit_code(
        'ps aux | grep -v grep | grep "sleep 40"') == 0

    # 3. user press enter (default value of util.yes_no_query used), we expect remote command to be stopped
    with pytest.raises(KeyboardInterrupt):
        # raise KeyboardInterrupt while command is running
        with mock.patch('select.select',
                        side_effect=KeyboardInterrupt('Fake Ctrl-C')):
            # send empty string simulating the user pressing enter in the terminal
            monkeypatch.setattr(mock_input, lambda x: '')
            gateway_session.run_cmd('sleep 50')

    # check command is no longer running on remote host
    assert gateway_session.get_exit_code(
        'ps aux | grep -v grep | grep "sleep 50"') == 1

    # 4. user press Contrl-C twice, check remote command is still running
    with pytest.raises(KeyboardInterrupt):
        # raise KeyboardInterrupt while command is running
        with mock.patch('select.select',
                        side_effect=KeyboardInterrupt('Fake Ctrl-C')):
            # user press a second time Contrl-C
            with mock.patch(mock_input,
                            side_effect=KeyboardInterrupt('2nd Fake Ctrl-C')):
                gateway_session.run_cmd('sleep 60')

    # check command is still running on remote host
    assert gateway_session.get_exit_code(
        'ps aux | grep -v grep | grep "sleep 60"') == 0

    # 5. user press Contrl-C once but take time to answer if remote must be closed or not, and channel is closed
    # so we cannot terminate remote command but remote command finished its execution
    with pytest.raises(KeyboardInterrupt):
        # raise KeyboardInterrupt while command is running
        with mock.patch('select.select',
                        side_effect=KeyboardInterrupt('Fake Ctrl-C')):
            # request to terminate remote command simulating the user entering "Y" in the terminal
            # but user answered after 4s while command finished after 3s so underline channel is already closed
            # and command still successfully run
            monkeypatch.setattr(mock_input, lambda x: time.sleep(4) or "Y")
            gateway_session.run_cmd('sleep 3')
    assert 'Remote command execution already finished with exit code' in caplog.text

    # 6. user press Contrl-C once but take time to answer if remote must be closed or not, and channel is closed
    # so we cannot terminate remote command and channel does't not have more information about remote command execution
    with pytest.raises(KeyboardInterrupt):
        # raise KeyboardInterrupt while command is running
        with mock.patch('select.select',
                        side_effect=KeyboardInterrupt('Fake Ctrl-C')):
            # request to terminate remote command simulating the user entering "Y" in the terminal
            # but user answered after 4s while command finished after 3s so underline channel is already closed
            monkeypatch.setattr('paramiko.channel.Channel.recv_exit_status',
                                lambda x: -1)
            gateway_session.run_cmd('sleep 3')
    assert 'Unable to terminate remote command because channel is closed.' in caplog.text
Beispiel #13
0
def test_run_cmd(docker_env, capfd):
    gateway_ip, gateway_port = docker_env.get_host_ip_port('gateway')

    gateway_session = SSHSession(host=gateway_ip,
                                 port=gateway_port,
                                 username='******',
                                 password='******').open()
    assert gateway_session.is_active()

    # basic successful command
    (exit_code, output) = gateway_session.run_cmd('hostname')
    assert exit_code == 0
    assert output == 'gateway.example.com'

    # successful list command
    gateway_session.run_cmd(['cd /etc', 'ls'])

    # wrong command
    (exit_code, output) = gateway_session.run_cmd('dummy commmand',
                                                  raise_if_error=False)
    assert exit_code == 127

    with pytest.raises(exception.RunCmdError) as excinfo:
        gateway_session.run_cmd('dummy commmand')
    assert excinfo.value.exit_code == 127
    assert excinfo.value.command == 'dummy commmand'

    # wrong command type
    with pytest.raises(TypeError):
        gateway_session.run_cmd({'key': 'value'})

    # standard output is empty by default (without continuous_output flag)
    gateway_session.run_cmd('ls -lta /')
    out, err = capfd.readouterr()
    assert len(out) == 0

    # display continuous output on stdout while command is running
    gateway_session.run_cmd('ls -lta /', continuous_output=True)
    out, err = capfd.readouterr()
    assert len(out) > 0
    assert isinstance(
        out,
        unicode if util.PY2 else str)  # noqa: unicode only exists in python 2
Beispiel #14
0
def respaldo_ssh_manual(hostname, ip, cisco_os, username, password,
                        enable_password):
    try:
        ruta = os.getcwd()
        with open(
                ruta + "/full backup manual/respaldo_" + hostname + "_" +
                datetime.now().strftime("%d%m%Y_%H%M"), "w") as file:
            if cisco_os == "nxos":
                nx_node = {
                    'device_type': 'cisco_nxos',
                    'ip': ip,
                    'username': username,
                    'password': password,
                    'secret': enable_password,
                    'port': 22,
                }
                ssh_session = SSHSession(ip, username,
                                         password=password).open()
                for comando in commands_nxos:
                    resultado = ssh_session.run_cmd(comando)
                    file.write(resultado.output)
                ssh_session.close()
            elif cisco_os == "iosxe":
                ssh_session = SSHSession(ip, username,
                                         password=password).open()
                for comando in commands_iosxe:
                    resultado = ssh_session.run_cmd(comando)
                    file.write(resultado.output)
                ssh_session.close()
            elif cisco_os == "junos":
                ssh_session = SSHSession(ip,
                                         username,
                                         password=password,
                                         timeout=10).open()
                for comando in commands_junos:
                    resultado = ssh_session.run_cmd(comando)
                    file.write(resultado.output)
                ssh_session.close()
            elif cisco_os == "ios":
                ios_node = {
                    'device_type': 'cisco_ios',
                    'ip': ip,
                    'username': username,
                    'password': password,
                    'secret': enable_password,
                    'port': 22,
                }
                net_connect_ios = ConnectHandler(**ios_node)
                net_connect_ios.enable()
                for comando in commands_ios:
                    resultado = net_connect_ios.send_command(
                        comando, strip_prompt=False, strip_command=False)
                    file.write(resultado)
            elif cisco_os == "asa":
                asa_node = {
                    'device_type': 'cisco_asa',
                    'ip': ip,
                    'username': username,
                    'password': password,
                    'secret': enable_password,
                    'port': 22,
                }
                net_connect_asa = ConnectHandler(**asa_node)
                net_connect_asa.enable()
                for comando in commands_asa:
                    resultado = net_connect_asa.send_command(comando)
                    file.write(resultado)
        return ({"resultado": "equipo " + hostname + " OK"})

    except Exception as e:
        return ("Error " + str(e))

    return ("realizado")