Skip to content

Commit eef0a6d

Browse files
author
Juliya Smith
committed
Merge branch 'master' into add-results-param-to-get-all
2 parents b1998cb + 7b67339 commit eef0a6d

3 files changed

Lines changed: 87 additions & 47 deletions

File tree

Packs/Code42/Integrations/Code42/Code42.py

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -162,25 +162,34 @@ class Code42Client(BaseClient):
162162

163163
def __init__(self, sdk, base_url, auth, verify=True, proxy=False):
164164
super().__init__(base_url, verify=verify, proxy=proxy)
165-
# Create the Code42 SDK instance
166-
self._sdk = sdk or py42.sdk.from_local_account(base_url, auth[0], auth[1])
165+
# Allow sdk parameter for unit testing.
166+
# Otherwise, lazily load the SDK so that the TEST Command can effectively check auth.
167+
self._sdk = sdk
168+
self._sdk_factory = lambda: py42.sdk.from_local_account(base_url, auth[0], auth[1]) if not self._sdk else None
167169
py42.settings.set_user_agent_suffix("Cortex XSOAR")
168170

171+
def _get_sdk(self):
172+
if self._sdk is None:
173+
self._sdk = self._sdk_factory()
174+
return self._sdk
175+
169176
def add_user_to_departing_employee(self, username, departure_date=None, note=None):
170177
user_id = self.get_user_id(username)
171-
self._sdk.detectionlists.departing_employee.add(user_id, departure_date=departure_date)
178+
self._get_sdk().detectionlists.departing_employee.add(
179+
user_id, departure_date=departure_date
180+
)
172181
if note:
173-
self._sdk.detectionlists.update_user_notes(user_id, note)
182+
self._get_sdk().detectionlists.update_user_notes(user_id, note)
174183
return user_id
175184

176185
def remove_user_from_departing_employee(self, username):
177186
user_id = self.get_user_id(username)
178-
self._sdk.detectionlists.departing_employee.remove(user_id)
187+
self._get_sdk().detectionlists.departing_employee.remove(user_id)
179188
return user_id
180189

181190
def get_all_departing_employees(self, results):
182191
res = []
183-
pages = self._sdk.detectionlists.departing_employee.get_all()
192+
pages = self._get_sdk().detectionlists.departing_employee.get_all()
184193
for page in pages:
185194
employees = page["items"]
186195
for employee in employees:
@@ -191,32 +200,32 @@ def get_all_departing_employees(self, results):
191200

192201
def add_user_to_high_risk_employee(self, username, note=None):
193202
user_id = self.get_user_id(username)
194-
self._sdk.detectionlists.high_risk_employee.add(user_id)
203+
self._get_sdk().detectionlists.high_risk_employee.add(user_id)
195204
if note:
196-
self._sdk.detectionlists.update_user_notes(user_id, note)
205+
self._get_sdk().detectionlists.update_user_notes(user_id, note)
197206
return user_id
198207

199208
def remove_user_from_high_risk_employee(self, username):
200209
user_id = self.get_user_id(username)
201-
self._sdk.detectionlists.high_risk_employee.remove(user_id)
210+
self._get_sdk().detectionlists.high_risk_employee.remove(user_id)
202211
return user_id
203212

204213
def add_user_risk_tags(self, username, risk_tags):
205214
risk_tags = _try_convert_str_list_to_list(risk_tags)
206215
user_id = self.get_user_id(username)
207-
self._sdk.detectionlists.add_user_risk_tags(user_id, risk_tags)
216+
self._get_sdk().detectionlists.add_user_risk_tags(user_id, risk_tags)
208217
return user_id
209218

210219
def remove_user_risk_tags(self, username, risk_tags):
211220
risk_tags = _try_convert_str_list_to_list(risk_tags)
212221
user_id = self.get_user_id(username)
213-
self._sdk.detectionlists.remove_user_risk_tags(user_id, risk_tags)
222+
self._get_sdk().detectionlists.remove_user_risk_tags(user_id, risk_tags)
214223
return user_id
215224

216225
def get_all_high_risk_employees(self, risk_tags, results):
217226
risk_tags = _try_convert_str_list_to_list(risk_tags)
218227
res = []
219-
pages = self._sdk.detectionlists.high_risk_employee.get_all()
228+
pages = self._get_sdk().detectionlists.high_risk_employee.get_all()
220229
for page in pages:
221230
employees = _get_all_high_risk_employees_from_page(page, risk_tags)
222231
for employee in employees:
@@ -227,31 +236,31 @@ def get_all_high_risk_employees(self, risk_tags, results):
227236

228237
def fetch_alerts(self, start_time, event_severity_filter):
229238
query = _create_alert_query(event_severity_filter, start_time)
230-
res = self._sdk.alerts.search(query)
239+
res = self._get_sdk().alerts.search(query)
231240
return res["alerts"]
232241

233242
def get_alert_details(self, alert_id):
234-
res = self._sdk.alerts.get_details(alert_id)["alerts"]
243+
res = self._get_sdk().alerts.get_details(alert_id)["alerts"]
235244
if not res:
236245
raise Exception("No alert found with ID {0}.".format(alert_id))
237246
return res[0]
238247

