def test_scan_with_options(self, mock_run):
        """Setup second scan with scan and source options."""
        # setup source with paramiko option for scan
        source_options = SourceOptions()
        source_options.save()
        self.source = Source(name='source2',
                             port=22,
                             options=source_options,
                             hosts='["1.2.3.4"]')
        self.source.save()
        self.source.credentials.add(self.cred)

        # setup scan with options
        extended = ExtendedProductSearchOptions()
        extended.save()
        scan_options = ScanOptions(enabled_extended_product_search=extended)
        scan_options.save()

        self.scan_job, self.scan_task = create_scan_job(
            self.source,
            ScanTask.SCAN_TYPE_INSPECT,
            'scan2',
            scan_options=scan_options)

        # run scan
        scanner = InspectTaskRunner(self.scan_job, self.scan_task)

        scanner.connect_scan_task = self.connect_scan_task
        scanner._inspect_scan(self.host_list)
        mock_run.assert_called_with(ANY)
Exemple #2
0
    def setUp(self):
        """Create test case setup."""
        self.cred = Credential(name='cred1',
                               username='******',
                               password='******',
                               sudo_password='******',
                               ssh_keyfile='keyfile')
        self.cred.save()

        self.source = Source(name='source1', port=22)
        self.source.save()
        self.source.credentials.add(self.cred)

        self.host = HostRange(host_range='1.2.3.4', source_id=self.source.id)
        self.host.save()

        self.source.hosts.add(self.host)

        self.scan_task = ScanTask(source=self.source,
                                  scan_type=ScanTask.SCAN_TYPE_CONNECT)
        self.scan_task.systems_failed = 0
        self.scan_task.save()

        self.scan_job = ScanJob(scan_type=ScanTask.SCAN_TYPE_CONNECT)
        self.scan_job.save()
        self.scan_job.sources.add(self.source)
        self.scan_job.tasks.add(self.scan_task)
        scan_options = ScanOptions()
        scan_options.save()
        self.scan_job.options = scan_options
        self.scan_job.save()

        self.conn_results = ConnectionResults(scan_job=self.scan_job)
        self.conn_results.save()
Exemple #3
0
    def test_get_extra_vars_false(self):
        """Tests the get_extra_vars method with all False."""
        extended = ExtendedProductSearchOptions()
        extended.save()
        disabled = DisabledOptionalProductsOptions(
            jboss_eap=True,
            jboss_fuse=True,
            jboss_brms=True)
        disabled.save()
        scan_options = ScanOptions(
            disabled_optional_products=disabled,
            enabled_extended_product_search=extended)
        scan_options.save()
        scan_job, _ = create_scan_job(self.source,
                                      ScanTask.SCAN_TYPE_INSPECT,
                                      scan_options=scan_options)

        extra_vars = scan_job.options.get_extra_vars()

        expected_vars = {'jboss_eap': False,
                         'jboss_fuse': False,
                         'jboss_brms': False,
                         'jboss_eap_ext': False,
                         'jboss_fuse_ext': False,
                         'jboss_brms_ext': False}
        self.assertEqual(extra_vars, expected_vars)
Exemple #4
0
    def create(self, validated_data):
        """Create a scan job."""
        options = validated_data.pop('options', None)
        scanjob = super().create(validated_data)
        if options:
            options = ScanOptions.objects.create(**options)
        else:
            options = ScanOptions()
        options.save()
        scanjob.options = options
        scanjob.save()

        return scanjob
Exemple #5
0
 def test_get_extra_vars(self):
     """Tests the get_extra_vars method with empty dict."""
     scan_job = ScanJob(scan_type=ScanTask.SCAN_TYPE_INSPECT)
     scan_job.save()
     scan_options = ScanOptions()
     scan_options.disable_optional_products = {}
     scan_options.save()
     scan_job.options = scan_options
     scan_job.save()
     extra_vars = scan_job.get_extra_vars()
     expected_vars = {
         'jboss_eap': True,
         'jboss_fuse': True,
         'jboss_brms': True
     }
     self.assertEqual(extra_vars, expected_vars)
