def test_mssh_no_target_no_public_ip(self, mock_instance_data,
                                         mock_push_key, mock_run):
        mock_file = "identity"
        flag = '-f flag'
        command = 'command arg'
        logger = EC2InstanceConnectLogger()
        instance_bundles = [{
            'username': self.default_user,
            'instance_id': self.instance_id,
            'target': None,
            'zone': self.availability_zone,
            'region': self.region,
            'profile': self.profile
        }]

        mock_instance_data.return_value = self.private_instance_info
        mock_push_key.return_value = None

        cli_command = EC2InstanceConnectCommand("ssh", instance_bundles,
                                                mock_file, flag, command,
                                                logger.get_logger())
        cli = EC2InstanceConnectCLI(instance_bundles, "", cli_command,
                                    logger.get_logger())
        cli.invoke_command()

        expected_command = 'ssh -o "IdentitiesOnly=yes" -i {0} {1} {2}@{3} {4}'.format(
            mock_file, flag, self.default_user, self.private_ip, command)

        # Check that we successfully get to the run
        self.assertTrue(mock_instance_data.called)
        self.assertTrue(mock_push_key.called)
        mock_run.assert_called_with(expected_command)
    def test_mssh_with_target(self, mock_instance_data, mock_push_key,
                              mock_run):
        mock_file = 'identity'
        flag = '-f flag'
        command = 'command arg'
        host = '0.0.0.0'
        logger = EC2InstanceConnectLogger()
        instance_bundles = [{
            'username': self.default_user,
            'instance_id': self.instance_id,
            'target': host,
            'zone': self.availability_zone,
            'region': self.region,
            'profile': self.profile
        }]

        mock_instance_data.return_value = self.instance_info
        mock_push_key.return_value = None

        cli_command = EC2InstanceConnectCommand("ssh", instance_bundles,
                                                mock_file, flag, command,
                                                logger.get_logger())
        cli = EC2InstanceConnectCLI(instance_bundles, "", cli_command,
                                    logger.get_logger())
        cli.invoke_command()

        expected_command = 'ssh -o "IdentitiesOnly=yes" -i {0} {1} {2}@{3} {4}'.format(
            mock_file, flag, self.default_user, host, command)
        # Check that we successfully get to the run
        # Since both target and availability_zone are provided, mock_instance_data should not be called
        self.assertFalse(mock_instance_data.called)
        self.assertTrue(mock_push_key.called)
        mock_run.assert_called_with(expected_command)
Example #3
0
    def test_mscp(self,
                   mock_instance_data,
                   mock_push_key,
                   mock_run):
        mock_file = 'identity'
        flag = '-f flag'
        command = 'file2 file3'
        logger = EC2InstanceConnectLogger()
        instance_bundles = [{'username': self.default_user, 'instance_id': self.instance_id,
                                     'target': None, 'zone': self.availability_zone, 'region': self.region,
                                     'profile': self.profile, 'file': 'file1'},
                                    {'username': self.default_user, 'instance_id': self.instance_id,
                                     'target': None, 'zone': self.availability_zone, 'region': self.region,
                                     'profile': self.profile, 'file': 'file4'}]

        mock_instance_data.return_value = self.instance_info
        mock_push_key.return_value = None

        expected_command = "scp -i {0} {1} {2}@{3}:{4} {5} {6}@{7}:{8}".format(mock_file, flag, self.default_user,
                                                                                self.public_ip, 'file1', command,
                                                                                self.default_user,
                                                                                self.public_ip, 'file4')

        cli_command = EC2InstanceConnectCommand("scp", instance_bundles, mock_file, flag, command, logger.get_logger())
        cli = EC2InstanceConnectCLI(instance_bundles, "", cli_command, logger.get_logger())
        cli.invoke_command()

        # Check that we successfully get to the run
        self.assertTrue(mock_instance_data.called)
        self.assertTrue(mock_push_key.called)
        mock_run.assert_called_with(expected_command)
