Exemplo n.º 1
0
class DeploymentReportSerializer(NotEmptySerializer):
    """Serializer for the Fingerprint model."""

    # Scan information
    report_type = CharField(read_only=True)
    report_version = CharField(max_length=64, read_only=True)
    report_platform_id = UUIDField(format='hex_verbose', read_only=True)
    details_report = PrimaryKeyRelatedField(
        queryset=DetailsReport.objects.all())
    report_id = IntegerField(read_only=True)
    cached_fingerprints = CustomJSONField(read_only=True)
    cached_masked_fingerprints = CustomJSONField(read_only=True)
    cached_csv = CharField(read_only=True)
    cached_masked_csv = CharField(read_only=True)
    cached_insights = CharField(read_only=True)

    status = ChoiceField(read_only=True,
                         choices=DeploymentsReport.STATUS_CHOICES)
    system_fingerprints = FingerprintField(many=True, read_only=True)

    class Meta:
        """Meta class for DeploymentReportSerializer."""

        model = DeploymentsReport
        fields = '__all__'
Exemplo n.º 2
0
class ProductSerializer(NotEmptySerializer):
    """Serializer for the Product model."""

    version = CustomJSONField(required=False)
    metadata = CustomJSONField(required=True)

    class Meta:
        """Meta class for ProductSerializer."""

        model = Product
        fields = ('name', 'version', 'presence', 'metadata')
Exemplo n.º 3
0
class ScanOptionsSerializer(NotEmptySerializer):
    """Serializer for the ScanOptions model."""

    max_concurrency = IntegerField(required=False, min_value=1, default=50)
    disable_optional_products = CustomJSONField(required=False)

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

        model = ScanOptions
        fields = ['max_concurrency',
                  'disable_optional_products']

    # pylint: disable=invalid-name
    @staticmethod
    def validate_disable_optional_products(disable_optional_products):
        """Make sure that extra vars are a dictionary with boolean values."""
        disable_optional_products = ScanJob.get_optional_products(
            disable_optional_products)

        if not isinstance(disable_optional_products, dict):
            raise ValidationError(_(messages.SJ_EXTRA_VARS_DICT))
        for key in disable_optional_products:
            if not isinstance(disable_optional_products[key], bool):
                raise ValidationError(_(messages.SJ_EXTRA_VARS_BOOL))
            elif key not in [ScanJob.JBOSS_EAP,
                             ScanJob.JBOSS_BRMS,
                             ScanJob.JBOSS_FUSE]:
                raise ValidationError(_(messages.SJ_EXTRA_VARS_KEY))
        return json.dumps(disable_optional_products)
Exemplo n.º 4
0
class EntitlementSerializer(NotEmptySerializer):
    """Serializer for the Entitlement model."""

    metadata = CustomJSONField(required=True)

    class Meta:
        """Meta class for EntitlementSerializer."""

        model = Entitlement
        fields = ('name', 'entitlement_id', 'metadata')
Exemplo n.º 5
0
class RawFactSerializer(NotEmptySerializer):
    """Serializer for the SystemInspectionResult model."""

    name = CharField(required=True, max_length=1024)
    value = CustomJSONField(required=True)

    class Meta:
        """Metadata for serialzer."""

        model = RawFact
        fields = ['name', 'value']
        qpc_allow_empty_fields = []
Exemplo n.º 6
0
class DetailsReportSerializer(NotEmptySerializer):
    """Serializer for the DetailsReport model."""

    sources = CustomJSONField(required=True)
    report_id = IntegerField(read_only=True)
    cached_csv = CharField(required=False, read_only=True)

    class Meta:
        """Meta class for DetailsReportSerializer."""

        model = DetailsReport
        exclude = ('id', 'deployment_report')
Exemplo n.º 7
0
class FactCollectionSerializer(NotEmptySerializer):
    """Serializer for the FactCollection model."""

    sources = CustomJSONField(required=True)
    csv_content = CharField(required=False, read_only=True)
    status = ChoiceField(
        read_only=True, choices=FactCollection.FC_STATUS_CHOICES)

    class Meta:
        """Meta class for FactCollectionSerializer."""

        model = FactCollection
        fields = '__all__'
Exemplo n.º 8
0
class DetailsReportSerializer(NotEmptySerializer):
    """Serializer for the DetailsReport model."""

    report_type = CharField(read_only=True)
    report_version = CharField(max_length=64, read_only=True)

    sources = CustomJSONField(required=True)
    report_id = IntegerField(read_only=True)
    report_platform_id = UUIDField(format='hex_verbose',
                                   read_only=True)
    cached_csv = CharField(required=False, read_only=True)

    class Meta:
        """Meta class for DetailsReportSerializer."""

        model = DetailsReport
        exclude = ('id', 'deployment_report')