Exemple #6
0
    def run_with_result_store(self, manager_interrupt, result_store):
        """Run with a given ConnectResultStore."""
        serializer = SourceSerializer(self.scan_task.source)
        source = serializer.data

        if self.scan_job.options is not None:
            forks = self.scan_job.options.max_concurrency
        else:
            forks = ScanOptions.get_default_forks()

        if self.scan_task.source.options is not None:
            use_paramiko = self.scan_task.source.options.use_paramiko
        else:
            use_paramiko = False

        connection_port = source['port']
        credentials = source['credentials']

        remaining_hosts = result_store.remaining_hosts()

        for cred_id in credentials:
            check_manager_interrupt(manager_interrupt.value)
            credential = Credential.objects.get(pk=cred_id)
            if not remaining_hosts:
                message = 'Skipping credential %s.  No remaining hosts.' % \
                    credential.name
                self.scan_task.log_message(message)
                break

            message = 'Attempting credential %s.' % credential.name
            self.scan_task.log_message(message)

            try:
                scan_message, scan_result = _connect(manager_interrupt,
                                                     self.scan_task,
                                                     remaining_hosts,
                                                     result_store, credential,
                                                     connection_port, forks,
                                                     use_paramiko)
                if scan_result != ScanTask.COMPLETED:
                    return scan_message, scan_result
            except AnsibleRunnerException as ansible_error:
                remaining_hosts_str = ', '.join(result_store.remaining_hosts())
                error_message = 'Connect scan task failed with credential %s.'\
                    ' Error: %s Hosts: %s' %\
                    (credential.name, ansible_error, remaining_hosts_str)
                return error_message, ScanTask.FAILED

            remaining_hosts = result_store.remaining_hosts()

            logger.debug('Failed systems: %s', remaining_hosts)

        for host in remaining_hosts:
            # We haven't connected to these hosts with any
            # credentials, so they have failed.
            result_store.record_result(host, self.scan_task.source, None,
                                       SystemConnectionResult.FAILED)

        return None, ScanTask.COMPLETED
Exemple #7
0
    def test_queue_task(self):
        """Test create queue state change."""
        # Cannot use util because its testing queue
        # Create scan configuration
        scan = Scan(name='test',
                    scan_type=ScanTask.SCAN_TYPE_INSPECT)
        scan.save()

        # Add source to scan
        scan.sources.add(self.source)

        options_to_use = ScanOptions()
        options_to_use.save()

        scan.options = options_to_use
        scan.save()

        # Create Job
        scan_job = ScanJob(scan=scan)
        scan_job.save()

        # Job in created state
        self.assertEqual(scan_job.status, ScanTask.CREATED)
        tasks = scan_job.tasks.all()
        self.assertEqual(len(tasks), 0)

        # Queue job to run
        scan_job.queue()

        # Job should be in pending state
        self.assertEqual(scan_job.status, ScanTask.PENDING)

        # Queue should have created scan tasks
        tasks = scan_job.tasks.all()
        self.assertEqual(len(tasks), 2)

        # Validate connect task created and correct
        connect_task = tasks[0]
        self.assertEqual(connect_task.scan_type, ScanTask.SCAN_TYPE_CONNECT)
        self.assertEqual(connect_task.status, ScanTask.PENDING)

        # Validate inspect task created and correct
        inspect_task = tasks[1]
        self.assertEqual(inspect_task.scan_type, ScanTask.SCAN_TYPE_INSPECT)
        self.assertEqual(inspect_task.status, ScanTask.PENDING)
Exemple #8
0
    def test_get_extra_vars_missing_extended_search(self):
        """Tests the get_extra_vars with disabled products None."""
        extended = ExtendedProductSearchOptions()
        extended.save()
        scan_options = ScanOptions(
            enabled_extended_product_search=extended)
        scan_options.save()
        scan_job, _ = create_scan_job(self.source,
                                      ScanTask.SCAN_TYPE_INSPECT,
                                      scan_options=scan_options)
        extra_vars = scan_job.options.get_extra_vars()

        expected_vars = {'jboss_eap': True,
                         'jboss_fuse': True,
                         'jboss_brms': True,
                         'jboss_eap_ext': False,
                         'jboss_fuse_ext': False,
                         'jboss_brms_ext': False}
        self.assertEqual(extra_vars, expected_vars)
Exemple #9
0
    def test_get_extra_vars_missing_disable_product(self):
        """Tests the get_extra_vars with extended search None."""
        disabled = DisabledOptionalProductsOptions()
        disabled.save()
        scan_options = ScanOptions(
            disabled_optional_products=disabled)
        scan_options.save()
        scan_job, _ = create_scan_job(self.source,
                                      ScanTask.SCAN_TYPE_INSPECT,
                                      scan_options=scan_options)
        extra_vars = scan_job.options.get_extra_vars()

        expected_vars = {'jboss_eap': True,
                         'jboss_fuse': True,
                         'jboss_brms': True,
                         'jboss_eap_ext': False,
                         'jboss_fuse_ext': False,
                         'jboss_brms_ext': False}
        self.assertEqual(extra_vars, expected_vars)
