All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
The intended audience of this file is for py42 consumers -- as such, changes that don't affect how a consumer would use the library (e.g. adding unit tests, updating documentation, etc) are not captured here.
- Updated readme to clarify deprecation.
- Removed version cap for urllib3 dependency, allowing the use of more modern versions.
- An issue where file download methods did not work in some conditions.
- The internal method
ExfiltratedDataService.get_download_tokennow takes only one parameter, downloadRequestUrl. This is the full URL (with parameters) that will be used to request the download token.
- All Incydr functionality is deprecated. Use the Incydr SDK instead: https://developer.code42.com/
- Ended support for python 3.8, which is end-of-life.
- A setting to add a prefix to the user-agent.
- An issue where the page size of file event queries was higher than intended.
- An issue where streaming file by hash did not use the hash.
- Increased HTTP client timeout from 1 minute to 3 minutes.
- Removed the
detectionlistsclient, which includedhigh_risk_employeeanddeparting_employeeclients. - APIs had been deprecated and were replaced by the
Watchlistsclient. APIs are no longer available regardless of Py42 version.
- Updated required versions of
requests>=2.25.0andurllib3>=1.26.6,<2
sdk.watchlists.create()now supports theCUSTOMwatchlist type, and acceptstitleanddescriptionkeyword arguments (only applicable toCUSTOMwatchlist types).
- Reverted
sdk.orgs.get_page()method to use/v1/orgsendpoint due to paging bug in/v3/orgsendpoint.sdk.orgs.get_all()has also been reverted accordingly. sdk.userriskprofile.get_by_username()now uses a more efficient method to look up the userUid from the username for retrieving the User Risk Profile.
-
Support for Code42 API Clients. You can instantiate py42 using a client ID and secret via
py42.sdk.from_api_client(). -
New Legal Hold Client which supports API Client authentication. This updated client will only be attached to the SDK if initialized with
py42.sdk.from_api_client(), otherwise the original client will be used. This new client includes the following changes from the existing client:create_policy()- Does not allow optional argpolicy.get_custodians_page()- Does not allow optional arglegal_hold_membership_uid.get_events_page()/get_all_events()- Not available.
- Internal authentication flow changes for
sdk.archive.stream_from_backup()andsdk.archive.stream_to_device()methods.
- Added new filter terms for the following file event fields to
py42.sdk.queries.fileevents.v2.filters:destination.Categorysource.Categoryrisk.Indicators
- Added remaining query filter terms and classes for all V2 file event fields.
- Support for V2 file event data.
- Use queries built with V2 filters by importing the appropriate modules with
from py42.sdk.queries.fileevents.v2 import *. Documentation is available for all V2 filter terms. - The following functions will now use V2 apis for searching file events if sent a V2 query object:
securitydata.search_file_events()securitydata.search_all_file_events()
- All saved search methods now have an optional
use_v2=Falseargument. Setuse_v2=Trueto opt into using the V2 saved search APIs. The following methods now accept this arg:securitydata.savedsearches.get()securitydata.savedsearches.get_by_id()securitydata.savedsearches.get_query()securitydata.savedsearches.execute()securitydata.savedsearches.search_file_events()
- Use queries built with V2 filters by importing the appropriate modules with
- A bug where
sdk.watchlists.add_included_users_by_watchlist_type()andsdk.watchlists.delete_included_users_by_watchlist_type()were not returning the response object.
-
WatchlistsandUserRiskProfileclients- These features replace the
DetectionListsclient as well as itsDepartingEmployeeandHighRiskEmployeeservices. All related classes and methods have been marked as deprecated and will raise deprecation warnings. Watchlistsclient includes the following methods:get()delete()get_all()create()get_all_included_users()add_included_users_by_watchlist_id()add_included_users_by_watchlist_type()remove_included_users_by_watchlist_id()remove_included_users_by_watchlist_type()get_all_watchlist_members()get_watchlist_member()
UserRiskProfileclient includes the following methods:get_by_id()get_by_username()update()get_page()get_all()add_cloud_aliases()delete_cloud_aliases()
- These features replace the
-
sdk.devices.upgrade()to instruct the Code42 cloud to upgrade an individual device to the latest available version. -
sdk.archive.stream_from_backup()andsdk.archive.stream_to_device()methods now accept an optionalbackup_set_idparameter to identify which backup set to restore from (only applicable to V3 archives).
- Bug where attempting to restore from an empty archive would throw a confusing
TypeError, we now raise appropriatePy42ArchiveFileNotFoundError. - Py42 now automatically sleeps and retries file event search queries if a 429 (too many requests) error is hit.
- The
DetectionListsclient including itsDepartingEmployeeandHighRiskEmployeeservices.
IncydrDeviceSettingsclass to allow users to manage the settings on individual Incydr devices.
- Bug with incorrect error being raised
sdk.detectionlists.add_user_cloud_alias()
- New file event filter query classes:
- in
sdk.queries.fileevents.filters.source_filters:SourceCategorySourceNameSourceTabTitlesSourceTabUrls
- in
sdk.queries.filevents.filters.exposure_filters:DestinationCategoryDestinationName
- in
- Improved error handling for
sdk.detectionlists.add_user_cloud_alias()
- New file event filter query
sdk.queries.fileevents.filers.risk_filter.RiskScoreto search for file events based on riskScore values.
- Updated
sdk.queries.alerts.filters.alerts_filter.Severityenum to use updatedriskSeveritysearch propert instead of deprecatedseverity.- New values
CRITICALandMODERATE. - Aliased previous
severity.MEDIUM>riskSeverity.MODERATEfor backwards compatibility.
- New values
- Updated custom exception behavior such that the parameters relating to the exception are:
- Printed in addition to the error message.
- Accessible as properties of the custom exception class.
- Removed method Get_alert_log(), method was no longer functional
- updated URI paths to use new standardized versioning scheme
- Decreased
get_all_alert_detailsbatch size to 25 when retrieving alert queries due to performance concerns.
- The following enums classes are now available to reference in
py42.constantsin addition to their original modules:CaseStatusRiskTagsTrustedActivityTypeDepartingEmployeeFiltersHighRiskEmployeeFilters
- Bug where
sdk.alerts.get_all_alert_details()was raising error when no alerts were found in query.
-
New
trustedactivitiesclient with the following new methods:sdk.trustedactivities.get_all()to get all trusted activities.sdk.trustedactivities.create()to create a new trusted activity.sdk.trustedactivities.get()to get details about a single trusted activity.sdk.trustedactivities.update()to update a trusted activity.sdk.trustedactivities.delete()to delete a trusted activity
-
New custom exceptions
Py42TrustedActivityInvalidChangeErrorPy42TrustedActivityConflictErrorPy42TrustedActivityInvalidCharacterErrorPy42TrustedActivityIdNotFound
-
New custom
HTTP 409 errorwrapper classPy42ConflictError
- Bug where
sdk.securitydata.search_all_file_events()errored whenpage_tokenparam wasNone. - Issue where
sdk.devices.get_page()raises a vague error message when provided with invalid org UID.
-
New alias method
sdk.securitydata.savedsearches.search_file_events()for existing methodsdk.securitydata.savedsearches.execute(). -
Two new
riskIndicator.UserBehaviorfilter valuesFirst use of destinationRare use of destination
- Updated minimum version of
requestslibrary to 2.4.2
-
RiskIndicatorandRiskSeverityfilter classes to newpy42.sdk.queries.fileevents.filters.risk_filtermodule. -
Support for Incydr SKUs that do not include backup and restore functionality to
sdk.securitydata.stream_file_by_sha256()andsdk.securitydata.stream_file_by_md5(). -
New method
sdk.alerts.get_all_alert_details()as a helper to make getting alerts with details easier (combinessdk.alerts.search_all_pages()andsdk.alerts.get_details()). -
New method
sdk.loginconfig.get_for_user()to identify if a user's login type isLOCAL,LOCAL_2FA, orCLOUD_SSO.
-
py42 no longer supports python 2.7 or python 3.5.
-
Usage of
Py42MFARequiredError. Usesdk.loginconfig.get_for_user()instead to check if a user is configured for two-factor authentication. -
FED (File Extraction Detection) - related functionality from the
SecurityDataClientclassget_security_plan_storage_info_list()get_all_plan_security_events()get_all_user_security_events()PlanStorageInfoclass
-
Issue where debug logs double-stringified JSON data while logging requests.
-
Issue where
sdk.securitydata.search_file_events()andsdk.alerts.search()would raiseUnicodeErrorwhen queries included certain unicode characters.
-
sdk.securitydata.search_all_file_events()now automatically escapes double-quote characters in thepage_tokenparam when passed. -
An issue where
FileEventQuery.sort_directionandFileEventQuery.sort_keyproperties were not applied to searches when apage_tokenwas passed in calls tosdk.securitydata.search_all_file_events(). -
Methods
sdk.auditlogs.get_all()andsdk.auditlogs.get_page()now honor microseconds when parametersbegin_timeorend_timeare epoch times.
-
Custom exception
Py42InvalidEmailErrorwhen providing an invalid email tosdk.users.update_user(). -
Custom exception
Py42InvalidPasswordErrorwhen providing an invalid password tosdk.users.update_user(). -
Custom exception
Py42InvalidUsernameErrorwhen providing an invalid username tosdk.users.update_user().
-
The
DateObservedalert query filter now parses timestamps using microsecond precision. -
Change JWT auth token label from
v3_user_tokentoBearerwhen authenticating against the/c42api/v3/auth/jwtendpoint.
- Python2.7 bug where non-unicode
strtimestamps would fail when used in a query filter.
- Issue where
sdk.detectionlists.create_user()would always fail because of API changes. The method has been deprecated and now returns the response fromsdk.detectionlists.get().
-
New custom exception
Py42UnableToCreateProfileErrorthat is raised when calling the methodsdk.detectionlists.create_user()due to the user not existing in Code42 or is already in the process of being created on the back-end. -
SyncDestinationUsernamefilter class topy42.sdk.queries.fileevents.filters.exposure_filtermodule.
- Issue where
sdk.users.get_roles()was using a deprecated API.
- Issue when calling
sdk.alerts.update_state()without specifying anoteparameter would set the existing alert's note's message to the empty string.
- Custom exception
Py42OrgNotFoundError.
-
sdk.users.get_all()now raisesPy42OrgNotFoundErrorwhen the givenorg_uidwas not found. -
sdk.users.get_page()now raisesPy42OrgNotFoundErrorwhen the givenorg_uidwas not found.
-
New method
sdk.alerts.search_all_pages()to retrieve all alert pages. -
New method
sdk.alerts.get_aggregate_data()to get alert summary and observations.
-
Method
sdk.alerts.search()now accepts optional argumentspage_numandpage_size. -
Methods
sdk.cases.update()andsdk.cases.create()now raise custom exceptionPy42InvalidCaseUserErrorwhen trying to add an invalid user as a subject or an assignee of a case. -
sdk.cases.update()now raisesPy42CaseNameExistsErrorwhen the name of the case already exists in the system.
-
sdk.legalhold.get_events_page()to get a page of legal hold events. -
sdk.legalhold.get_all_events()to search for legal hold events. -
sdk.users.update_user()to update an existing user in Code42. -
sdk.alerts.update_note()to add or update a note regarding an alert. -
sdk.from_jwt_provider()method to create anSDKClientthat supports custom auth mechanism.
-
Bug where proxy settings were not being applied correctly.
-
Bug where 500 errors would not raise during
sdk.users.create_user().
-
sdk.cases.create()now raisesPy42CaseNameExistsErrorwhen the case name already exists in the system. -
sdk.cases.create()now raisesPy42DescriptionLimitExceededErrorwhen the description is more than 250 characters. -
sdk.cases.update()now raisesPy42DescriptionLimitExceededErrorwhen the description is more than 250 characters. -
sdk.cases.file_events.add()now raisesPy42CaseAlreadyHasEventErrorwhen the same event is added to a case more than once. -
sdk.cases.file_events.add()now raisesPy42UpdateClosedCaseErrorwhen the event is added to a closed case. -
sdk.cases.file_events.delete()now raisesPy42UpdateClosedCaseErrorwhen the event is deleted from a closed case.
sdk.legalhold.get_custodians_page()now raisesPy42LegalHoldCriteriaMissingErrorwhen missing one of the required options.
-
Python 3.9 support.
-
sdk.casesmethods:sdk.cases.create()sdk.cases.get_all()sdk.cases.get_page()sdk.cases.export_summary()sdk.cases.get()sdk.case.update()
-
sdk.cases.file_eventsmethods for managing file events associated with a given case:sdk.cases.file_events.add()sdk.cases.file_events.delete()sdk.cases.file_events.get()sdk.cases.file_events.get_all()
- Bug where trying to retrieve device settings for a device on legal holds caused an exception to be raised.
-
Bug that occurs when trying to add a user to an alert rule who had never been on any detection list before.
-
Bug where an empty destination list in a device's backup set broke creation of DeviceSettings objects for that device.
-
Bug where all 401 Unauthorized error responses were being raised as Py42MFARequired exceptions.
-
Bug where requests to storage nodes were only using single-use tokens for authentication, causing many extraneous requests.
-
sdk.archive.stream_to_device()for pushing a restore to another device. -
Added new exception
Py42CloudAliasLimitExceededErrorto throw ifadd_cloud_alias()throws400and body contains reasonCloud usernames must be less than or equal to. -
Added new exception
Py42UserNotOnListErrorto throw error ifremove()throws404when the user is not on a detection list. -
Added new exception
Py42TooManyRequestsErrorto raise errors with 429 HTTP status code. -
Added new method
sdk.securitydata.search_all_file_events()to retrieve all events when events are more than 10,000. -
Added new custom exception
sdk.exceptions.Py42InvalidPageTokenthat gets raised when the page token fromsdk.securitydata.search_all_file_events()causes a specific bad request error.
-
The following methods now support string timestamp formats (
yyyy-MM-dd HH:MM:SS) as well as adatetimeinstance:sdk.auditlogs.get_page(), argumentsbegin_timeandend_time.sdk.auditlogs.get_all(), argumentsbegin_timeandend_time.sdk.securitydata.get_all_plan_security_events(), argumentsmin_timestampandmax_timestamp.sdk.securitydata.get_all_user_security_events(), argumentsmin_timestampandmax_timestamp.
-
The
departure_dateparameter for methods:sdk.detectionlists.departing_employee.add()sdk.detectionlists.departing_employee.update_departure_date()now support adatetimeinstance.
-
The following methods on timestamp-based query filters (e.g.
EventTimestamp,DateObserved) now support string timestamp format (yyyy-MM-dd HH:MM:SS) as well as adatetimeinstance:on_or_before()or_or_after()in_range()
- Removed faulty
within_the_last()method fromsdk.queries.alerts.filters.alert_filter.DateObserved.
-
Added new exception
Py42UserAlreadyExistsErrorto throw ifcreate_user()throws500and body containsUSER_DUPLICATE -
Added
Py42ActiveLegalHoldErrorexception when attempting to deactivate a user or device in an active legal hold.py42.sdk.users.deactivate()py42.sdk.devices.deactivate()
-
Added additional user-adjustable setting for security events page size:
py42.settings.security_events_per_page
-
Page page_number and page_size parameters for saved search queries:
py42.securitydata.savedsearches.get_query()py42.securitydata.savedsearches.execute()
-
sdk.alerts.update_state()method to update state. -
Support for two-factor authentication in
sdk.from_local_account() -
OrgSettingsandDeviceSettingsclasses to help with Org and Device setting management.sdk.orgs.get_settings(org_id)now returns an instance ofOrgSettingswhich can be used to view existing Org settings and modify them by passing the updatedOrgSettingsobject tosdk.orgs.update_settings()sdk.devices.get_settings(org_id)now returns an instance ofDeviceSettingswhich can be used to view existing Device settings and modify them by passing the updatedDeviceSettingsobject tosdk.devices.update_settings()
-
sdk.auditlogsmethod:sdk.auditlogs.get_page()sdk.auditlogs.get_all()
py42.sdk.queries.query_filter.filter_attributesrenamed topy42.util.get_attribute_keys_from_class
- Corrected an issue that caused
sdk.detectionlists.departing_employee.get_all()andsdk.detectionslists.high_risk_employee.get_all()to only return the first page (first 100) records. This same issue also caused otherget_all_X()methods to only return the first page if the requestedpage_sizewas less thansettings.items_per_page.
page_sizeparameter to:sdk.detectionlists.departing_employee.get_all()sdk.detectionlists.high_rsik_employee.get_all()
- Corrected error logic for trying to add or remove users from a system rule.
- Removed
tenant_idparameter from methods:sdk.alerts.get_details()sdk.alerts.resolve()sdk.alerts.reopen()
- Issue that in rare circumstance could cause py42 to exhaust network sockets. This could sometimes occur if you were running a multi-threaded program that communicated with many Code42 storage nodes.
-
Methods for obtaining archive information:
sdk.archive.get_by_archive_guidsdk.archive.get_all_by_device_guid
-
Debug logs for restore progress during the method call
py42.archive.stream_from_backup(). -
.netrc support. Calling
py42.sdk.from_local_account()with no username and password will now result in py42 attempting to authenticate via an entry in your.netrcfile, if you have one. -
py42.constants.SortDirectionconstantsDESCandASC. -
sdk.detectionlists.departing_employee.DepartingEmployeeFiltersconstantsOPEN,EXFILTRATION_30_DAYS,EXFILTRATION_24_HOURS, andLEAVING_TODAY. -
sdk.detectionlists.high_risk_employee.HighRiskEmployeeFiltersconstantsOPEN,EXFILTRATION_30_DAYS, andEXFILTRATION_24_HOURS. -
Methods for calling the agent-state APIs:
sdk.devices.get_agent_state()sdk.devices.get_agent_full_disk_access_state()sdk.orgs.get_agent_state()sdk.orgs.get_agent_full_disk_access_states()
-
Exception classes (
py42.exceptions)Py42ResponseErrorPy42UserAlreadyAddedErrorPy42LegalHoldNotFoundOrPermissionDeniedErrorPy42InvalidRuleOperationError
-
Methods for getting individual response pages:
sdk.detectionlists.departing_employee.get_page()sdk.detectionlists.high_risk.get_page()sdk.users.get_page()sdk.devices.get_page()sdk.orgs.get_page()sdk.legalhold.get_matters_page()sdk.legalhold.get_custodians_page()sdk.alerts.get_rules_page()
-
Added enum object
py42.modules.detectionlists.RiskTagswith constants:FLIGHT_RISKHIGH_IMPACT_EMPLOYEEELEVATED_ACCESS_PRIVILEGESPERFORMANCE_CONCERNSSUSPICIOUS_SYSTEM_ACTIVITYPOOR_SECURITY_PRACTICESCONTRACT_EMPLOYEE
-
Added below event filter support
- TrustedActivity
- RemoteActivity
- PrintJobName
- Printer
- DeviceSignedInUserName
-
Added attributes to below event filters and added
choicesmethod to return list of all available attributes- FileCategory
- SyncDestination
- ExposureType
- Source
- EventTimestamp
- EventType
- SharingTypeAdded
- RuleSource
- RuleType
- AlertState
- Severity
sdk.archive.stream_from_backup()now calculates file sizes and accepts afile_size_calc_timeoutparameter.- Parameter
file_pathonsdk.archive.stream_from_backup()renamed tofile_pathsand can now take a list of file paths to restore. sdk.detectionlists.departing_employee.add()now raisesPy42UserAlreadyAddedErrorwhen the user is already on the list.sdk.detectionlists.high_risk_employee.add()now raisesPy42UserAlreadyAddedErrorwhen the user already on the list.sdk.legalhold.add_to_matter()now raisesPy42UserAlreadyAddedErrorwhen the user is already on the matter.sdk.legalhold.get_matter_by_uid()now raisesPy42LegalHoldNotFoundOrPermissionDeniedErrorwhen the user does not have access or the ID does not exist.sdk.alerts.rules.add_user()now raisesPy42InvalidRuleOperationErroron 404s.sdk.alerts.rules.remove_user()now raisesPy42InvalidRuleOperationErroron 404s.sdk.alerts.rules.remove_all_users()now raisesPy42InvalidRuleOperationErroron 404s.Py42ArchiveFileNotFoundErrornow includes the response.Py42ChecksumNotFoundErrornow includes the response.Py42FeatureUnavailableErrornow includes the response.Py42StorageSessionInitializationErrornow includes the response.
sdk.securitydata.stream_file_by_md5()now raisesPy42ChecksumNotFoundErrorwhen no matching md5 is found (previously wasPy42ArchiveFileNotFoundError).sdk.securitydata.stream_file_by_sha256()now raisesPy42ChecksumNotFoundErrorwhen no matching md5 is found (previously wasPy42Error).
- functions now return
Py42Responseobjects as expected:sdk.detectionlists.update_user_notes()sdk.detectionlists.add_user_risk_tags()sdk.detectionlists.remove_user_risk_tags()sdk.detectionlists.add_user_cloud_alias()sdk.detectionlists.remove_user_cloud_alias()
sdk.archive.get_all_org_cold_storage_archives()now actually uses parametersinclude_child_orgs,sort_keyandsort_dir.
-
Functions for managing role assignment:
sdk.users.get_available_roles()sdk.users.get_roles()sdk.users.add_role()sdk.users.remove_role()
-
__eq__and__hash__methods to thepy42.sdk.queries.query_filter.QueryFilterclass to enable easier comparison of filters -
__eq__and__contains__methods to thepy42.sdk.queries.query_filter.FilterGroupclass to enable easier comparison of and membership tests of filter groups
- When calling
__str__or__iter__on aFilterGroupinstance, the filter results haveset()called on them to remove duplicate filters (if they exist) as well as sorts the results. This enables comparing twoFilterGroups that might have been constructed differently but ultimately return the exact same results in a query. FilterGroup.filter_clauseproperty now has a setter, making it easy to change the clause on an existing filter group.
filter_clausearg onFilterGroup.from_dictmethod. The clause will automatically be derived from the dict itself.
-
datatoPy42Response. This allows a developer to retrieve the full dict of the response under thedatajson node, if present, enabling the use of typical dict functions such asget(). -
contenttoPy42Response. This exposes the underlyingrequests.Response.content, which contains the fully body of the response as a byte array.
-
An issue where
sdk.securitydata.stream_file_by_md5()andsdk.securitydata.stream_file_by_sha256()would return streams containing an error message instead of properly failing. -
An issue where streaming methods would load the stream completely into memory instead of retrieving it one chunk at a time.
- Make
ExposureType.OUTSIDE_TRUSTED_DOMAINSconstant available. sdk.securitydatamethodsstream_file_by_sha256()stream_file_by_md5()
emailis now a required param onpy42.users.create_user().
- Faulty
py42.orgs.get_by_name()method. Usepy42.orgs.get_all()and/or any of the otherget_by_()methods.
- An unintended regression that caused
import py42.sdk.settings.debugto fail.
- For security reasons, debug output no longer logs the headers on http requests.
- Ability for users to provide their own logger for debug logging
- adds
sdk.detectionlists.refresh_user_scim_attributes()to update user SCIM attributes in detection lists.
- An issue that caused requests to
sdk.alerts.rules.get_all(),sdk.alerts.rules.get_all_by_name(), andsdk.alerts.rules.get_by_observer_id()to fail due to a change made to their backing api.
- The default value of
py42.settings.items_per_pagehas been changed to 500 (was 1000). - Default debug logging moved from print statements to a logger writing to
sys.stderr - Debug logging levels now use standard levels from the
loggingmodule (old levels still work but are now automatically mapped to appropriateloggingmodule level, with bothdebug.DEBUGanddebug.TRACEbeing mapped tologging.DEBUG, asDEBUGis the lowest level of theloggingmodule options).
get_all_org_cold_storage_archives()function toArchiveModule, available atsdk.archive.get_all_org_cold_storage_archives().
AlertQuerynow defaults to apage_sizeof 500. A change made to the backing api ofsdk.alerts.search()was causing all requests made with the previous default (10000) to fail.
-
SavedSearchClientavailable atsdk.securitydata.savedsearcheswith the following functions:get()get_by_id()execute()
-
get_scim_data_by_uid()function toUserClient, available atsdk.users.get_scim_data_by_uid().
sdk.alerts.rules.get_by_observer_id()to look up an alert rule by its observer id.
- The following methods that required either a single str or list of string argument can now also accept a tuple of strings:
sdk.alerts.get_details()sdk.alerts.resolve()sdk.alerts.reopen()sdk.detectionlists.add_risk_tags()sdk.detectionlists.remove_risk_tags()
sdk.alerts.rules.get_by_name(). Usesdk.alerts.rules.get_all_by_name()instead. It functions identically except for that it returns a generator ofPy42Responseobjects rather than a list.
sdk.alerts.get_details()now attempts to parse the "observation data" json string from the response data automatically.
-
RuleId,RuleSourceandRuleTypefilter classes topy42.sdk.queries.alerts.filters.alert_filtermodule. -
Py42Responseitems now have__setitem__support in order facilitate manipulating a response. For example,response["users"][0]["username"] = "something elseis now possible. -
Py42Responseitems can now be iterated over multiple times.
- Issue causing
detectionlistsfunctions to fail.
-
sdk.alert.rulesmethods:add_user()remove_user()remove_all_users()get_all()get_by_name()
-
sdk.alert.rules.exfiltrationmethods:get()
-
sdk.alert.rules.cloudsharemethods:get()
-
sdk.alert.rules.filetypemismatchmethods:get()
sdk.securitydata.alerts. usesdk.alertsinstead.
sdk.archive.update_cold_storage_purge_date(), allowing the changing of the date at which a cold storage archive will be purged.
-
Exceptions that inherit from
Py42HTTPErrornow return the originalrequests.Responseobject on the exception's.responseproperty instead of a string representation of theHTTPErrorthat was raised. -
departure_dateis now an optional parameter forsdk.detectionlists.departing_employee.add(). -
py42.sdk.queries.alerts.alert_query.AlertQueryno longer requires atenant_idto be added to the query manually, theAlertClient.search()method now adds the tenant_id automatically from the user_context.
sdk.detectionlistsmethods:add_cloud_aliases()>add_cloud_alias()remove_cloud_aliases()>remove_cloud_alias.
The above methods no longer support lists for their alias parameter.
sdk.detectionlists.departing_employeemethods:set_alerts_enabled()
sdk.detectionlists.departing_employeemethods:create()->add()resolve()->remove()update()->update_departure_date()get_by_id()->get()
sdk.detectionlistsmethod renames:create()->create_user()get()->get_user()get_by_id()->get_user_by_id()update_notes()->update_user_notes()add_risk_tag()->add_user_risk_tags()remove_risk_tag()->remove_user_risk_tags()add_cloud_alias()->add_user_cloud_aliases()remove_cloud_alias()->remove_user_cloud_aliases()
-
sdk.detectionlistsmethods:update_notes()remove_risk_tag()add_risk_tag()add_cloud_alias()remove_cloud_alias()create()get()get_by_id()
-
sdk.detectionlists.high_risk_employeemethods:add()remove()get()search()set_alerts_enabled()
- Parameter
classificationremoved fromOrgClient.create_org() - Parameter
legal_hold_membership_uidremoved fromLegalHoldClient.get_all_matter_custodians() - Removed
ArchiveClient. UseArchiveModule. - Removed function
ArchiveModule.get_data_key_token(). - Removed function
ArchiveModule.get_web_restore_info(). - Parameter
classificationremoved fromOrgClient.create_org(). - Parameter
legal_hold_membership_uidremoved fromLegalHoldClient.get_all_matter_custodians(). - Removed
SecurityClient. UseSecurityModule. py42.sdk.util. Usepy42.utilinstead.py42.sdk.settings. Usepy42.settingsinstead.py42.sdk.response. Usepy42.responseinstead.py42.sdk.usercontext. Usepy42.usercontextinstead.
- Parameter
active_statewas renamed toactiveand now accepts (True, False, or None) instead of ("ACTIVE", "INACTIVE", or "ALL") on the followingLegalHoldClientmethods:get_all_matters()get_all_matter_custodians()
- Parameter
storageaccesswas removed fromSDKClient. To restore files, just useSDKClient.archive.stream_from_backup(). - Parameter
active_statewas renamed toactiveand now accepts (True, False, or None) instead of ("ACTIVE", "INACTIVE", or "ALL") on the followingLegalHoldClientmethods:get_all_matters()get_all_matter_custodians()
py42.sdk.archive.stream_from_backup()now raisesPy42ArchiveFileNotFoundErrorwhen it does not find a file.py42.sdk.alertsandpy42.sdk.detectionlistsraisePy42SessionInitializationErrorif they are unable to connect to the necessary microservice andPy42FeatureUnavailableErrorif their environment does not support the microservice.py42.sdk.securitydata.get_security_plan_storage_info_list()raisesPy42SecurityPlanConnectionErrorif it can't connect to get plan info.- Storage node connection issues may raise
Py42StorageSessionInitializationError. - All requests may raise a subclass of
Py42HTTPErrordenoting which type of HTTP error it is:Py42BadRequestErrorPy42UnauthorizedErrorPy42ForbiddenErrorPy42NotFoundErrorPy42InternalServerError
py42.modules.ArchiveModulemethods:get_all_device_restore_history()(formerlyget_restore_history_by_device_id())get_all_user_restore_history()(formerlyget_restore_history_by_user_id())get_all_org_restore_history()(formerlyget_restore_history_by_org_id()) now all return generator objects that handle paging through restore history.
- Renamed
AlertClient.get_query_details()toAlertClient.get_details(). - Renamed
SecurityModule.get_plan_security_events()toget_all_plan_security_events(). - Renamed
SecurityModule.get_user_security_events()toget_all_user_security_events().
- py42 specific exceptions at new module
py42.exceptions:Py42ErrorPy42ArchiveFileNotFoundErrorPy42SessionInitializationErrorPy42FeatureUnavailableErrorPy42SecurityPlanConnectionErrorPy42HTTPErrorPy42BadRequestErrorPy42UnauthorizedErrorPy42ForbiddenErrorPy42NotFoundErrorPy42InternalServerError
- Parameters
archive_passwordandencryption_keyadded toArchiveModule.stream_from_backup().
- To import alert filters, do:
from py42.sdk.queries.alerts.filters import *instead of importing them individually.
-
The following methods from
py42.util:get_obj_from_response()filter_out_none()print_dict()
-
py42.debugmodule. Usepy42.settings.debuginstead. -
py42.utilmodule. Usepy42.sdk.utilinstead. -
ArchiveModule.download_from_backup(). UseArchiveModule.stream_from_backup()instead.
All client methods now return a Py42Response object that simplifies accessing the most meaningful parts
of the returned JSON object.
Renamed methods to reduce redundancy:
-
SDK>SDKClientcreate_using_local_account()>from_local_account()administration>serveradminlegal_hold>legalholdstorage>storageacesssecurity>securitydatauser_context>usercontextemployee_case_management>detectionlists
-
StorageClientFactoryget_storage_client_from_device_guid()>from_device_guid()get_storage_client_from_plan_uid()>from_plan_info()
-
StorageClientsecurity>securitydata
-
StorageSecurityClientget_security_detection_events_for_plan()>get_plan_security_events()get_security_detection_events_for_user()>get_user_security_events()
-
FileEventClientsearch_file_events()>search()
-
StorageArchiveClientsearch_archive()>search()get_archive_tree_node()>get_file_path_metadata()create_web_restore_session()>create_restore_session()submit_web_restore_job()>start_restore()get_web_restore_job()>get_restore_status()cancel_web_restore_job()>cancel_restore()get_web_restore_job_result()>stream_restore_result()
-
DepartingEmployeeClientcreate_departing_employee()>create()resolve_departing_employee()>resolve()get_all_departing_employees()>get_all()get_case_by_username()>get_by_username()get_case_by_id()>get_by_id()update_case()>update()
-
LegalHoldClientcreate_legal_hold()>create_matter()get_legal_hold_policy_by_uid()>get_policy_by_uid()get_all_legal_hold_policies()>get_all_policies()get_legal_hold_by_uid()>get_matter_by_uid()get_legal_holds()>get_all_matters()get_legal_hold_memberships()>get_all_matter_custodians()add_user_to_legal_hold()>add_to_matter()remove_user_from_legal_hold()>remove_from_matter()deactivate_legal_hold()>deactivate_matter()reactivate_legal_hold()>reactivate_matter()create_legal_hold_policy()>create_policy()create_legal_hold()>create_matter()
-
AlertClientsearch_alerts()>search()resolve_alert()>resolve()reopen_alert()>reopen()
-
OrgClientget_orgs()>get_all()get_org_by_id()>get_by_id()get_org_by_uid()>get_by_uid()block_org()>block()unblock_org()>unblock()deactivate_org()>deactivate()reactivate_org()>reactivate()get_current_user_org>get_current
-
UserClientget_user_by_id()>get_by_id()get_user_by_uid()>get_by_uid()get_user_by_username()>get_by_username()get_current_user()>get_current()get_users()>get_all()block_user()>block()unblock_user()>unblock()deactivate_user()>deactivate()reactivate_user()>reactivate()change_user_org_assignment()>change_org_assignment()
-
DeviceClientget_device_by_id()>get_by_id()get_device_by_guid()>get_by_guid()get_devices()>get_all()block_device()>block()unblock_device()>unblock()deactivate_device()>deactivate()reactivate_device()>reactivate()deauthorize_device()>deauthorize()get_device_settings()>get_settings()
Issue where large API responses were read very slowly.
Support for querying file events by:
- DirectoryID
- EmailRecipients
- EmailSender
- FileCategory
- FileOwner
- ProcessOwner
- ProcessName
- RemovableMediaName
- Shared
- SharedWith
- SharingTypeAdded
- Source
- SyncDestination
- TabURL
- WindowTitle
py42.settings.items_per_pageno long affectsDepartingEmployeeClient.get_all_departing_employees(), which is now always set at 100 items per page.FileEventQueryandAlertQueryobjects will now return up to 10,000 results by default (the previous default value was 100).
- Issue where
DepartingEmployeeClient.get_all_departing_employees()always resulted in a 400 status code.
py42.settings.items_per_page. This effectively replacespage_sizefor the methods that were changed below.
The following resources no longer accept page_num and page_size parameters and no longer return a
requests.Response object:
UserClient.get_users()DeviceClient.get_devices()OrgClient.get_orgs()LegalHoldClient.get_legal_holds()LegalHoldClient.get_legal_hold_memberships()DepartingEmployeeClient.get_all_departing_employees()
They instead return a generator object that is iterated over to retrieve all the pages, eliminating the need to manually compose loops to retrieve each page. For example, the below snippet will retrieve all pages of users:
for page in users.get_users():
user_list = json.loads(page.text)["data"]["users"]- Support for querying file events by Actor.
- Issue where setting
AlertQuery.sort_directiondid not properly apply the specified direction.
- Added
alertstoSecurityModulewithsearch_alerts()get_query_details()resolve_alert()reopen_alert()
- For querying alerts, build an
AlertQueryobject with fields:AlertStateDescriptionSeverityActorRuleNameNew filter operatorscontainsandnot_containsfor alert string fields.
- Added
EmployeeCaseManagementmodule withdeparting_employeewith:create_departing_employee()resolve_departing_employee()get_all_departing_employees()toggle_alerts()get_case_by_username()get_case_by_id()update_case()Access viapy42.SDK.employee_case_management.departing_employee
- Added
get_current_tenanttopy42.SDK.administration. - Added
py42.SDK.user_context.get_current_tenant_id.
SecurityModule.get_security_plan_storage_info_list()SecurityModule.get_user_security_events()SecurityModule.get_plan_security_events()
- Removed
SecurityModule.get_security_event_locations(). UseSecurityClient.get_security_event_locations()instead. - Removed
get_normalized_security_event_plan_info().Support for pre-6.7 format security event plan info responses has been removed, and as a result this method is no longer necessary. UseSecurityClient.get_security_event_locations()instead.
- a timeout of 60 seconds is now enforced on all http requests. Previously the timeout was infinite. This allowed for the possibility of requests that would hang forever under certain circumstances.
py42.sdk.util.queued_logger. Use loggers in Python'sloggingnamespace instead (they are threadsafe).is_asyncoption fromsdk.create_from_local_account. This was an intentionally undocumented feature.force_sync,then, andcatchoptions from all client requests. These were only meaningful when used withis_async.users.for_each_user(). Loop overresponse["data"]["users"]instead.devices.for_each_device(). Loop overresponse["data"]["computers"]instead.py42.settings.global_exception_receiver. Handle your exceptions as you otherwise normally would instead.
ExposureType.anyhas been renamed toExposureType.exists
- Issue where
_FileEventFilterTimestampFielddisguised localized times as UTC - Issue where
_FileEventFilterTimestampFieldignored milliseconds - Issue on Python 3 where
FileEventQuery.__repr__did not return typestr
existsandnot_existsadded tofile_event_querystring fields.InsertionTimestampfile event filter support
- Python 3.5.0+ support.
users.get_user_by_id()orgs.get_org_by_id()devices.get_device_by_id()
- Issue that caused
users.for_each_user()anddevices.for_each_device()to only apply filter criteria to the first 1000 items returned.
SecurityModule.get_security_detection_event_client
-
The following methods from
SecurityModule. UseStorageSecurityClient(viaSecurityModule.get_security_detection_event_client) instead.get_security_detection_events_for_user()get_security_detection_events_summary()
-
get_security_detection_eventsfromStorageSecurityClient. Useget_security_detection_events_for_plan(),get_security_detection_events_for_user(), orget_security_detection_event_summary()instead. -
include_filesandevent_typesparameters fromStorageSecurityClient.get_security_detection_event_summary(). These had no effect.
- Request URL to request exception message
- Issue with creating security plan clients when a session for one client failed to be created
- Regression that removed an optimization that allowed user to make requests to the same storage node without getting a new storage auth token for each request
- Bug in authentication handling logic that caused authentication tokens to not automatically renew properly when they expired.
- Bug in creating security plan clients that caused some clients to not be created for users with multiple plans or archives
- Issues with unicode support in
securitydata.search_file_events()andarchive.download_from_backup()
- Bug in the path-matching logic of
archive.download_from_backupthat caused:- downloads to fail if the drive/root path didn't match, case-sensitive
- the API to return
Noneinstead of raising an exception
- requests made by py42 now use a user agent string that contains the py42 version and python version.
This user agent string can be retrieved using
py42.settings.get_user_agent_string() - A custom suffix can be added to the end of this user agent string by using
py42.settings.set_user_agent_suffix(). SDK.users.get_users()andSDK.devices.get_devices()now both support aqparameter that can be used to check common distinguishing fields on those items for an input string (e.g.SDK.users.get_user(q="test")will return all users whose username or email address contain "test").
SDK.archive.download_from_backup()will now download the most recent non-deleted version of a file. Previously, file paths that were deleted would not be downloaded.
- Asynchronously searching for file events and then later attempting to download a file with the same SDK object no longer hangs indefinitely.
SDK.securitydata.search_file_events()to search for file events using the Forensic File Search (FFS) servicepy42.sdk.file_event_querymodule with classes to easily build file event queries- Ability to print various levels of debug statements for troubleshooting purposes. See
settings.debug_level - pytest test framework
- Merged
SDK.restorewithSDK.archiveRestoreModulewas renamed toArchiveModuleRestoreClientmerged intoArchiveClientStorageRestoreClientmerged intoStorageArchiveClient
- Tests from distribution package
SDK.restore.download_from_backup()SDK.users.change_user_org_assignment()
- Simplified APIs
- Merged and flattened modules under
authorityandstorage.- Example:
SDK.authority.admininstration.usersbecameSDK.users
- Example:
- You no longer need to know whether you're connecting to an authority or storage node.
- Merged and flattened modules under
- Added to
SDK.authority.administration.orgsmodule:create_org()get_org_by_uid()block_org()unblock_org()deactivate_org()reactivate_org()
- Added to
SDK.authority.administration.devicemodule:get_device_by_guid()block_device()unblock_device()deauthorize_device()for_each_device()get_device_settings()deactivate_device()reactivate_device()
- Added to
SDK.authority.administration.usersmodule:create_user()get_user_by_uid()get_user_by_username()block_user()unblock_user()deactivate_user()reactivate_user()
- Added
SDK.authority.legal_holdmodule with:create_legal_hold_policy()create_legal_hold()get_legal_hold_policy_by_uid()get_all_legal_hold_policies()get_legal_hold_by_uid()get_legal_holds()get_legal_hold_memberships()add_user_to_legal_hold()remove_user_from_legal_hold()deactivate_legal_hold()reactivate_legal_hold()
- Added
SDK.authority.archivemodule with:get_data_key_token()get_backup_sets()
- Added to
SDK.authority.restoremodule:get_web_restore_info()
- Added
SDK.storage.archivemodule with:search_archive()get_file_size()get_archive_tree_node()
- Added
SDK.storage.restoremodule with:create_web_restore_session()submit_web_restore_job()get_web_restore_job()cancel_web_restore_job()get_web_restore_job_result()
- Added setup.py to support package installation
- Renamed
SDK.device.get_computers()toSDK.device.get_devices()