Example #1
0
 def service_list(self, workspace_name, host_id):
     """
     ---
     get:
       tags: ["Host", "Service"]
       summary: Get the services of a host
       responses:
         200:
           description: Ok
           content:
             application/json:
               schema: ServiceSchema
     tags: ["Host", "Service"]
     responses:
       200:
         description: Ok
     """
     services = self._get_object(host_id, workspace_name).services
     return ServiceSchema(many=True).dump(services)
Example #2
0
class VulnerabilitySchema(AutoSchema):
    _id = fields.Integer(dump_only=True, attribute='id')

    _rev = fields.String(dump_only=True, default='')
    _attachments = fields.Method(serialize='get_attachments',
                                 deserialize='load_attachments',
                                 default=[])
    owned = fields.Boolean(dump_only=True, default=False)
    owner = PrimaryKeyRelatedField('username',
                                   dump_only=True,
                                   attribute='creator')
    impact = SelfNestedField(ImpactSchema())
    desc = fields.String(attribute='description')
    description = fields.String(dump_only=True)
    policyviolations = fields.List(fields.String,
                                   attribute='policy_violations')
    refs = fields.List(fields.String(), attribute='references')
    issuetracker = fields.Method(serialize='get_issuetracker', dump_only=True)
    parent = fields.Method(serialize='get_parent',
                           deserialize='load_parent',
                           required=True)
    parent_type = MutableField(fields.Method('get_parent_type'),
                               fields.String(),
                               required=True)
    tags = PrimaryKeyRelatedField('name', dump_only=True, many=True)
    easeofresolution = fields.String(attribute='ease_of_resolution',
                                     validate=OneOf(
                                         Vulnerability.EASE_OF_RESOLUTIONS),
                                     allow_none=True)
    hostnames = PrimaryKeyRelatedField('name', many=True, dump_only=True)
    service = fields.Nested(ServiceSchema(only=[
        '_id', 'ports', 'status', 'protocol', 'name', 'version', 'summary'
    ]),
                            dump_only=True)
    host = fields.Integer(dump_only=True, attribute='host_id')
    severity = SeverityField(required=True)
    status = fields.Method(serialize='get_status',
                           validate=OneOf(Vulnerability.STATUSES + ['opened']),
                           deserialize='load_status')
    type = fields.Method(serialize='get_type',
                         deserialize='load_type',
                         required=True)
    obj_id = fields.String(dump_only=True, attribute='id')
    target = fields.String(dump_only=True, attribute='target_host_ip')
    host_os = fields.String(dump_only=True, attribute='target_host_os')
    metadata = SelfNestedField(CustomMetadataSchema())
    date = fields.DateTime(attribute='create_date',
                           dump_only=True)  # This is only used for sorting
    custom_fields = FaradayCustomField(table_name='vulnerability',
                                       attribute='custom_fields')
    external_id = fields.String(allow_none=True)

    class Meta:
        model = Vulnerability
        fields = ('_id', 'status', 'issuetracker', 'description', 'parent',
                  'parent_type', 'tags', 'severity', '_rev',
                  'easeofresolution', 'owned', 'hostnames', 'owner', 'date',
                  'data', 'refs', 'desc', 'impact', 'confirmed', 'name',
                  'service', 'obj_id', 'type', 'policyviolations',
                  '_attachments', 'target', 'host_os', 'resolution',
                  'metadata', 'custom_fields', 'external_id')

    def get_type(self, obj):
        return obj.__class__.__name__

    def get_attachments(self, obj):
        res = {}

        for file_obj in obj.evidence:
            try:
                ret, errors = EvidenceSchema().dump(file_obj)
                if errors:
                    raise ValidationError(errors, data=ret)
                res[file_obj.filename] = ret
            except IOError:
                logger.warning("File not found. Did you move your server?")

        return res

    def load_attachments(self, value):
        return value

    def get_parent(self, obj):
        return obj.service_id or obj.host_id

    def get_parent_type(self, obj):
        assert obj.service_id is not None or obj.host_id is not None
        return 'Service' if obj.service_id is not None else 'Host'

    def get_status(self, obj):
        if obj.status == 'open':
            return 'opened'
        return obj.status

    def get_issuetracker(self, obj):
        return {}

    def load_status(self, value):
        if value == 'opened':
            return 'open'
        return value

    def load_type(self, value):
        if value == 'Vulnerability':
            return 'vulnerability'
        if value == 'VulnerabilityWeb':
            return 'vulnerability_web'
        else:
            raise ValidationError('Invalid vulnerability type.')

    def load_parent(self, value):
        try:
            # sometimes api requests send str or unicode.
            value = int(value)
        except ValueError:

            raise ValidationError("Invalid parent type")
        return value

    @post_load
    def post_load_impact(self, data):
        # Unflatten impact (move data[impact][*] to data[*])
        impact = data.pop('impact', None)
        if impact:
            data.update(impact)
        return data

    @post_load
    def post_load_parent(self, data):
        # schema guarantees that parent_type exists.
        parent_class = None
        parent_type = data.pop('parent_type', None)
        parent_id = data.pop('parent', None)
        if not (parent_type and parent_id):
            # Probably a partial load, since they are required
            return
        if parent_type == 'Host':
            parent_class = Host
            parent_field = 'host_id'
        if parent_type == 'Service':
            parent_class = Service
            parent_field = 'service_id'
        if not parent_class:
            raise ValidationError('Unknown parent type')
        if parent_type == 'Host' and data['type'] == 'vulnerability_web':
            raise ValidationError(
                'Trying to set a host for a vulnerability web')

        try:
            parent = db.session.query(parent_class).join(Workspace).filter(
                Workspace.name == self.context['workspace_name'],
                parent_class.id == parent_id).one()
        except NoResultFound:
            raise ValidationError('Parent id not found: {}'.format(parent_id))
        data[parent_field] = parent.id
        # TODO migration: check what happens when updating the parent from
        # service to host or viceverse
        return data
Example #3
0
 def service_list(self, workspace_name, host_id):
     services = self._get_object(host_id, workspace_name).services
     return ServiceSchema(many=True).dump(services)