Exemplo n.º 9
0
class DeploymentReportSerializer(NotEmptySerializer):
    """Serializer for the Fingerprint model."""

    # Scan information
    details_report = PrimaryKeyRelatedField(
        queryset=DetailsReport.objects.all())
    report_id = IntegerField(read_only=True)
    cached_json = CustomJSONField(read_only=True)
    cached_csv = CharField(read_only=True)

    status = ChoiceField(read_only=True,
                         choices=DeploymentsReport.STATUS_CHOICES)
    system_fingerprints = FingerprintField(many=True, read_only=True)

    class Meta:
        """Meta class for DeploymentReportSerializer."""

        model = DeploymentsReport
        fields = '__all__'
Exemplo n.º 10
0
class ExtendedProductSearchOptionsSerializer(NotEmptySerializer):
    """The extended production search options of a scan."""

    jboss_eap = BooleanField(required=False)
    jboss_fuse = BooleanField(required=False)
    jboss_brms = BooleanField(required=False)
    jboss_ws = BooleanField(required=False)
    search_directories = CustomJSONField(required=False)

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

        model = ExtendedProductSearchOptions
        fields = ['jboss_eap',
                  'jboss_fuse',
                  'jboss_brms',
                  'jboss_ws',
                  'search_directories']

    @staticmethod
    def validate_search_directories(search_directories):
        """Validate search directories."""
        try:
            search_directories_list = json.loads(search_directories)
            if not isinstance(search_directories_list, list):
                raise ValidationError(
                    _(messages.SCAN_OPTIONS_EXTENDED_SEARCH_DIR_NOT_LIST))
            for directory in search_directories_list:
                if not isinstance(directory, str):
                    raise ValidationError(
                        _(messages.SCAN_OPTIONS_EXTENDED_SEARCH_DIR_NOT_LIST))
            invalid_paths = check_path_validity(search_directories_list)
            if bool(invalid_paths):
                raise ValidationError(
                    _(messages.SCAN_OPTIONS_EXTENDED_SEARCH_DIR_NOT_LIST))
        except json_exception_class:
            raise ValidationError(
                _(messages.SCAN_OPTIONS_EXTENDED_SEARCH_DIR_NOT_LIST))
        return search_directories
Exemplo n.º 11
0
class SystemFingerprintSerializer(NotEmptySerializer):
    """Serializer for the Fingerprint model."""

    # Common facts
    system_platform_id = UUIDField(format='hex_verbose', read_only=True)
    name = CharField(required=False, max_length=256)

    os_name = CharField(required=False, max_length=64)
    os_release = CharField(required=False, max_length=128)
    os_version = CharField(required=False, max_length=64)

    infrastructure_type = ChoiceField(
        required=False, choices=SystemFingerprint.INFRASTRUCTURE_TYPE)

    mac_addresses = CustomJSONField(required=False)
    ip_addresses = CustomJSONField(required=False)

    cpu_count = IntegerField(required=False, min_value=0)

    architecture = CharField(required=False, max_length=64)

    # Network scan facts
    bios_uuid = CharField(required=False, max_length=36)
    subscription_manager_id = CharField(required=False, max_length=36)

    cpu_socket_count = IntegerField(required=False, min_value=0)
    cpu_core_count = FloatField(required=False, min_value=0)
    cpu_core_per_socket = IntegerField(required=False, min_value=0)

    system_creation_date = DateField(required=False)
    system_last_checkin_date = DateField(required=False)

    system_role = CharField(required=False, max_length=128)
    system_addons = JSONField(required=False)
    system_service_level_agreement = CharField(required=False, max_length=128)
    system_usage_type = CharField(required=False, max_length=128)

    insights_client_id = CharField(required=False, max_length=128)

    virtualized_type = CharField(required=False, max_length=64)

    # VCenter scan facts
    vm_state = CharField(required=False, max_length=24)
    vm_uuid = CharField(required=False, max_length=36)
    vm_dns_name = CharField(required=False, max_length=256)

    vm_host = CharField(required=False, max_length=128)
    vm_host_socket_count = IntegerField(required=False, min_value=0)
    vm_host_core_count = IntegerField(required=False, min_value=0)

    vm_cluster = CharField(required=False, max_length=128)
    vm_datacenter = CharField(required=False, max_length=128)

    products = ProductSerializer(many=True, allow_null=True, required=False)
    entitlements = EntitlementSerializer(many=True,
                                         allow_null=True,
                                         required=False)

    # Red Hat facts
    is_redhat = NullBooleanField(required=False)
    redhat_certs = CharField(required=False)
    # pylint: disable=invalid-name
    redhat_package_count = IntegerField(required=False, min_value=0)

    metadata = CustomJSONField(required=True)
    sources = CustomJSONField(required=True)
    etc_machine_id = CharField(required=False, max_length=48)

    class Meta:
        """Meta class for SystemFingerprintSerializer."""

        model = SystemFingerprint
        fields = '__all__'

    def create(self, validated_data):
        """Create a system fingerprint."""
        products_data = validated_data.pop('products', [])
        entitlements_data = validated_data.pop('entitlements', [])
        fingerprint = SystemFingerprint.objects.create(**validated_data)
        for product_data in products_data:
            Product.objects.create(fingerprint=fingerprint, **product_data)
        for entitlement_data in entitlements_data:
            Entitlement.objects.create(fingerprint=fingerprint,
                                       **entitlement_data)
        return fingerprint
