Google 函数 HTTP 触发器 - 使用服务帐户的服务器到服务器的身份验证问题
Google function HTTP trigger - authentication problem server to server with service account
-
server-to-server
-
google-authentication
-
google-cloud-platform
-
google-cloud-functions
-
google-cloud-iam
我想做什么:从我的 server/machine 调用一个 google 函数并通过(简单的)身份验证限制它的使用。
我用什么: Node.js, google-auth-library 用于验证的库。
我有什么done/tried:
1) 在 Google Cloud Functions
中创建了一个项目
2) 创建了一个简单的 google 函数
exports.helloWorld = (req, res) => {
let message = req.query.message || req.body.message || 'Hello World!';
res.status(200).send(message);
};
3) 设置我的自定义服务帐户
4) 已启用 api:
- 云功能 API
- IAM 服务帐户凭据 API
-云运行API
- 计算引擎 API
- IAM 服务帐户凭证 API
5) 授予我的服务器帐户必要的授权(项目所有者、云功能管理员、IAM 项目管理员...(需要更多?)
6) 从我的服务帐户生成密钥并将其保存为 json 格式
注意:在所有用户许可下(无需授权),我可以毫无问题地调用我的端点
7) 在我的项目中,我尝试以这种方式验证我的功能
const { JWT } = require('google-auth-library');
const fetch = require('node-fetch');
const keys = require('./service-account-keys.json');
async function callFunction(text) {
const url = `https://europe-west1-myFunction.cloudfunctions.net/test`;
const client = new JWT({
email: keys.client_email,
keyFile: keys,
key: keys.private_key,
scopes: [
'https://www.googleapis.com/auth/cloud-platform',
'https://www.googleapis.com/auth/iam',
],
});
const res = await client.request({ url });
const tokenInfo = await client.getTokenInfo(client.credentials.access_token);
try {
const response = await fetch(url, {
method: 'GET',
headers: {
Authorization: `Bearer ${client.credentials.access_token}`,
},
});
if (response.status !== 200) {
console.log(response);
return {};
}
return response.json();
} catch (e) {
console.error(e);
}
}
ℹ️ 如果我尝试在 client.request() url 处传递而没有函数名称 (https://europe-west1-myFunction.cloudfunctions.net),我没有收到错误,但是当使用在 fetch 调用中获得的 JWT 令牌时,我收到了同样的错误。
结果:
Error:
<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>401 Unauthorized</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Unauthorized</h1>
<h2>Your client does not have permission to the requested URL <code>/test1</code>.</h2>
<h2></h2>
</body></html>
❓ 我如何调用带有任何保护的 google 函数以防止任何人使用它? (我不需要特定的安全性,只是随机用户不使用它)
在此先感谢您的帮助
当您调用私有函数(或私有云 运行)时,您必须使用 google 签名身份令牌.
在您的代码中,您使用了访问令牌
headers: {
Authorization: `Bearer ${client.credentials.access_token}`,
},
当您必须请求 Google 云 API 而不是您的服务时访问令牌工作
并且 google signed 很重要,因为您可以使用 google 身份验证库轻松生成自签名身份令牌,但它不会没工作
你有代码示例here and I wrote a tool in Go如果你想试一试
** 编辑 **
我做了一个例子,即使我不喜欢 Javascript,我也不得不承认我很嫉妒!!在 Node 中非常简单!!
这是我的工作示例
const {GoogleAuth} = require('google-auth-library');
async function main() {
// Define your URL, here with Cloud Run but the security is exactly the same with Cloud Functions (same underlying infrastructure)
const url = "https://go111-vqg64v3fcq-uc.a.run.app"
// Here I use the default credential, not an explicit key like you
const auth = new GoogleAuth();
//Example with the key file, not recommended on GCP environment.
//const auth = new GoogleAuth({keyFilename:"/path/to/key.json"})
//Create your client with an Identity token.
const client = await auth.getIdTokenClient(url);
const res = await client.request({url});
console.log(res.data);
}
main().catch(console.error);
注意:只有服务帐户才能生成观众身份令牌。如果您在本地计算机上,请不要使用默认凭据模式的用户帐户。
server-to-server
google-authentication
google-cloud-platform
google-cloud-functions
google-cloud-iam
我想做什么:从我的 server/machine 调用一个 google 函数并通过(简单的)身份验证限制它的使用。
我用什么: Node.js, google-auth-library 用于验证的库。
我有什么done/tried:
1) 在 Google Cloud Functions
中创建了一个项目2) 创建了一个简单的 google 函数
exports.helloWorld = (req, res) => {
let message = req.query.message || req.body.message || 'Hello World!';
res.status(200).send(message);
};
3) 设置我的自定义服务帐户
4) 已启用 api: - 云功能 API - IAM 服务帐户凭据 API -云运行API - 计算引擎 API - IAM 服务帐户凭证 API
5) 授予我的服务器帐户必要的授权(项目所有者、云功能管理员、IAM 项目管理员...(需要更多?)
6) 从我的服务帐户生成密钥并将其保存为 json 格式
注意:在所有用户许可下(无需授权),我可以毫无问题地调用我的端点
7) 在我的项目中,我尝试以这种方式验证我的功能
const { JWT } = require('google-auth-library');
const fetch = require('node-fetch');
const keys = require('./service-account-keys.json');
async function callFunction(text) {
const url = `https://europe-west1-myFunction.cloudfunctions.net/test`;
const client = new JWT({
email: keys.client_email,
keyFile: keys,
key: keys.private_key,
scopes: [
'https://www.googleapis.com/auth/cloud-platform',
'https://www.googleapis.com/auth/iam',
],
});
const res = await client.request({ url });
const tokenInfo = await client.getTokenInfo(client.credentials.access_token);
try {
const response = await fetch(url, {
method: 'GET',
headers: {
Authorization: `Bearer ${client.credentials.access_token}`,
},
});
if (response.status !== 200) {
console.log(response);
return {};
}
return response.json();
} catch (e) {
console.error(e);
}
}
ℹ️ 如果我尝试在 client.request() url 处传递而没有函数名称 (https://europe-west1-myFunction.cloudfunctions.net),我没有收到错误,但是当使用在 fetch 调用中获得的 JWT 令牌时,我收到了同样的错误。
结果:
Error:
<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>401 Unauthorized</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Unauthorized</h1>
<h2>Your client does not have permission to the requested URL <code>/test1</code>.</h2>
<h2></h2>
</body></html>
❓ 我如何调用带有任何保护的 google 函数以防止任何人使用它? (我不需要特定的安全性,只是随机用户不使用它) 在此先感谢您的帮助
当您调用私有函数(或私有云 运行)时,您必须使用 google 签名身份令牌.
在您的代码中,您使用了访问令牌
headers: {
Authorization: `Bearer ${client.credentials.access_token}`,
},
当您必须请求 Google 云 API 而不是您的服务时访问令牌工作
并且 google signed 很重要,因为您可以使用 google 身份验证库轻松生成自签名身份令牌,但它不会没工作
你有代码示例here and I wrote a tool in Go如果你想试一试
** 编辑 **
我做了一个例子,即使我不喜欢 Javascript,我也不得不承认我很嫉妒!!在 Node 中非常简单!!
这是我的工作示例
const {GoogleAuth} = require('google-auth-library');
async function main() {
// Define your URL, here with Cloud Run but the security is exactly the same with Cloud Functions (same underlying infrastructure)
const url = "https://go111-vqg64v3fcq-uc.a.run.app"
// Here I use the default credential, not an explicit key like you
const auth = new GoogleAuth();
//Example with the key file, not recommended on GCP environment.
//const auth = new GoogleAuth({keyFilename:"/path/to/key.json"})
//Create your client with an Identity token.
const client = await auth.getIdTokenClient(url);
const res = await client.request({url});
console.log(res.data);
}
main().catch(console.error);
注意:只有服务帐户才能生成观众身份令牌。如果您在本地计算机上,请不要使用默认凭据模式的用户帐户。