Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
137 changes: 137 additions & 0 deletions cycode/cli/commands/configure/configure_command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
from typing import Optional

import click

from cycode.cli import config, consts
from cycode.cli.user_settings.configuration_manager import ConfigurationManager
from cycode.cli.user_settings.credentials_manager import CredentialsManager
from cycode.cli.utils.string_utils import obfuscate_text

_URLS_UPDATED_SUCCESSFULLY_MESSAGE = 'Successfully configured Cycode URLs! Saved to: {filename}'
_URLS_ARE_SET_IN_ENVIRONMENT_VARIABLES_MESSAGE = (
'Note that the URLs (APP and API) that already exist in environment variables '
f'({consts.CYCODE_API_URL_ENV_VAR_NAME} and {consts.CYCODE_APP_URL_ENV_VAR_NAME}) '
'take precedent over these URLs; either update or remove the environment variables.'
)
_CREDENTIALS_UPDATED_SUCCESSFULLY_MESSAGE = 'Successfully configured CLI credentials! Saved to: {filename}'
_CREDENTIALS_ARE_SET_IN_ENVIRONMENT_VARIABLES_MESSAGE = (
'Note that the credentials that already exist in environment variables '
f'({config.CYCODE_CLIENT_ID_ENV_VAR_NAME} and {config.CYCODE_CLIENT_SECRET_ENV_VAR_NAME}) '
'take precedent over these credentials; either update or remove the environment variables.'
)
_CREDENTIALS_MANAGER = CredentialsManager()
_CONFIGURATION_MANAGER = ConfigurationManager()


@click.command(short_help='Initial command to configure your CLI client authentication.')
def configure_command() -> None:
"""Configure your CLI client authentication manually."""
global_config_manager = _CONFIGURATION_MANAGER.global_config_file_manager

current_api_url = global_config_manager.get_api_url()
current_app_url = global_config_manager.get_app_url()
api_url = _get_api_url_input(current_api_url)
app_url = _get_app_url_input(current_app_url)

config_updated = False
if _should_update_value(current_api_url, api_url):
global_config_manager.update_api_base_url(api_url)
config_updated = True
if _should_update_value(current_app_url, app_url):
global_config_manager.update_app_base_url(app_url)
config_updated = True

current_client_id, current_client_secret = _CREDENTIALS_MANAGER.get_credentials_from_file()
client_id = _get_client_id_input(current_client_id)
client_secret = _get_client_secret_input(current_client_secret)

credentials_updated = False
if _should_update_value(current_client_id, client_id) or _should_update_value(current_client_secret, client_secret):
credentials_updated = True
_CREDENTIALS_MANAGER.update_credentials_file(client_id, client_secret)

if config_updated:
click.echo(_get_urls_update_result_message())
if credentials_updated:
click.echo(_get_credentials_update_result_message())


def _get_client_id_input(current_client_id: Optional[str]) -> Optional[str]:
prompt_text = 'Cycode Client ID'

prompt_suffix = ' (optional): '
if current_client_id:
prompt_suffix = f' [{obfuscate_text(current_client_id)}]: '

new_client_id = click.prompt(text=prompt_text, prompt_suffix=prompt_suffix, default='', show_default=False)
return new_client_id or current_client_id


def _get_client_secret_input(current_client_secret: Optional[str]) -> Optional[str]:
prompt_text = 'Cycode Client Secret'

prompt_suffix = ' (optional): '
if current_client_secret:
prompt_suffix = f' [{obfuscate_text(current_client_secret)}]: '

new_client_secret = click.prompt(text=prompt_text, prompt_suffix=prompt_suffix, default='', show_default=False)
return new_client_secret or current_client_secret


def _get_app_url_input(current_app_url: Optional[str]) -> str:
prompt_text = 'Cycode APP URL'

default = consts.DEFAULT_CYCODE_APP_URL
if current_app_url:
default = current_app_url

return click.prompt(text=prompt_text, default=default, type=click.STRING)


def _get_api_url_input(current_api_url: Optional[str]) -> str:
prompt_text = 'Cycode API URL'

default = consts.DEFAULT_CYCODE_API_URL
if current_api_url:
default = current_api_url

return click.prompt(text=prompt_text, default=default, type=click.STRING)


