Coverage for src/chuck_data/databricks/permission_validator.py: 0%
63 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-06-05 22:56 -0700
« prev ^ index » next coverage.py v7.8.0, created at 2025-06-05 22:56 -0700
1"""
2Module for validating Databricks API token permissions.
3Provides functions to check access levels for different Databricks resources.
4"""
6import logging
7from typing import Dict, Any
10def validate_all_permissions(client) -> Dict[str, Dict[str, Any]]:
11 """
12 Run all permission checks and return detailed results.
14 Args:
15 client: API client instance with token
17 Returns:
18 Dict of permission check results by resource area
19 """
20 results = {
21 "basic_connectivity": check_basic_connectivity(client),
22 "unity_catalog": check_unity_catalog(client),
23 "sql_warehouse": check_sql_warehouse(client),
24 "jobs": check_jobs(client),
25 "models": check_models(client),
26 "volumes": check_volumes(client),
27 }
29 return results
32def check_basic_connectivity(client):
33 """
34 Check basic API connectivity using identity API.
35 """
36 try:
37 response = client.get("/api/2.0/preview/scim/v2/Me")
38 username = response.get("userName", "unknown")
39 return {
40 "authorized": True,
41 "details": f"Connected as {username}",
42 "api_path": "/api/2.0/preview/scim/v2/Me",
43 }
44 except Exception as e:
45 logging.debug(f"Basic connectivity check failed: {e}")
46 return {
47 "authorized": False,
48 "error": str(e),
49 "api_path": "/api/2.0/preview/scim/v2/Me",
50 }
53def check_unity_catalog(client):
54 """
55 Check Unity Catalog access permission.
56 """
57 try:
58 # Try listing catalogs with minimal results
59 response = client.get("/api/2.1/unity-catalog/catalogs?max_results=1")
60 catalog_count = len(response.get("catalogs", []))
61 return {
62 "authorized": True,
63 "details": f"Unity Catalog access granted ({catalog_count} catalogs visible)",
64 "api_path": "/api/2.1/unity-catalog/catalogs",
65 }
66 except Exception as e:
67 logging.debug(f"Unity Catalog check failed: {e}")
68 return {
69 "authorized": False,
70 "error": str(e),
71 "api_path": "/api/2.1/unity-catalog/catalogs",
72 }
75def check_sql_warehouse(client):
76 """
77 Check SQL warehouse access permission.
78 """
79 try:
80 response = client.get("/api/2.0/sql/warehouses?page_size=1")
81 warehouse_count = len(response.get("warehouses", []))
82 return {
83 "authorized": True,
84 "details": f"SQL Warehouse access granted ({warehouse_count} warehouses visible)",
85 "api_path": "/api/2.0/sql/warehouses",
86 }
87 except Exception as e:
88 logging.debug(f"SQL Warehouse check failed: {e}")
89 return {
90 "authorized": False,
91 "error": str(e),
92 "api_path": "/api/2.0/sql/warehouses",
93 }
96def check_jobs(client):
97 """
98 Check Jobs access permission.
99 """
100 try:
101 response = client.get("/api/2.1/jobs/list?limit=1")
102 job_count = len(response.get("jobs", []))
103 return {
104 "authorized": True,
105 "details": f"Jobs access granted ({job_count} jobs visible)",
106 "api_path": "/api/2.1/jobs/list",
107 }
108 except Exception as e:
109 logging.debug(f"Jobs check failed: {e}")
110 return {"authorized": False, "error": str(e), "api_path": "/api/2.1/jobs/list"}
113def check_models(client):
114 """
115 Check ML models access permission.
116 """
117 try:
118 response = client.get("/api/2.0/mlflow/registered-models/list?max_results=1")
119 model_count = len(response.get("registered_models", []))
120 return {
121 "authorized": True,
122 "details": f"ML Models access granted ({model_count} models visible)",
123 "api_path": "/api/2.0/mlflow/registered-models/list",
124 }
125 except Exception as e:
126 logging.debug(f"Models check failed: {e}")
127 return {
128 "authorized": False,
129 "error": str(e),
130 "api_path": "/api/2.0/mlflow/registered-models/list",
131 }
134def check_volumes(client):
135 """
136 Check Volumes access permission in Unity Catalog.
137 """
138 # For volumes, we need a catalog and schema
139 try:
140 # First get a catalog
141 catalog_response = client.get("/api/2.1/unity-catalog/catalogs?max_results=1")
142 catalogs = catalog_response.get("catalogs", [])
144 if not catalogs:
145 return {
146 "authorized": False,
147 "error": "No catalogs available to check volumes access",
148 "api_path": "/api/2.1/unity-catalog/volumes",
149 }
151 catalog_name = catalogs[0].get("name")
153 # Then get a schema
154 schema_response = client.get(
155 f"/api/2.1/unity-catalog/schemas?catalog_name={catalog_name}&max_results=1"
156 )
157 schemas = schema_response.get("schemas", [])
159 if not schemas:
160 return {
161 "authorized": False,
162 "error": f"No schemas available in catalog '{catalog_name}' to check volumes access",
163 "api_path": "/api/2.1/unity-catalog/volumes",
164 }
166 schema_name = schemas[0].get("name")
168 # Now check volumes
169 volume_response = client.get(
170 f"/api/2.1/unity-catalog/volumes?catalog_name={catalog_name}&schema_name={schema_name}"
171 )
172 volume_count = len(volume_response.get("volumes", []))
174 return {
175 "authorized": True,
176 "details": f"Volumes access granted in {catalog_name}.{schema_name} ({volume_count} volumes visible)",
177 "api_path": "/api/2.1/unity-catalog/volumes",
178 }
179 except Exception as e:
180 logging.debug(f"Volumes check failed: {e}")
181 return {
182 "authorized": False,
183 "error": str(e),
184 "api_path": "/api/2.1/unity-catalog/volumes",
185 }