bluemalkin opened a new issue, #41906:
URL: https://github.com/apache/superset/issues/41906

   ### Bug description
   
   ## Bug description
   
   When a BigQuery connection uses **Application Default Credentials** (in our 
case: GKE Workload Identity — the pod's Kubernetes Service Account is bound to 
a Google Service Account that lives in the GKE project but has been granted 
read access to BigQuery datasets in a *different* project), adding a physical 
dataset fails as soon as a table is selected:
   
   ```json
   {
     "errors": [{
       "message": "GET 
https://bigquery.googleapis.com/bigquery/v2/projects/<GSA-PROJECT>/datasets/support/tables/api_events?prettyPrint=false:
 Not found: Dataset <GSA-PROJECT>:support",
       "error_type": "GENERIC_BACKEND_ERROR",
       "level": "error"
     }]
   }
   ```
   
   The connection URI is `bigquery://<DATA-PROJECT>`, but the request targets 
`<GSA-PROJECT>` — the project the ADC credentials belong to (where GKE runs), 
not the project where the datasets live.
   
   Notably, the **schema and table dropdowns populate correctly** (those go 
through the SQLAlchemy dialect, which honors the URI host); only selecting a 
table fails ("Unable to load columns for the selected table"). Enabling 
`allow_multi_catalog` and selecting the correct catalog in the dataset panel 
does not help.
   
   This worked in 4.x and 5.x with the same connection URI, the same Workload 
Identity setup, and the same `sqlalchemy-bigquery` version (1.17.0).
   
   ## Root cause
   
   `BigQueryEngineSpec._get_client` builds the raw Google client **without a 
`project=` argument** ([bigquery.py L527-L553 @ 
6.1.0](https://github.com/apache/superset/blob/6.1.0/superset/db_engine_specs/bigquery.py#L527-L553)):
   
   ```python
   credentials = google.auth.default()[0]
   return bigquery.Client(credentials=credentials)   # project defaults to the 
ADC project
   ```
   
   so `client.project` is the credentials' project, ignoring the project in the 
connection URI (`engine.url.host`).
   
   This bug is present but *latent* in ≤5.0 — nothing in the dataset-creation 
flow called `_get_client`. Superset 6.0's partition-metadata feature added 
`get_time_partition_column` ([L409-L423 @ 
6.1.0](https://github.com/apache/superset/blob/6.1.0/superset/db_engine_specs/bigquery.py#L409-L423)),
 which is invoked from `get_extra_table_metadata` on every table selection and 
passes an **unqualified two-part table ID** to that client:
   
   ```python
   bq_table = client.get_table(f"{table.schema}.{table.table}")
   ```
   
   A two-part ID is resolved against `client.project` → wrong project → 404. 
Other `_get_client` consumers (`get_catalog_names`, `estimate_query_cost`) are 
affected the same way.
   
   ## How to reproduce
   
   1. Run Superset ≥6.0 on GKE with Workload Identity; the bound GSA lives in 
project **A** and has `bigquery.dataViewer`/`bigquery.jobUser` on datasets in 
project **B**.
   2. Create a BigQuery connection with URI `bigquery://<project-B>` and no 
`credentials_info` (ADC only).
   3. **Datasets → New dataset** → pick the connection → schema and table 
dropdowns list project B's contents correctly.
   4. Select a table → error: `Not found: Dataset <project-A>:<schema>`.
   
   ## Expected results
   
   The table metadata call should target the project from the connection URI 
(or the selected catalog), consistent with how the SQLAlchemy dialect resolves 
it.
   
   ## Suggested fix
   
   Pass the engine's project to the client, and/or fully qualify the table 
reference:
   
   ```python
   # _get_client
   return bigquery.Client(credentials=credentials, project=engine.url.host or 
None)
   ```
   
   ## Workaround we deployed (confirmed working)
   
   Monkeypatch via `superset_config.py` (`FLASK_APP_MUTATOR` to avoid circular 
imports at config-load time):
   
   ```python
   def FLASK_APP_MUTATOR(app):
       import google.auth
       from google.cloud import bigquery
       from google.oauth2 import service_account
       from superset.db_engine_specs.bigquery import BigQueryEngineSpec
   
       @classmethod
       def _get_client(cls, engine, database):
           project = engine.url.host or None
           if credentials_info := engine.dialect.credentials_info:
               credentials = 
service_account.Credentials.from_service_account_info(credentials_info)
               return bigquery.Client(credentials=credentials, project=project)
           try:
               credentials = google.auth.default()[0]
           except google.auth.exceptions.DefaultCredentialsError as ex:
               from superset.db_engine_specs.exceptions import 
SupersetDBAPIConnectionError
               raise SupersetDBAPIConnectionError("The database credentials 
could not be found.") from ex
           return bigquery.Client(credentials=credentials, project=project)
   
       BigQueryEngineSpec._get_client = _get_client
   ```
   
   After this patch, cross-project dataset creation works again.
   
   ## Environment
   
   - Superset: 6.1.0 (official Helm chart 0.17.2); the affected code is 
unchanged in `master`
   - `sqlalchemy-bigquery`: 1.17.0 (same version worked on Superset 5.0 — not a 
driver issue)
   - Deployment: GKE, Workload Identity (KSA → GSA), GSA project ≠ dataset 
project
   - Auth to BigQuery: Application Default Credentials (no `credentials_info` 
on the connection)
   
   
   
   ### Screenshots/recordings
   
   _No response_
   
   ### Superset version
   
   6.1.0
   
   ### Python version
   
   3.10
   
   ### Node version
   
   I don't know
   
   ### Browser
   
   Chrome
   
   ### Additional context
   
   _No response_
   
   ### Checklist
   
   - [x] I have searched Superset docs and Slack and didn't find a solution to 
my problem.
   - [x] I have searched the GitHub issue tracker and didn't find a similar bug 
report.
   - [x] I have checked Superset's logs for errors and if I found a relevant 
Python stacktrace, I included it here as text in the "additional context" 
section.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to