Exemplo n.º 12
0
class SourceSerializer(NotEmptySerializer):
    """Serializer for the Source model."""

    name = CharField(required=True, max_length=64)
    source_type = ValidStringChoiceField(required=False,
                                         choices=Source.SOURCE_TYPE_CHOICES)
    port = IntegerField(required=False, min_value=0, allow_null=True)
    hosts = CustomJSONField(required=True)
    exclude_hosts = CustomJSONField(required=False)
    options = SourceOptionsSerializer(required=False, many=False)
    credentials = CredentialsField(many=True,
                                   queryset=Credential.objects.all())

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

        model = Source
        fields = '__all__'

    @classmethod
    def validate_opts(cls, options, source_type):
        """Raise an error if options are invalid for the source type.

        :param options: dictionary of source options
        :param source_type: string denoting source type
        """
        valid_net_options = ['use_paramiko']
        valid_vc_options = ['ssl_cert_verify', 'ssl_protocol', 'disable_ssl']
        valid_sat_options = ['ssl_cert_verify', 'ssl_protocol', 'disable_ssl']

        if source_type == Source.SATELLITE_SOURCE_TYPE:
            invalid_options = [
                opt for opt in options if opt not in valid_sat_options
            ]
            if invalid_options:
                error = {
                    'options': [
                        _(messages.SAT_INVALID_OPTIONS %
                          ', '.join(invalid_options))
                    ]
                }
                raise ValidationError(error)
            if options.get('ssl_cert_verify') is None:
                options['ssl_cert_verify'] = True

        elif source_type == Source.VCENTER_SOURCE_TYPE:
            invalid_options = [
                opt for opt in options if opt not in valid_vc_options
            ]
            if invalid_options:
                error = {
                    'options': [
                        _(messages.VC_INVALID_OPTIONS %
                          ', '.join(invalid_options))
                    ]
                }
                raise ValidationError(error)
            if options.get('ssl_cert_verify') is None:
                options['ssl_cert_verify'] = True

        elif source_type == Source.NETWORK_SOURCE_TYPE:
            invalid_options = [
                opt for opt in options if opt not in valid_net_options
            ]
            if invalid_options:
                error = {
                    'options': [
                        _(messages.NET_SSL_OPTIONS_NOT_ALLOWED %
                          ', '.join(invalid_options))
                    ]
                }
                raise ValidationError(error)

    # pylint: disable=too-many-branches,too-many-statements
    @transaction.atomic
    def create(self, validated_data):
        """Create a source."""
        name = validated_data.get('name')
        check_for_existing_name(Source.objects, name,
                                _(messages.SOURCE_NAME_ALREADY_EXISTS % name))

        if 'source_type' not in validated_data:
            error = {'source_type': [_(messages.SOURCE_TYPE_REQ)]}
            raise ValidationError(error)
        source_type = validated_data.get('source_type')
        credentials = validated_data.pop('credentials')
        hosts_list = validated_data.pop('hosts', None)
        exclude_hosts_list = validated_data.pop('exclude_hosts', None)
        port = None
        if 'port' in validated_data:
            port = validated_data['port']

        options = validated_data.pop('options', None)

        if source_type == Source.NETWORK_SOURCE_TYPE:
            if credentials:
                for cred in credentials:
                    SourceSerializer.check_credential_type(source_type, cred)
            if port is None:
                validated_data['port'] = 22

        elif source_type == Source.VCENTER_SOURCE_TYPE:
            if port is None:
                validated_data['port'] = 443
            if hosts_list and len(hosts_list) != 1:
                error = {'hosts': [_(messages.VC_ONE_HOST)]}
                raise ValidationError(error)
            if hosts_list and '[' in hosts_list[0]:
                error = {'hosts': [_(messages.VC_ONE_HOST)]}
                raise ValidationError(error)
            if exclude_hosts_list is not None:
                error = {
                    'exclude_hosts': [_(messages.VC_EXCLUDE_HOSTS_INCLUDED)]
                }
                raise ValidationError(error)
            if credentials and len(credentials) > 1:
                error = {'credentials': [_(messages.VC_ONE_CRED)]}
                raise ValidationError(error)
            if credentials and len(credentials) == 1:
                SourceSerializer.check_credential_type(source_type,
                                                       credentials[0])
        elif source_type == Source.SATELLITE_SOURCE_TYPE:
            if port is None:
                validated_data['port'] = 443
            if hosts_list and len(hosts_list) != 1:
                error = {'hosts': [_(messages.SAT_ONE_HOST)]}
                raise ValidationError(error)
            if hosts_list and '[' in hosts_list[0]:
                error = {'hosts': [_(messages.VC_ONE_HOST)]}
                raise ValidationError(error)
            if exclude_hosts_list is not None:
                error = {
                    'exclude_hosts': [_(messages.SAT_EXCLUDE_HOSTS_INCLUDED)]
                }
                raise ValidationError(error)
            if credentials and len(credentials) > 1:
                error = {'credentials': [_(messages.SAT_ONE_CRED)]}
                raise ValidationError(error)
            if credentials and len(credentials) == 1:
                SourceSerializer.check_credential_type(source_type,
                                                       credentials[0])

        source = Source.objects.create(**validated_data)

        if options:
            SourceSerializer.validate_opts(options, source_type)
            options = SourceOptions.objects.create(**options)
            options.save()
            source.options = options
        elif not options and source_type == Source.SATELLITE_SOURCE_TYPE:
            options = SourceOptions()
            options.ssl_cert_verify = True
            options.save()
            source.options = options
        elif not options and source_type == Source.VCENTER_SOURCE_TYPE:
            options = SourceOptions()
            options.ssl_cert_verify = True
            options.save()
            source.options = options

        source.hosts = json.dumps(hosts_list)
        if exclude_hosts_list:
            source.exclude_hosts = json.dumps(exclude_hosts_list)

        for credential in credentials:
            source.credentials.add(credential)

        source.save()
        return source

    @transaction.atomic
    def update(self, instance, validated_data):
        """Update a source."""
        # If we ever add optional fields to Source, we need to
        # add logic here to clear them on full update even if they are
        # not supplied.
        name = validated_data.get('name')
        check_for_existing_name(Source.objects,
                                name,
                                _(messages.SOURCE_NAME_ALREADY_EXISTS % name),
                                search_id=instance.id)

        if 'source_type' in validated_data:
            error = {'source_type': [_(messages.SOURCE_TYPE_INV)]}
            raise ValidationError(error)
        source_type = instance.source_type
        credentials = validated_data.pop('credentials', None)
        hosts_list = validated_data.pop('hosts', None)
        exclude_hosts_list = validated_data.pop('exclude_hosts', None)
        options = validated_data.pop('options', None)

        if source_type == Source.NETWORK_SOURCE_TYPE:
            if credentials:
                for cred in credentials:
                    SourceSerializer.check_credential_type(source_type, cred)
        elif source_type == Source.VCENTER_SOURCE_TYPE:
            if hosts_list and len(hosts_list) != 1:
                error = {'hosts': [_(messages.VC_ONE_HOST)]}
                raise ValidationError(error)
            if hosts_list and '[' in hosts_list[0]:
                error = {'hosts': [_(messages.VC_ONE_HOST)]}
                raise ValidationError(error)
            if exclude_hosts_list is not None:
                error = {
                    'exclude_hosts': [_(messages.VC_EXCLUDE_HOSTS_INCLUDED)]
                }
                raise ValidationError(error)
            if credentials and len(credentials) > 1:
                error = {'credentials': [_(messages.VC_ONE_CRED)]}
                raise ValidationError(error)
            if credentials and len(credentials) == 1:
                SourceSerializer.check_credential_type(source_type,
                                                       credentials[0])
        elif source_type == Source.SATELLITE_SOURCE_TYPE:
            if hosts_list and len(hosts_list) != 1:
                error = {'hosts': [_(messages.SAT_ONE_HOST)]}
                raise ValidationError(error)
            if hosts_list and '[' in hosts_list[0]:
                error = {'hosts': [_(messages.VC_ONE_HOST)]}
                raise ValidationError(error)
            if exclude_hosts_list is not None:
                error = {
                    'exclude_hosts': [_(messages.SAT_EXCLUDE_HOSTS_INCLUDED)]
                }
                raise ValidationError(error)
            if credentials and len(credentials) > 1:
                error = {'credentials': [_(messages.SAT_ONE_CRED)]}
                raise ValidationError(error)
            if credentials and len(credentials) == 1:
                SourceSerializer.check_credential_type(source_type,
                                                       credentials[0])

        for name, value in validated_data.items():
            setattr(instance, name, value)
        instance.save()

        # If hosts_list was not supplied and this is a full update,
        # then we should already have raised a ValidationError before
        # this point, so it's safe to use hosts_list as an indicator
        # of whether to replace the hosts.
        if hosts_list:
            instance.hosts = json.dumps(hosts_list)

        if exclude_hosts_list:
            instance.exclude_hosts = json.dumps(exclude_hosts_list)

        # credentials is safe to use as a flag for the same reason as
        # hosts_data above.
        if credentials:
            instance.credentials.set(credentials)

        if options:
            SourceSerializer.validate_opts(options, source_type)
            if instance.options is None:
                options = SourceOptions.objects.create(**options)
                options.save()
                instance.options = options
            else:
                self.update_options(options, instance.options)

        instance.save()
        return instance

    @staticmethod
    def update_options(options, instance_options):
        """Update the incoming options overlapping the existing options.

        :param options: the passed in options
        :param instance_options: the existing options
        """
        ssl_protocol = options.pop('ssl_protocol', None)
        ssl_cert_verify = options.pop('ssl_cert_verify', None)
        disable_ssl = options.pop('disable_ssl', None)
        use_paramiko = options.pop('use_paramiko', None)
        if ssl_protocol is not None:
            instance_options.ssl_protocol = ssl_protocol
        if ssl_cert_verify is not None:
            instance_options.ssl_cert_verify = ssl_cert_verify
        if disable_ssl is not None:
            instance_options.disable_ssl = disable_ssl
        if use_paramiko is not None:
            instance_options.use_paramiko = use_paramiko
        instance_options.save()

    @staticmethod
    def check_credential_type(source_type, credential):
        """Look for existing credential with same type as the source.

        :param source_type: The source type
        :param credential: The credential to obtain
        """
        if credential.cred_type != source_type:
            error = {'source_type': [_(messages.SOURCE_CRED_WRONG_TYPE)]}
            raise ValidationError(error)

    @staticmethod
    def validate_name(name):
        """Validate the name of the Source."""
        if not isinstance(name, str) or not name.isprintable():
            raise ValidationError(_(messages.SOURCE_NAME_VALIDATION))

        return name

    # pylint: disable=too-many-locals, too-many-branches, too-many-statements
    @staticmethod
    def validate_ipaddr_list(hosts):
        """Make sure the hosts list is present and has valid IP addresses."""
        ipaddr_list = json.loads(hosts)
        if isinstance(ipaddr_list, list):
            ipaddr_list = [item for item in ipaddr_list if item]

        if not isinstance(ipaddr_list, list):
            raise ValidationError(_(messages.SOURCE_HOST_MUST_BE_JSON_ARRAY))

        if not ipaddr_list:
            raise ValidationError(_(messages.SOURCE_HOSTS_CANNOT_BE_EMPTY))

        for host_value in ipaddr_list:
            if not isinstance(host_value, str):
                raise ValidationError(
                    _(messages.SOURCE_HOST_MUST_BE_JSON_ARRAY))

        # Regex for octet, CIDR bit range, and check
        # to see if it is like an IP/CIDR
        octet_regex = r'(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])'
        bit_range = r'(3[0-2]|[1-2][0-9]|[0-9])'
        relaxed_ip_pattern = r'[0-9]*\.[0-9]*\.[0-9\[\]:]*\.[0-9\[\]:]*'
        relaxed_cidr_pattern = r'[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\/[0-9]*'
        greedy_subset = r'[0-9]*'
        range_subset = r'[0-9]*-[0-9]*'
        relaxed_invalid_ip_range = [
            r'{0}\.{0}\.{0}\.{0}-{0}\.{0}\.{0}\.{0}'.format(greedy_subset),
            r'{0}\.{0}\.{0}\.{1}'.format(greedy_subset, range_subset),
            r'{0}\.{0}\.{1}\.{0}'.format(greedy_subset, range_subset),
            r'{0}\.{1}\.{0}\.{0}'.format(greedy_subset, range_subset),
            r'{1}\.{0}\.{0}\.{0}'.format(greedy_subset, range_subset),
            r'{1}\.{1}\.{0}\.{0}'.format(greedy_subset, range_subset),
            r'{1}\.{0}\.{1}\.{0}'.format(greedy_subset, range_subset),
            r'{1}\.{0}\.{0}\.{1}'.format(greedy_subset, range_subset),
            r'{1}\.{1}\.{0}\.{1}'.format(
                greedy_subset, range_subset), r'{1}\.{0}\.{1}\.{1}'.format(
                    greedy_subset,
                    range_subset), r'{0}\.{0}\.{0}\.{0}'.format(range_subset),
            r'{0}\.{1}\.{0}\.{1}'.format(greedy_subset, range_subset),
            r'{0}\.{1}\.{1}\.{0}'.format(greedy_subset, range_subset)
        ]

        # type IP:          192.168.0.1
        # type CIDR:        192.168.0.0/16
        # type RANGE 1:     192.168.0.[1:15]
        # type RANGE 2:     192.168.[2:18].1
        # type RANGE 3:     192.168.[2:18].[4:46]
        ip_regex_list = [
            r'^{0}\.{0}\.{0}\.{0}$'.format(octet_regex),
            r'^{0}\.{0}\.{0}\.{0}\/{1}$'.format(octet_regex, bit_range),
            r'^{0}\.{0}\.{0}\.\[{0}:{0}\]$'.format(octet_regex),
            r'^{0}\.{0}\.\[{0}:{0}\]\.{0}$'.format(octet_regex),
            r'^{0}\.{0}\.\[{0}:{0}\]\.\[{0}:{0}\]$'.format(octet_regex)
        ]

        # type HOST:                abcd
        # type HOST NUMERIC RANGE:  abcd[2:4].foo.com
        # type HOST ALPHA RANGE:    abcd[a:f].foo.com
        host_regex_list = [
            r'[a-zA-Z0-9-_\.]+',
            r'[a-zA-Z0-9-_\.]*\[[0-9]+:[0-9]+\]*[a-zA-Z0-9-_\.]*',
            r'[a-zA-Z0-9-_\.]*\[[a-zA-Z]{1}:[a-zA-Z]{1}\][a-zA-Z0-9-_\.]*'
        ]

        normalized_hosts = []
        host_errors = []
        for host_range in ipaddr_list:
            result = None
            ip_match = re.match(relaxed_ip_pattern, host_range)
            cidr_match = re.match(relaxed_cidr_pattern, host_range)
            invalid_ip_range_match = [
                re.match(invalid_ip_range, host_range)
                for invalid_ip_range in relaxed_invalid_ip_range
            ]
            is_likely_ip = ip_match and ip_match.end() == len(host_range)
            is_likely_cidr = cidr_match and cidr_match.end() == len(host_range)
            is_likely_invalid_ip_range = any(invalid_ip_range_match)

            if is_likely_invalid_ip_range:
                err_message = _(messages.NET_INVALID_RANGE_FORMAT %
                                (host_range, ))
                result = ValidationError(err_message)

            elif is_likely_ip or is_likely_cidr:
                # This is formatted like an IP or CIDR
                # (e.g. #.#.#.# or #.#.#.#/#)
                for reg in ip_regex_list:
                    match = re.match(reg, host_range)
                    if match and match.end() == len(host_range):
                        result = host_range
                        break

                if result is None or is_likely_cidr:
                    # Attempt to convert CIDR to ansible range
                    if is_likely_cidr:
                        try:
                            normalized_cidr = SourceSerializer \
                                .cidr_to_ansible(host_range)
                            result = normalized_cidr
                        except ValidationError as validate_error:
                            result = validate_error
                    else:
                        err_message = _(messages.NET_INVALID_RANGE_CIDR %
                                        (host_range, ))
                        result = ValidationError(err_message)
            else:
                # Possibly a host_range addr
                for reg in host_regex_list:
                    match = re.match(reg, host_range)
                    if match and match.end() == len(host_range):
                        result = host_range
                        break
                if result is None:
                    err_message = _(messages.NET_INVALID_HOST % (host_range, ))
                    result = ValidationError(err_message)

            if isinstance(result, ValidationError):
                host_errors.append(result)
            elif result is not None:
                normalized_hosts.append(result)
            else:
                # This is an unexpected case. Allow/log for analysis
                normalized_hosts.append(host_range)
                logging.warning('%s did not match a pattern or produce error',
                                host_range)
        if not host_errors:
            return normalized_hosts
        error_message = [error.detail.pop() for error in host_errors]
        raise ValidationError(error_message)

    @staticmethod
    def validate_hosts(hosts):
        """Validate hosts list."""
        return SourceSerializer.validate_ipaddr_list(hosts)

    @staticmethod
    def validate_exclude_hosts(exclude_hosts):
        """Validate exclude_hosts list."""
        return SourceSerializer.validate_ipaddr_list(exclude_hosts)

    # pylint: disable=too-many-locals
    @staticmethod
    def cidr_to_ansible(ip_range):
        """Convert an IP address range from CIDR to Ansible notation.

        :param ip_range: the IP range, as a string
        :returns: the IP range, as an Ansible-formatted string
        :raises NotCIDRException: if ip_range doesn't look similar to CIDR
            notation. If it does look like CIDR but isn't quite right, print
            out error messages and exit.
        """
        # In the case of an input error, we want to distinguish between
        # strings that are "CIDR-like", so the user probably intended to
        # use CIDR and we should give them a CIDR error message, and not
        # at all CIDR-like, in which case we tell the caller to parse it a
        # different way.
        cidr_like = r'[0-9\.]*/[0-9]+'
        if not re.match(cidr_like, ip_range):
            err_msg = _(messages.NET_NO_CIDR_MATCH %
                        (ip_range, str(cidr_like)))
            raise ValidationError(err_msg)

        try:
            base_address, prefix_bits = ip_range.split('/')
        except ValueError:
            err_msg = _(messages.NET_CIDR_INVALID % (ip_range, ))
            raise ValidationError(err_msg)

        prefix_bits = int(prefix_bits)

        if prefix_bits < 0 or prefix_bits > 32:
            err_msg = _(messages.NET_CIDR_BIT_MASK % {
                'ip_range': ip_range,
                'prefix_bits': prefix_bits
            })
            raise ValidationError(err_msg)

        octet_strings = base_address.split('.')
        if len(octet_strings) != 4:
            err_msg = _(messages.NET_FOUR_OCTETS % (ip_range, ))
            raise ValidationError(err_msg)

        octets = [None] * 4
        for i in range(4):
            if not octet_strings[i]:
                err_msg = _(messages.NET_EMPTY_OCTET % (ip_range, ))
                raise ValidationError(err_msg)

            val = int(octet_strings[i])
            if val < 0 or val > 255:
                # pylint: disable=too-many-locals
                err_msg = _(messages.NET_CIDR_RANGE % {
                    'ip_range': ip_range,
                    'octet': val
                })
                raise ValidationError(err_msg)
            octets[i] = val

        ansible_out = [None] * 4
        for i in range(4):
            # "prefix_bits" is the number of high-order bits we want to
            # keep for the whole CIDR range. "mask" is the number of
            # low-order bits we want to mask off. Here prefix_bits is for
            # the whole IP address, but mask_bits is just for this octet.

            if prefix_bits <= i * 8:
                ansible_out[i] = '[0:255]'
            elif prefix_bits >= (i + 1) * 8:
                ansible_out[i] = str(octets[i])
            else:
                # The number of bits of this octet that we want to
                # preserve
                this_octet_bits = prefix_bits - 8 * i
                assert 0 < this_octet_bits < 8
                # mask is this_octet_bits 1's followed by (8 -
                # this_octet_bits) 0's.
                mask = -1 << (8 - this_octet_bits)

                lower_bound = octets[i] & mask
                upper_bound = lower_bound + ~mask
                ansible_out[i] = '[{0}:{1}]'.format(lower_bound, upper_bound)

        return '.'.join(ansible_out)

    @staticmethod
    def validate_port(port):
        """Validate the port."""
        if not port:
            pass
        elif port < 0 or port > 65536:
            raise ValidationError(_(messages.NET_INVALID_PORT))

        return port

    @staticmethod
    def validate_credentials(credentials):
        """Make sure the credentials list is present."""
        if not credentials:
            raise ValidationError(_(messages.SOURCE_MIN_CREDS))

        return credentials