Exemple #10
0
    def create(self, request, *args, **kwargs):
        """Create a source."""
        response = super().create(request, args, kwargs)

        # Modify json for response
        json_source = response.data
        source_id = json_source.get('id')
        if not source_id or (source_id and not isinstance(source_id, int)):
            error = {'id': [_(messages.COMMON_ID_INV)]}
            raise ValidationError(error)

        get_object_or_404(self.queryset, pk=source_id)

        # Create expanded host cred JSON
        expand_credential(json_source)

        # check to see if a connection scan was requested
        # through query parameter
        scan = request.query_params.get('scan', False)
        # If the scan was requested, create a connection scan
        if scan:
            if is_boolean(scan):
                if convert_to_boolean(scan):
                    # Grab the source id
                    source_id = response.data['id']
                    # Define the scan options object
                    scan_options = ScanOptions()
                    scan_options.save()
                    # Create the scan job
                    scan_job = ScanJob(scan_type=ScanTask.SCAN_TYPE_CONNECT,
                                       options=scan_options)
                    scan_job.save()
                    # Add the source
                    scan_job.sources.add(source_id)
                    scan_job.save()
                    # Start the scan
                    start_scan.send(sender=self.__class__, instance=scan_job)
            else:
                error = {'scan': [_(messages.SOURCE_CONNECTION_SCAN)]}
                raise ValidationError(error)
        return response
Exemple #11
0
    def test_hosts_facts(self, mock_pool):
        """Test the hosts_facts method."""
        scan_options = ScanOptions(max_concurrency=10)
        scan_options.save()
        scan_job, scan_task = create_scan_job(self.source,
                                              ScanTask.SCAN_TYPE_INSPECT,
                                              scan_name='test_62',
                                              scan_options=scan_options)
        scan_task.update_stats('TEST_SAT.', sys_scanned=0)
        api = SatelliteSixV2(scan_job, scan_task)
        job_conn_result = JobConnectionResult()
        job_conn_result.save()
        connection_results = TaskConnectionResult(
            job_connection_result=job_conn_result)
        connection_results.save()
        api.connect_scan_task.connection_result = connection_results
        api.connect_scan_task.connection_result.save()

        sys_result = SystemConnectionResult(
            name='sys1_1',
            status=SystemInspectionResult.SUCCESS,
            task_connection_result=api.connect_scan_task.connection_result)
        sys_result.save()
        api.connect_scan_task.save()
        hosts_url = 'https://{sat_host}:{port}/api/v2/hosts'
        with requests_mock.Mocker() as mocker:
            url = construct_url(url=hosts_url, sat_host='1.2.3.4')
            jsonresult = {
                'total': 1,
                'subtotal': 1,
                'page': 1,
                'per_page': 100,
                'results': [{
                    'id': 10,
                    'name': 'sys10'
                }]
            }  # noqa
            mocker.get(url, status_code=200, json=jsonresult)
            api.hosts_facts(Value('i', ScanJob.JOB_RUN))
            inspect_result = scan_task.inspection_result
            self.assertEqual(len(inspect_result.systems.all()), 1)
Exemple #12
0
    def run_with_result_store(self, result_store):
        """Run with a given ConnectResultStore."""
        serializer = SourceSerializer(self.scan_task.source)
        source = serializer.data

        if self.scan_job.options is None:
            forks = ScanOptions.get_default_forks()
        else:
            forks = self.scan_job.options.max_concurrency
        connection_port = source['port']
        credentials = source['credentials']

        remaining_hosts = result_store.remaining_hosts()

        for cred_id in credentials:
            credential = Credential.objects.get(pk=cred_id)
            if not remaining_hosts:
                message = 'Skipping credential %s.  No remaining hosts.' % \
                    credential.name
                self.scan_task.log_message(message)
                break

            message = 'Attempting credential %s.' % credential.name
            self.scan_task.log_message(message)

            cred_data = CredentialSerializer(credential).data
            callback = ConnectResultCallback(result_store, credential,
                                             self.scan_task.source)
            try:
                connect(remaining_hosts,
                        callback,
                        cred_data,
                        connection_port,
                        forks=forks)
            except AnsibleError as ansible_error:
                remaining_hosts_str = ', '.join(result_store.remaining_hosts())
                error_message = 'Connect scan task failed with credential %s.'\
                    ' Error: %s Hosts: %s' %\
                    (credential.name, ansible_error, remaining_hosts_str)
                return error_message, ScanTask.FAILED

            remaining_hosts = result_store.remaining_hosts()

            logger.debug('Failed systems: %s', remaining_hosts)

        for host in remaining_hosts:
            # We haven't connected to these hosts with any
            # credentials, so they have failed.
            result_store.record_result(host, self.scan_task.source, None,
                                       SystemConnectionResult.FAILED)

        return None, ScanTask.COMPLETED