239248
def resolve_alert(self, id):
240-
self._sdk.alerts.resolve(id)
249+
self._get_sdk().alerts.resolve(id)
241250
return id
242251

243252
def get_current_user(self):
244-
res = self._sdk.users.get_current()
253+
res = self._get_sdk().users.get_current()
245254
return res
246255

247256
def get_user_id(self, username):
248-
res = self._sdk.users.get_by_username(username)["users"]
257+
res = self._get_sdk().users.get_by_username(username)["users"]
249258
if not res:
250259
raise Exception("No user found with username {0}.".format(username))
251260
return res[0]["userUid"]
252261

253262
def search_file_events(self, payload):
254-
res = self._sdk.securitydata.search_file_events(payload)
263+
res = self._get_sdk().securitydata.search_file_events(payload)
255264
return res["fileEvents"]
256265

257266

@@ -364,7 +373,7 @@ class ObservationToSecurityQueryMapper(object):
364373
exposure_type_map = {
365374
"PublicSearchableShare": ExposureType.IS_PUBLIC,
366375
"PublicLinkShare": ExposureType.SHARED_VIA_LINK,
367-
"SharedOutsideTrustedDomain": "OutsideTrustedDomains"
376+
"SharedOutsideTrustedDomain": "OutsideTrustedDomains",
368377
}
369378

