通过身份验证保护Google Cloud功能http触发器

Tri*_*yen 34 security authentication google-cloud-datastore google-cloud-functions

我正在按照本指南尝试Google云端功能:https://cloud.google.com/functions/docs/quickstart

我创建了一个带有HTTP触发器的函数,并且能够执行POST请求以触发函数写入数据存储区.

我想知道是否有办法保护这个HTTP端点?目前似乎它将接受来自任何地方/任何人的请求.

当谷歌搜索时,我看到大多数结果都谈到使用Firebase保护内容.但是,我没有在这里使用Firebase服务.

我的选择是让它打开,希望没有人知道URL端点(默默无闻的安全性),或者在函数本身中实现我自己的auth检查?

Tri*_*yen 12

在进一步研究之后,并从@ ricka的答案中得到一个提示,我决定使用以授权标头访问令牌形式传入的JWT令牌对我的云功能进行身份验证检查.

这是Node中的实现:

const client = jwksClient({
  cache: true,
  rateLimit: true,
  jwksRequestsPerMinute: 5,
  jwksUri: "https://<auth0-account>.auth0.com/.well-known/jwks.json"
});

function verifyToken(token, cb) {
  let decodedToken;
  try {
    decodedToken = jwt.decode(token, {complete: true});
  } catch (e) {
    console.error(e);
    cb(e);
    return;
  }
  client.getSigningKey(decodedToken.header.kid, function (err, key) {
    if (err) {
      console.error(err);
      cb(err);
      return;
    }
    const signingKey = key.publicKey || key.rsaPublicKey;
    jwt.verify(token, signingKey, function (err, decoded) {
      if (err) {
        console.error(err);
        cb(err);
        return
      }
      console.log(decoded);
      cb(null, decoded);
    });
  });
}

function checkAuth (fn) {
  return function (req, res) {
    if (!req.headers || !req.headers.authorization) {
      res.status(401).send('No authorization token found.');
      return;
    }
    const parts = req.headers.authorization.split(' ');
    if (parts.length != 2) {
      res.status(401).send('Bad credential format.');
      return;
    }
    const scheme = parts[0];
    const credentials = parts[1];

    if (!/^Bearer$/i.test(scheme)) {
      res.status(401).send('Bad credential format.');
      return;
    }
    verifyToken(credentials, function (err) {
      if (err) {
        res.status(401).send('Invalid token');
        return;
      }
      fn(req, res);
    });
  };
}
Run Code Online (Sandbox Code Playgroud)

jsonwebtoken用来验证JWT令牌,并jwks-rsa检索公钥.我使用Auth0,因此请到公钥jwks-rsa列表中检索它们.

checkAuth然后,该功能可用于保护云功能:

exports.get = checkAuth(function (req, res) {
    // do things safely here
});
Run Code Online (Sandbox Code Playgroud)

你可以在我的github repo上看到这个变化,网址是https://github.com/tnguyen14/functions-datastore/commit/a6b32704f0b0a50cd719df8c1239f993ef74dab6

可以通过多种方式检索JWT /访问令牌.对于Auth0,可以在https://auth0.com/docs/api/authentication#authorize-client找到API文档.

一旦到位,您可以触发云功能(如果您使用http触发器启用了您的功能)

curl -X POST -H "Content-Type: application/json" \
-H "Authorization: Bearer access-token" \
-d '{"foo": "bar"}' \
"https://<cloud-function-endpoint>.cloudfunctions.net/get"
Run Code Online (Sandbox Code Playgroud)


use*_*825 6

三年后,我在同一个问题上苦恼了一天,而 Google 文档是 er,不是很有说明性。对于那些不想在代码中实现这一点的人(我),我在下面概述了如何仅使用 GCP 控制台对 Cloud Functions 进行身份验证。以下示例将 HTTP 触发器验证到新服务帐户,然后计划在 Cloud Scheduler 中运行该帐户。您可以进一步扩展和概括它以满足其他需求。

假设: 1.您已经创建了一个使用 HTTP 的云函数并使其需要身份验证。2.当您进行测试运行时,您的功能有效。这很重要,您不希望以后同时解决两个或更多问题。3.您知道如何绕过 GCP Web 浏览器控制台。

脚步

  1. 我建议创建一个新的服务帐户,用于调用 HTTP 云函数的任务。通过 GCP 的“IAM 和管理”页面执行此操作。转到“服务帐户”,然后“新建” 在此处输入图片说明

  2. 为您的新服务帐户命名。服务帐户 ID 将根据您创建的名称自动生成。它看起来像 GCP 服务帐户电子邮件。“@yourproject-name.iam.gserviceaccount.com。复制此内容以备后用。单击“创建”按钮以完成新帐户的创建。

  3. 在下一页上,您需要为服务帐户选择一个角色。仅运行函数的最佳实践是“Cloud Functions Invoker”。单击“继续”按钮。你可以跳过第三部分。(授予用户访问此服务帐户的权限) 在此处输入图片说明

  4. 好的,现在让我们将这个新的服务帐户添加到需要保护的云功能中。转到 Cloud Function 面板并选中函数名称左侧的框。然后在同一面板的右上角,单击“显示信息面板” - 在屏幕中注意需要身份验证。(您必须从这里添加,而不是从“权限”页面添加功能 - 您不能从那里添加新成员。) 在此处输入图片说明

  5. 现在将服务帐户添加为新成员。将您之前复制的服务帐户电子邮件粘贴到红色框中的空白字段中。您必须输入电子邮件帐户,仅凭名称是行不通的。对于“角色” - 在下拉列表中,再次选择“云函数调用者”。单击保存。 在此处输入图片说明

  6. 在 Cloud Functions 的属性中,有提供的 HTTP 触发器,复制你的并放在手边以备后用。 在此处输入图片说明

  7. 现在转到 Google Cloud Scheduler 并选择一个计划。(如果您还没有,请创建一个。下面的屏幕显示已经制作的一个。) 在此处输入图片说明

  8. 选中“计划”框后,单击“编辑”,您将看到下面的屏幕。选择初始屏幕底部的“显示更多”以查看所有字段。关于权限的重要字段:

对于“URL” - 粘贴您在第 6 步中复制的触发器 URL。
对于“Auth Header”,选择 OIDC 令牌。这些由 GCP 为您的项目管理,足以进行身份​​验证。
对于“服务帐户”,粘贴与上述步骤相同的内容。
“观众”会自动填充,无需在那里放任何东西。完成后,根据您的入口点单击“更新”或“保存”。 在此处输入图片说明

  1. 返回 Cloud Scheduler 仪表板,单击“立即运行”按钮运行您的函数。如果一切顺利,它应该会运行并出现“成功”状态。如果没有,请检查日志以查看发生了什么。 在此处输入图片说明

  2. 所以现在您知道您的经过身份验证的 Cloud Function 与为其创建的服务帐户一起使用。从这里,您可以根据项目需要在此服务帐户的上下文中执行各种操作。

  3. 作为检查,请务必将 HTTP 触发器 URL 粘贴到浏览器中以确保它无法运行。你应该得到以下禁止: 在此处输入图片说明

  • 感谢您的精彩回答。现在我想从第三方应用程序(例如 LMS 或任何自定义服务器)调用该 HTTP 函数,那么如何确保 HTTP 函数将由您在此处创建的服务帐户执行。这里你已经在调度程序中添加了服务帐户,但是如果我从 thordpary 服务器调用它怎么办? (6认同)