Exemple #13
0
    def test_get_extra_vars_missing_options(self):
        """Tests the get_default_extra_vars."""
        extra_vars = ScanOptions.get_default_extra_vars()

        expected_vars = {
            'jboss_eap': True,
            'jboss_fuse': True,
            'jboss_brms': True,
            'jboss_ws': True,
            'jboss_eap_ext': False,
            'jboss_fuse_ext': False,
            'jboss_brms_ext': False,
            'jboss_ws_ext': False
        }
        self.assertEqual(extra_vars, expected_vars)
    def setUp(self):
        """Create test case setup."""
        self.cred = Credential(name='cred1',
                               username='******',
                               password='******',
                               ssh_keyfile='keyfile',
                               become_method='sudo',
                               become_user='******',
                               become_password='******')
        self.cred.save()

        self.source = Source(name='source1', port=22)
        self.source.save()
        self.source.credentials.add(self.cred)

        self.source.hosts = '["1.2.3.4"]'
        self.source.save()

        self.scan_task = ScanTask(source=self.source,
                                  scan_type=ScanTask.SCAN_TYPE_CONNECT,
                                  start_time=datetime.utcnow())
        self.scan_task.update_stats('TEST NETWORK CONNECT.', sys_failed=0)

        self.scan_job = ScanJob(scan_type=ScanTask.SCAN_TYPE_CONNECT)
        self.scan_job.save()
        self.scan_job.sources.add(self.source)
        self.scan_job.tasks.add(self.scan_task)
        scan_options = ScanOptions()
        scan_options.save()
        self.scan_job.options = scan_options
        self.scan_job.save()

        self.conn_results = JobConnectionResult()
        self.conn_results.save()
        self.scan_job.connection_results = self.conn_results
        self.scan_job.save()
Exemple #15
0
    def __init__(self, scan_job, scan_task):
        """Set context for interface."""
        self.scan_job = scan_job
        if scan_job.options is None:
            self.max_concurrency = ScanOptions.get_default_forks()
        else:
            self.max_concurrency = scan_job.options.max_concurrency

        if scan_task.scan_type == ScanTask.SCAN_TYPE_CONNECT:
            self.connect_scan_task = scan_task
            self.inspect_scan_task = None
        else:
            self.connect_scan_task = scan_task.prerequisites.first()
            self.inspect_scan_task = scan_task
        self.source = scan_task.source
Exemple #16
0
    def setUp(self):
        """Create test setup."""
        management.call_command('flush', '--no-input')
        self.cred = Credential.objects.create(name='cred1',
                                              username='******',
                                              password='******',
                                              become_password=None,
                                              ssh_keyfile=None)
        self.cred_for_upload = self.cred.id

        self.source = Source(name='source1', source_type='network', port=22)
        self.source.save()

        self.source2 = Source(name='source2', source_type='network', port=22)
        self.source2.save()
        self.source2.credentials.add(self.cred)
        self.concurrency = ScanOptions.get_default_forks()
Exemple #17
0
class ScanOptionsSerializer(NotEmptySerializer):
    """Serializer for the ScanOptions model."""

    max_concurrency = IntegerField(required=False,
                                   min_value=1,
                                   max_value=200,
                                   default=ScanOptions.get_default_forks())
    disabled_optional_products = DisableOptionalProductsOptionsSerializer(
        required=False)
    enabled_extended_product_search = ExtendedProductSearchOptionsSerializer(
        required=False)

    class Meta:
        """Metadata for serializer."""

        model = ScanOptions
        fields = [
            'max_concurrency', 'disabled_optional_products',
            'enabled_extended_product_search'
        ]