370379
def __init__(self, observation, actor):
@@ -824,11 +833,16 @@ def fetch_incidents(
824833

825834

826835
def test_module(client):
827-
if client.get_current_user():
836+
try:
837+
# Will fail if unauthorized
838+
client.get_current_user()
828839
return "ok"
829-
return "Invalid credentials or host address. Check that the username and password are correct, \
830-
that the host is available and reachable, and that you have supplied the full scheme, \
831-
domain, and port (e.g. https://myhost.code42.com:4285)"
840+
except Exception:
841+
return (
842+
"Invalid credentials or host address. Check that the username and password are correct, that the host "
843+
"is available and reachable, and that you have supplied the full scheme, domain, and port "
844+
"(e.g. https://myhost.code42.com:4285)."
845+
)
832846

833847

834848
def main():

Packs/Code42/Integrations/Code42/Code42_test.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,18 @@ def get_empty_detectionlist_response(mocker, base_text):
10741074
"""TESTS"""
10751075

10761076

1077+
def test_client_lazily_inits_sdk(mocker):
1078+
mocker.patch("py42.sdk.from_local_account")
1079+
1080+
# test that sdk does not init during ctor
1081+
client = Code42Client(sdk=None, base_url=MOCK_URL, auth=MOCK_AUTH, verify=False, proxy=None)
1082+
assert client._sdk is None
1083+
1084+
# test that sdk init from first method call
1085+
client.get_user_id("Test")
1086+
assert client._sdk is not None
1087+
1088+
10771089
def test_client_when_no_alert_found_raises_exception(code42_sdk_mock):
10781090
code42_sdk_mock.alerts.get_details.return_value = (
10791091
"""{'type$': 'ALERT_DETAILS_RESPONSE', 'alerts': []}"""

Packs/Code42/Integrations/Code42/integration-Code42.yml

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ configuration:
1111
defaultvalue: console.us.code42.com
1212
type: 0
1313
required: true
14-
- display: ""
14+
- display: "Username"
1515
name: credentials
1616
defaultvalue: ""
1717
type: 9
@@ -227,88 +227,97 @@ script:
227227
228228
def __init__(self, sdk, base_url, auth, verify=True, proxy=False):
229229
super().__init__(base_url, verify=verify, proxy=proxy)
230-
# Create the Code42 SDK instance
231-
self._sdk = sdk or py42.sdk.from_local_account(base_url, auth[0], auth[1])
230+
# Allow sdk parameter for unit testing.
231+
# Otherwise, lazily load the SDK so that the TEST Command can effectively check auth.
232+
self._sdk = sdk
233+
self._sdk_factory = lambda: py42.sdk.from_local_account(base_url, auth[0], auth[1]) if not self._sdk else None
232234
py42.settings.set_user_agent_suffix("Cortex XSOAR")
233235
236+
def _get_sdk(self):
237+
if self._sdk is None:
238+
self._sdk = self._sdk_factory()
239+
return self._sdk
240+
234241
def add_user_to_departing_employee(self, username, departure_date=None, note=None):
235242
user_id = self.get_user_id(username)
236-
self._sdk.detectionlists.departing_employee.add(user_id, departure_date=departure_date)
243+
self._get_sdk().detectionlists.departing_employee.add(
244+
user_id, departure_date=departure_date
245+
)
237246
if note:
238-
self._sdk.detectionlists.update_user_notes(user_id, note)
247+
self._get_sdk().detectionlists.update_user_notes(user_id, note)
239248
return user_id
240249
241250
def remove_user_from_departing_employee(self, username):
242251
user_id = self.get_user_id(username)
243-
self._sdk.detectionlists.departing_employee.remove(user_id)
252+
self._get_sdk().detectionlists.departing_employee.remove(user_id)
244253
return user_id
245254
246255
def get_all_departing_employees(self):
247256
res = []
248-
pages = self._sdk.detectionlists.departing_employee.get_all()
257+
pages = self._get_sdk().detectionlists.departing_employee.get_all()
249258
for page in pages:
250259
employees = page["items"]
251260
res.extend(employees)
252261
return res
253262
254263
def add_user_to_high_risk_employee(self, username, note=None):
255264
user_id = self.get_user_id(username)
256-
self._sdk.detectionlists.high_risk_employee.add(user_id)
265+
self._get_sdk().detectionlists.high_risk_employee.add(user_id)
257266
if note:
258-
self._sdk.detectionlists.update_user_notes(user_id, note)
267+
self._get_sdk().detectionlists.update_user_notes(user_id, note)
259268
return user_id
260269
261270
def remove_user_from_high_risk_employee(self, username):
262271
user_id = self.get_user_id(username)
263-
self._sdk.detectionlists.high_risk_employee.remove(user_id)
272+
self._get_sdk().detectionlists.high_risk_employee.remove(user_id)
264273
return user_id
265274
266275
def add_user_risk_tags(self, username, risk_tags):
267276
user_id = self.get_user_id(username)
268-
self._sdk.detectionlists.add_user_risk_tags(user_id, risk_tags)
277+
self._get_sdk().detectionlists.add_user_risk_tags(user_id, risk_tags)
269278
return user_id
270279
271280
def remove_user_risk_tags(self, username, risk_tags):
272281
user_id = self.get_user_id(username)
273-
self._sdk.detectionlists.remove_user_risk_tags(user_id, risk_tags)
282+
self._get_sdk().detectionlists.remove_user_risk_tags(user_id, risk_tags)
274283
return user_id
275284
276285
def get_all_high_risk_employees(self, risk_tags=None):
277286
if isinstance(risk_tags, str):
278287
risk_tags = [risk_tags]
279288
res = []
280-
pages = self._sdk.detectionlists.high_risk_employee.get_all()
289+
pages = self._get_sdk().detectionlists.high_risk_employee.get_all()
281290
for page in pages:
282291
res.extend(_get_all_high_risk_employees_from_page(page, risk_tags))
283292
return res
284293
285294
def fetch_alerts(self, start_time, event_severity_filter):
286295
query = _create_alert_query(event_severity_filter, start_time)
287-
res = self._sdk.alerts.search(query)
296+
res = self._get_sdk().alerts.search(query)
288297
return res["alerts"]
289298
290299
def get_alert_details(self, alert_id):
291-
res = self._sdk.alerts.get_details(alert_id)["alerts"]
300+
res = self._get_sdk().alerts.get_details(alert_id)["alerts"]
292301
if not res:
293302
raise Exception("No alert found with ID {0}.".format(alert_id))
294303
return res[0]
295304
296305
def resolve_alert(self, id):
297-
self._sdk.alerts.resolve(id)
306+
self._get_sdk().alerts.resolve(id)
298307
return id
299308
300309
def get_current_user(self):
301-
res = self._sdk.users.get_current()
310+
res = self._get_sdk().users.get_current()
302311
return res
303312
304313
def get_user_id(self, username):
305-
res = self._sdk.users.get_by_username(username)["users"]
314+
res = self._get_sdk().users.get_by_username(username)["users"]
306315
if not res:
307316
raise Exception("No user found with username {0}.".format(username))
308317
return res[0]["userUid"]
309318
310319
def search_file_events(self, payload):
311-
res = self._sdk.securitydata.search_file_events(payload)
320+
res = self._get_sdk().securitydata.search_file_events(payload)
312321
return res["fileEvents"]
313322
314323
@@ -422,7 +431,7 @@ script:
422431
exposure_type_map = {
423432
"PublicSearchableShare": ExposureType.IS_PUBLIC,
424433
"PublicLinkShare": ExposureType.SHARED_VIA_LINK,
425-
"SharedOutsideTrustedDomain": "OutsideTrustedDomains"
434+
"SharedOutsideTrustedDomain": "OutsideTrustedDomains",
426435
}
427436
428437
def __init__(self, observation, actor):
@@ -892,11 +901,16 @@ script:
892901
893902
894903
def test_module(client):
895-
if client.get_current_user():
904+
try:
905+
# Will fail if unauthorized
906+
client.get_current_user()
896907
return "ok"
897-
return "Invalid credentials or host address. Check that the username and password are correct, \
898-
that the host is available and reachable, and that you have supplied the full scheme, \
899-
domain, and port (e.g. https://myhost.code42.com:4285)"
908+
except Exception:
909+
return (
910+
"Invalid credentials or host address. Check that the username and password are correct, that the host "
911+
"is available and reachable, and that you have supplied the full scheme, domain, and port "
912+
"(e.g. https://myhost.code42.com:4285)."
913+
)
900914
901915
902916
def main():

0 commit comments

Comments
 (0)