Skip to content

Commit

Permalink
feat: add implementation of AppTotal API endpoints
Browse files Browse the repository at this point in the history
docs: add docstrings and docs
tests: add tests for AppTotal API endpoints

Signed-off-by: mkelly <[email protected]>
  • Loading branch information
mitchos committed Sep 14, 2023
1 parent 22313c9 commit 66a640a
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 0 deletions.
11 changes: 11 additions & 0 deletions docsrc/zs/zia/apptotal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
apptotal
============

The following methods allow for interaction with the ZIA AppTotal API endpoints.

Methods are accessible via ``zia.apptotal``

.. _zia-apptotal:

.. automodule:: pyzscaler.zia.apptotal
:members:
9 changes: 9 additions & 0 deletions pyzscaler/zia/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from pyzscaler import __version__

from .admin_and_role_management import AdminAndRoleManagementAPI
from .apptotal import AppTotalAPI
from .audit_logs import AuditLogsAPI
from .config import ActivationAPI
from .dlp import DLPAPI
Expand Down Expand Up @@ -99,6 +100,14 @@ def admin_and_role_management(self):
"""
return AdminAndRoleManagementAPI(self)

@property
def apptotal(self):
"""
The interface object for the :ref:`ZIA AppTotal interface <zia-apptotal>`.
"""
return AppTotalAPI(self)

@property
def audit_logs(self):
"""
Expand Down
51 changes: 51 additions & 0 deletions pyzscaler/zia/apptotal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from box import Box
from restfly.endpoint import APIEndpoint


class AppTotalAPI(APIEndpoint):
def get_app(self, app_id: str, verbose: bool = False) -> Box:
"""
Searches the AppTotal App Catalog by app ID. If the app exists in the catalog, the app's information is
returned. If not, the app is submitted for analysis. After analysis is complete, a subsequent GET request is
required to fetch the app's information.
Args:
app_id (str): The app ID to search for.
verbose (bool, optional): Defaults to False.
Returns:
:obj:`Box`: The response object.
Examples:
Return verbose information on an app with ID 12345::
zia.apptotal.get_app(app_id="12345", verbose=True)
"""
params = {
"app_id": app_id,
"verbose": verbose,
}
return self._get("apps/app", params=params)

def scan_app(self, app_id: str) -> Box:
"""
Submits an app for analysis in the AppTotal Sandbox. After analysis is complete, a subsequent GET request is
required to fetch the app's information.
Args:
app_id (str): The app ID to scan.
Returns:
:obj:`Box`: The response object.
Examples:
Scan an app with ID 12345::
zia.apptotal.scan_app(app_id="12345")
"""
payload = {
"appId": app_id,
}
return self._post("apps/app", json=payload)
27 changes: 27 additions & 0 deletions tests/zia/test_apptotal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import responses
from box import Box


@responses.activate
def test_get_app(zia):
app_info = {"id": "12345", "name": "AppName", "verbose": False}
responses.add(
method="GET", url="https://zsapi.zscaler.net/api/v1/apps/app?app_id=12345&verbose=False", json=app_info, status=200
)
resp = zia.apptotal.get_app(app_id="12345", verbose=False)
assert isinstance(resp, Box)
assert resp.id == "12345"
assert resp.name == "AppName"


@responses.activate
def test_scan_app(zia):
scan_status = {
"id": "12345",
"status": "Scanned",
}
responses.add(method="POST", url="https://zsapi.zscaler.net/api/v1/apps/app", json=scan_status, status=200)
resp = zia.apptotal.scan_app(app_id="12345")
assert isinstance(resp, Box)
assert resp.id == "12345"
assert resp.status == "Scanned"

0 comments on commit 66a640a

Please sign in to comment.