Beispiel #1
0
    def launch_command(self, cmd, instance, key, path, **kwargs):
        cwd = '/tmp/'
        env = {}
        env['BORG_PASSPHRASE'] = key
        env['BORG_REPO'] = path
        env['BORG_RELOCATED_REPO_ACCESS_IS_OK'] = 'yes'
        env['BORG_RSH'] = 'ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null'
        args = cmd
        safe_args = args

        kwargs['private_data_dir'] = self.build_private_data_dir(
            instance, **kwargs)
        kwargs['private_data_files'] = self.build_private_data_files(
            instance, **kwargs)
        kwargs['passwords'] = self.build_passwords(instance, **kwargs)

        expect_passwords = {}
        for k, v in self.get_password_prompts(**kwargs).items():
            expect_passwords[k] = kwargs['passwords'].get(v, '') or ''

        _kw = dict(
            expect_passwords=expect_passwords,
            job_timeout=getattr(settings, 'DEFAULT_JOB_TIMEOUT', 0),
            idle_timeout=getattr(settings, 'JOB_RUN_IDLE_TIMEOUT', None),
            extra_update_fields={},
            pexpect_timeout=getattr(settings, 'PEXPECT_TIMEOUT', 5),
        )
        stdout_handle = StringIO()

        ssh_key_path = self.get_ssh_key_path(instance, **kwargs)
        # If we're executing on an isolated host, don't bother adding the
        # key to the agent in this environment
        if ssh_key_path:
            ssh_auth_sock = os.path.join(kwargs['private_data_dir'],
                                         'ssh_auth.sock')
            args = run.wrap_args_with_ssh_agent(args, ssh_key_path,
                                                ssh_auth_sock)
            safe_args = run.wrap_args_with_ssh_agent(safe_args, ssh_key_path,
                                                     ssh_auth_sock)

        status, rc = run.run_pexpect(args, cwd, env, stdout_handle, **_kw)

        lines = stdout_handle.getvalue().splitlines()
        shutil.rmtree(kwargs['private_data_dir'])
        return lines
Beispiel #2
0
    def _run(self, cmd, sudo=False, queryargs=None):
        args = []
        rc = -1
        finalOutput = []

        if self.client_user != 'root' and sudo:
            args = ['sudo', '-E'] + args
        args += cmd

        kwargs = {}
        try:
            env = {}
            for attr in dir(settings):
                if attr == attr.upper() and attr.startswith('CYBORGBACKUP_'):
                    env[attr] = str(getattr(settings, attr))

            path = tempfile.mkdtemp(prefix='cyborgbackup_module', dir='/tmp/')
            os.chmod(path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)
            kwargs['private_data_dir'] = path

            if 'private_data_dir' in kwargs.keys():
                env['PRIVATE_DATA_DIR'] = kwargs['private_data_dir']
            passwords = {}
            for setting in Setting.objects.filter(key__contains='ssh_key'):
                set = Setting.objects.get(
                    key=setting.key.replace('ssh_key', 'ssh_password'))
                passwords['credential_{}'.format(setting.key)] = decrypt_field(
                    set, 'value')
            kwargs['passwords'] = passwords

            private_data = {'credentials': {}}
            for sets in Setting.objects.filter(key__contains='ssh_key'):
                # If we were sent SSH credentials, decrypt them and send them
                # back (they will be written to a temporary file).
                private_data['credentials'][sets] = decrypt_field(
                    sets, 'value') or ''
            private_data_files = {'credentials': {}}
            if private_data is not None:
                listpaths = []
                for sets, data in private_data.get('credentials', {}).items():
                    # OpenSSH formatted keys must have a trailing newline to be
                    # accepted by ssh-add.
                    if 'OPENSSH PRIVATE KEY' in data and not data.endswith(
                            '\n'):
                        data += '\n'
                    # For credentials used with ssh-add, write to a named pipe which
                    # will be read then closed, instead of leaving the SSH key on disk.
                    if sets:
                        name = 'credential_{}'.format(sets.key)
                        path = os.path.join(kwargs['private_data_dir'], name)
                        run.open_fifo_write(path, data)
                        listpaths.append(path)
                if len(listpaths) > 1:
                    private_data_files['credentials']['ssh'] = listpaths
                elif len(listpaths) == 1:
                    private_data_files['credentials']['ssh'] = listpaths[0]

            kwargs['private_data_files'] = private_data_files

            # May have to serialize the value
            kwargs['private_data_files'] = private_data_files
            cwd = '/tmp'

            new_args = []
            new_args += [
                'ssh', '-Ao', 'StrictHostKeyChecking=no', '-o',
                'UserKnownHostsFile=/dev/null'
            ]
            new_args += [
                '{}@{}'.format(self.client_user, self.client.hostname)
            ]
            new_args += [
                '\"echo \'####CYBMOD#####\';', ' '.join(args),
                '; exitcode=\$?; echo \'####CYBMOD#####\'; exit \$exitcode\"'
            ]
            args = new_args

            # If there is an SSH key path defined, wrap args with ssh-agent.
            private_data_files = kwargs.get('private_data_files', {})
            if 'ssh' in private_data_files.get('credentials', {}):
                ssh_key_path = private_data_files['credentials']['ssh']
            else:
                ssh_key_path = ''
            if ssh_key_path:
                ssh_auth_sock = os.path.join(kwargs['private_data_dir'],
                                             'ssh_auth.sock')
                args = run.wrap_args_with_ssh_agent(args, ssh_key_path,
                                                    ssh_auth_sock)
            # args = cmd

            expect_passwords = {}
            d = {}

            for k, v in kwargs['passwords'].items():
                d[re.compile(r'Enter passphrase for .*' + k + r':\s*?$',
                             re.M)] = k
                d[re.compile(r'Enter passphrase for .*' + k, re.M)] = k
            d[re.compile(r'Bad passphrase, try again for .*:\s*?$', re.M)] = ''

            for k, v in d.items():
                expect_passwords[k] = kwargs['passwords'].get(v, '') or ''

            if queryargs and 'password' in queryargs.keys():
                expect_passwords[re.compile(r'Enter password: \s*?$',
                                            re.M)] = queryargs['password']

            stdout_handle = io.StringIO()

            _kw = dict(
                expect_passwords=expect_passwords,
                job_timeout=120,
                idle_timeout=None,
                pexpect_timeout=getattr(settings, 'PEXPECT_TIMEOUT', 5),
            )
            status, rc = run.run_pexpect(args, cwd, env, stdout_handle, **_kw)
            stdout_handle.flush()
            output = stdout_handle.getvalue().split('\r\n')
            finalOutput = []
            start = False
            for line in output:
                if 'Enter password: '******'Enter password: '******'')
                if line == '####CYBMOD#####' and not start:
                    start = True
                if start and line != '####CYBMOD#####' and line != '':
                    finalOutput += [line]

            shutil.rmtree(kwargs['private_data_dir'])
        except Exception:
            tb = traceback.format_exc()
            if settings.DEBUG:
                logger.exception('Exception occurred while running task')
        finally:
            try:
                logger.info('finished running, producing  events.')
            except Exception:
                logger.exception(
                    'Error flushing stdout and saving event count.')
        print(rc)
        print(status)
        return finalOutput, rc