Example #4
0
def main(program, mode):
    """
    Parses system arguments and sets defaults
    Calls `ssh` or `sftp` to SSH into the Instance or transfer files.

    :param program: Client program to be used for SSH/SFTP operations.
    :type program: basestring
    :param mode: Identifies either SSH/SFTP operation.
    :type mode: basestring
    """

    usage = ""
    if mode == "ssh":
        usage="""
            mssh [-t instance_id] [-u profile] [-z availability_zone] [-r region] [supported ssh flags] target [command]

            target                => [user@]instance_id | [user@]hostname
            [supported ssh flags] => [-l login_name] [-p port]
        """
    elif mode == "sftp":
        usage="""
            msftp [-u aws_profile] [-z availability_zone] [supported sftp flags] target
            target                 => [user@]instance_id[:file ...][:dir[/]] | [user@]hostname[:file ...][:dir[/]]
            [supported sftp flags] => [-P port] [-b batchfile]
        """

    parser = argparse.ArgumentParser(usage=usage)
    parser.add_argument('-r', '--region', action='store', help='AWS region', type=str, metavar='')
    parser.add_argument('-z', '--zone', action='store', help='Availability zone', type=str, metavar='')
    parser.add_argument('-u', '--profile', action='store', help='AWS Config Profile', type=str, default=DEFAULT_PROFILE, metavar='')
    parser.add_argument('-t', '--instance_id', action='store', help='EC2 Instance ID. Required if target is hostname', type=str, default=DEFAULT_INSTANCE, metavar='')
    parser.add_argument('-d', '--debug', action="store_true", help='Turn on debug logging')

    args = parser.parse_known_args()

    logger = EC2InstanceConnectLogger(args[0].debug)
    try:
        instance_bundles, flags, program_command = input_parser.parseargs(args, mode)
    except Exception as e:
        print(str(e))
        parser.print_help()
        sys.exit(1)

    #Generate temp key
    cli_key = EC2InstanceConnectKey(logger.get_logger())
    cli_command = EC2InstanceConnectCommand(program, instance_bundles, cli_key.get_priv_key_file(), flags, program_command, logger.get_logger())

    try:
        # TODO: Handling for if the '-i' flag is passed
        cli = EC2InstanceConnectCLI(instance_bundles, cli_key.get_pub_key(), cli_command, logger.get_logger())
        cli.invoke_command()
    except Exception as e:
        print('Failed with:\n' + str(e))
        sys.exit(1)
Example #5
0
def main(program, mode):
    """
    Parses system arguments sets defaults
    Calls `putty or psftp` to SSH or do file operations using EC2InstanceConnect.

    :param program: Client program to be used for SSH/SFTP operations.
    :type program: basestring
    :param mode: Identifies either SSH/SFTP operation.
    :type mode: basestring
    """

    usage = ""
    if mode == "ssh":
        usage = """
            mssh-putty [-t instance_id] [-u profile] [-r region] [-z availability_zone] [-i identity_file_ppk] [supported putty flags] target

            target                  => [user@]instance_id | [user@]dns_name
            [supported putty flags] => [-l login_name] [ -P port] [-m remote_command_file]
        """
    elif mode == "sftp":
        usage = """
            msftp-putty [-t instance_id] [-u profile] [-r region] [-z availability_zone] [-i identity_file_ppk] [supported psftp flags] target

            target                  => [user@]instance_id | [user@]dns_name
            [supported psftp flags] => [-l login_name] [ -P port] [-bc] [-b batchfile]
        """

    parser = argparse.ArgumentParser(usage=usage)
    parser.add_argument('-r',
                        '--region',
                        action='store',
                        help='AWS region',
                        type=str,
                        metavar='')
    parser.add_argument('-z',
                        '--zone',
                        action='store',
                        help='Availability zone',
                        type=str,
                        metavar='')
    parser.add_argument('-i',
                        '--identity',
                        action='store',
                        help="Required. Identity file in ppk format",
                        type=str,
                        required=True,
                        metavar='')
    parser.add_argument('-u',
                        '--profile',
                        action='store',
                        help='AWS Config Profile',
                        type=str,
                        default=DEFAULT_PROFILE,
                        metavar='')
    parser.add_argument(
        '-t',
        '--instance_id',
        action='store',
        help='EC2 Instance ID.  Required if target is hostname',
        type=str,
        default=DEFAULT_INSTANCE,
        metavar='')
    parser.add_argument('-d',
                        '--debug',
                        action="store_true",
                        help='Turn on debug logging')

    args = parser.parse_known_args()

    #Read public key from ppk file.
    #Public key is unencrypted and in rsa format.
    pub_key_lines = []
    pub_key = "ssh-rsa "
    try:
        with open(args[0].identity, 'r') as f:
            pub_key_lines = f.readlines()

        #Validate that the identity file format is ppk.
        if pub_key_lines[0].find("PuTTY-User-Key-File-") == -1:
            print("Not a valid Putty key.")
            sys.exit(1)

        #public key starts from 4th line in ppk file.
        line_len = int(pub_key_lines[3].split(':')[1].strip())
        pub_key_lines = pub_key_lines[4:(4 + line_len)]
        for pub_key_line in pub_key_lines:
            pub_key += pub_key_line[:-1]
    except Exception as e:
        print(str(e))
        sys.exit(1)

    logger = EC2InstanceConnectLogger(args[0].debug)
    try:
        instance_bundles, flags, program_command = input_parser.parseargs(
            args, mode)
    except Exception as e:
        print(str(e))
        parser.print_help()
        sys.exit(1)

    cli_command = EC2InstanceConnectCommand(program, instance_bundles,
                                            args[0].identity,
                                            flags, program_command,
                                            logger.get_logger())
    cli_command.get_command()

    try:
        mssh = EC2InstanceConnectCLI(instance_bundles, pub_key, cli_command,
                                     logger.get_logger())
        mssh.invoke_command()
    except Exception as e:
        print("Failed with:\n" + str(e))
        sys.exit(1)