Exemplo n.º 13
0
class FingerprintSerializer(ModelSerializer):
    """Serializer for the Fingerprint model."""

    # Scan information
    fact_collection_id = PrimaryKeyRelatedField(
        queryset=FactCollection.objects.all())

    # Common facts
    name = CharField(required=False, max_length=256)

    os_name = CharField(required=False, max_length=64)
    os_release = CharField(required=False, max_length=128)
    os_version = CharField(required=False, max_length=64)

    infrastructure_type = ChoiceField(
        required=False, choices=SystemFingerprint.INFRASTRUCTURE_TYPE)
    virtualized_is_guest = NullBooleanField(default=None)

    mac_addresses = CustomJSONField(required=False)
    ip_addresses = CustomJSONField(required=False)

    cpu_count = IntegerField(required=False, min_value=0)

    # Network scan facts
    bios_uuid = CharField(required=False, max_length=36)
    subscription_manager_id = CharField(required=False, max_length=36)

    cpu_core_per_socket = IntegerField(required=False, min_value=0)
    cpu_siblings = IntegerField(required=False, min_value=0)
    cpu_hyperthreading = NullBooleanField(required=False)
    cpu_socket_count = IntegerField(required=False, min_value=0)
    cpu_core_count = IntegerField(required=False, min_value=0)

    system_creation_date = DateField(required=False)

    virtualized_type = CharField(required=False, max_length=64)
    virtualized_num_guests = IntegerField(required=False, min_value=0)
    virtualized_num_running_guests = IntegerField(required=False, min_value=0)

    # VCenter scan facts
    vm_state = CharField(required=False, max_length=24)
    vm_uuid = CharField(required=False, max_length=36)
    vm_memory_size = IntegerField(required=False, min_value=0)
    vm_dns_name = CharField(required=False, max_length=128)

    vm_host = CharField(required=False, max_length=128)
    vm_host_socket_count = IntegerField(required=False, min_value=0)
    vm_host_cpu_cores = IntegerField(required=False, min_value=0)

    vm_host_cpu_threads = IntegerField(required=False, min_value=0)

    vm_cluster = CharField(required=False, max_length=128)
    vm_datacenter = CharField(required=False, max_length=128)

    metadata = CustomJSONField(required=True)

    class Meta:
        """Meta class for FingerprintSerializer."""

        model = SystemFingerprint
        fields = '__all__'
