classifyre-cli 0.4.11__tar.gz → 0.4.12__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.
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/.turbo/turbo-build.log +1 -1
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/PKG-INFO +1 -1
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/package.json +1 -1
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/pyproject.toml +1 -1
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/models/generated_input.py +32 -4
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/databricks/source.py +61 -8
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/uv.lock +164 -134
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/.gitignore +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/.python-version +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/README.md +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/main.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/scripts/generate_models.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/base.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/broken_links/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/broken_links/detector.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/config.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/content/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/custom/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/custom/detector.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/custom/extractor.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/custom/runners/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/custom/runners/_base.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/custom/runners/_factory.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/custom/runners/_feature_extraction.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/custom/runners/_gliner2.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/custom/runners/_image_classification.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/custom/runners/_llm.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/custom/runners/_object_detection.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/custom/runners/_regex.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/custom/runners/_text_classification.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/custom/trainer.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/dependencies.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/pii/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/pii/detector.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/secrets/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/secrets/detector.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/threat/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/threat/code_security_detector.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/detectors/threat/yara_detector.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/main.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/models/generated_detectors.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/models/generated_single_asset_scan_results.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/outputs/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/outputs/base.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/outputs/console.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/outputs/factory.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/outputs/file.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/outputs/rest.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/pipeline/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/pipeline/content_provider.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/pipeline/detector_pipeline.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/pipeline/parsed_content_provider.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/pipeline/worker_pool.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sandbox/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sandbox/runner.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/atlassian_common.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/azure_blob_storage/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/azure_blob_storage/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/base.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/confluence/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/confluence/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/databricks/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/dependencies.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/google_cloud_storage/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/google_cloud_storage/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/hive/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/hive/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/jira/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/jira/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/mongodb/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/mongodb/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/mssql/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/mssql/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/mysql/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/mysql/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/neo4j/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/neo4j/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/object_storage/base.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/oracle/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/oracle/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/postgresql/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/postgresql/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/powerbi/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/powerbi/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/recipe_normalizer.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/s3_compatible_storage/README.md +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/s3_compatible_storage/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/s3_compatible_storage/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/servicedesk/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/servicedesk/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/slack/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/slack/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/snowflake/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/snowflake/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/sqlite/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/sqlite/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/tableau/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/tableau/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/tabular_base.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/tabular_utils.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/wordpress/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/sources/wordpress/source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/telemetry.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/utils/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/utils/content_extraction.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/utils/embedded_images.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/utils/file_parser.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/utils/file_to_images.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/utils/hashing.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/utils/uv_sync.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/src/utils/validation.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/conftest.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/broken_links/test_broken_links_detector.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/conftest.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/content/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/custom/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/custom/conftest.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/custom/test_invoice_extraction.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/custom/test_llm_runner.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/custom/test_pipeline_integration.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/custom/test_regex_runner.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/custom/test_transformer_runners.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/pii/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/pii/conftest.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/pii/sample_invoice.pdf +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/pii/test_pii_detector.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/pii/test_pii_detector_extended.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/secrets/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/secrets/test_secrets_detector.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/secrets/test_secrets_detector_extended.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/test_base_detector.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/test_custom_detector_examples_runtime.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/test_detector_catalog_commercial.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/test_detector_pipeline_types.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/test_detector_schema_examples.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/test_detector_types.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/test_phase2_detectors.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/test_registry.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/threat/__init__.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/threat/test_code_security_detector.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/detectors/threat/test_yara_detector.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/integration/test_wordpress_broken_links_detector.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/integration/test_wordpress_links_assets.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/pipeline/test_detector_pipeline.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/pipeline/test_worker_pool.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_azure_blob_storage_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_base_source_attachment.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_base_source_sampling.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_confluence_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_custom_extractor.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_databricks_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_google_cloud_storage_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_hashing.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_hive_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_jira_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_mongodb_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_mssql_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_mysql_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_neo4j_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_oracle_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_outputs.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_postgresql_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_powerbi_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_recipe_normalizer.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_s3_compatible_storage_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_sandbox_runner.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_servicedesk_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_slack_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_snowflake_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_source_dependency_groups.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_sqlite_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_tableau_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_tabular_utils.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/test_wordpress_source.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/utils/test_content_extraction.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/utils/test_embedded_images.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/utils/test_file_parser.py +0 -0
- {classifyre_cli-0.4.11 → classifyre_cli-0.4.12}/tests/utils/test_file_to_images.py +0 -0
|
@@ -1078,9 +1078,10 @@ class DatabricksAuthMode(StrEnum):
|
|
|
1078
1078
|
|
|
1079
1079
|
PAT_TOKEN = 'PAT_TOKEN'
|
|
1080
1080
|
SERVICE_PRINCIPAL = 'SERVICE_PRINCIPAL'
|
|
1081
|
+
AZURE_SERVICE_PRINCIPAL = 'AZURE_SERVICE_PRINCIPAL'
|
|
1081
1082
|
|
|
1082
1083
|
|
|
1083
|
-
class
|
|
1084
|
+
class PersonalAccessToken(BaseModel):
|
|
1084
1085
|
model_config = ConfigDict(
|
|
1085
1086
|
extra='forbid',
|
|
1086
1087
|
)
|
|
@@ -1094,7 +1095,7 @@ class DatabricksRequiredPat(BaseModel):
|
|
|
1094
1095
|
)
|
|
1095
1096
|
|
|
1096
1097
|
|
|
1097
|
-
class
|
|
1098
|
+
class ServicePrincipalOAuthM2M(BaseModel):
|
|
1098
1099
|
model_config = ConfigDict(
|
|
1099
1100
|
extra='forbid',
|
|
1100
1101
|
)
|
|
@@ -1109,6 +1110,24 @@ class DatabricksRequiredServicePrincipal(BaseModel):
|
|
|
1109
1110
|
client_id: str = Field(..., description='Databricks service principal client ID')
|
|
1110
1111
|
|
|
1111
1112
|
|
|
1113
|
+
class AzureServicePrincipal(BaseModel):
|
|
1114
|
+
model_config = ConfigDict(
|
|
1115
|
+
extra='forbid',
|
|
1116
|
+
)
|
|
1117
|
+
auth_mode: Literal['AZURE_SERVICE_PRINCIPAL']
|
|
1118
|
+
workspace_url: AnyUrl = Field(
|
|
1119
|
+
...,
|
|
1120
|
+
description='Azure Databricks workspace URL (for example, https://adb-1234567890123456.7.azuredatabricks.net)',
|
|
1121
|
+
)
|
|
1122
|
+
warehouse_id: str = Field(
|
|
1123
|
+
..., description='Databricks SQL warehouse ID used for sampling queries'
|
|
1124
|
+
)
|
|
1125
|
+
client_id: str = Field(
|
|
1126
|
+
..., description='Azure AD application (client) ID for the service principal'
|
|
1127
|
+
)
|
|
1128
|
+
tenant_id: str = Field(..., description='Azure AD tenant ID')
|
|
1129
|
+
|
|
1130
|
+
|
|
1112
1131
|
class DatabricksMaskedPat(BaseModel):
|
|
1113
1132
|
model_config = ConfigDict(
|
|
1114
1133
|
extra='forbid',
|
|
@@ -1125,6 +1144,15 @@ class DatabricksMaskedServicePrincipal(BaseModel):
|
|
|
1125
1144
|
)
|
|
1126
1145
|
|
|
1127
1146
|
|
|
1147
|
+
class DatabricksMaskedAzureServicePrincipal(BaseModel):
|
|
1148
|
+
model_config = ConfigDict(
|
|
1149
|
+
extra='forbid',
|
|
1150
|
+
)
|
|
1151
|
+
client_secret: str = Field(
|
|
1152
|
+
..., description='Azure AD client secret for the service principal'
|
|
1153
|
+
)
|
|
1154
|
+
|
|
1155
|
+
|
|
1128
1156
|
class DatabricksOptionalConnection(BaseModel):
|
|
1129
1157
|
"""
|
|
1130
1158
|
Databricks API and SQL statement execution tuning options.
|
|
@@ -2020,8 +2048,8 @@ class DatabricksInput(CoreInput):
|
|
|
2020
2048
|
type: Literal['DATABRICKS'] = Field(
|
|
2021
2049
|
'DATABRICKS', description='Type of the asset or source'
|
|
2022
2050
|
)
|
|
2023
|
-
required:
|
|
2024
|
-
..., title='DatabricksRequired'
|
|
2051
|
+
required: PersonalAccessToken | ServicePrincipalOAuthM2M | AzureServicePrincipal = (
|
|
2052
|
+
Field(..., title='DatabricksRequired')
|
|
2025
2053
|
)
|
|
2026
2054
|
masked: DatabricksMaskedPat | DatabricksMaskedServicePrincipal = Field(
|
|
2027
2055
|
..., title='DatabricksMasked'
|
|
@@ -13,16 +13,18 @@ from urllib.parse import urlparse
|
|
|
13
13
|
import requests
|
|
14
14
|
|
|
15
15
|
from ...models.generated_input import (
|
|
16
|
+
AzureServicePrincipal,
|
|
16
17
|
DatabricksInput,
|
|
18
|
+
DatabricksMaskedAzureServicePrincipal,
|
|
17
19
|
DatabricksMaskedPat,
|
|
18
20
|
DatabricksMaskedServicePrincipal,
|
|
19
21
|
DatabricksOptionalConnection,
|
|
20
22
|
DatabricksOptionalExtraction,
|
|
21
23
|
DatabricksOptionalScope,
|
|
22
|
-
|
|
23
|
-
DatabricksRequiredServicePrincipal,
|
|
24
|
+
PersonalAccessToken,
|
|
24
25
|
SamplingConfig,
|
|
25
26
|
SamplingStrategy,
|
|
27
|
+
ServicePrincipalOAuthM2M,
|
|
26
28
|
)
|
|
27
29
|
from ...models.generated_single_asset_scan_results import (
|
|
28
30
|
AssetType as OutputAssetType,
|
|
@@ -106,14 +108,20 @@ class DatabricksSource(BaseTabularSource):
|
|
|
106
108
|
required = self.config.required
|
|
107
109
|
masked = self.config.masked
|
|
108
110
|
|
|
109
|
-
if isinstance(required,
|
|
111
|
+
if isinstance(required, PersonalAccessToken):
|
|
110
112
|
if not isinstance(masked, DatabricksMaskedPat):
|
|
111
113
|
raise ValueError("DATABRICKS PAT_TOKEN auth requires masked.token")
|
|
112
114
|
return
|
|
113
|
-
if isinstance(required,
|
|
115
|
+
if isinstance(required, ServicePrincipalOAuthM2M):
|
|
114
116
|
if not isinstance(masked, DatabricksMaskedServicePrincipal):
|
|
115
117
|
raise ValueError("DATABRICKS SERVICE_PRINCIPAL auth requires masked.client_secret")
|
|
116
118
|
return
|
|
119
|
+
if isinstance(required, AzureServicePrincipal):
|
|
120
|
+
if not isinstance(masked, DatabricksMaskedAzureServicePrincipal):
|
|
121
|
+
raise ValueError(
|
|
122
|
+
"DATABRICKS AZURE_SERVICE_PRINCIPAL auth requires masked.client_secret"
|
|
123
|
+
)
|
|
124
|
+
return
|
|
117
125
|
raise ValueError("Unsupported DATABRICKS auth configuration")
|
|
118
126
|
|
|
119
127
|
# ── Identity ─────────────────────────────────────────────────────────
|
|
@@ -163,7 +171,10 @@ class DatabricksSource(BaseTabularSource):
|
|
|
163
171
|
return int(self._connection_options().statement_timeout_seconds or 60)
|
|
164
172
|
|
|
165
173
|
def _is_pat_mode(self) -> bool:
|
|
166
|
-
return isinstance(self.config.required,
|
|
174
|
+
return isinstance(self.config.required, PersonalAccessToken)
|
|
175
|
+
|
|
176
|
+
def _is_azure_sp_mode(self) -> bool:
|
|
177
|
+
return isinstance(self.config.required, AzureServicePrincipal)
|
|
167
178
|
|
|
168
179
|
def _masked_pat_token(self) -> str:
|
|
169
180
|
masked = self.config.masked
|
|
@@ -174,12 +185,23 @@ class DatabricksSource(BaseTabularSource):
|
|
|
174
185
|
def _service_principal_credentials(self) -> tuple[str, str]:
|
|
175
186
|
required = self.config.required
|
|
176
187
|
masked = self.config.masked
|
|
177
|
-
if not isinstance(required,
|
|
188
|
+
if not isinstance(required, ServicePrincipalOAuthM2M):
|
|
178
189
|
raise ValueError("SERVICE_PRINCIPAL auth mode is required")
|
|
179
190
|
if not isinstance(masked, DatabricksMaskedServicePrincipal):
|
|
180
191
|
raise ValueError("DATABRICKS SERVICE_PRINCIPAL auth requires masked.client_secret")
|
|
181
192
|
return required.client_id, masked.client_secret
|
|
182
193
|
|
|
194
|
+
def _azure_sp_credentials(self) -> tuple[str, str, str]:
|
|
195
|
+
required = self.config.required
|
|
196
|
+
masked = self.config.masked
|
|
197
|
+
if not isinstance(required, AzureServicePrincipal):
|
|
198
|
+
raise ValueError("AZURE_SERVICE_PRINCIPAL auth mode is required")
|
|
199
|
+
if not isinstance(masked, DatabricksMaskedAzureServicePrincipal):
|
|
200
|
+
raise ValueError(
|
|
201
|
+
"DATABRICKS AZURE_SERVICE_PRINCIPAL auth requires masked.client_secret"
|
|
202
|
+
)
|
|
203
|
+
return required.tenant_id, required.client_id, masked.client_secret
|
|
204
|
+
|
|
183
205
|
def _is_access_token_expired(self) -> bool:
|
|
184
206
|
if self._access_token_expiry is None:
|
|
185
207
|
return True
|
|
@@ -206,12 +228,38 @@ class DatabricksSource(BaseTabularSource):
|
|
|
206
228
|
self._access_token_expiry = datetime.now(UTC) + timedelta(seconds=max(expires_in - 300, 0))
|
|
207
229
|
return token.strip()
|
|
208
230
|
|
|
231
|
+
def _acquire_azure_token(self) -> str:
|
|
232
|
+
# Azure AD v1 token endpoint; resource ID is the fixed Databricks app in Azure
|
|
233
|
+
_databricks_azure_resource = "2ff814a6-3304-4ab8-85cb-cd0e6f879c1d"
|
|
234
|
+
tenant_id, client_id, client_secret = self._azure_sp_credentials()
|
|
235
|
+
response = self.session.post(
|
|
236
|
+
f"https://login.microsoftonline.com/{tenant_id}/oauth2/token",
|
|
237
|
+
data={
|
|
238
|
+
"grant_type": "client_credentials",
|
|
239
|
+
"client_id": client_id,
|
|
240
|
+
"client_secret": client_secret,
|
|
241
|
+
"resource": _databricks_azure_resource,
|
|
242
|
+
},
|
|
243
|
+
timeout=self._timeout_seconds(),
|
|
244
|
+
)
|
|
245
|
+
response.raise_for_status()
|
|
246
|
+
payload = response.json()
|
|
247
|
+
token = payload.get("access_token")
|
|
248
|
+
if not isinstance(token, str) or not token.strip():
|
|
249
|
+
raise ValueError("Azure AD token response did not include access_token")
|
|
250
|
+
expires_in = int(payload.get("expires_in", 3600))
|
|
251
|
+
self._access_token_expiry = datetime.now(UTC) + timedelta(seconds=max(expires_in - 300, 0))
|
|
252
|
+
return token.strip()
|
|
253
|
+
|
|
209
254
|
def _access_token_value(self) -> str:
|
|
210
255
|
if self._is_pat_mode():
|
|
211
256
|
return self._masked_pat_token().strip()
|
|
212
257
|
if self._access_token and not self._is_access_token_expired():
|
|
213
258
|
return self._access_token
|
|
214
|
-
|
|
259
|
+
if self._is_azure_sp_mode():
|
|
260
|
+
self._access_token = self._acquire_azure_token()
|
|
261
|
+
else:
|
|
262
|
+
self._access_token = self._acquire_service_principal_token()
|
|
215
263
|
return self._access_token
|
|
216
264
|
|
|
217
265
|
def _authorization_header(self) -> str:
|
|
@@ -860,7 +908,12 @@ class DatabricksSource(BaseTabularSource):
|
|
|
860
908
|
with conn.cursor() as cursor:
|
|
861
909
|
cursor.execute("SELECT 1")
|
|
862
910
|
cursor.fetchone()
|
|
863
|
-
|
|
911
|
+
if self._is_pat_mode():
|
|
912
|
+
auth_mode = "PAT_TOKEN"
|
|
913
|
+
elif self._is_azure_sp_mode():
|
|
914
|
+
auth_mode = "AZURE_SERVICE_PRINCIPAL"
|
|
915
|
+
else:
|
|
916
|
+
auth_mode = "SERVICE_PRINCIPAL"
|
|
864
917
|
result["status"] = "SUCCESS"
|
|
865
918
|
result["message"] = (
|
|
866
919
|
"Successfully connected to Databricks Unity Catalog "
|