Exemple #18
0
    def _inspect_scan(self,
                      manager_interrupt,
                      connected,
                      roles=DEFAULT_ROLES,
                      base_ssh_executable=None,
                      ssh_timeout=None):
        """Execute the host scan with the initialized source.

        :param manager_interrupt: Signal used to communicate termination
            of scan
        :param connected: list of (host, credential) pairs to inspect
        :param roles: list of roles to execute
        :param base_ssh_executable: ssh executable, or None for
            'ssh'. Will be wrapped with a timeout before being passed
            to Ansible.
        :param ssh_timeout: string in the format of the 'timeout'
            command. Timeout for individual tasks.
        :returns: An array of dictionaries of facts

        """
        connection_port = self.scan_task.source.port

        if self.scan_task.source.options is not None:
            use_paramiko = self.scan_task.source.options.use_paramiko
        else:
            use_paramiko = None

        if self.scan_job.options is not None:
            forks = self.scan_job.options.max_concurrency
            extra_vars = self.scan_job.options.get_extra_vars()
        else:
            forks = ScanOptions.get_default_forks()
            extra_vars = ScanOptions.get_default_extra_vars()

        if extra_vars.get(ScanOptions.EXT_PRODUCT_SEARCH_DIRS) is None:
            extra_vars[ScanOptions.EXT_PRODUCT_SEARCH_DIRS] = \
                ' '.join(DEFAULT_SCAN_DIRS)

        ssh_executable = os.path.abspath(
            os.path.join(os.path.dirname(__file__),
                         '../../../bin/timeout_ssh'))

        base_ssh_executable = base_ssh_executable or 'ssh'
        ssh_timeout = ssh_timeout or settings.QPC_SSH_INSPECT_TIMEOUT

        # pylint: disable=line-too-long
        # the ssh arg is required for become-pass because
        # ansible checks for an exact string match of ssh
        # anywhere in the command array
        # See https://github.com/ansible/ansible/blob/stable-2.3/lib/ansible/plugins/connection/ssh.py#L490-L500 # noqa
        # timeout_ssh will remove the ssh argument before running the command
        ssh_args = [
            '--executable=' + base_ssh_executable, '--timeout=' + ssh_timeout,
            'ssh'
        ]

        group_names, inventory = _construct_scan_inventory(
            connected,
            connection_port,
            forks,
            ssh_executable=ssh_executable,
            ssh_args=ssh_args)
        inventory_file = write_inventory(inventory)

        error_msg = ''
        log_message = 'START INSPECT PROCESSING GROUPS'\
            ' with use_paramiko: %s, '\
            '%d forks and extra_vars=%s' % (use_paramiko,
                                            forks,
                                            extra_vars)
        self.scan_task.log_message(log_message)
        scan_result = ScanTask.COMPLETED
        scan_message = 'success'
        for idx, group_name in enumerate(group_names):
            if manager_interrupt.value == ScanJob.JOB_TERMINATE_CANCEL:
                raise NetworkCancelException()

            if manager_interrupt.value == ScanJob.JOB_TERMINATE_PAUSE:
                raise NetworkPauseException()

            log_message = 'START INSPECT PROCESSING GROUP %d of %d' % (
                (idx + 1), len(group_names))
            self.scan_task.log_message(log_message)
            callback =\
                InspectResultCallback(
                    scan_task=self.scan_task)
            playbook = {
                'name': 'scan systems for product fingerprint facts',
                'hosts': group_name,
                'gather_facts': False,
                'roles': roles
            }
            result = run_playbook(inventory_file,
                                  callback,
                                  playbook,
                                  extra_vars,
                                  use_paramiko,
                                  forks=forks)

            if result != TaskQueueManager.RUN_OK:
                new_error_msg = _construct_error_msg(result)
                callback.finalize_failed_hosts()
                if result not in [
                        TaskQueueManager.RUN_UNREACHABLE_HOSTS,
                        TaskQueueManager.RUN_FAILED_HOSTS
                ]:
                    error_msg += '{}\n'.format(new_error_msg)

        if error_msg != '':
            raise AnsibleError(error_msg)

        return scan_message, scan_result
Exemple #19
0
    def setUp(self):
        """Create test case setup."""
        self.cred = Credential(name='cred1',
                               username='******',
                               password='******',
                               sudo_password=None,
                               ssh_keyfile=None)
        self.cred.save()

        self.source = Source(name='source1', port=22)
        self.source.save()
        self.source.credentials.add(self.cred)

        self.host = HostRange(host_range='1.2.3.4', source_id=self.source.id)
        self.host.save()

        self.source.hosts.add(self.host)

        self.connect_scan_task = ScanTask(source=self.source,
                                          scan_type=ScanTask.SCAN_TYPE_CONNECT,
                                          status=ScanTask.COMPLETED)
        self.connect_scan_task.systems_failed = 0
        self.connect_scan_task.save()

        self.inspect_scan_task = ScanTask(source=self.source,
                                          scan_type=ScanTask.SCAN_TYPE_INSPECT)
        self.inspect_scan_task.systems_failed = 0
        self.inspect_scan_task.save()
        self.inspect_scan_task.prerequisites.add(self.connect_scan_task)
        self.inspect_scan_task.save()

        self.scan_job = ScanJob(scan_type=ScanTask.SCAN_TYPE_INSPECT)
        self.scan_job.save()

        self.scan_job.tasks.add(self.connect_scan_task)
        self.scan_job.tasks.add(self.inspect_scan_task)
        scan_options = ScanOptions()
        scan_options.save()
        self.scan_job.options = scan_options
        self.scan_job.save()

        self.fact_endpoint = 'http://testserver' + reverse('facts-list')

        self.conn_results = ConnectionResults(scan_job=self.scan_job)
        self.conn_results.save()

        self.conn_result = ConnectionResult(scan_task=self.connect_scan_task,
                                            source=self.source)
        self.conn_result.save()

        success_sys = SystemConnectionResult(
            name='1.2.3.4',
            credential=self.cred,
            status=SystemConnectionResult.SUCCESS)
        success_sys.save()
        failed_sys = SystemConnectionResult(
            name='1.1.1.2', status=SystemConnectionResult.FAILED)
        failed_sys.save()
        self.conn_result.systems.add(success_sys)
        self.conn_result.systems.add(failed_sys)
        self.conn_result.save()
        self.conn_results.results.add(self.conn_result)
        self.conn_results.save()

        self.inspect_results = InspectionResults(scan_job=self.scan_job)
        self.inspect_results.save()
