0

我不断收到带有下面测试代码的 403。只是我还是在同一个项目中调用函数过于复杂?我在这里这里做了一些研究。

我已经在两个函数的默认服务帐户上设置了云函数调用程序。和allow internal traffic

所以我尝试了下面的两个代码。令牌在第一个函数中打印到日志中,那么为什么我仍然得到 403?

脚本1:

const axios = require("axios");
/**
 * Responds to any HTTP request.
 *
 * @param {!express:Request} req HTTP request context.
 * @param {!express:Response} res HTTP response context.
 */
exports.helloWorld = async (req, res) => {
  console.log(JSON.stringify(process.env));

  const sample_api_url = `https://someRegionAndSomeProject.cloudfunctions.net/sample-api`;
  const metadataServerURL =
    "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=";
  const tokenUrl = metadataServerURL + sample_api_url;

  // Fetch the token
  const tokenResponse = await axios(tokenUrl, {
    method: "GET",
    headers: {
      "Metadata-Flavor": "Google",
    },
  });

  const token = tokenResponse.data;

  console.log(token);

  const functionResponse = await axios(sample_api_url, {
    method: "GET",
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
    },
  });
  
  const data = functionResponse.data;
  console.log(data);
  res.status(200).json({ token, data });
};

脚本2:

const {GoogleAuth} = require('google-auth-library');
/**
 * Responds to any HTTP request.
 *
 * @param {!express:Request} req HTTP request context.
 * @param {!express:Response} res HTTP response context.
 */
exports.helloWorld = async (req, res) => {

const url = 'https://someRegionAndSomeProject.cloudfunctions.net/sample-api';
const targetAudience = url;
const auth = new GoogleAuth();
const client = await auth.getIdTokenClient(targetAudience);
const response = await client.request({url});

res.status(200).json({data: response.data})

};
4

2 回答 2

1

根据您的帖子,我创建了一个适合我的示例。我创建了两个 GCP 函数“func1”和“func2”。然后,我确定了如何从 func1 调用 func2,其中 func2 仅公开以由 func1 运行的服务帐户身份调用。

func1的最终代码如下:

const func2Url = 'https://us-central1-XXX.cloudfunctions.net/func2';
const targetAudience = func2Url;
const {GoogleAuth} = require('google-auth-library');
const auth = new GoogleAuth();

async function request() {
  console.info(`request ${func2Url} with target audience ${targetAudience}`);
  const client = await auth.getIdTokenClient(targetAudience);
  const res = await client.request({url: func2Url});
  console.info(res.data);
  return res;
}


exports.func1 = async (req, res) => {
  let message = `Hello from func1`;
  try {
    let response = await request();
    res.status(200).send(`${message} + ${response.data}`);
  }
  catch(e) {
    console.log(e);
    res.status(500).send('failed');
  }
};

此处使用的主要配方如此处的 Google 文档中所述。我还发现这篇中等文章很有帮助。

于 2022-02-21T23:43:24.627 回答
1

Cloud Functions 有 2 种类型的安全性

  • 基于身份的安全性:如果您在没有 allow-unauthenticated 参数的情况下部署 Cloud Functions,则必须发送带有Authorization: bearer <token>标头的请求,其中 token 是至少具有云函数调用者角色的身份令牌。您还可以添加allUsers具有云函数调用者角色的用户,以使函数可公开访问(不需要安全标头)
  • 基于网络的安全性:这一次,仅允许来自您的项目 VPC 或您的 VPC SC 的请求访问 Cloud Functions。如果您尝试从未经授权的网络访问云功能,则会收到 403(您的错误)。

如果需要,您可以结合使用 2 个安全解决方案。在您的代码中,您正确添加了安全标头。但是,您的请求被网络检查拒绝。


解决方案不是那么简单,不是免费的,我完全同意你的观点,这种模式应该更简单。

为此,您必须创建一个无服务器 VPC 连接器并将其附加到执行调用的函数上。您还必须在该功能上将出口设置为 ALL。就这样

结果如下:由于无服务器 VPC 连接器,源自您的函数的流量将被路由到您的 VPC。Cloud Functions URL 始终是公共 URL,您必须将出口设置为 ALL,才能通过无服务器 VPC 连接器将前往公共 URL 的流量路由。

于 2022-02-22T12:43:59.837 回答