def _get_credentials_update_result_message() -> str:
success_message = _CREDENTIALS_UPDATED_SUCCESSFULLY_MESSAGE.format(filename=_CREDENTIALS_MANAGER.get_filename())
if _are_credentials_exist_in_environment_variables():
return f'{success_message}. {_CREDENTIALS_ARE_SET_IN_ENVIRONMENT_VARIABLES_MESSAGE}'

return success_message


def _are_credentials_exist_in_environment_variables() -> bool:
client_id, client_secret = _CREDENTIALS_MANAGER.get_credentials_from_environment_variables()
return any([client_id, client_secret])


def _get_urls_update_result_message() -> str:
success_message = _URLS_UPDATED_SUCCESSFULLY_MESSAGE.format(
filename=_CONFIGURATION_MANAGER.global_config_file_manager.get_filename()
)
if _are_urls_exist_in_environment_variables():
return f'{success_message}. {_URLS_ARE_SET_IN_ENVIRONMENT_VARIABLES_MESSAGE}'

return success_message


def _are_urls_exist_in_environment_variables() -> bool:
api_url = _CONFIGURATION_MANAGER.get_api_url_from_environment_variables()
app_url = _CONFIGURATION_MANAGER.get_app_url_from_environment_variables()
return any([api_url, app_url])


def _should_update_value(
old_value: Optional[str],
new_value: Optional[str],
) -> bool:
if not new_value:
return False

return old_value != new_value
Empty file.
Original file line number Diff line number Diff line change
@@ -1,41 +1,21 @@
import os.path
import os
import re
from typing import Optional

import click

from cycode.cli import consts
from cycode.cli.config import config, configuration_manager
from cycode.cli.user_settings.credentials_manager import CredentialsManager
from cycode.cli.utils.path_utils import get_absolute_path
from cycode.cli.utils.string_utils import hash_string_to_sha256, obfuscate_text
from cycode.cli.utils.string_utils import hash_string_to_sha256
from cycode.cyclient import logger

CREDENTIALS_UPDATED_SUCCESSFULLY_MESSAGE = 'Successfully configured CLI credentials!'
CREDENTIALS_ARE_SET_IN_ENVIRONMENT_VARIABLES_MESSAGE = (
'Note that the credentials that already exist in environment'
' variables (CYCODE_CLIENT_ID and CYCODE_CLIENT_SECRET) take'
' precedent over these credentials; either update or remove '
'the environment variables.'
)
credentials_manager = CredentialsManager()


@click.command(
short_help='Initial command to authenticate your CLI client with Cycode using a client ID and client secret.'
)
def set_credentials() -> None:
"""Authenticates your CLI client with Cycode manually by using a client ID and client secret."""
click.echo(f'Update credentials in file ({credentials_manager.get_filename()})')
current_client_id, current_client_secret = credentials_manager.get_credentials_from_file()
client_id = _get_client_id_input(current_client_id)
client_secret = _get_client_secret_input(current_client_secret)
def _is_path_to_ignore_exists(path: str) -> bool:
return os.path.exists(path)

if not _should_update_credentials(current_client_id, current_client_secret, client_id, client_secret):
return

credentials_manager.update_credentials_file(client_id, client_secret)
click.echo(_get_credentials_update_result_message())
def _is_package_pattern_valid(package: str) -> bool:
return re.search('^[^@]+@[^@]+$', package) is not None


@click.command(short_help='Ignores a specific value, path or rule ID.')
Expand Down Expand Up @@ -83,7 +63,7 @@ def set_credentials() -> None:
required=False,
help='Add an ignore rule to the global CLI config.',
)
def add_exclusions(
def ignore_command(
by_value: str, by_sha: str, by_path: str, by_rule: str, by_package: str, scan_type: str, is_global: bool
) -> None:
"""Ignores a specific value, path or rule ID."""
Expand Down Expand Up @@ -126,48 +106,3 @@ def add_exclusions(
},
)
configuration_manager.add_exclusion(configuration_scope, scan_type, exclusion_type, exclusion_value)


def _get_client_id_input(current_client_id: str) -> str:
new_client_id = click.prompt(
f'cycode client id [{_obfuscate_credential(current_client_id)}]', default='', show_default=False
)

return new_client_id if new_client_id else current_client_id