Exemple #20
0
    def _inspect_scan(self, connected, roles=DEFAULT_ROLES,
                      base_ssh_executable=None,
                      ssh_timeout=None):
        """Execute the host scan with the initialized source.

        :param connected: list of (host, credential) pairs to inspect
        :param roles: list of roles to execute
        :param base_ssh_executable: ssh executable, or None for
            'ssh'. Will be wrapped with a timeout before being passed
            to Ansible.
        :param ssh_timeout: string in the format of the 'timeout'
            command. Timeout for individual tasks.
        :returns: An array of dictionaries of facts

        """
        playbook = {'name': 'scan systems for product fingerprint facts',
                    'hosts': 'all',
                    'gather_facts': False,
                    'strategy': 'free',
                    'roles': roles}
        connection_port = self.scan_task.source.port

        if self.scan_job.options is not None:
            forks = self.scan_job.options.max_concurrency
            extra_vars = self.scan_job.options.get_extra_vars()
        else:
            forks = ScanOptions.get_default_forks()
            extra_vars = ScanOptions.get_default_extra_vars()

        if extra_vars.get(ScanOptions.EXT_PRODUCT_SEARCH_DIRS) is None:
            extra_vars[ScanOptions.EXT_PRODUCT_SEARCH_DIRS] = \
                ' '.join(DEFAULT_SCAN_DIRS)

        ssh_executable = os.path.abspath(
            os.path.join(os.path.dirname(__file__),
                         '../../../bin/timeout_ssh'))

        base_ssh_executable = base_ssh_executable or 'ssh'
        ssh_timeout = ssh_timeout or DEFAULT_TIMEOUT
        ssh_args = ['--executable=' + base_ssh_executable,
                    '--timeout=' + ssh_timeout]

        group_names, inventory = _construct_scan_inventory(
            connected, connection_port, forks,
            ssh_executable=ssh_executable,
            ssh_args=ssh_args)
        inventory_file = write_inventory(inventory)

        error_msg = ''
        log_message = 'START PROCESSING GROUPS with %d forks' \
            ' and extra_vars=%s' % (forks, extra_vars)
        self.scan_task.log_message(log_message)
        scan_result = ScanTask.COMPLETED
        scan_message = 'success'
        for idx, group_name in enumerate(group_names):
            log_message = 'START PROCESSING GROUP %d of %d' % (
                (idx + 1), len(group_names))
            self.scan_task.log_message(log_message)
            callback =\
                InspectResultCallback(
                    scan_task=self.scan_task)
            playbook = {'name': 'scan systems for product fingerprint facts',
                        'hosts': group_name,
                        'gather_facts': False,
                        'roles': roles}
            result = run_playbook(
                inventory_file, callback, playbook,
                extra_vars, forks=forks)

            if result != TaskQueueManager.RUN_OK:
                new_error_msg = _construct_error_msg(result)
                callback.finalize_failed_hosts()
                if result != TaskQueueManager.RUN_UNREACHABLE_HOSTS and \
                        result != TaskQueueManager.RUN_FAILED_HOSTS:
                    error_msg += '{}\n'.format(new_error_msg)

        if error_msg != '':
            raise AnsibleError(error_msg)

        return scan_message, scan_result
    def setUp(self):
        """Create test case setup."""
        self.cred = Credential(
            name='cred1',
            username='******',
            password='******',
            ssh_keyfile='keyfile',
            become_method='sudo',
            become_user='******',
            become_password='******')
        self.cred.save()

        # Source with excluded hosts
        self.source = Source(
            name='source1',
            hosts='["1.2.3.4", "1.2.3.5"]',
            exclude_hosts='["1.2.3.5", "1.2.3.6"]',
            source_type='network',
            port=22)
        self.source.save()
        self.source.credentials.add(self.cred)
        self.source.save()

        self.scan_job, self.scan_task = create_scan_job(
            self.source, ScanTask.SCAN_TYPE_CONNECT)

        self.scan_task.update_stats('TEST NETWORK CONNECT.', sys_failed=0)

        # Source without excluded hosts
        self.source2 = Source(
            name='source2',
            hosts='["1.2.3.4"]',
            source_type='network',
            port=22)
        self.source2.save()
        self.source2.credentials.add(self.cred)
        self.source2.save()

        self.scan_job2, self.scan_task2 = create_scan_job(
            self.source2, ScanTask.SCAN_TYPE_CONNECT, 'source2',)

        self.scan_task2.update_stats('TEST NETWORK CONNECT.', sys_failed=0)

        # Scans with options & no excluded hosts
        source_options = SourceOptions(use_paramiko=True)
        source_options.save()
        self.source3 = Source(
            name='source3',
            hosts='["1.2.3.4","1.2.3.5","1.2.3.6"]',
            source_type='network',
            port=22,
            options=source_options)
        self.source3.save()
        self.source3.credentials.add(self.cred)
        self.source3.save()

        scan_options = ScanOptions(max_concurrency=2)
        scan_options.save()

        self.scan_job3, self.scan_task3 = create_scan_job(
            self.source3, ScanTask.SCAN_TYPE_CONNECT, 'source3', scan_options)
        self.scan_task3.update_stats('TEST NETWORK CONNECT.', sys_failed=0)
        self.concurrency = ScanOptions.get_default_forks()
