Package: netskopesdk
Netskope SDKNeskope SDK is Python library for dealing with API's to download the Netskope events.InstallationUse the package managerpipto install NetskopeSDK.pipinstallnetskopesdkRest sdk Usage to pull the Alert & Eventsfromnetskope_api.iterator.netskope_iteratorimportNetskopeIteratorfromnetskope_api.iterator.constimportConstfromrequests.exceptionsimportRequestExceptionimporttime# Construct the params dict to pass the authentication detailsparams={Const.NSKP_TOKEN:"<REST-API-TOKEN>",Const.NSKP_TENANT_HOSTNAME:"<HOSTNAME>",# Optional param to pass the proxy hosts.Const.NSKP_PROXIES:{"<PROXY-HOSTS>"},Const.NSKP_EVENT_TYPE:"<EVENT-TYPE>",Const.NSKP_ITERATOR_NAME:"<ITERATOR-NAME>",Const.NSKP_USER_AGENT:"<SPLUNK-TENANT-HOSTNAME>"# To query specific alert pass the NSKP_EVENT_TYPE as "alert" and the alert type.# Const.NSKP_EVENT_TYPE : Const.EVENT_TYPE_ALERT,# Const.NSKP_ALERT_TYPE : Const.ALERT_TYPE_DLP}DEFAULT_WAIT_TIME=30RESULT="result"WAIT_TIME="wait_time"# Create an Iteratoriterator=NetskopeIterator(params)# Use the next() iterator to download the logs.# Consume the message indefinitely in a loop and ingest the data to SIEMwhileTrue:response=(iterator.next())try:ifresponse:data=response.json()ifRESULTindataandlen(data[RESULT])!=0:# processData()# sleep() the thread to avoid constant pollingifWAIT_TIMEindata:time.sleep(data[WAIT_TIME])else:time.sleep(DEFAULT_WAIT_TIME)else:print("No response received from the iterator")time.sleep(DEFAULT_WAIT_TIME)exceptExceptionase:time.sleep(DEFAULT_WAIT_TIME)raiseRequestException(e)Rest sdk Usage to pull the Alert & Events in CSV format.importcsvfromioimportStringIOfromnetskope_api.iterator.netskope_iteratorimportNetskopeIteratorfromnetskope_api.iterator.constimportConstfromrequests.exceptionsimportRequestException# Construct the params dict to pass the authentication details# Note: For CSV iterator - only the next(), resend() and tail() apis are supported.params={Const.NSKP_TOKEN:"<REST-API-TOKEN>",Const.NSKP_TENANT_HOSTNAME:"<HOSTNAME>",# Optional param to pass the proxy hosts.Const.NSKP_PROXIES:{"<PROXY-HOSTS>"},Const.NSKP_EVENT_TYPE:"<EVENT-TYPE>",Const.NSKP_ITERATOR_NAME:"<ITERATOR-NAME>",Const.NSKP_USER_AGENT:"<SPLUNK-TENANT-HOSTNAME>"# To query specific alert pass the NSKP_EVENT_TYPE as "alert" and the alert type.# Const.NSKP_EVENT_TYPE : Const.EVENT_TYPE_ALERT,# Const.NSKP_ALERT_TYPE : Const.ALERT_TYPE_DLP}# Create an Iteratoriterator=NetskopeIterator(params)# Create an Iterator. Next is the only API supported.iterator=NetskopeIterator(params)# Consume the message indefinitely in a loop and ingest the data to SIEMwhileTrue:try:# Use the next() iterator to download the logs.response=(iterator.next())ifresponse.status_code==200:# Parse the CSV data from the responseheaders=response.headers["schema_headers"]csv_data=StringIO(response.text)# Create a CSV reader objectcsv_reader=csv.reader(csv_data)# Print or use the headers as neededprint("CSV Headers:",headers)# Iterate over each row in the CSV dataforrowincsv_reader:# Process each row as neededprint(row)else:print("API failed with response code:{}, response content{}".format(response.status_code,response.text))exceptExceptionase:raiseRequestException(e)Rest sdk Usage to retrieve tokens used for subscribing to transaction events from PSL.fromrequests.exceptionsimportRequestExceptionfromnetskope_api.iterator.constimportConstfromnetskope_api.token_management.netskope_managementimportNetskopeTokenManagementif__name__=='__main__':params={Const.NSKP_TOKEN:"",Const.NSKP_TENANT_HOSTNAME:"<HOSTNAME>",# Optional param to pass the proxy hosts.Const.NSKP_PROXIES:{"<PROXY-HOSTS>"}}sub_path_response=Nonesub_key_response=Nonetry:# Create token_management clienttoken_management=NetskopeTokenManagement(params)token_management_response=token_management.get()iftoken_management_response:if"subscription"intoken_management_response:sub_path_response=token_management_response["subscription"]if"subscription-key"intoken_management_response:sub_key_response=token_management_response["subscription-key"]exceptExceptionase:raiseRequestException(e)1. 200 response code means Customer is authorized to create/get subscription key and path.

2. 401 response code means Customer is not authorized to create/get subscription key and path.
   This is a licensed feature, please contact Netskope support to purchase.

