diff --git a/synology_dsm/api/core/security.py b/synology_dsm/api/core/security.py new file mode 100644 index 0000000..aa4644d --- /dev/null +++ b/synology_dsm/api/core/security.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +"""DSM Security data.""" + + +class SynoCoreSecurity(object): + """Class containing Security data.""" + + API_KEY = "SYNO.Core.SecurityScan.Status" + + def __init__(self, raw_data): + self._data = {} + self.update(raw_data) + + def update(self, raw_data): + """Updates security data.""" + if raw_data: + self._data = raw_data["data"] + + @property + def checks(self): + """Gets the checklist.""" + return self._data.get("items", {}) + + @property + def last_scan_time(self): + """Gets the last scan time.""" + return self._data.get("lastScanTime") + + @property + def start_time(self): + """Gets the start time (if in progress).""" + return self._data.get("startTime") + + @property + def success(self): + """Gets the last scan success.""" + return self._data.get("success") + + @property + def progress(self): + """Gets the scan progress (100 if finished).""" + return self._data.get("sysProgress") + + @property + def status(self): + """Gets the last scan status (safe, ...).""" + return self._data.get("sysStatus") diff --git a/synology_dsm/synology_dsm.py b/synology_dsm/synology_dsm.py index 3f8c2b3..b624be2 100644 --- a/synology_dsm/synology_dsm.py +++ b/synology_dsm/synology_dsm.py @@ -17,6 +17,7 @@ from .exceptions import ( SynologyDSMLogin2SARequiredException, SynologyDSMLogin2SAFailedException, ) +from .api.core.security import SynoCoreSecurity from .api.core.utilization import SynoCoreUtilization from .api.dsm.information import SynoDSMInformation from .api.dsm.network import SynoDSMNetwork @@ -62,6 +63,7 @@ class SynologyDSM(object): } self._information = None self._network = None + self._security = None self._utilisation = None self._storage = None @@ -259,6 +261,10 @@ class SynologyDSM(object): data = self.get(SynoDSMInformation.API_KEY, "getinfo") self._information.update(data) + if self._security: + data = self.get(SynoCoreSecurity.API_KEY, "system_get") + self._security = SynoCoreSecurity(data) + if self._utilisation: data = self.get(SynoCoreUtilization.API_KEY, "get") self._utilisation.update(data) @@ -283,6 +289,14 @@ class SynologyDSM(object): self._network = SynoDSMNetwork(data) return self._network + @property + def security(self): + """Gets NAS security informations.""" + if not self._security: + data = self.get(SynoCoreSecurity.API_KEY, "system_get") + self._security = SynoCoreSecurity(data) + return self._security + @property def utilisation(self): """Gets NAS utilisation informations.""" diff --git a/tests/__init__.py b/tests/__init__.py index 82b60e5..8501e3d 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -6,6 +6,7 @@ from simplejson.errors import JSONDecodeError from synology_dsm import SynologyDSM from synology_dsm.exceptions import SynologyDSMRequestException +from synology_dsm.api.core.security import SynoCoreSecurity from synology_dsm.api.core.utilization import SynoCoreUtilization from synology_dsm.api.dsm.information import SynoDSMInformation from synology_dsm.api.dsm.network import SynoDSMNetwork @@ -25,6 +26,7 @@ from .api_data.dsm_6 import ( DSM_6_DSM_INFORMATION, DSM_6_DSM_NETWORK, DSM_6_CORE_UTILIZATION, + DSM_6_CORE_SECURITY, DSM_6_STORAGE_STORAGE_DS213_PLUS_SHR1_2DISKS_2VOLS, DSM_6_STORAGE_STORAGE_DS918_PLUS_RAID5_3DISKS_1VOL, DSM_6_STORAGE_STORAGE_DS1819_PLUS_SHR2_8DISKS_1VOL, @@ -59,6 +61,7 @@ API_SWITCHER = { "AUTH_LOGIN_2SA_OTP": DSM_6_AUTH_LOGIN_2SA_OTP, "DSM_INFORMATION": DSM_6_DSM_INFORMATION, "DSM_NETWORK": DSM_6_DSM_NETWORK, + "CORE_SECURITY": DSM_6_CORE_SECURITY, "CORE_UTILIZATION": DSM_6_CORE_UTILIZATION, "STORAGE_STORAGE": { "RAID": DSM_6_STORAGE_STORAGE_DS918_PLUS_RAID5_3DISKS_1VOL, @@ -176,6 +179,9 @@ class SynologyDSMMock(SynologyDSM): if SynoDSMNetwork.API_KEY in url: return API_SWITCHER[self.dsm_version]["DSM_NETWORK"] + if SynoCoreSecurity.API_KEY in url: + return API_SWITCHER[self.dsm_version]["CORE_SECURITY"] + if SynoCoreUtilization.API_KEY in url: return API_SWITCHER[self.dsm_version]["CORE_UTILIZATION"] diff --git a/tests/api_data/dsm_6/__init__.py b/tests/api_data/dsm_6/__init__.py index aeb1e09..5ed17ad 100644 --- a/tests/api_data/dsm_6/__init__.py +++ b/tests/api_data/dsm_6/__init__.py @@ -6,6 +6,7 @@ from .const_6_api_auth import ( DSM_6_AUTH_LOGIN_2SA_OTP, ) from .core.const_6_core_utilization import DSM_6_CORE_UTILIZATION +from .core.const_6_core_security import DSM_6_CORE_SECURITY from .dsm.const_6_dsm_info import DSM_6_DSM_INFORMATION from .dsm.const_6_dsm_network import DSM_6_DSM_NETWORK from .storage.const_6_storage_storage import ( diff --git a/tests/api_data/dsm_6/core/const_6_core_security.py b/tests/api_data/dsm_6/core/const_6_core_security.py new file mode 100644 index 0000000..edef53d --- /dev/null +++ b/tests/api_data/dsm_6/core/const_6_core_security.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +"""DSM 6 SYNO.Core.SecurityScan.Status data.""" + +DSM_6_CORE_SECURITY = { + "data": { + "items": { + "malware": { + "category": "malware", + "fail": { + "danger": 0, + "info": 0, + "outOfDate": 0, + "risk": 0, + "warning": 0, + }, + "failSeverity": "safe", + "progress": 100, + "runningItem": "", + "total": 3, + "waitNum": 0, + }, + "network": { + "category": "network", + "fail": { + "danger": 0, + "info": 0, + "outOfDate": 0, + "risk": 0, + "warning": 0, + }, + "failSeverity": "safe", + "progress": 100, + "runningItem": "", + "total": 4, + "waitNum": 0, + }, + "securitySetting": { + "category": "securitySetting", + "fail": { + "danger": 0, + "info": 0, + "outOfDate": 0, + "risk": 0, + "warning": 0, + }, + "failSeverity": "safe", + "progress": 100, + "runningItem": "", + "total": 0, + "waitNum": 0, + }, + "systemCheck": { + "category": "systemCheck", + "fail": { + "danger": 0, + "info": 0, + "outOfDate": 0, + "risk": 0, + "warning": 0, + }, + "failSeverity": "safe", + "progress": 100, + "runningItem": "", + "total": 6, + "waitNum": 0, + }, + "update": { + "category": "update", + "fail": { + "danger": 0, + "info": 0, + "outOfDate": 0, + "risk": 0, + "warning": 0, + }, + "failSeverity": "safe", + "progress": 100, + "runningItem": "", + "total": 4, + "waitNum": 0, + }, + "userInfo": { + "category": "userInfo", + "fail": { + "danger": 0, + "info": 0, + "outOfDate": 0, + "risk": 0, + "warning": 0, + }, + "failSeverity": "safe", + "progress": 100, + "runningItem": "", + "total": 6, + "waitNum": 0, + }, + }, + "lastScanTime": "1588298442", + "startTime": "", + "success": True, + "sysProgress": 100, + "sysStatus": "safe", + }, + "success": True, +} diff --git a/tests/test_synology_dsm.py b/tests/test_synology_dsm.py index 6d934ad..6447370 100644 --- a/tests/test_synology_dsm.py +++ b/tests/test_synology_dsm.py @@ -212,6 +212,16 @@ class TestSynologyDSM(TestCase): assert self.api.network.macs assert self.api.network.workgroup + def test_security(self): + """Test security.""" + assert self.api.security + assert self.api.security.checks + assert self.api.security.last_scan_time + assert not self.api.security.start_time # Finished scan + assert self.api.security.success + assert self.api.security.progress + assert self.api.security.status + def test_utilisation(self): """Test utilization.""" assert self.api.utilisation