Exemple #22
0
    def _inspect_scan(self,
                      manager_interrupt,
                      connected,
                      base_ssh_executable=None,
                      ssh_timeout=None):
        """Execute the host scan with the initialized source.

        :param manager_interrupt: Signal used to communicate termination
            of scan
        :param connected: list of (host, credential) pairs to inspect
        :param roles: list of roles to execute
        :param base_ssh_executable: ssh executable, or None for
            'ssh'. Will be wrapped with a timeout before being passed
            to Ansible.
        :param ssh_timeout: string in the format of the 'timeout'
            command. Timeout for individual tasks.
        :returns: An array of dictionaries of facts

        Note: base_ssh_executable & ssh_timeout are parameters that
        are only used for testing.
        """
        # pylint: disable=too-many-locals,too-many-arguments
        # pylint: disable=too-many-branches,too-many-statements
        connection_port = self.scan_task.source.port

        if self.scan_task.source.options is not None:
            use_paramiko = self.scan_task.source.options.use_paramiko
        else:
            use_paramiko = False

        if self.scan_job.options is not None:
            forks = self.scan_job.options.max_concurrency
            extra_vars = self.scan_job.options.get_extra_vars()
        else:
            forks = ScanOptions.get_default_forks()
            extra_vars = ScanOptions.get_default_extra_vars()

        if extra_vars.get(ScanOptions.EXT_PRODUCT_SEARCH_DIRS) is None:
            extra_vars[ScanOptions.EXT_PRODUCT_SEARCH_DIRS] = \
                ' '.join(DEFAULT_SCAN_DIRS)

        ssh_executable = os.path.abspath(
            os.path.join(os.path.dirname(__file__),
                         '../../../bin/timeout_ssh'))

        base_ssh_executable = base_ssh_executable or 'ssh'
        ssh_timeout = ssh_timeout or settings.QPC_SSH_INSPECT_TIMEOUT
        # pylint: disable=line-too-long
        # the ssh arg is required for become-pass because
        # ansible checks for an exact string match of ssh
        # anywhere in the command array
        # See https://github.com/ansible/ansible/blob/stable-2.3/lib/ansible/plugins/connection/ssh.py#L490-L500 # noqa
        # timeout_ssh will remove the ssh argument before running the command
        ssh_args = [
            '--executable=' + base_ssh_executable, '--timeout=' + ssh_timeout,
            'ssh'
        ]

        group_names, inventory = _construct_scan_inventory(
            connected,
            connection_port,
            forks,
            ssh_executable=ssh_executable,
            ssh_args=ssh_args)
        inventory_file = write_to_yaml(inventory)

        error_msg = None
        log_message = 'START INSPECT PROCESSING GROUPS'\
            ' with use_paramiko: %s, '\
            '%d forks and extra_vars=%s' % (use_paramiko,
                                            forks,
                                            extra_vars)
        self.scan_task.log_message(log_message)
        scan_result = ScanTask.COMPLETED

        # Build Ansible Runner Dependencies
        for idx, group_name in enumerate(group_names):
            check_manager_interrupt(manager_interrupt.value)
            log_message = 'START INSPECT PROCESSING GROUP %d of %d' % (
                (idx + 1), len(group_names))
            self.scan_task.log_message(log_message)
            call = InspectResultCallback(self.scan_task, manager_interrupt)

            # Build Ansible Runner Parameters
            runner_settings = {
                'idle_timeout': int(settings.NETWORK_INSPECT_JOB_TIMEOUT),
                'job_timeout': int(settings.NETWORK_INSPECT_JOB_TIMEOUT),
                'pexpect_timeout': 5
            }
            playbook_path = os.path.join(settings.BASE_DIR,
                                         'scanner/network/runner/inspect.yml')
            extra_vars['variable_host'] = group_name
            cmdline_list = []
            vault_file_path = '--vault-password-file=%s' % (
                settings.DJANGO_SECRET_PATH)
            cmdline_list.append(vault_file_path)
            forks_cmd = '--forks=%s' % (forks)
            cmdline_list.append(forks_cmd)
            if use_paramiko:
                cmdline_list.append('--connection=paramiko')
            all_commands = ' '.join(cmdline_list)

            if int(settings.ANSIBLE_LOG_LEVEL) == 0:
                quiet_bool = True
                verbosity_lvl = 0
            else:
                quiet_bool = False
                verbosity_lvl = int(settings.ANSIBLE_LOG_LEVEL)

            try:
                runner_obj = ansible_runner.run(
                    quiet=quiet_bool,
                    settings=runner_settings,
                    inventory=inventory_file,
                    extravars=extra_vars,
                    event_handler=call.event_callback,
                    cancel_callback=call.cancel_callback,
                    playbook=playbook_path,
                    cmdline=all_commands,
                    verbosity=verbosity_lvl)
            except Exception as error:
                error_msg = error
                raise AnsibleRunnerException(error_msg)

            final_status = runner_obj.status
            if final_status != 'successful':
                if final_status == 'canceled':
                    interrupt = manager_interrupt.value
                    if interrupt == ScanJob.JOB_TERMINATE_CANCEL:
                        msg = log_messages.NETWORK_PLAYBOOK_STOPPED % (
                            'INSPECT', 'canceled')
                    else:
                        msg = log_messages.NETWORK_PLAYBOOK_STOPPED % (
                            'INSPECT', 'paused')
                    self.scan_task.log_message(msg)
                    check_manager_interrupt(interrupt)
                if final_status not in ['unreachable', 'failed']:
                    if final_status == 'timeout':
                        error_msg = log_messages.NETWORK_TIMEOUT_ERR
                    else:
                        error_msg = log_messages.NETWORK_UNKNOWN_ERR
                    scan_result = ScanTask.FAILED
                call.finalize_failed_hosts()
        return error_msg, scan_result
