vgrem / Office365-REST-Python-Client

Microsoft 365 & Microsoft Graph Library for Python
MIT License
1.31k stars 333 forks source link

Bug Loading Security Incidents from Microsoft Defender API using GraphClient #898

Open matt-davis27 opened 1 week ago

matt-davis27 commented 1 week ago

I'm trying to use the code below to load the GET /security/incidents endpoint following the Microsoft Documentation. However, I'm facing a TypeError when I try to run the security.get_all() function.

Code to reproduce:

from office365.graph_client import GraphClient

client = GraphClient.with_client_secret(tenant id, client id, client secret)
result = client.security.incidents.get_all().execute_query()

Full error:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[4], line 1
----> 1 result = client.security.incidents.get_all().execute_query()
      2 print(result)

File ~/Library/Python/3.12/lib/python/site-packages/office365/runtime/client_object.py:55, in ClientObject.execute_query(self)
     52 def execute_query(self):
     53     # type: () -> Self
     54     """Submit request(s) to the server."""
---> 55     self.context.execute_query()
     56     return self

File ~/Library/Python/3.12/lib/python/site-packages/office365/runtime/client_runtime_context.py:173, in ClientRuntimeContext.execute_query(self)
    171 while self.has_pending_request:
    172     qry = self._get_next_query()
--> 173     self.pending_request().execute_query(qry)
    174 return self

File ~/Library/Python/3.12/lib/python/site-packages/office365/runtime/client_request.py:38, in ClientRequest.execute_query(self, query)
     36     request = self.build_request(query)
     37     response = self.execute_request_direct(request)
---> 38     self.process_response(response, query)
     39     self.afterExecute.notify(response)
     40 except HTTPError as e:

File ~/Library/Python/3.12/lib/python/site-packages/office365/runtime/odata/request.py:70, in ODataRequest.process_response(self, response, query)
     67     if isinstance(query, (ServiceOperationQuery, FunctionQuery)):
     68         json_format.function = query.name
---> 70 self.map_json(response.json(), return_type, json_format)

File ~/Library/Python/3.12/lib/python/site-packages/office365/runtime/odata/request.py:79, in ODataRequest.map_json(self, json, return_type, json_format)
     77 if json and return_type is not None:
     78     for k, v in self._next_property(json, json_format):
---> 79         return_type.set_property(k, v, False)

File ~/Library/Python/3.12/lib/python/site-packages/office365/runtime/client_object_collection.py:64, in ClientObjectCollection.set_property(self, key, value, persist_changes)
     61     client_object = self.create_typed_object()
     62     self.add_child(client_object)
     63     [
---> 64         client_object.set_property(k, v, persist_changes)
     65         for k, v in value.items()
     66     ]
     67 return self

File ~/Library/Python/3.12/lib/python/site-packages/office365/entity.py:63, in Entity.set_property(self, name, value, persist_changes)
     61 def set_property(self, name, value, persist_changes=True):
     62     # type: (str, T, bool) -> Self
---> 63     super(Entity, self).set_property(name, value, persist_changes)
     64     if name == self.property_ref_name:
     65         if self._resource_path is None:

File ~/Library/Python/3.12/lib/python/site-packages/office365/runtime/client_object.py:160, in ClientObject.set_property(self, name, value, persist_changes)
    157 if persist_changes:
    158     self._ser_property_names.append(name)
--> 160 typed_value = self.get_property(name)
    161 if isinstance(typed_value, (ClientObject, ClientValue)):
    162     if isinstance(value, list):

File ~/Library/Python/3.12/lib/python/site-packages/office365/directory/security/incidents/incident.py:62, in Incident.get_property(self, name, default_value)
     60 def get_property(self, name, default_value=None):
     61     if default_value is None:
---> 62         property_mapping = {"createdDateTime": self.created_datetime}
     63         default_value = property_mapping.get(name, None)
     64     return super(Incident, self).get_property(name, default_value)

File ~/Library/Python/3.12/lib/python/site-packages/office365/directory/security/incidents/incident.py:47, in Incident.created_datetime(self)
     44 @property
     45 def created_datetime(self):
     46     """Time when the incident was first created."""
---> 47     return self.properties("createdDateTime", datetime.min)

TypeError: 'dict' object is not callable

System information: Python 3.12.5 Office365-REST-Python-Client 2.5.13

matt-davis27 commented 1 week ago

Not sure if it's relevant or not, but I was able to load GET /security/alerts_v2 just fine without the same error:

from office365.graph_client import GraphClient

client = GraphClient.with_client_secret(tenant id, client id, client secret)
result = client.security.alerts_v2.get_all(page_size=10).execute_query()
print(result)