Сходство BigQuery с «подписанными URL»

У меня есть следующий вариант использования в BigQuery:

  • Ненадежный пользователь будет запрашивать таблицу BigQuery. Допустим, запрос SELECT * FROM [bigquery.table123] .
  • Запрос вернет большое количество данных, скажем, 200 МБ, которые затем будут отображаться в браузере пользователя.

Наша цель - предоставить наиболее эффективный способ передачи 200-мегабайтных данных в браузер пользователя (и наихудшим способом, по-видимому, является выполнение двух поездок вместо одной - от BQ до нашего сервера и затем (сжато) до клиента). Я думаю, что решение для этого, вероятно, состояло бы в том, чтобы дать конечному (ненадежному) пользователю возможность получить что-то вроде «подписанного URL» для выполнения запроса непосредственно из браузера в BigQuery. Поток будет таким:

  • Пользователь выдает запрос к нашему бэкэнду.
  • Проверка подлинности завершена, подписанный URL-адрес генерируется и передается обратно в javascript.
  • Затем клиент отправляет подписанный URL-адрес, и данные загружаются непосредственно в браузер.
  • Только тот точный запрос, который был авторизован, может быть выполнен, и никакие другие запросы не могут быть выполнены (например, если клиент скопировал какие-либо токены из javascript)

Я бы никогда не хотел, чтобы конечный пользователь знал ProjectId или имена таблиц, которые они запрашивают.

Можно ли что-то подобное сделать в BigQuery? Вот пример аналогичной потребности в облачном хранилище . Вот пример аутентифицированного / доверенного пользователя, который делает это в браузере: https://github.com/googleapis/nodejs-bigquery/blob/master/samples/browseRows.js или.

Всего 1 ответ


Ниже представлен вариант, который включает два уровня авторизованных представлений. Это позволяет не только скрыть основные данные от конечного пользователя, но и скрыть, какие именно данные используются.

Давайте предположим, что данные находятся в DatasetA. Ниже приведены шаги, объясняющие логику

  1. Создайте InternalView в DatasetB - он будет нацелен на реальные данные из DatasetA.
  2. Сделать InternalView авторизованным представлением для DatasetA
  3. Создать PublicView в DatasetC - этот будет нацелен на InternalView
  4. Сделать PublicView авторизованным представлением для DatasetB
  5. Предоставьте пользователям доступ для чтения к DatasetC

Пользователи смогут запускать PublicView, который на самом деле будет запускать PrivateView для данных readl.
Тем временем пользователи не смогут увидеть определение PrivateView, поэтому никогда не узнают ProjectId or Table Name(s) that they are querying , и т. Д.

Примечание. Это не касается how we'd prevent users from being able to issue queries that we haven't pre-authorized? часть вашего вопроса, но я добавляю свой ответ, как вы просили меня сделать

Тем временем - по крайней мере, теоретически - вы можете встроить некоторую логику в свой PrivateView, который будет запрашивать некоторые внутренние метатаблицы с информацией о том, какому пользователю и когда позволено получить результат. Предполагая, что такая мета-таблица будет управляться вашим бэкэндом на основе аутентификации / токена или того, что вы имеете в виду

Ниже приведено упрощенное и краткое описание этого подхода.

#standardSQL
WITH `projectA.datasetA.table` AS (
  SELECT 'data1' col UNION ALL
  SELECT 'data2' UNION ALL
  SELECT 'data3'
), `projectA.datasetA.applicationPermissions` AS (
  SELECT 'user1@gmail.com' user UNION ALL
  SELECT 'user2@gmail.com'
), `projectA.datasetB.privateView` AS (
  SELECT d.* 
  FROM `projectA.datasetA.table` d
  CROSS JOIN `projectA.datasetA.applicationPermissions` p
  WHERE LOWER(user) = LOWER(SESSION_USER()) 
), `projectA.datasetC.publicView` AS (
  SELECT *
  FROM `projectA.datasetB.privateView`
)
SELECT *
FROM `projectA.datasetC.publicView`  

Если user1@gmail.com или user2@gmail.com будут выполняться ниже запроса

SELECT *
FROM `projectA.datasetC.publicView`  

они получат ниже результата

Row col  
1   data1    
2   data2    
3   data3    

в то время как если user3@gmail.com будет выполнять тот же самый запрос - результат будет

Row col  
Query returned zero records.

Очевидно, что вы можете расширить свою мета-таблицу (applicationPermissions), например, с периодом времени, в течение которого пользователю будет разрешено получать результат (необходимо добавить соответствующие строки для проверки временных условий в projectA.datasetB.privateView ).


Есть идеи?

10000