使用用户帐户凭据访问私有云运行/云功能 [英] Use user account Credential for reaching private Cloud Run/Cloud Functions
问题描述
这是我的用例.
- 我已经有一个以私有模式部署的Cloud Run服务. (与Cloud Function相同的问题)
- 我正在开发使用此Cloud Run的新服务.我在应用程序中使用默认凭据进行身份验证.它可以在Compute Engine和Cloud Run上使用,因为默认证书是从元数据服务器获取的.
但是,在我的本地环境中,我需要使用服务帐户密钥文件来实现此目的. (例如,当我设置GOOGLE_APPLICATION_CREDENTIALS环境变量时)
But, on my local environment, I need to use a service account key file for achieving this. (for example, when I set the GOOGLE_APPLICATION_CREDENTIALS env var)
但是,我无法使用我的用户帐户凭据.
在Java,Node或Go中,日志跟踪非常清晰:无法在用户凭证类型上生成身份令牌.
The log trace are very clear in Java, Node or Go: impossible to generate an identity token on a user credential type.
所以
- 为什么Google身份验证库不允许这样做?
- 为什么Google前端仅接受Google签名的身份令牌?
- 是否存在继续使用用户帐户的解决方法?
还有一段上下文: 我们要避免使用服务帐户密钥文件.今天,这是我们的主要安全漏洞(文件被复制,通过电子邮件发送,甚至在Github上公开提交...). 用户帐户默认凭据可用于所有Google Cloud API,但不能与IAP和CLoud Run/Functions一起使用.
And a piece of context: we want to avoid to use service account key file. Today, it's our major security breach (files are copied, sent by email, even committed on Github publicly...). The user account default credential work with all Google Cloud API but not with IAP and CLoud Run/Functions.
编辑
这里有一些错误示例.
JAVA
我这样做
Credentials credentials = GoogleCredentials.getApplicationDefault().createScoped("https://www.googleapis.com/auth/cloud-platform");
IdTokenCredentials idTokenCredentials = IdTokenCredentials.newBuilder()
.setIdTokenProvider((IdTokenProvider) credentials)
.setTargetAudience(myUri).build();
HttpRequestFactory factory = new NetHttpTransport().createRequestFactory(new HttpCredentialsAdapter(idTokenCredentials));
我的用户凭证不符合IdTokenProvider
界面
And my user credential is not compliant with IdTokenProvider
interface
Caused by: java.lang.ClassCastException: class com.google.auth.oauth2.UserCredentials cannot be cast to class com.google.auth.oauth2.IdTokenProvider (com.google.auth.oauth2.UserCredentials and com.google.auth.oauth2.IdTokenProvider are in unnamed module of loader 'app')
节点
使用节点,此代码可用于服务帐户
With node, this code work with a service account
const {GoogleAuth} = require('google-auth-library');
const auth = new GoogleAuth()
const client = await auth.getIdTokenClient(url);
const res = await client.request({url});
console.log(res.data);
但是使用我的用户帐户,我收到了此错误
But with my user account, I got this error
Error: Cannot fetch ID token in this environment, use GCE or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to a service account credentials JSON file.
at GoogleAuth.getIdTokenClient(....)
推荐答案
gcloud auth activate-service-account --key-file
仅适用于您"运行gcloud命令,不会被需要GOOGLE_APPLICATION_CREDENTIALS
的应用程序"使用.
gcloud auth activate-service-account --key-file
is only for "you" running gcloud commands, it won’t be picked up by "applications" that need GOOGLE_APPLICATION_CREDENTIALS
.
从Java调用Google Cloud Run 或如何从在Cloud Run/GCP之外?,您要么需要具有Service Account的JSON密钥文件,要么必须在GCE/GKE/Cloud Run/App Engine/GCF实例中运行.
As you can see from Invoke a Google Cloud Run from java or How to call Cloud Run from out side of Cloud Run/GCP?, you either need to have the JSON key file of Service Account, or have to be running inside a GCE/GKE/Cloud Run/App Engine/GCF instance.
要使其在您的本地环境中正常工作,建议您使用gcloud auth application-default login
命令登录(此命令的作用就像您在本地设置了GOOGLE_APPLICATION_CREDENTIALS
一样).让我知道这是否有效.
For this to work on your local environment, I recommend logging in with gcloud auth application-default login
command (this command is meant to work like as if you’ve set GOOGLE_APPLICATION_CREDENTIALS
locally). Let me know if this works.
如果这不起作用,则万不得已时,您可以重构代码以在本地工作时从环境变量(如果设置)中获取身份令牌,例如:
If that doesn't work, as a last resort you can refactor your code to pick up identity token from an environment variable (if set) while working locally, such as:
$ export ID_TOKEN="$(gcloud auth print-identity-token -q)"
$ ./your-app
附录
按照Guillaume的要求,此gcloud auth print-identity-token
如何与我的个人Google凭据配合使用"?
Appendix
Per Guillaume's request "how does this gcloud auth print-identity-token
work with my personal Google credentials"?
方法如下:
-
gcloud
是向Google注册的OAuth客户端,要获取JWT令牌,您需要在GCE/GCF/GKE/GAE/CR环境中工作或拥有OAuth应用.
gcloud
is an OAuth client registered to Google, to get a JWT token you either need to work inside a GCE/GCF/GKE/GAE/CR environment OR have an OAuth app.
gcloud
发出这样的请求:
POST https://www.googleapis.com/oauth2/v4/token
连身:
grant_type=refresh_token&client_id=REDACTED.apps.googleusercontent.com&client_secret=REDACTED&refresh_token=REDACTED
对于我们来说,最可能的client_id
和client_secret
值是相同的,因为它们是gcloud的值.但是,它将用新令牌交换您的refresh_token
.
Most likely client_id
and client_secret
values are the same for us because they are gcloud’s. However, it exchanges your refresh_token
with a new token.
/token
响应将包含一个access_token
和id_token
.例如:
The /token
response will contain an access_token
and id_token
. e.g.:
{
"access_token": ".....",
"id_token": "eyJhbG....."
"expires_in": 3599,
"scope": "https://www.googleapis.com/auth/userinfo.email
https://www.googleapis.com/auth/appengine.admin
https://www.googleapis.com/auth/compute
https://www.googleapis.com/auth/cloud-platform
https://www.googleapis.com/auth/accounts.reauth openid",
"token_type": "Bearer",
}
gcloud
这是为您打印身份令牌的方式.
This is how gcloud
prints an identity token for you.
如果您对代码如何使用JSON密钥文件感到好奇,将会看到非常相似的内容.例如,在Go中有 http://google.golang.org/api/idtoken 包并且您会看到在那里有类似的实现方式.
If you are curious how does the code do it with a JSON key file, you’ll see something very similar. For example, in Go there's http://google.golang.org/api/idtoken package and you'll see a similar implementation there.
这篇关于使用用户帐户凭据访问私有云运行/云功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!