Exemplo n.º 1
0
def health():
    key = get_key()

    if key is None:
        raise AuthenticationRequiredError

    url = current_app.config['AVOTX_URL']
    headers = {'User-Agent': current_app.config['CTR_USER_AGENT']}

    client = Client(key, url, headers=headers)
    _ = client.query('/api/v1/user/me')

    return jsonify_data({'status': 'ok'})
    def observe(self, client: Client, limit: Optional[int] = None) -> Bundle:
        """Build a CTIM bundle for the current observable."""

        bundle = Bundle()

        # Implement a workaround instead of using the "/api/v1/search/pulses"
        # endpoint as it works too slow and is not really optimizable...

        category = {
            'ip': 'IPv4',
            'ipv6': 'IPv6',
        }.get(
            self.type(),
            self.category(),
        )

        endpoint = (f'/api/v1/indicators/{category}/'
                    f"{quote(self.value, safe='@:')}/general")

        data = client.query(endpoint)
        if data is None:
            return bundle

        # Make sure to filter out redundant pulses that do not match anyway.
        pulses = [
            pulse for pulse in data['pulse_info']['pulses']
            if data['base_indicator']['type'] in pulse['indicator_type_counts']
        ]
        if not pulses:
            return bundle

        def indicator_for(pulse, page=1):
            # This limit provides a decent tradeoff between the number of
            # requests to be made and the size of each response coming back.
            limit = 10000

            endpoint = f"/api/v1/pulses/{pulse['id']}/indicators"
            params = {'sort': '-created', 'limit': limit, 'page': page}

            data = client.query(endpoint, params=params)

            for indicator in data['results']:
                if indicator['indicator'] == self.value:
                    return indicator

            if data['next'] is None:
                return None

            return indicator_for(pulse, page=(page + 1))

        with ThreadPoolExecutor(max_workers=get_workers(pulses)) as executor:
            iterator = executor.map(indicator_for, pulses)

        indicators = []

        while True:
            try:
                indicator = next(iterator)
            except RelayError:
                continue
            except StopIteration:
                break
            else:
                if indicator is None:
                    continue
                indicators.append(indicator)

        indicators.sort(key=itemgetter('created'), reverse=True)

        if limit is None:
            limit = len(indicators)

        indicators = indicators[:limit]

        observable = self.json()

        for indicator in indicators:
            pulse = next(pulse for pulse in pulses
                         if pulse['id'] == indicator['pulse_key'])

            # Enrich each AVOTX pulse with some additional context in order to
            # simplify further mapping of that pulse into CTIM entities.
            pulse['indicator'] = indicator
            pulse['observable'] = observable
            pulse['url'] = client.url

            sighting = Sighting.map(pulse)
            indicator = Indicator.map(pulse)
            relationship = Relationship.map(sighting, indicator)

            bundle.add(sighting)
            bundle.add(indicator)
            bundle.add(relationship)

        return bundle