コード例 #1
0
ファイル: jobs.py プロジェクト: skyle97/cyborgbackup
    def pre_start(self, **kwargs):
        if not self.can_start:
            msg = u'%s is not in a startable state: %s, expecting one of %s' % (
                self._meta.verbose_name, self.status, str(('new', 'waiting')))
            self.job_explanation = msg
            self.save(update_fields=['job_explanation'])
            return (False, None)

        needed = self.get_passwords_needed_to_start()
        try:
            start_args = json.loads(decrypt_field(self, 'start_args'))
        except Exception:
            start_args = None

        if start_args in (None, ''):
            start_args = kwargs

        opts = dict([(field, start_args.get(field, '')) for field in needed])

        if not all(opts.values()):
            missing_fields = ', '.join([k for k, v in opts.items() if not v])
            self.job_explanation = u'Missing needed fields: %s.' % missing_fields
            self.save(update_fields=['job_explanation'])
            return (False, None)

        return (True, opts)
コード例 #2
0
ファイル: settings.py プロジェクト: zymbiosis/cyborgbackup
 def get_value(self, name):
     objs = self.objects.filter(key=name)
     if len(objs) == 1:
         setting = objs[0]
         return decrypt_field(setting, 'value')
     else:
         return None
コード例 #3
0
 def build_passwords(self, job, **kwargs):
     '''
     Build a dictionary of passwords for SSH private key, SSH user, sudo/su.
     '''
     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')
     return passwords
コード例 #4
0
    def build_private_data(self, instance, **kwargs):
        '''
        Return SSH private key data (only if stored in DB as ssh_key_data).
        Return structure is a dict of the form:
        '''
        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 ''

        return private_data
コード例 #5
0
ファイル: __init__.py プロジェクト: loki36/cyborgbackup
 def has_encrypted_ssh_key_data(self):
     if self.pk:
         ssh_key_data = decrypt_field(self, 'ssh_key_data')
     else:
         ssh_key_data = self.ssh_key_data
     try:
         pem_objects = validate_ssh_private_key(ssh_key_data)
         for pem_object in pem_objects:
             if pem_object.get('key_enc', False):
                 return True
     except ValidationError:
         pass
     return False
コード例 #6
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