cycode 3.7.2.dev1__tar.gz → 3.7.2.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/PKG-INFO +16 -5
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/README.md +15 -4
- cycode-3.7.2.dev2/cycode/__init__.py +1 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/app.py +8 -0
- cycode-3.7.2.dev2/cycode/cli/apps/auth/auth_common.py +69 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/configure/configure_command.py +10 -1
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/configure/prompts.py +11 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/config.py +1 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/user_settings/credentials_manager.py +25 -1
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/utils/get_api_client.py +27 -5
- cycode-3.7.2.dev1/cycode/cyclient/cycode_token_based_client.py → cycode-3.7.2.dev2/cycode/cyclient/base_token_auth_client.py +21 -18
- cycode-3.7.2.dev2/cycode/cyclient/client_creator.py +51 -0
- cycode-3.7.2.dev2/cycode/cyclient/cycode_oidc_based_client.py +24 -0
- cycode-3.7.2.dev2/cycode/cyclient/cycode_token_based_client.py +24 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/pyproject.toml +1 -1
- cycode-3.7.2.dev1/cycode/__init__.py +0 -1
- cycode-3.7.2.dev1/cycode/cli/apps/auth/auth_common.py +0 -34
- cycode-3.7.2.dev1/cycode/cyclient/client_creator.py +0 -29
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/LICENCE +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/__main__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/ai_remediation/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/ai_remediation/ai_remediation_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/ai_remediation/apply_fix.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/ai_remediation/print_remediation.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/auth/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/auth/auth_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/auth/auth_manager.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/auth/models.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/configure/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/configure/consts.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/configure/messages.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/ignore/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/ignore/ignore_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/mcp/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/mcp/mcp_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/report/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/report/report_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/report/sbom/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/report/sbom/common.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/report/sbom/path/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/report/sbom/path/path_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/report/sbom/repository_url/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/report/sbom/repository_url/repository_url_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/report/sbom/sbom_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/report/sbom/sbom_report_file.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/report_import/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/report_import/report_import_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/report_import/sbom/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/report_import/sbom/sbom_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/aggregation_report.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/code_scanner.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/commit_history/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/commit_history/commit_history_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/commit_range_scanner.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/detection_excluder.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/path/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/path/path_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/pre_commit/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/pre_commit/pre_commit_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/pre_push/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/pre_push/pre_push_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/pre_receive/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/pre_receive/pre_receive_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/remote_url_resolver.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/repository/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/repository/repository_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/scan_ci/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/scan_ci/ci_integrations.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/scan_ci/scan_ci_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/scan_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/scan_parameters.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/scan/scan_result.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/status/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/status/get_cli_status.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/status/models.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/status/status_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/status/version_command.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/cli_types.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/console.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/consts.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/exceptions/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/exceptions/custom_exceptions.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/exceptions/handle_ai_remediation_errors.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/exceptions/handle_auth_errors.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/exceptions/handle_errors.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/exceptions/handle_report_sbom_errors.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/exceptions/handle_scan_errors.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/commit_range_documents.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/documents_walk_ignore.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/file_excluder.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/iac/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/iac/tf_content_generator.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/models/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/models/in_memory_zip.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/path_documents.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/repository_documents.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/sca/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/sca/base_restore_dependencies.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/sca/go/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/sca/go/restore_go_dependencies.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/sca/maven/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/sca/npm/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/sca/npm/restore_npm_dependencies.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/sca/nuget/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/sca/nuget/restore_nuget_dependencies.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/sca/ruby/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/sca/ruby/restore_ruby_dependencies.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/sca/sbt/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/sca/sbt/restore_sbt_dependencies.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/sca/sca_file_collector.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/walk_ignore.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/files_collector/zip_documents.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/logger.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/main.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/models.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/console_printer.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/json_printer.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/printer_base.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/rich_printer.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/tables/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/tables/sca_table_printer.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/tables/table.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/tables/table_models.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/tables/table_printer.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/tables/table_printer_base.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/text_printer.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/utils/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/utils/code_snippet_syntax.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/utils/detection_data.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/utils/detection_ordering/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/utils/detection_ordering/common_ordering.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/utils/detection_ordering/sca_ordering.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/printers/utils/rich_helpers.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/user_settings/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/user_settings/base_file_manager.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/user_settings/config_file_manager.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/user_settings/configuration_manager.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/user_settings/jwt_creator.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/utils/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/utils/enum_utils.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/utils/git_proxy.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/utils/ignore_utils.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/utils/jwt_utils.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/utils/path_utils.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/utils/progress_bar.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/utils/scan_batch.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/utils/scan_utils.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/utils/sentry.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/utils/shell_executor.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/utils/string_utils.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/utils/task_timer.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/utils/version_checker.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/utils/yaml_utils.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/config.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cyclient/__init__.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cyclient/auth_client.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cyclient/config.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cyclient/config_dev.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cyclient/cycode_client.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cyclient/cycode_client_base.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cyclient/cycode_dev_based_client.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cyclient/headers.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cyclient/import_sbom_client.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cyclient/logger.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cyclient/models.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cyclient/report_client.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cyclient/scan_client.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cyclient/scan_config_base.py +0 -0
- {cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/logger.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cycode
|
|
3
|
-
Version: 3.7.2.
|
|
3
|
+
Version: 3.7.2.dev2
|
|
4
4
|
Summary: Boost security in your dev lifecycle via SAST, SCA, Secrets & IaC scanning.
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
License-File: LICENCE
|
|
@@ -144,7 +144,7 @@ To install the Cycode CLI application on your local machine, perform the followi
|
|
|
144
144
|
./cycode
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
-
3. Finally authenticate the CLI. There are three methods to set the Cycode client ID and client secret:
|
|
147
|
+
3. Finally authenticate the CLI. There are three methods to set the Cycode client ID and credentials (client secret or OIDC ID token):
|
|
148
148
|
|
|
149
149
|
- [cycode auth](#using-the-auth-command) (**Recommended**)
|
|
150
150
|
- [cycode configure](#using-the-configure-command)
|
|
@@ -207,11 +207,15 @@ To install the Cycode CLI application on your local machine, perform the followi
|
|
|
207
207
|
|
|
208
208
|
`Cycode Client ID []: 7fe5346b-xxxx-xxxx-xxxx-55157625c72d`
|
|
209
209
|
|
|
210
|
-
5. Enter your Cycode Client Secret value.
|
|
210
|
+
5. Enter your Cycode Client Secret value (skip if you plan to use an OIDC ID token).
|
|
211
211
|
|
|
212
212
|
`Cycode Client Secret []: c1e24929-xxxx-xxxx-xxxx-8b08c1839a2e`
|
|
213
213
|
|
|
214
|
-
6.
|
|
214
|
+
6. Enter your Cycode OIDC ID Token value (optional).
|
|
215
|
+
|
|
216
|
+
`Cycode ID Token []: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...`
|
|
217
|
+
|
|
218
|
+
7. If the values were entered successfully, you'll see the following message:
|
|
215
219
|
|
|
216
220
|
`Successfully configured CLI credentials!`
|
|
217
221
|
|
|
@@ -236,6 +240,12 @@ and
|
|
|
236
240
|
export CYCODE_CLIENT_SECRET={your Cycode Secret Key}
|
|
237
241
|
```
|
|
238
242
|
|
|
243
|
+
If your organization uses OIDC authentication, you can provide the ID token instead (or in addition):
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
export CYCODE_ID_TOKEN={your Cycode OIDC ID token}
|
|
247
|
+
```
|
|
248
|
+
|
|
239
249
|
#### On Windows
|
|
240
250
|
|
|
241
251
|
1. From the Control Panel, navigate to the System menu:
|
|
@@ -250,7 +260,7 @@ export CYCODE_CLIENT_SECRET={your Cycode Secret Key}
|
|
|
250
260
|
|
|
251
261
|
<img height="30" src="https://raw.githubusercontent.com/cycodehq/cycode-cli/main/images/image3.png" alt="environments variables button"/>
|
|
252
262
|
|
|
253
|
-
4. Create `CYCODE_CLIENT_ID` and `CYCODE_CLIENT_SECRET` variables with values matching your ID and Secret Key, respectively:
|
|
263
|
+
4. Create `CYCODE_CLIENT_ID` and `CYCODE_CLIENT_SECRET` variables with values matching your ID and Secret Key, respectively. If you authenticate via OIDC, add `CYCODE_ID_TOKEN` with your OIDC ID token value as well:
|
|
254
264
|
|
|
255
265
|
<img height="100" src="https://raw.githubusercontent.com/cycodehq/cycode-cli/main/images/image4.png" alt="environment variables window"/>
|
|
256
266
|
|
|
@@ -364,6 +374,7 @@ The following are the options and commands available with the Cycode CLI applica
|
|
|
364
374
|
| `-o`, `--output [rich\|text\|json\|table]` | Specify the output type. The default is `rich`. |
|
|
365
375
|
| `--client-id TEXT` | Specify a Cycode client ID for this specific scan execution. |
|
|
366
376
|
| `--client-secret TEXT` | Specify a Cycode client secret for this specific scan execution. |
|
|
377
|
+
| `--id-token TEXT` | Specify a Cycode OIDC ID token for this specific scan execution. |
|
|
367
378
|
| `--install-completion` | Install completion for the current shell.. |
|
|
368
379
|
| `--show-completion [bash\|zsh\|fish\|powershell\|pwsh]` | Show completion for the specified shell, to copy it or customize the installation. |
|
|
369
380
|
| `-h`, `--help` | Show options for given command. |
|
|
@@ -101,7 +101,7 @@ To install the Cycode CLI application on your local machine, perform the followi
|
|
|
101
101
|
./cycode
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
-
3. Finally authenticate the CLI. There are three methods to set the Cycode client ID and client secret:
|
|
104
|
+
3. Finally authenticate the CLI. There are three methods to set the Cycode client ID and credentials (client secret or OIDC ID token):
|
|
105
105
|
|
|
106
106
|
- [cycode auth](#using-the-auth-command) (**Recommended**)
|
|
107
107
|
- [cycode configure](#using-the-configure-command)
|
|
@@ -164,11 +164,15 @@ To install the Cycode CLI application on your local machine, perform the followi
|
|
|
164
164
|
|
|
165
165
|
`Cycode Client ID []: 7fe5346b-xxxx-xxxx-xxxx-55157625c72d`
|
|
166
166
|
|
|
167
|
-
5. Enter your Cycode Client Secret value.
|
|
167
|
+
5. Enter your Cycode Client Secret value (skip if you plan to use an OIDC ID token).
|
|
168
168
|
|
|
169
169
|
`Cycode Client Secret []: c1e24929-xxxx-xxxx-xxxx-8b08c1839a2e`
|
|
170
170
|
|
|
171
|
-
6.
|
|
171
|
+
6. Enter your Cycode OIDC ID Token value (optional).
|
|
172
|
+
|
|
173
|
+
`Cycode ID Token []: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...`
|
|
174
|
+
|
|
175
|
+
7. If the values were entered successfully, you'll see the following message:
|
|
172
176
|
|
|
173
177
|
`Successfully configured CLI credentials!`
|
|
174
178
|
|
|
@@ -193,6 +197,12 @@ and
|
|
|
193
197
|
export CYCODE_CLIENT_SECRET={your Cycode Secret Key}
|
|
194
198
|
```
|
|
195
199
|
|
|
200
|
+
If your organization uses OIDC authentication, you can provide the ID token instead (or in addition):
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
export CYCODE_ID_TOKEN={your Cycode OIDC ID token}
|
|
204
|
+
```
|
|
205
|
+
|
|
196
206
|
#### On Windows
|
|
197
207
|
|
|
198
208
|
1. From the Control Panel, navigate to the System menu:
|
|
@@ -207,7 +217,7 @@ export CYCODE_CLIENT_SECRET={your Cycode Secret Key}
|
|
|
207
217
|
|
|
208
218
|
<img height="30" src="https://raw.githubusercontent.com/cycodehq/cycode-cli/main/images/image3.png" alt="environments variables button"/>
|
|
209
219
|
|
|
210
|
-
4. Create `CYCODE_CLIENT_ID` and `CYCODE_CLIENT_SECRET` variables with values matching your ID and Secret Key, respectively:
|
|
220
|
+
4. Create `CYCODE_CLIENT_ID` and `CYCODE_CLIENT_SECRET` variables with values matching your ID and Secret Key, respectively. If you authenticate via OIDC, add `CYCODE_ID_TOKEN` with your OIDC ID token value as well:
|
|
211
221
|
|
|
212
222
|
<img height="100" src="https://raw.githubusercontent.com/cycodehq/cycode-cli/main/images/image4.png" alt="environment variables window"/>
|
|
213
223
|
|
|
@@ -321,6 +331,7 @@ The following are the options and commands available with the Cycode CLI applica
|
|
|
321
331
|
| `-o`, `--output [rich\|text\|json\|table]` | Specify the output type. The default is `rich`. |
|
|
322
332
|
| `--client-id TEXT` | Specify a Cycode client ID for this specific scan execution. |
|
|
323
333
|
| `--client-secret TEXT` | Specify a Cycode client secret for this specific scan execution. |
|
|
334
|
+
| `--id-token TEXT` | Specify a Cycode OIDC ID token for this specific scan execution. |
|
|
324
335
|
| `--install-completion` | Install completion for the current shell.. |
|
|
325
336
|
| `--show-completion [bash\|zsh\|fish\|powershell\|pwsh]` | Show completion for the specified shell, to copy it or customize the installation. |
|
|
326
337
|
| `-h`, `--help` | Show options for given command. |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '3.7.2.dev2' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
|
|
@@ -110,6 +110,13 @@ def app_callback(
|
|
|
110
110
|
rich_help_panel=_AUTH_RICH_HELP_PANEL,
|
|
111
111
|
),
|
|
112
112
|
] = None,
|
|
113
|
+
id_token: Annotated[
|
|
114
|
+
Optional[str],
|
|
115
|
+
typer.Option(
|
|
116
|
+
help='Specify a Cycode OIDC ID token for this specific scan execution.',
|
|
117
|
+
rich_help_panel=_AUTH_RICH_HELP_PANEL,
|
|
118
|
+
),
|
|
119
|
+
] = None,
|
|
113
120
|
_: Annotated[
|
|
114
121
|
Optional[bool],
|
|
115
122
|
typer.Option(
|
|
@@ -152,6 +159,7 @@ def app_callback(
|
|
|
152
159
|
|
|
153
160
|
ctx.obj['client_id'] = client_id
|
|
154
161
|
ctx.obj['client_secret'] = client_secret
|
|
162
|
+
ctx.obj['id_token'] = id_token
|
|
155
163
|
|
|
156
164
|
ctx.obj['progress_bar'] = get_progress_bar(hidden=no_progress_meter, sections=SCAN_PROGRESS_BAR_SECTIONS)
|
|
157
165
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from typing import TYPE_CHECKING, Optional
|
|
2
|
+
|
|
3
|
+
from cycode.cli.apps.auth.models import AuthInfo
|
|
4
|
+
from cycode.cli.exceptions.custom_exceptions import HttpUnauthorizedError, RequestHttpError
|
|
5
|
+
from cycode.cli.user_settings.credentials_manager import CredentialsManager
|
|
6
|
+
from cycode.cli.utils.jwt_utils import get_user_and_tenant_ids_from_access_token
|
|
7
|
+
from cycode.cyclient.cycode_oidc_based_client import CycodeOidcBasedClient
|
|
8
|
+
from cycode.cyclient.cycode_token_based_client import CycodeTokenBasedClient
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from typer import Context
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_authorization_info(ctx: 'Context') -> Optional[AuthInfo]:
|
|
15
|
+
printer = ctx.obj.get('console_printer')
|
|
16
|
+
|
|
17
|
+
client_id = ctx.obj.get('client_id')
|
|
18
|
+
client_secret = ctx.obj.get('client_secret')
|
|
19
|
+
id_token = ctx.obj.get('id_token')
|
|
20
|
+
|
|
21
|
+
credentials_manager = CredentialsManager()
|
|
22
|
+
|
|
23
|
+
auth_info = _try_oidc_authorization(ctx, printer, client_id, id_token)
|
|
24
|
+
if auth_info:
|
|
25
|
+
return auth_info
|
|
26
|
+
|
|
27
|
+
if not client_id or not client_secret:
|
|
28
|
+
stored_client_id, stored_id_token = credentials_manager.get_oidc_credentials()
|
|
29
|
+
auth_info = _try_oidc_authorization(ctx, printer, stored_client_id, stored_id_token)
|
|
30
|
+
if auth_info:
|
|
31
|
+
return auth_info
|
|
32
|
+
|
|
33
|
+
client_id, client_secret = credentials_manager.get_credentials()
|
|
34
|
+
|
|
35
|
+
if not client_id or not client_secret:
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
try:
|
|
39
|
+
access_token = CycodeTokenBasedClient(client_id, client_secret).get_access_token()
|
|
40
|
+
if not access_token:
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
user_id, tenant_id = get_user_and_tenant_ids_from_access_token(access_token)
|
|
44
|
+
return AuthInfo(user_id=user_id, tenant_id=tenant_id)
|
|
45
|
+
except (RequestHttpError, HttpUnauthorizedError):
|
|
46
|
+
if ctx:
|
|
47
|
+
printer.print_exception()
|
|
48
|
+
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _try_oidc_authorization(
|
|
53
|
+
ctx: 'Context', printer: any, client_id: Optional[str], id_token: Optional[str]
|
|
54
|
+
) -> Optional[AuthInfo]:
|
|
55
|
+
if not client_id or not id_token:
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
try:
|
|
59
|
+
access_token = CycodeOidcBasedClient(client_id, id_token).get_access_token()
|
|
60
|
+
if not access_token:
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
user_id, tenant_id = get_user_and_tenant_ids_from_access_token(access_token)
|
|
64
|
+
return AuthInfo(user_id=user_id, tenant_id=tenant_id)
|
|
65
|
+
except (RequestHttpError, HttpUnauthorizedError):
|
|
66
|
+
if ctx:
|
|
67
|
+
printer.print_exception()
|
|
68
|
+
|
|
69
|
+
return None
|
|
@@ -7,6 +7,7 @@ from cycode.cli.apps.configure.prompts import (
|
|
|
7
7
|
get_app_url_input,
|
|
8
8
|
get_client_id_input,
|
|
9
9
|
get_client_secret_input,
|
|
10
|
+
get_id_token_input,
|
|
10
11
|
)
|
|
11
12
|
from cycode.cli.console import console
|
|
12
13
|
from cycode.cli.utils.sentry import add_breadcrumb
|
|
@@ -32,6 +33,7 @@ def configure_command() -> None:
|
|
|
32
33
|
* APP URL: The base URL for Cycode's web application (for on-premise or EU installations)
|
|
33
34
|
* Client ID: Your Cycode client ID for authentication
|
|
34
35
|
* Client Secret: Your Cycode client secret for authentication
|
|
36
|
+
* ID Token: Your Cycode ID token for authentication
|
|
35
37
|
|
|
36
38
|
Example usage:
|
|
37
39
|
* `cycode configure`: Start interactive configuration
|
|
@@ -55,15 +57,22 @@ def configure_command() -> None:
|
|
|
55
57
|
config_updated = True
|
|
56
58
|
|
|
57
59
|
current_client_id, current_client_secret = CREDENTIALS_MANAGER.get_credentials_from_file()
|
|
60
|
+
_, current_id_token = CREDENTIALS_MANAGER.get_oidc_credentials_from_file()
|
|
58
61
|
client_id = get_client_id_input(current_client_id)
|
|
59
62
|
client_secret = get_client_secret_input(current_client_secret)
|
|
63
|
+
id_token = get_id_token_input(current_id_token)
|
|
60
64
|
|
|
61
65
|
credentials_updated = False
|
|
62
66
|
if _should_update_value(current_client_id, client_id) or _should_update_value(current_client_secret, client_secret):
|
|
63
67
|
credentials_updated = True
|
|
64
68
|
CREDENTIALS_MANAGER.update_credentials(client_id, client_secret)
|
|
65
69
|
|
|
70
|
+
oidc_credentials_updated = False
|
|
71
|
+
if _should_update_value(current_client_id, client_id) or _should_update_value(current_id_token, id_token):
|
|
72
|
+
oidc_credentials_updated = True
|
|
73
|
+
CREDENTIALS_MANAGER.update_oidc_credentials(client_id, id_token)
|
|
74
|
+
|
|
66
75
|
if config_updated:
|
|
67
76
|
console.print(get_urls_update_result_message())
|
|
68
|
-
if credentials_updated:
|
|
77
|
+
if credentials_updated or oidc_credentials_updated:
|
|
69
78
|
console.print(get_credentials_update_result_message())
|
|
@@ -46,3 +46,14 @@ def get_api_url_input(current_api_url: Optional[str]) -> str:
|
|
|
46
46
|
default = current_api_url
|
|
47
47
|
|
|
48
48
|
return typer.prompt(text=prompt_text, default=default, type=str)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def get_id_token_input(current_id_token: Optional[str]) -> Optional[str]:
|
|
52
|
+
prompt_text = 'Cycode ID Token'
|
|
53
|
+
|
|
54
|
+
prompt_suffix = ' []: '
|
|
55
|
+
if current_id_token:
|
|
56
|
+
prompt_suffix = f' [{obfuscate_text(current_id_token)}]: '
|
|
57
|
+
|
|
58
|
+
new_id_token = typer.prompt(text=prompt_text, prompt_suffix=prompt_suffix, default='', show_default=False)
|
|
59
|
+
return new_id_token or current_id_token
|
|
@@ -2,7 +2,11 @@ import os
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
from typing import Optional
|
|
4
4
|
|
|
5
|
-
from cycode.cli.config import
|
|
5
|
+
from cycode.cli.config import (
|
|
6
|
+
CYCODE_CLIENT_ID_ENV_VAR_NAME,
|
|
7
|
+
CYCODE_CLIENT_SECRET_ENV_VAR_NAME,
|
|
8
|
+
CYCODE_ID_TOKEN_ENV_VAR_NAME,
|
|
9
|
+
)
|
|
6
10
|
from cycode.cli.user_settings.base_file_manager import BaseFileManager
|
|
7
11
|
from cycode.cli.user_settings.jwt_creator import JwtCreator
|
|
8
12
|
from cycode.cli.utils.sentry import setup_scope_from_access_token
|
|
@@ -15,6 +19,7 @@ class CredentialsManager(BaseFileManager):
|
|
|
15
19
|
|
|
16
20
|
CLIENT_ID_FIELD_NAME: str = 'cycode_client_id'
|
|
17
21
|
CLIENT_SECRET_FIELD_NAME: str = 'cycode_client_secret'
|
|
22
|
+
ID_TOKEN_FIELD_NAME: str = 'cycode_id_token'
|
|
18
23
|
ACCESS_TOKEN_FIELD_NAME: str = 'cycode_access_token'
|
|
19
24
|
ACCESS_TOKEN_EXPIRES_IN_FIELD_NAME: str = 'cycode_access_token_expires_in'
|
|
20
25
|
ACCESS_TOKEN_CREATOR_FIELD_NAME: str = 'cycode_access_token_creator'
|
|
@@ -38,6 +43,25 @@ class CredentialsManager(BaseFileManager):
|
|
|
38
43
|
client_secret = file_content.get(self.CLIENT_SECRET_FIELD_NAME)
|
|
39
44
|
return client_id, client_secret
|
|
40
45
|
|
|
46
|
+
def get_oidc_credentials_from_file(self) -> tuple[Optional[str], Optional[str]]:
|
|
47
|
+
file_content = self.read_file()
|
|
48
|
+
client_id = file_content.get(self.CLIENT_ID_FIELD_NAME)
|
|
49
|
+
id_token = file_content.get(self.ID_TOKEN_FIELD_NAME)
|
|
50
|
+
return client_id, id_token
|
|
51
|
+
|
|
52
|
+
def get_oidc_credentials(self) -> tuple[Optional[str], Optional[str]]:
|
|
53
|
+
client_id = os.getenv(CYCODE_CLIENT_ID_ENV_VAR_NAME)
|
|
54
|
+
id_token = os.getenv(CYCODE_ID_TOKEN_ENV_VAR_NAME)
|
|
55
|
+
|
|
56
|
+
if client_id is not None and id_token is not None:
|
|
57
|
+
return client_id, id_token
|
|
58
|
+
|
|
59
|
+
return self.get_oidc_credentials_from_file()
|
|
60
|
+
|
|
61
|
+
def update_oidc_credentials(self, client_id: str, id_token: str) -> None:
|
|
62
|
+
file_content_to_update = {self.CLIENT_ID_FIELD_NAME: client_id, self.ID_TOKEN_FIELD_NAME: id_token}
|
|
63
|
+
self.write_content_to_file(file_content_to_update)
|
|
64
|
+
|
|
41
65
|
def update_credentials(self, client_id: str, client_secret: str) -> None:
|
|
42
66
|
file_content_to_update = {self.CLIENT_ID_FIELD_NAME: client_id, self.CLIENT_SECRET_FIELD_NAME: client_secret}
|
|
43
67
|
self.write_content_to_file(file_content_to_update)
|
|
@@ -14,8 +14,22 @@ if TYPE_CHECKING:
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def _get_cycode_client(
|
|
17
|
-
create_client_func: callable,
|
|
17
|
+
create_client_func: callable,
|
|
18
|
+
client_id: Optional[str],
|
|
19
|
+
client_secret: Optional[str],
|
|
20
|
+
hide_response_log: bool,
|
|
21
|
+
id_token: Optional[str] = None,
|
|
18
22
|
) -> Union['ScanClient', 'ReportClient']:
|
|
23
|
+
if client_id and id_token:
|
|
24
|
+
return create_client_func(client_id, None, hide_response_log, id_token)
|
|
25
|
+
|
|
26
|
+
if not client_id or not id_token:
|
|
27
|
+
oidc_client_id, oidc_id_token = _get_configured_oidc_credentials()
|
|
28
|
+
if oidc_client_id and oidc_id_token:
|
|
29
|
+
return create_client_func(oidc_client_id, None, hide_response_log, oidc_id_token)
|
|
30
|
+
if oidc_id_token and not oidc_client_id:
|
|
31
|
+
raise click.ClickException('Cycode client id needed for OIDC authentication.')
|
|
32
|
+
|
|
19
33
|
if not client_id or not client_secret:
|
|
20
34
|
client_id, client_secret = _get_configured_credentials()
|
|
21
35
|
if not client_id:
|
|
@@ -23,28 +37,36 @@ def _get_cycode_client(
|
|
|
23
37
|
if not client_secret:
|
|
24
38
|
raise click.ClickException('Cycode client secret is needed.')
|
|
25
39
|
|
|
26
|
-
return create_client_func(client_id, client_secret, hide_response_log)
|
|
40
|
+
return create_client_func(client_id, client_secret, hide_response_log, None)
|
|
27
41
|
|
|
28
42
|
|
|
29
43
|
def get_scan_cycode_client(ctx: 'typer.Context') -> 'ScanClient':
|
|
30
44
|
client_id = ctx.obj.get('client_id')
|
|
31
45
|
client_secret = ctx.obj.get('client_secret')
|
|
46
|
+
id_token = ctx.obj.get('id_token')
|
|
32
47
|
hide_response_log = not ctx.obj.get('show_secret', False)
|
|
33
|
-
return _get_cycode_client(create_scan_client, client_id, client_secret, hide_response_log)
|
|
48
|
+
return _get_cycode_client(create_scan_client, client_id, client_secret, hide_response_log, id_token)
|
|
34
49
|
|
|
35
50
|
|
|
36
51
|
def get_report_cycode_client(ctx: 'typer.Context', hide_response_log: bool = True) -> 'ReportClient':
|
|
37
52
|
client_id = ctx.obj.get('client_id')
|
|
38
53
|
client_secret = ctx.obj.get('client_secret')
|
|
39
|
-
|
|
54
|
+
id_token = ctx.obj.get('id_token')
|
|
55
|
+
return _get_cycode_client(create_report_client, client_id, client_secret, hide_response_log, id_token)
|
|
40
56
|
|
|
41
57
|
|
|
42
58
|
def get_import_sbom_cycode_client(ctx: 'typer.Context', hide_response_log: bool = True) -> 'ImportSbomClient':
|
|
43
59
|
client_id = ctx.obj.get('client_id')
|
|
44
60
|
client_secret = ctx.obj.get('client_secret')
|
|
45
|
-
|
|
61
|
+
id_token = ctx.obj.get('id_token')
|
|
62
|
+
return _get_cycode_client(create_import_sbom_client, client_id, client_secret, hide_response_log, id_token)
|
|
46
63
|
|
|
47
64
|
|
|
48
65
|
def _get_configured_credentials() -> tuple[str, str]:
|
|
49
66
|
credentials_manager = CredentialsManager()
|
|
50
67
|
return credentials_manager.get_credentials()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _get_configured_oidc_credentials() -> tuple[Optional[str], Optional[str]]:
|
|
71
|
+
credentials_manager = CredentialsManager()
|
|
72
|
+
return credentials_manager.get_oidc_credentials()
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
1
2
|
from threading import Lock
|
|
2
|
-
from typing import Optional
|
|
3
|
+
from typing import Any, Optional
|
|
3
4
|
|
|
4
5
|
import arrow
|
|
5
6
|
from requests import Response
|
|
@@ -15,12 +16,11 @@ _NGINX_PLAIN_ERRORS = [
|
|
|
15
16
|
]
|
|
16
17
|
|
|
17
18
|
|
|
18
|
-
class
|
|
19
|
-
"""
|
|
19
|
+
class BaseTokenAuthClient(CycodeClient, ABC):
|
|
20
|
+
"""Base client for token-based authentication flows with cached JWTs."""
|
|
20
21
|
|
|
21
|
-
def __init__(self, client_id: str
|
|
22
|
+
def __init__(self, client_id: str) -> None:
|
|
22
23
|
super().__init__()
|
|
23
|
-
self.client_secret = client_secret
|
|
24
24
|
self.client_id = client_id
|
|
25
25
|
|
|
26
26
|
self._credentials_manager = CredentialsManager()
|
|
@@ -28,7 +28,8 @@ class CycodeTokenBasedClient(CycodeClient):
|
|
|
28
28
|
access_token, expires_in, creator = self._credentials_manager.get_access_token()
|
|
29
29
|
|
|
30
30
|
self._access_token = self._expires_in = None
|
|
31
|
-
|
|
31
|
+
expected_creator = self._create_jwt_creator()
|
|
32
|
+
if creator == expected_creator:
|
|
32
33
|
# we must be sure that cached access token is created using the same client id and client secret.
|
|
33
34
|
# because client id and client secret could be passed via command, via env vars or via config file.
|
|
34
35
|
# we must not use cached access token if client id or client secret was changed.
|
|
@@ -54,18 +55,12 @@ class CycodeTokenBasedClient(CycodeClient):
|
|
|
54
55
|
self.refresh_access_token()
|
|
55
56
|
|
|
56
57
|
def refresh_access_token(self) -> None:
|
|
57
|
-
auth_response = self.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
)
|
|
63
|
-
auth_response_data = auth_response.json()
|
|
64
|
-
|
|
65
|
-
self._access_token = auth_response_data['token']
|
|
66
|
-
self._expires_in = arrow.utcnow().shift(seconds=auth_response_data['expires_in'] * 0.8)
|
|
67
|
-
|
|
68
|
-
jwt_creator = JwtCreator.create(self.client_id, self.client_secret)
|
|
58
|
+
auth_response = self._request_new_access_token()
|
|
59
|
+
self._access_token = auth_response['token']
|
|
60
|
+
|
|
61
|
+
self._expires_in = arrow.utcnow().shift(seconds=auth_response['expires_in'] * 0.8)
|
|
62
|
+
|
|
63
|
+
jwt_creator = self._create_jwt_creator()
|
|
69
64
|
self._credentials_manager.update_access_token(self._access_token, self._expires_in.timestamp(), jwt_creator)
|
|
70
65
|
|
|
71
66
|
def get_request_headers(self, additional_headers: Optional[dict] = None, without_auth: bool = False) -> dict:
|
|
@@ -95,3 +90,11 @@ class CycodeTokenBasedClient(CycodeClient):
|
|
|
95
90
|
response = super()._execute(*args, **kwargs)
|
|
96
91
|
|
|
97
92
|
return response
|
|
93
|
+
|
|
94
|
+
@abstractmethod
|
|
95
|
+
def _create_jwt_creator(self) -> JwtCreator:
|
|
96
|
+
"""Create a JwtCreator instance for the current credential type."""
|
|
97
|
+
|
|
98
|
+
@abstractmethod
|
|
99
|
+
def _request_new_access_token(self) -> dict[str, Any]:
|
|
100
|
+
"""Return the authentication payload with token and expires_in."""
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from cycode.cyclient.config import dev_mode
|
|
4
|
+
from cycode.cyclient.config_dev import DEV_CYCODE_API_URL
|
|
5
|
+
from cycode.cyclient.cycode_dev_based_client import CycodeDevBasedClient
|
|
6
|
+
from cycode.cyclient.cycode_oidc_based_client import CycodeOidcBasedClient
|
|
7
|
+
from cycode.cyclient.cycode_token_based_client import CycodeTokenBasedClient
|
|
8
|
+
from cycode.cyclient.import_sbom_client import ImportSbomClient
|
|
9
|
+
from cycode.cyclient.report_client import ReportClient
|
|
10
|
+
from cycode.cyclient.scan_client import ScanClient
|
|
11
|
+
from cycode.cyclient.scan_config_base import DefaultScanConfig, DevScanConfig
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def create_scan_client(
|
|
15
|
+
client_id: str, client_secret: Optional[str] = None, hide_response_log: bool = False, id_token: Optional[str] = None
|
|
16
|
+
) -> ScanClient:
|
|
17
|
+
if dev_mode:
|
|
18
|
+
client = CycodeDevBasedClient(DEV_CYCODE_API_URL)
|
|
19
|
+
scan_config = DevScanConfig()
|
|
20
|
+
else:
|
|
21
|
+
if id_token:
|
|
22
|
+
client = CycodeOidcBasedClient(client_id, id_token)
|
|
23
|
+
else:
|
|
24
|
+
client = CycodeTokenBasedClient(client_id, client_secret)
|
|
25
|
+
scan_config = DefaultScanConfig()
|
|
26
|
+
|
|
27
|
+
return ScanClient(client, scan_config, hide_response_log)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def create_report_client(
|
|
31
|
+
client_id: str, client_secret: Optional[str] = None, _: bool = False, id_token: Optional[str] = None
|
|
32
|
+
) -> ReportClient:
|
|
33
|
+
if dev_mode:
|
|
34
|
+
client = CycodeDevBasedClient(DEV_CYCODE_API_URL)
|
|
35
|
+
elif id_token:
|
|
36
|
+
client = CycodeOidcBasedClient(client_id, id_token)
|
|
37
|
+
else:
|
|
38
|
+
client = CycodeTokenBasedClient(client_id, client_secret)
|
|
39
|
+
return ReportClient(client)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def create_import_sbom_client(
|
|
43
|
+
client_id: str, client_secret: Optional[str] = None, _: bool = False, id_token: Optional[str] = None
|
|
44
|
+
) -> ImportSbomClient:
|
|
45
|
+
if dev_mode:
|
|
46
|
+
client = CycodeDevBasedClient(DEV_CYCODE_API_URL)
|
|
47
|
+
elif id_token:
|
|
48
|
+
client = CycodeOidcBasedClient(client_id, id_token)
|
|
49
|
+
else:
|
|
50
|
+
client = CycodeTokenBasedClient(client_id, client_secret)
|
|
51
|
+
return ImportSbomClient(client)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from cycode.cli.user_settings.jwt_creator import JwtCreator
|
|
4
|
+
from cycode.cyclient.base_token_auth_client import BaseTokenAuthClient
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CycodeOidcBasedClient(BaseTokenAuthClient):
|
|
8
|
+
"""Send requests with JWT obtained via OIDC ID token."""
|
|
9
|
+
|
|
10
|
+
def __init__(self, client_id: str, id_token: str) -> None:
|
|
11
|
+
self.id_token = id_token
|
|
12
|
+
super().__init__(client_id)
|
|
13
|
+
|
|
14
|
+
def _request_new_access_token(self) -> dict[str, Any]:
|
|
15
|
+
auth_response = self.post(
|
|
16
|
+
url_path='api/v1/auth/oidc/api-token',
|
|
17
|
+
body={'client_id': self.client_id, 'id_token': self.id_token},
|
|
18
|
+
without_auth=True,
|
|
19
|
+
hide_response_content_log=True,
|
|
20
|
+
)
|
|
21
|
+
return auth_response.json()
|
|
22
|
+
|
|
23
|
+
def _create_jwt_creator(self) -> JwtCreator:
|
|
24
|
+
return JwtCreator.create(self.client_id, self.id_token)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from cycode.cli.user_settings.jwt_creator import JwtCreator
|
|
4
|
+
from cycode.cyclient.base_token_auth_client import BaseTokenAuthClient
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class CycodeTokenBasedClient(BaseTokenAuthClient):
|
|
8
|
+
"""Send requests with JWT."""
|
|
9
|
+
|
|
10
|
+
def __init__(self, client_id: str, client_secret: str) -> None:
|
|
11
|
+
self.client_secret = client_secret
|
|
12
|
+
super().__init__(client_id)
|
|
13
|
+
|
|
14
|
+
def _request_new_access_token(self) -> dict[str, Any]:
|
|
15
|
+
auth_response = self.post(
|
|
16
|
+
url_path='api/v1/auth/api-token',
|
|
17
|
+
body={'clientId': self.client_id, 'secret': self.client_secret},
|
|
18
|
+
without_auth=True,
|
|
19
|
+
hide_response_content_log=True,
|
|
20
|
+
)
|
|
21
|
+
return auth_response.json()
|
|
22
|
+
|
|
23
|
+
def _create_jwt_creator(self) -> JwtCreator:
|
|
24
|
+
return JwtCreator.create(self.client_id, self.client_secret)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '3.7.2.dev1' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
from typing import TYPE_CHECKING, Optional
|
|
2
|
-
|
|
3
|
-
from cycode.cli.apps.auth.models import AuthInfo
|
|
4
|
-
from cycode.cli.exceptions.custom_exceptions import HttpUnauthorizedError, RequestHttpError
|
|
5
|
-
from cycode.cli.user_settings.credentials_manager import CredentialsManager
|
|
6
|
-
from cycode.cli.utils.jwt_utils import get_user_and_tenant_ids_from_access_token
|
|
7
|
-
from cycode.cyclient.cycode_token_based_client import CycodeTokenBasedClient
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
from typer import Context
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def get_authorization_info(ctx: 'Context') -> Optional[AuthInfo]:
|
|
14
|
-
printer = ctx.obj.get('console_printer')
|
|
15
|
-
|
|
16
|
-
client_id, client_secret = ctx.obj.get('client_id'), ctx.obj.get('client_secret')
|
|
17
|
-
if not client_id or not client_secret:
|
|
18
|
-
client_id, client_secret = CredentialsManager().get_credentials()
|
|
19
|
-
|
|
20
|
-
if not client_id or not client_secret:
|
|
21
|
-
return None
|
|
22
|
-
|
|
23
|
-
try:
|
|
24
|
-
access_token = CycodeTokenBasedClient(client_id, client_secret).get_access_token()
|
|
25
|
-
if not access_token:
|
|
26
|
-
return None
|
|
27
|
-
|
|
28
|
-
user_id, tenant_id = get_user_and_tenant_ids_from_access_token(access_token)
|
|
29
|
-
return AuthInfo(user_id=user_id, tenant_id=tenant_id)
|
|
30
|
-
except (RequestHttpError, HttpUnauthorizedError):
|
|
31
|
-
if ctx:
|
|
32
|
-
printer.print_exception()
|
|
33
|
-
|
|
34
|
-
return None
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
from cycode.cyclient.config import dev_mode
|
|
2
|
-
from cycode.cyclient.config_dev import DEV_CYCODE_API_URL
|
|
3
|
-
from cycode.cyclient.cycode_dev_based_client import CycodeDevBasedClient
|
|
4
|
-
from cycode.cyclient.cycode_token_based_client import CycodeTokenBasedClient
|
|
5
|
-
from cycode.cyclient.import_sbom_client import ImportSbomClient
|
|
6
|
-
from cycode.cyclient.report_client import ReportClient
|
|
7
|
-
from cycode.cyclient.scan_client import ScanClient
|
|
8
|
-
from cycode.cyclient.scan_config_base import DefaultScanConfig, DevScanConfig
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def create_scan_client(client_id: str, client_secret: str, hide_response_log: bool) -> ScanClient:
|
|
12
|
-
if dev_mode:
|
|
13
|
-
client = CycodeDevBasedClient(DEV_CYCODE_API_URL)
|
|
14
|
-
scan_config = DevScanConfig()
|
|
15
|
-
else:
|
|
16
|
-
client = CycodeTokenBasedClient(client_id, client_secret)
|
|
17
|
-
scan_config = DefaultScanConfig()
|
|
18
|
-
|
|
19
|
-
return ScanClient(client, scan_config, hide_response_log)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def create_report_client(client_id: str, client_secret: str, _: bool) -> ReportClient:
|
|
23
|
-
client = CycodeDevBasedClient(DEV_CYCODE_API_URL) if dev_mode else CycodeTokenBasedClient(client_id, client_secret)
|
|
24
|
-
return ReportClient(client)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def create_import_sbom_client(client_id: str, client_secret: str, _: bool) -> ImportSbomClient:
|
|
28
|
-
client = CycodeDevBasedClient(DEV_CYCODE_API_URL) if dev_mode else CycodeTokenBasedClient(client_id, client_secret)
|
|
29
|
-
return ImportSbomClient(client)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.7.2.dev1 → cycode-3.7.2.dev2}/cycode/cli/apps/ai_remediation/ai_remediation_command.py
RENAMED
|
File without changes
|
|
File without changes
|