以编程方式为 BigQuery 服务传递服务帐户凭据(JSON 文件)
Posted
技术标签:
【中文标题】以编程方式为 BigQuery 服务传递服务帐户凭据(JSON 文件)【英文标题】:Passing Service Account Credential(JSON File) programmatically for BigQuery Service 【发布时间】:2017-07-21 20:44:54 【问题描述】:我正在将BigQuery
表中的数据导出到Google Cloud Storage
,并且我可以使用应用程序默认凭据成功地做到这一点。我在bash_profile
中设置了环境变量GOOGLE_APPLICATION_CREDENTIALS
(此环境变量指向我的服务帐户JSON
文件),这就是我能够检索BigQuery Service
(我正在使用Scala
(Java API 是用过的))。
val bigquery: BigQuery = BigQueryOptions.getDefaultInstance().getService()
现在,我正在尝试通过以编程方式传递服务帐户JSON
文件而不是使用环境变量(即GOOGLE_APPLICATION_CREDENTIALS
)来找到一种方法来检索BigQuery
服务
val inputStream = this.getClass.getResourceAsStream("/GCCredentials.json")
val credentials = GoogleCredentials.fromStream(inputStream)
val bigquery = BigQueryOptions.newBuilder().setCredentials(credentials).build().getService
但此代码不起作用,我收到以下异常
Exception in thread "main" java.lang.NullPointerException
at com.google.api.client.repackaged.com.google.common.base.Preconditions.checkNotNull(Preconditions.java:213)
at com.google.api.client.util.Preconditions.checkNotNull(Preconditions.java:127)
我的代码中缺少什么?
【问题讨论】:
【参考方案1】:TL;DR - 你错过了FileInputStream
。
加长版
试试这个:
val fileInputStream = new FileInputStream("/GCCredentials.json")
var credentials = GoogleCredentials.fromStream(fileInputStream)
val bigquery = BigQueryOptions.newBuilder().setCredentials(credentials).build().getService()
使用FileInputStream
读取服务帐户json 文件的内容并将FileInputStream
对象传递给GoogleCredentials
以构建凭据。
或者(仅用于添加信息),如果您知道 json 文件的格式是服务帐户凭据格式,则可以使用 ServiceAccountCredentials
而不是 GoogleCredentials
。
GoogleCredentials
是读取 OAuth2 凭据以用于任何 Google API 的基类,而 ServiceAccountCredentials
特定于服务帐户。使用其中任何一个都适用于您的情况。
指定要使用的项目
您很可能必须指定要使用的项目 ID(如果您的环境不提供此信息)。如果您没有明确设置,库将尝试猜测要使用的项目 ID。
您可以使用以下环境变量之一指定项目 ID:
GOOGLE_CLOUD_PROJECT
GCLOUD_PROJECT
如果未指定这些,它会查看您当前活动的gcloud
配置以检测要使用的项目。
您也可以在代码中明确设置(就像您在 cmets 中描述的那样),如下所示:
val bigquery = BigQueryOptions.newBuilder().setCredentials(credentials).setProjectId("MY_PROJECT_ID").build().getService()
【讨论】:
看起来代码最初可以工作,因为它使用了环境变量GOOGLE_APPLICATION_CREDENTIALS
。现在我收到此错误Exception in thread "main" java.lang.IllegalArgumentException: A project ID is required for this service but could not be determined from the builder or the environment. Please set a project ID using the builder.
...虽然该文件具有项目 ID
看来我必须通过调用BigQueryOptions.newBuilder().setCredentials(credentials).setProjectId(projectID).build().getService()
来指定项目ID。该代码现在有效。但如果项目 ID 已被 API 开箱即用读取会更好
@Raj - 您的服务帐户 json 文件是否包含 project_id
字段?
它确实有字段project_id
@Raj - 刚刚意识到它会根据您当前活动的本地 gcloud
配置选择一个默认项目,如果它存在,如果您没有在 BigQueryOptions.Builder
中指定一个。如果没有指定 projectId
并且在您当前的环境中不存在,我会看到您提到的相同错误。或者,可以使用GCLOUD_PROJECT
环境变量来指定项目。以上是关于以编程方式为 BigQuery 服务传递服务帐户凭据(JSON 文件)的主要内容,如果未能解决你的问题,请参考以下文章
Google BigQuery:授予服务帐户权限以仅在某些特定数据集中创建作业