Exemplo n.º 14
0
class FingerprintSerializer(ModelSerializer):
    """Serializer for the Fingerprint model."""

    # Scan information
    report_id = PrimaryKeyRelatedField(queryset=FactCollection.objects.all())

    # Common facts
    name = CharField(required=False, max_length=256)

    os_name = CharField(required=False, max_length=64)
    os_release = CharField(required=False, max_length=128)
    os_version = CharField(required=False, max_length=64)

    infrastructure_type = ChoiceField(
        required=False, choices=SystemFingerprint.INFRASTRUCTURE_TYPE)

    mac_addresses = CustomJSONField(required=False)
    ip_addresses = CustomJSONField(required=False)

    cpu_count = IntegerField(required=False, min_value=0)

    architecture = CharField(required=False, max_length=64)

    # Network scan facts
    bios_uuid = CharField(required=False, max_length=36)
    subscription_manager_id = CharField(required=False, max_length=36)

    cpu_socket_count = IntegerField(required=False, min_value=0)
    cpu_core_count = IntegerField(required=False, min_value=0)

    system_creation_date = DateField(required=False)

    virtualized_type = CharField(required=False, max_length=64)

    # VCenter scan facts
    vm_state = CharField(required=False, max_length=24)
    vm_uuid = CharField(required=False, max_length=36)
    vm_dns_name = CharField(required=False, max_length=128)

    vm_host = CharField(required=False, max_length=128)
    vm_host_socket_count = IntegerField(required=False, min_value=0)

    vm_cluster = CharField(required=False, max_length=128)
    vm_datacenter = CharField(required=False, max_length=128)

    products = ProductSerializer(many=True, allow_null=True, required=False)
    entitlements = EntitlementSerializer(many=True,
                                         allow_null=True,
                                         required=False)

    # Red Hat facts
    is_redhat = NullBooleanField(required=False)
    redhat_certs = CharField(required=False, max_length=128)
    # pylint: disable=invalid-name
    redhat_package_count = IntegerField(required=False, min_value=0)

    metadata = CustomJSONField(required=True)
    sources = CustomJSONField(required=True)

    class Meta:
        """Meta class for FingerprintSerializer."""

        model = SystemFingerprint
        fields = '__all__'

    def create(self, validated_data):
        """Create a system fingerprint."""
        products_data = validated_data.pop('products', [])
        entitlements_data = validated_data.pop('entitlements', [])
        fingerprint = SystemFingerprint.objects.create(**validated_data)
        for product_data in products_data:
            Product.objects.create(fingerprint=fingerprint, **product_data)
        for entitlement_data in entitlements_data:
            Entitlement.objects.create(fingerprint=fingerprint,
                                       **entitlement_data)
        return fingerprint