3. 403 response code means Netskope token used is not valid. Token is either expired or invalid.

4. 449 response code means Existing customer authorized for transaction events, subscription key and path were already downloaded.
   Use regenerate_and_get() to regenerate the subscription key.
   This is a one time step to onboard the existing customer to the API.When to use regenerate_and_get() API.regenerate_and_get() API must only be used if google-cloud-pubsublite throws 401 invalid credentials exception
while using subscription key and path retrieved by using Netskope API. Or to handle 449 response code.

Example error:
google.api_core.exceptions.Unauthenticated: 401 Request had invalid authentication credentials
grpc.aio._call.AioRpcError: <AioRpcError of RPC that terminated with:
status = StatusCode.UNAUTHENTICATED
details = "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential.

Regenerating subscription key will invalidate the existing key but subscription path will not be updated
so that clients can continue consuming events where they left off.How to use regenerate_and_get() API.1. regenerate_and_get() API must only be used if google-cloud-pubsublite throws 401 Request had invalid authentication credentials errors.
2. Retry 3 times with get() API with some Exponential backoff logic with an intial time interval of 60 seconds.
3. If the responses returned by get() API continues to be invalid credentials. Use regenerate_and_get() API and use the new credentials.Note: Regenerating subscription key will invalidate the existing key.fromrequests.exceptionsimportRequestExceptionfromnetskope_api.iterator.constimportConstfromnetskope_api.token_management.netskope_managementimportNetskopeTokenManagementif__name__=='__main__':params={Const.NSKP_TOKEN:"",Const.NSKP_TENANT_HOSTNAME:"<HOSTNAME>",# Optional param to pass the proxy hosts.Const.NSKP_PROXIES:{"<PROXY-HOSTS>"}}sub_path_response=Nonesub_key_response=Nonetry:# Create token_management clienttoken_management=NetskopeTokenManagement(params)token_management_response=token_management.regenerate_and_get()iftoken_management_response:if"subscription"intoken_management_response:sub_path_response=token_management_response["subscription"]if"subscription-key"intoken_management_response:sub_key_response=token_management_response["subscription-key"]exceptExceptionase:raiseRequestException(e)Example usage of web txn tokens using Pubsublite client libraryPlease install Pubsublite client library if not present.pipinstallgoogle-cloud-pubsubliteimportconcurrent.futuresimportloggingimportosfromconcurrent.futures._baseimportTimeoutErrorfromgoogle.cloud.pubsublite.cloudpubsubimportSubscriberClientfromgoogle.cloud.pubsublite.typesimportFlowControlSettings,MessageMetadatafromgoogle.pubsub_v1importPubsubMessagefromrequests.exceptionsimportRequestExceptionfromnetskope_api.iterator.constimportConstfromnetskope_api.token_management.netskope_managementimportNetskopeTokenManagement_logger=logging.getLogger()defcallback(message:PubsubMessage):message_data=message.data.decode("utf-8")metadata=MessageMetadata.decode(message.message_id)_logger.info(f"Received{message_data}of ordering key{message.ordering_key}with id{metadata}.")message.ack()classPSLSubscriberClient:def__init__(self):configs={"messages_outstanding":1000,"bytes_outstanding":3.5*1024*1024,"timeout":60,"thread_count":1}self.configs=configsdefmake_default_thread_pool_executor(self):returnconcurrent.futures.ThreadPoolExecutor(self.configs.get("thread_count"))defstream(self,subscription_path):globalstreaming_pull_futureper_partition_flow_control_settings=FlowControlSettings(# Must be >0.messages_outstanding=self.configs.get("messages_outstanding"),# Must be greater than the allowed size of the largest message.bytes_outstanding=self.configs.get("bytes_outstanding"),)executor=self.make_default_thread_pool_executor()withSubscriberClient(executor=executor)assubscriber_client:_logger.info("Listening for messages on the pub sub lite subscription{}".format(subscription_path))streaming_pull_future=subscriber_client.subscribe(subscription_path,callback=callback,per_partition_flow_control_settings=per_partition_flow_control_settings,)try:timeout=self.configs.get("timeout")iftimeout:streaming_pull_future.result(timeout=self.configs.get("timeout"))else:streaming_pull_future.result()exceptTimeoutErrororKeyboardInterrupt:streaming_pull_future.cancel()assertstreaming_pull_future.done()if__name__=='__main__':params={Const.NSKP_TOKEN:"",Const.NSKP_TENANT_HOSTNAME:"<HOSTNAME>",# Optional param to pass the proxy hosts.Const.NSKP_PROXIES:{"<PROXY-HOSTS>"}}sub_path_response=Nonesub_key_response=Nonetry:# Create token_management clienttoken_management=NetskopeTokenManagement(params)token_management_response=token_management.get()iftoken_management_response:if"subscription"intoken_management_response:sub_path_response=token_management_response["subscription"]if"subscription-key"intoken_management_response:sub_key_response=token_management_response["subscription-key"]exceptExceptionase:raiseRequestException(e)os.environ['GOOGLE_APPLICATION_CREDENTIALS']=sub_key_responsepsl_client=PSLSubscriberClient()psl_client.stream(subscription_path=sub_path_response)