diff --git a/cycode/cli/consts.py b/cycode/cli/consts.py index 27730720..65db60c4 100644 --- a/cycode/cli/consts.py +++ b/cycode/cli/consts.py @@ -107,8 +107,9 @@ COMMIT_RANGE_BASED_COMMAND_SCAN_TYPES = [PRE_RECEIVE_COMMAND_SCAN_TYPE, COMMIT_HISTORY_COMMAND_SCAN_TYPE] -DEFAULT_CYCODE_API_URL = 'https://api.cycode.com' -DEFAULT_CYCODE_APP_URL = 'https://app.cycode.com' +DEFAULT_CYCODE_DOMAIN = 'cycode.com' +DEFAULT_CYCODE_API_URL = f'https://api.{DEFAULT_CYCODE_DOMAIN}' +DEFAULT_CYCODE_APP_URL = f'https://app.{DEFAULT_CYCODE_DOMAIN}' # env var names CYCODE_API_URL_ENV_VAR_NAME = 'CYCODE_API_URL' diff --git a/cycode/cli/sentry.py b/cycode/cli/sentry.py index 44e55945..e132bcf8 100644 --- a/cycode/cli/sentry.py +++ b/cycode/cli/sentry.py @@ -4,12 +4,16 @@ import sentry_sdk from sentry_sdk.integrations.atexit import AtexitIntegration +from sentry_sdk.integrations.dedupe import DedupeIntegration +from sentry_sdk.integrations.excepthook import ExcepthookIntegration +from sentry_sdk.integrations.logging import LoggingIntegration from sentry_sdk.scrubber import DEFAULT_DENYLIST, EventScrubber from cycode import __version__ from cycode.cli import consts from cycode.cli.utils.jwt_utils import get_user_and_tenant_ids_from_access_token from cycode.cyclient import logger +from cycode.cyclient.config import on_premise_installation # when Sentry is blocked on the machine, we want to keep clean output without retries warnings logging.getLogger('urllib3.connectionpool').setLevel(logging.ERROR) @@ -36,9 +40,14 @@ def _get_sentry_local_release() -> str: _SENTRY_LOCAL_RELEASE = _get_sentry_local_release() +_SENTRY_DISABLED = on_premise_installation def _before_sentry_event_send(event: dict, _: dict) -> Optional[dict]: + if _SENTRY_DISABLED: + # drop all events when Sentry is disabled + return None + if event.get('release') == _SENTRY_LOCAL_RELEASE: logger.debug('Dropping Sentry event due to local development setup') return None @@ -58,8 +67,12 @@ def init_sentry() -> None: include_local_variables=consts.SENTRY_INCLUDE_LOCAL_VARIABLES, max_request_body_size=consts.SENTRY_MAX_REQUEST_BODY_SIZE, event_scrubber=EventScrubber(denylist=_DENY_LIST, recursive=True), + default_integrations=False, integrations=[ - AtexitIntegration(lambda _, __: None) # disable output to stderr about pending events + AtexitIntegration(lambda _, __: None), # disable output to stderr about pending events + ExcepthookIntegration(), + DedupeIntegration(), + LoggingIntegration(), ], ) diff --git a/cycode/cli/user_settings/base_file_manager.py b/cycode/cli/user_settings/base_file_manager.py index 37c9b0de..778b8d23 100644 --- a/cycode/cli/user_settings/base_file_manager.py +++ b/cycode/cli/user_settings/base_file_manager.py @@ -11,10 +11,7 @@ def get_filename(self) -> str: ... def read_file(self) -> Dict[Hashable, Any]: - try: - return read_file(self.get_filename()) - except FileNotFoundError: - return {} + return read_file(self.get_filename()) def write_content_to_file(self, content: Dict[Hashable, Any]) -> None: filename = self.get_filename() diff --git a/cycode/cli/utils/yaml_utils.py b/cycode/cli/utils/yaml_utils.py index 3f910537..251b6c24 100644 --- a/cycode/cli/utils/yaml_utils.py +++ b/cycode/cli/utils/yaml_utils.py @@ -1,23 +1,33 @@ -from typing import Any, Dict, Hashable +import os +from typing import Any, Dict, Hashable, TextIO import yaml +def _yaml_safe_load(file: TextIO) -> Dict[Hashable, Any]: + # loader.get_single_data could return None + loaded_file = yaml.safe_load(file) + if loaded_file is None: + return {} + + return loaded_file + + def read_file(filename: str) -> Dict[Hashable, Any]: - with open(filename, 'r', encoding='UTF-8') as file: - return yaml.safe_load(file) + if not os.path.exists(filename): + return {} + with open(filename, 'r', encoding='UTF-8') as file: + return _yaml_safe_load(file) -def update_file(filename: str, content: Dict[Hashable, Any]) -> None: - try: - with open(filename, 'r', encoding='UTF-8') as file: - file_content = yaml.safe_load(file) - except FileNotFoundError: - file_content = {} +def write_file(filename: str, content: Dict[Hashable, Any]) -> None: with open(filename, 'w', encoding='UTF-8') as file: - file_content = _deep_update(file_content, content) - yaml.safe_dump(file_content, file) + yaml.safe_dump(content, file) + + +def update_file(filename: str, content: Dict[Hashable, Any]) -> None: + write_file(filename, _deep_update(read_file(filename), content)) def _deep_update(source: Dict[Hashable, Any], overrides: Dict[Hashable, Any]) -> Dict[Hashable, Any]: @@ -26,4 +36,5 @@ def _deep_update(source: Dict[Hashable, Any], overrides: Dict[Hashable, Any]) -> source[key] = _deep_update(source.get(key, {}), value) else: source[key] = overrides[key] + return source diff --git a/cycode/cyclient/config.py b/cycode/cyclient/config.py index 926723d1..37183195 100644 --- a/cycode/cyclient/config.py +++ b/cycode/cyclient/config.py @@ -106,6 +106,13 @@ def is_valid_url(url: str) -> bool: ) cycode_api_url = consts.DEFAULT_CYCODE_API_URL + +def _is_on_premise_installation(cycode_domain: str) -> bool: + return not cycode_api_url.endswith(cycode_domain) + + +on_premise_installation = _is_on_premise_installation(consts.DEFAULT_CYCODE_DOMAIN) + timeout = get_val_as_int(consts.CYCODE_CLI_REQUEST_TIMEOUT_ENV_VAR_NAME) if not timeout: timeout = get_val_as_int(consts.TIMEOUT_ENV_VAR_NAME) diff --git a/tests/cyclient/test_config.py b/tests/cyclient/test_config.py new file mode 100644 index 00000000..c78a5f5d --- /dev/null +++ b/tests/cyclient/test_config.py @@ -0,0 +1,24 @@ +from typing import TYPE_CHECKING + +from cycode.cli.consts import DEFAULT_CYCODE_DOMAIN +from cycode.cyclient.config import _is_on_premise_installation + +if TYPE_CHECKING: + from _pytest.monkeypatch import MonkeyPatch + + +def test_is_on_premise_installation(monkeypatch: 'MonkeyPatch') -> None: + monkeypatch.setattr('cycode.cyclient.config.cycode_api_url', 'api.cycode.com') + assert not _is_on_premise_installation(DEFAULT_CYCODE_DOMAIN) + monkeypatch.setattr('cycode.cyclient.config.cycode_api_url', 'api.eu.cycode.com') + assert not _is_on_premise_installation(DEFAULT_CYCODE_DOMAIN) + + monkeypatch.setattr('cycode.cyclient.config.cycode_api_url', 'cycode.google.com') + assert _is_on_premise_installation(DEFAULT_CYCODE_DOMAIN) + monkeypatch.setattr('cycode.cyclient.config.cycode_api_url', 'cycode.blabla.google.com') + assert _is_on_premise_installation(DEFAULT_CYCODE_DOMAIN) + + monkeypatch.setattr('cycode.cyclient.config.cycode_api_url', 'api.cycode.com') + assert _is_on_premise_installation('blabla') + monkeypatch.setattr('cycode.cyclient.config.cycode_api_url', 'cycode.blabla.google.com') + assert _is_on_premise_installation('blabla')