Exemplo n.º 15
0
class SystemFingerprintSerializer(ModelSerializer):
    """Serializer for the Fingerprint model."""

    # Common facts
    name = CharField(max_length=256, **default_args)

    os_name = CharField(max_length=64, **default_args)
    os_release = CharField(max_length=128, **default_args)
    os_version = CharField(max_length=64, **default_args)

    infrastructure_type = ChoiceField(
        required=False, choices=SystemFingerprint.INFRASTRUCTURE_TYPE)

    cloud_provider = CharField(max_length=16, **default_args)

    mac_addresses = CustomJSONField(**default_args)
    ip_addresses = CustomJSONField(**default_args)

    cpu_count = IntegerField(min_value=0, **default_args)

    architecture = CharField(max_length=64, **default_args)

    # Network scan facts
    bios_uuid = CharField(max_length=36, **default_args)
    subscription_manager_id = CharField(max_length=36, **default_args)

    cpu_socket_count = IntegerField(min_value=0, **default_args)
    cpu_core_count = FloatField(min_value=0, **default_args)
    cpu_core_per_socket = IntegerField(min_value=0, **default_args)
    cpu_hyperthreading = BooleanField(**default_args)

    system_creation_date = DateField(**default_args)
    system_last_checkin_date = DateField(**default_args)

    system_purpose = JSONField(**default_args)
    system_role = CharField(max_length=128, **default_args)
    system_addons = JSONField(**default_args)
    system_service_level_agreement = CharField(max_length=128, **default_args)
    system_usage_type = CharField(max_length=128, **default_args)

    insights_client_id = CharField(max_length=128, **default_args)

    virtualized_type = CharField(max_length=64, **default_args)
    system_user_count = IntegerField(min_value=0, **default_args)
    user_login_history = CustomJSONField(**default_args)

    # VCenter scan facts
    vm_state = CharField(max_length=24, **default_args)
    vm_uuid = CharField(max_length=36, **default_args)
    vm_dns_name = CharField(max_length=256, **default_args)

    virtual_host_name = CharField(max_length=128, **default_args)
    virtual_host_uuid = CharField(max_length=36, **default_args)
    vm_host_socket_count = IntegerField(min_value=0, **default_args)
    vm_host_core_count = IntegerField(min_value=0, **default_args)

    vm_cluster = CharField(max_length=128, **default_args)
    vm_datacenter = CharField(max_length=128, **default_args)

    products = ProductSerializer(many=True, **default_args)
    entitlements = EntitlementSerializer(many=True, **default_args)

    # Red Hat facts
    is_redhat = BooleanField(**default_args)
    redhat_certs = CharField(**default_args)
    # pylint: disable=invalid-name
    redhat_package_count = IntegerField(min_value=0, **default_args)

    metadata = CustomJSONField(required=True)
    sources = CustomJSONField(required=True)
    etc_machine_id = CharField(max_length=48, **default_args)

    class Meta:
        """Meta class for SystemFingerprintSerializer."""

        model = SystemFingerprint
        fields = '__all__'

    def create(self, validated_data):
        """Create a system fingerprint."""
        products_data = validated_data.pop('products', [])
        entitlements_data = validated_data.pop('entitlements', [])
        fingerprint = SystemFingerprint.objects.create(**validated_data)
        for product_data in products_data:
            Product.objects.create(fingerprint=fingerprint,
                                   **product_data)
        for entitlement_data in entitlements_data:
            Entitlement.objects.create(fingerprint=fingerprint,
                                       **entitlement_data)
        return fingerprint