carbonblack / cbapi-python

Carbon Black API - Python language bindings
Other
147 stars 86 forks source link

[BUG] PSC Live Response API -- Cannot submit job -- Unauthorized #271

Closed liteman closed 4 years ago

liteman commented 4 years ago

I am seeing this behaviour on: (please complete the following information):

Describe the bug Attempting to use CbPSCBaseAPI.live_response which requires Live Response API key/access level

The CbPSCBaseAPI.live_response.submit_job function attempts to enumerate devices with URL https://defense-prod05.conferdeploy.net/appservices/v6/orgs/org_key/devices/_search <--- Which requires custom_access API key.

lr.live_response.submit_job(myjob, sensor.id) results in:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Python38\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "c:\dev\carbon_black\cbapi-python\src\cbapi\psc\cblr.py", line 183, in run
    self._schedule_jobs()
  File "c:\dev\carbon_black\cbapi-python\src\cbapi\psc\cblr.py", line 194, in _schedule_jobs
    self._spawn_new_workers()
  File "c:\dev\carbon_black\cbapi-python\src\cbapi\psc\cblr.py", line 243, in _spawn_new_workers
    sensors = [s for s in self._cb.select(Device) if s.deviceId in self._unscheduled_jobs
  File "c:\dev\carbon_black\cbapi-python\src\cbapi\psc\cblr.py", line 243, in <listcomp>
    sensors = [s for s in self._cb.select(Device) if s.deviceId in self._unscheduled_jobs
  File "c:\dev\carbon_black\cbapi-python\src\cbapi\psc\devices_query.py", line 244, in _perform_query
    resp = self._cb.post_object(url, body=request)
  File "c:\dev\carbon_black\cbapi-python\src\cbapi\connection.py", line 506, in post_object
    return self.api_json_request("POST", uri, data=body, **kwargs)
  File "c:\dev\carbon_black\cbapi-python\src\cbapi\connection.py", line 482, in api_json_request
    result = self.session.http_request(method, uri, headers=headers, data=raw_data, **kwargs)
  File "c:\dev\carbon_black\cbapi-python\src\cbapi\connection.py", line 284, in http_request
    raise ClientError(error_code=r.status_code, message=r.text)
cbapi.errors.ClientError: Received error code 403 from API: {"success":false,"message":"Forbidden"}

Expected behavior The Live Response API wrapper (with the appropriate API key) to successfully submit a job

avanbrunt-cb commented 4 years ago

@liteman What version of CBAPI are you using?

https://github.com/carbonblack/cbapi-python/blob/master/src/cbapi/psc/cblr.py#L232 I believe we fixed this mistake when we added device v6 so that the live response job runner will use integrationServices/v3/device which the LIVE RESPONSE type api key has permission

liteman commented 4 years ago

Pulled source recently

My post above was after some modification to the source (of my own). But reverting back to this commit:

commit fe3f9ea9113786506a5ad63acc53611cfdf5e98d (tag: 1.7.2, origin/master, origin/HEAD)
Merge: 728c1a9 41acded
Author: Amy Bowersox <53279811+abowersox-cb@users.noreply.github.com>
Date:   Tue Aug 18 11:05:40 2020 -0600

    Merge pull request #269 from carbonblack/release-1.7.2

    Release 1.7.2

Using this code:

from cbapi.psc import CbPSCBaseAPI
lr = CbPSCBaseAPI(profile="live_response")  #Using LiveResponse API Key
sensor_query = list(lr.select(Device))

I get this error ( print(uri) added to connection.py ):

https://defense-prod05.conferdeploy.net/appservices/v6/orgs/<redacted>/devices/_search
Traceback (most recent call last):
  File "C:/dev/carbon_black/jobs_poc.py", line 52, in <module>
    sensor_query = list(lr.select(Device))
  File "c:\dev\carbon_black\cbapi-python\src\cbapi\psc\base_query.py", line 265, in __len__
    return self._count()
  File "c:\dev\carbon_black\cbapi-python\src\cbapi\psc\devices_query.py", line 223, in _count
    resp = self._cb.post_object(url, body=request)
  File "c:\dev\carbon_black\cbapi-python\src\cbapi\connection.py", line 506, in post_object
    return self.api_json_request("POST", uri, data=body, **kwargs)
  File "c:\dev\carbon_black\cbapi-python\src\cbapi\connection.py", line 482, in api_json_request
    result = self.session.http_request(method, uri, headers=headers, data=raw_data, **kwargs)
  File "c:\dev\carbon_black\cbapi-python\src\cbapi\connection.py", line 284, in http_request
    raise ClientError(error_code=r.status_code, message=r.text)
cbapi.errors.ClientError: Received error code 403 from API: {"success":false,"message":"Forbidden"}

Process finished with exit code 1
avanbrunt-cb commented 4 years ago

@liteman Make sure to import Device from from cbapi.psc.defense.models import Device as this uses integrationServices/v3/device which supports the LIVE RESPONSE type api key.

If you want to use the device v6 API for fetching the device id then you will need a second key and API object. Make sure to use the corresponding API object based on the requests you are going to be making.

from cbapi.psc import CbPSCBaseAPI
lr = CbPSCBaseAPI(profile="live_response")  #Using LiveResponse API Key
custom = CbPSCBaseAPI(profile="custom")  #Using Custom API Key

Note we understand this complication and are working with our backend teams to eventually eliminate the need for two API keys

liteman commented 4 years ago

Update -- with regards to https://github.com/carbonblack/cbapi-python/blob/master/src/cbapi/psc/cblr.py#L232

I just changed the Device import in my code from

from cbapi.psc.models import Device

to

from cbapi.psc.defense.models import Device

Result:

Traceback (most recent call last):
  File "C:/dev/carbon_black/jobs_poc.py", line 53, in <module>
    sensor_query = list(lr.select(Device))
  File "c:\dev\carbon_black\cbapi-python\src\cbapi\connection.py", line 550, in select
    return self._perform_query(cls, **kwargs)
  File "c:\dev\carbon_black\cbapi-python\src\cbapi\psc\rest_api.py", line 28, in _perform_query
    raise ApiError("All PSC models should provide _query_implementation")
cbapi.errors.ApiError: All PSC models should provide _query_implementation
liteman commented 4 years ago

@liteman Make sure to import Device from from cbapi.psc.defense.models import Device as this uses integrationServices/v3/device which supports the LIVE RESPONSE type api key.

If you want to use the device v6 API for fetching the device id then you will need a second key and API object. Make sure to use the corresponding API object based on the requests you are going to be making.

from cbapi.psc import CbPSCBaseAPI
lr = CbPSCBaseAPI(profile="live_response")  #Using LiveResponse API Key
custom = CbPSCBaseAPI(profile="custom")  #Using Custom API Key

Note we understand this complication and are working with our backend teams to eventually eliminate the need for two API keys

I did work out something like this, but ultimately ran in to the issue when trying to submit_job. I can start a session and interact with a session, but can't take advantage of the Jobs API.

avanbrunt-cb commented 4 years ago

@liteman Thanks for letting me know this didn't work. You would instead need to use CbDefenseAPI which inherits CbPSCBaseAPI so you should still be able to use the live response functions

liteman commented 4 years ago

@liteman Thanks for letting me know this didn't work. You would instead need to use CbDefenseAPI which inherits CbPSCBaseAPI so you should still be able to use the live response functions

Ahhhhh - that seems to be the magic sauce. CbDefenseAPI with Live Response API key (seems to be read from credentials.psc).

from cbapi.psc.defense.models import Device
from cbapi.psc.defense import CbDefenseAPI
lr = CbDefenseAPI(profile="live_response")
sensor_query = list(lr.select(Device))

Thank you

avanbrunt-cb commented 4 years ago

Awesome! I'll take a note of this and make sure we have documentation for this with a future release