VirusTotal / vt-py

The official Python 3 client library for VirusTotal
https://virustotal.github.io/vt-py/
Apache License 2.0
531 stars 121 forks source link

Problem with client.py using 'client.get_object_async/get_object' with hunting_rulesets #153

Closed jxb5151 closed 1 year ago

jxb5151 commented 1 year ago

Greetings!

When attempting to get a client object using these methods I receive the following error back:

...
    result = await client.get_object_async(url)
  File "/home/testing/.local/lib/python3.10/site-packages/vt/client.py", line 539, in get_object_async
    return await self._response_to_object(response)
  File "/home/testing/.local/lib/python3.10/site-packages/vt/client.py", line 278, in _response_to_object
    raise ValueError(f'response is not an object: {err}') from err
ValueError: response is not an object: Expecting dictionary, got: list

While taking a closer look at the client.py file, it seems to be induced from the code here: https://github.com/VirusTotal/vt-py/blob/023c2e1b8609be997571ff8f83942e3821615bc0/vt/client.py#L265C5-L265C5

Was able to reproduce with the following:

>>>
import vt
client = vt.Client("...")
client.get_object("/intelligence/hunting_rulesets")

I am trying to put together some code that will sync differences between a YARA rule file and the current LiveHunt ruleset, any suggestions on a workaround and or solution here is greatly appreciated!

Thanks, Jason

plusvic commented 1 year ago

The "/intelligence/hunting_rulesets" endpoint doesn't return a single object, it returns multiple objects, therefore you must use an iterator. See: https://virustotal.github.io/vt-py/api/iterator.html

The get_object method is expected to be used with endpoints that return a single object. This may be useful for understanding the difference between an object and a collection: https://developers.virustotal.com/reference/key-concepts

jxb5151 commented 1 year ago

Thank you @plusvic ! Indeed, an iterator is exactly what I needed. Very quick and dirty example in case anyone else stumbles across this with the same issue (ensure a previously uploaded set of rulesets is enabled).

...
results = client.iterator(url)
async for rObj in results:
    rObj.enabled = True
    await client.patch_object_async(path=f'/intelligence/hunting_rulesets/{rObj.id}', obj=rObj)