def _get_client_secret_input(current_client_secret: str) -> str:
new_client_secret = click.prompt(
f'cycode client secret [{_obfuscate_credential(current_client_secret)}]', default='', show_default=False
)
return new_client_secret if new_client_secret else current_client_secret


def _get_credentials_update_result_message() -> str:
if not _are_credentials_exist_in_environment_variables():
return CREDENTIALS_UPDATED_SUCCESSFULLY_MESSAGE

return CREDENTIALS_UPDATED_SUCCESSFULLY_MESSAGE + ' ' + CREDENTIALS_ARE_SET_IN_ENVIRONMENT_VARIABLES_MESSAGE


def _are_credentials_exist_in_environment_variables() -> bool:
client_id, client_secret = credentials_manager.get_credentials_from_environment_variables()
return client_id is not None or client_secret is not None


def _should_update_credentials(
current_client_id: str, current_client_secret: str, new_client_id: str, new_client_secret: str
) -> bool:
return current_client_id != new_client_id or current_client_secret != new_client_secret


def _obfuscate_credential(credential: Optional[str]) -> str:
return '' if not credential else obfuscate_text(credential)


def _is_path_to_ignore_exists(path: str) -> bool:
return os.path.exists(path)


def _is_package_pattern_valid(package: str) -> bool:
return re.search('^[^@]+@[^@]+$', package) is not None
7 changes: 4 additions & 3 deletions cycode/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from cycode import __version__
from cycode.cli import code_scanner
from cycode.cli.auth.auth_command import authenticate
from cycode.cli.commands.configure.configure_command import configure_command
from cycode.cli.commands.ignore.ignore_command import ignore_command
from cycode.cli.commands.report.report_command import report_command
from cycode.cli.config import config
from cycode.cli.consts import (
Expand All @@ -19,7 +21,6 @@
)
from cycode.cli.models import Severity
from cycode.cli.user_settings.configuration_manager import ConfigurationManager
from cycode.cli.user_settings.user_settings_commands import add_exclusions, set_credentials
from cycode.cli.utils import scan_utils
from cycode.cli.utils.get_api_client import get_scan_cycode_client
from cycode.cli.utils.progress_bar import SCAN_PROGRESS_BAR_SECTIONS, get_progress_bar
Expand Down Expand Up @@ -183,8 +184,8 @@ def version(context: click.Context) -> None:
commands={
'scan': code_scan,
'report': report_command,
'configure': set_credentials,
'ignore': add_exclusions,
'configure': configure_command,
'ignore': ignore_command,
'auth': authenticate,
'version': version,
},
Expand Down
8 changes: 6 additions & 2 deletions cycode/cli/user_settings/config_file_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,12 @@ def get_exclude_detections_in_deleted_lines(self, command_scan_type: str) -> Opt
command_scan_type, self.EXCLUDE_DETECTIONS_IN_DELETED_LINES
)

def update_base_url(self, base_url: str) -> None:
update_data = {self.ENVIRONMENT_SECTION_NAME: {self.API_URL_FIELD_NAME: base_url}}
def update_api_base_url(self, api_url: str) -> None:
update_data = {self.ENVIRONMENT_SECTION_NAME: {self.API_URL_FIELD_NAME: api_url}}
self.write_content_to_file(update_data)

def update_app_base_url(self, app_url: str) -> None:
update_data = {self.ENVIRONMENT_SECTION_NAME: {self.APP_URL_FIELD_NAME: app_url}}
self.write_content_to_file(update_data)

def get_installation_id(self) -> Optional[str]:
Expand Down
4 changes: 0 additions & 4 deletions cycode/cli/user_settings/configuration_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,6 @@ def _merge_exclusions(self, local_exclusions: Dict, global_exclusions: Dict) ->
keys = set(list(local_exclusions.keys()) + list(global_exclusions.keys()))
return {key: local_exclusions.get(key, []) + global_exclusions.get(key, []) for key in keys}

def update_base_url(self, base_url: str, scope: str = 'local') -> None:
config_file_manager = self.get_config_file_manager(scope)
config_file_manager.update_base_url(base_url)

def get_or_create_installation_id(self) -> str:
config_file_manager = self.get_config_file_manager()

Expand Down
Loading