Exemple #23
0
    def setUp(self):
        """Create test case setup."""
        self.cred = Credential(
            name='cred1',
            username='******',
            password='******',
            ssh_keyfile=None,
            become_method=None,
            become_user=None,
            become_password=None)
        self.cred.save()

        hc_serializer = CredentialSerializer(self.cred)
        self.cred_data = hc_serializer.data

        self.source = Source(
            name='source1',
            port=22,
            hosts='["1.2.3.4"]')
        self.source.save()
        self.source.credentials.add(self.cred)

        self.host_list = [('1.2.3.4', self.cred_data)]
        self.connect_scan_task = ScanTask(source=self.source,
                                          scan_type=ScanTask.SCAN_TYPE_CONNECT,
                                          status=ScanTask.COMPLETED,
                                          start_time=datetime.utcnow())
        self.connect_scan_task.update_stats(
            'TEST NETWORK CONNECT.', sys_failed=0)

        self.inspect_scan_task = ScanTask(source=self.source,
                                          scan_type=ScanTask.SCAN_TYPE_INSPECT,
                                          start_time=datetime.utcnow())
        self.inspect_scan_task.update_stats(
            'TEST NETWORK INSPECT.', sys_failed=0)
        self.inspect_scan_task.prerequisites.add(self.connect_scan_task)
        self.inspect_scan_task.save()

        self.scan_job = ScanJob(scan_type=ScanTask.SCAN_TYPE_INSPECT)
        self.scan_job.save()

        self.scan_job.tasks.add(self.connect_scan_task)
        self.scan_job.tasks.add(self.inspect_scan_task)
        scan_options = ScanOptions()
        scan_options.disable_optional_products = {'jboss_eap': False,
                                                  'jboss_fuse': False,
                                                  'jboss_brms': False}
        scan_options.save()
        self.scan_job.options = scan_options
        self.scan_job.save()

        self.fact_endpoint = 'http://testserver' + reverse('facts-list')

        self.conn_results = JobConnectionResult()
        self.conn_results.save()
        self.scan_job.connection_results = self.conn_results

        self.conn_result = TaskConnectionResult(
            scan_task=self.connect_scan_task, source=self.source)
        self.conn_result.save()

        success_sys = SystemConnectionResult(
            name='1.2.3.4', credential=self.cred,
            status=SystemConnectionResult.SUCCESS)
        success_sys.save()
        failed_sys = SystemConnectionResult(
            name='1.1.1.2', status=SystemConnectionResult.FAILED)
        failed_sys.save()
        self.conn_result.systems.add(success_sys)
        self.conn_result.systems.add(failed_sys)
        self.conn_result.save()
        self.conn_results.results.add(self.conn_result)
        self.conn_results.save()
        self.scan_job.connection_results = self.conn_results

        self.inspect_results = JobInspectionResult()
        self.inspect_results.save()
        self.scan_job.inspection_results = self.inspect_results

        self.scan_job.save()