diff --git a/docs/api/ad/application_settings.rst b/docs/api/ad/application_settings.rst new file mode 100644 index 000000000..5dc4f8d93 --- /dev/null +++ b/docs/api/ad/application_settings.rst @@ -0,0 +1 @@ +.. automodule:: tenable.ad.application_settings.api diff --git a/tenable/ad/__init__.py b/tenable/ad/__init__.py index 3edddf3a7..9430ebfed 100644 --- a/tenable/ad/__init__.py +++ b/tenable/ad/__init__.py @@ -16,6 +16,7 @@ alert api_keys attack_types + application_settings category checker checker_option diff --git a/tenable/ad/application_settings/__init__.py b/tenable/ad/application_settings/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tenable/ad/application_settings/api.py b/tenable/ad/application_settings/api.py new file mode 100644 index 000000000..0a94d5cd4 --- /dev/null +++ b/tenable/ad/application_settings/api.py @@ -0,0 +1,76 @@ +''' +Application Settings +============= + +Methods described in this section relate to the application settings API. +These methods can be accessed at ``TenableAD.application_settings``. + +.. rst-class:: hide-signature +.. autoclass:: ApplicationSettingsAPI + :members: +''' +from typing import Dict +from tenable.ad.application_settings.schema import ApplicationSettingsSchema +from tenable.base.endpoint import APIEndpoint + + +class ApplicationSettingsAPI(APIEndpoint): + _path = 'application-settings' + _schema = ApplicationSettingsSchema() + + def details(self) -> Dict: + ''' + Get the application settings + + Returns: + dict: + The application settings objects + + Examples: + >>> tad.application_settings.get_settings() + ''' + return self._schema.load(self._get()) + + def update(self, + **kwargs + ) -> Dict: + ''' + Update the application settings + + Args: + smtp_server_address (optional, str): + The IP address of the SMTP server to use to send mails. + smtp_server_port (optional, int): + The port of SMTP server to use to send mails. + smtp_account (optional, str): + The login to use to authenticate against SMTP server. + smtp_account_password (optional, str): + The password to use to authenticate against SMTP server. + smtp_use_start_tls (optional, bool): + Whether the startTLS SMTP command should be used to secure + the connection to the SMTP server? + tls (optional, bool): + Whether the configured server should connect using TLS? + email_sender (optional, str): + The email address to display as the sender in the emails sent. + default_role_ids (optional, list[int]): + The default role identifiers. + default_profile_id (optional, int): + The default profile identifier. + internal_certificate (optional, str): + The certificate chain to use to verify certificates on TLS + connections. + + Return: + dict: + The application settings objects + + Example: + >>> tad.application_settings.update_settings( + ... smtp_use_start_tls=True, + ... tls=False, + ... default_profile_id=1, + ... ) + ''' + payload = self._schema.dump(self._schema.load(kwargs)) + return self._schema.load(self._patch(json=payload)) diff --git a/tenable/ad/application_settings/schema.py b/tenable/ad/application_settings/schema.py new file mode 100644 index 000000000..4cfe6a7e3 --- /dev/null +++ b/tenable/ad/application_settings/schema.py @@ -0,0 +1,23 @@ +from marshmallow import fields +from tenable.ad.base.schema import CamelCaseSchema, last_word_uppercase + + +class ApplicationSettingsSchema(CamelCaseSchema): + class Meta: + case_convertors = { + 'smtp_use_start_tls': last_word_uppercase + } + + user_registration = fields.Bool() + keep_audit_log = fields.Bool() + log_retention_period = fields.Int() + smtp_server_address = fields.Str(allow_none=True) + smtp_server_port = fields.Int(allow_none=True) + smtp_account = fields.Str(allow_none=True) + smtp_account_password = fields.Str(allow_none=True) + smtp_use_start_tls = fields.Bool() + tls = fields.Bool() + email_sender = fields.Str() + default_role_ids = fields.List(fields.Int()) + default_profile_id = fields.Int() + internal_certificate = fields.Str(allow_none=True) diff --git a/tenable/ad/session.py b/tenable/ad/session.py index 932eef0c5..b6ff2efa4 100644 --- a/tenable/ad/session.py +++ b/tenable/ad/session.py @@ -9,6 +9,7 @@ from .about import AboutAPI from .alert.api import AlertsAPI from .api_keys import APIKeyAPI +from .application_settings.api import ApplicationSettingsAPI from .attack_types.api import AttackTypesAPI from .category.api import CategoryAPI from .checker.api import CheckerAPI @@ -80,6 +81,14 @@ def api_keys(self): ''' return APIKeyAPI(self) + @property + def application_settings(self): + ''' + The interface object for the + :doc:`Tenable.ad Application Settings APIs `. + ''' + return ApplicationSettingsAPI(self) + @property def attack_types(self): ''' diff --git a/tests/ad/application_settings/test_application_setting_api.py b/tests/ad/application_settings/test_application_setting_api.py new file mode 100644 index 000000000..1aad55ad1 --- /dev/null +++ b/tests/ad/application_settings/test_application_setting_api.py @@ -0,0 +1,58 @@ +import responses + +from tests.ad.conftest import RE_BASE + + +@responses.activate +def test_application_settings_details(api): + responses.add(responses.GET, + f'{RE_BASE}/application-settings', + json={ + 'default_profile_id': 1, + 'default_role_ids': [2], + 'email_sender': 'default@tenable.ad', + 'internal_certificate': None, + 'keep_audit_log': True, + 'log_retention_period': 365, + 'smtp_account': None, + 'smtp_account_password': None, + 'smtp_server_address': None, + 'smtp_server_port': None, + 'smtp_use_start_tls': True, + 'tls': False, + 'user_registration': False + } + ) + resp = api.application_settings.details() + assert isinstance(resp, dict) + assert resp['default_profile_id'] == 1 + assert resp['log_retention_period'] == 365 + assert resp['smtp_use_start_tls'] is True + + +@responses.activate +def test_application_settings_update(api): + responses.add(responses.PATCH, + f'{RE_BASE}/application-settings', + json={ + 'default_profile_id': 1, + 'default_role_ids': [2], + 'email_sender': 'default@tenable.ad', + 'internal_certificate': None, + 'keep_audit_log': True, + 'log_retention_period': 300, + 'smtp_account': None, + 'smtp_account_password': None, + 'smtp_server_address': None, + 'smtp_server_port': None, + 'smtp_use_start_tls': False, + 'tls': False, + 'user_registration': False + } + ) + resp = api.application_settings.update( + smtp_use_start_tls=False, + ) + assert isinstance(resp, dict) + assert resp['default_profile_id'] == 1 + assert resp['smtp_use_start_tls'] is False diff --git a/tests/ad/application_settings/test_application_setting_schema.py b/tests/ad/application_settings/test_application_setting_schema.py new file mode 100644 index 000000000..c9b591200 --- /dev/null +++ b/tests/ad/application_settings/test_application_setting_schema.py @@ -0,0 +1,53 @@ +''' +Testing the application setting schema +''' +import pytest +from marshmallow import ValidationError +from tenable.ad.application_settings.schema import ApplicationSettingsSchema + + +@pytest.fixture() +def application_setting_schema(): + return { + 'default_profile_id': 1, + 'default_role_ids': [2], + 'email_sender': 'default@tenable.ad', + 'internal_certificate': None, + 'smtp_account': None, + 'smtp_account_password': None, + 'smtp_server_address': None, + 'smtp_server_port': None, + 'smtp_use_start_tls': False, + 'tls': False + } + + +def test_application_setting_schema(application_setting_schema): + ''' + test application setting schema + ''' + test_resp = { + 'defaultProfileId': 1, + 'defaultRoleIds': [2], + 'emailSender': 'default@tenable.ad', + 'internalCertificate': None, + 'keepAuditLog': True, + 'logRetentionPeriod': 300, + 'smtpAccount': None, + 'smtpAccountPassword': None, + 'smtpServerAddress': None, + 'smtpServerPort': None, + 'smtpUseStartTLS': False, + 'tls': False, + 'userRegistration': False + } + + schema = ApplicationSettingsSchema() + req = schema.dump(schema.load(application_setting_schema)) + assert test_resp['defaultProfileId'] == req['defaultProfileId'] + assert test_resp['emailSender'] == req['emailSender'] + assert test_resp['smtpUseStartTLS'] == req['smtpUseStartTLS'] + + with pytest.raises(ValidationError): + application_setting_schema['some_val'] = 'something' + schema.load(application_setting_schema)