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

时间:2017-09-22 06:14:50

标签: security authentication google-cloud-datastore google-cloud-functions

我今天按照本指南试用了Google云端功能:https://cloud.google.com/functions/docs/quickstart

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

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

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

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

6 个答案:

答案 0 :(得分: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);
    });
  };
}

我使用jsonwebtoken来验证JWT令牌,使用jwks-rsa来检索公钥。我使用Auth0,因此jwks-rsa会到达公钥列表以检索它们。

然后可以使用checkAuth函数来保护云功能:

exports.get = checkAuth(function (req, res) {
    // do things safely here
});

您可以在https://github.com/tnguyen14/functions-datastore/commit/a6b32704f0b0a50cd719df8c1239f993ef74dab6

上的github repo上看到此更改

可以通过多种方式检索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"

答案 1 :(得分:3)

您可以在功能的外部中设置项目范围或每个功能的权限,这样,即使经过身份验证的用户尝试击中终结点,也可以触发该功能。< / p>

有关setting permissionsauthenticating users的Google Cloud Platform文档。请注意,在撰写本文时,我相信使用此方法要求用户使用Google帐户进行身份验证。

答案 2 :(得分:1)

目前似乎有两种方法可以保护Google Cloud Function HTTP端点。

1)使用难以猜测的函数名称(例如:my-function-vrf55m6f5Dvkrerytf35)

2)检查函数本身内的密码/凭证/签名请求(使用标题或参数)

可能最好两者兼顾。

答案 3 :(得分:0)

你不应该“保持开放,希望没有人知道”。您可以实施自己的安全检查,也可以尝试使用Google功能授权模块(https://www.npmjs.com/package/google-function-authorizer)。

答案 4 :(得分:0)

您可以创建自定义身份验证算法来验证客户端。

从中检查算法; https://security.stackexchange.com/q/210085/22239

答案 5 :(得分:0)

三年后,我花了一天的时间烦恼这个问题,而Google文档是错误的,不是很好的说明。对于那些不想在代码中实现此功能的人,我在下面概述了如何仅使用GCP控制台对Cloud Functions进行身份验证。以下是将HTTP触发器认证到新服务帐户的示例,该新服务帐户随后计划在Cloud Scheduler中运行。您可以对此进行进一步扩展和概括,以适应其他需求。

假设: 1.您已经创建了一个使用HTTP的Cloud Function,并使其需要身份验证。 2.当您执行“测试运行”时,您的功能将起作用。这很重要,您不想以后再解决两个或多个问题。 3.您知道如何避开GCP Web浏览器控制台。

步骤

  1. 我建议创建一个新的服务帐户,该帐户将用于调用HTTP Cloud Function的任务。通过GCP的“ IAM和管理员”页面执行此操作。转到“服务帐户”,然后“新建” enter image description here

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

  3. 在下一页上,您需要为服务帐户选择一个角色。仅运行功能的最佳实践是“ Cloud Functions Invoker”。点击“继续”按钮。您可以跳过第3部分。 (授予用户访问此服务帐户的权限) enter image description here

  4. 现在,
  5. Ok可以将此新服务帐户添加到需要保护的云功能中。转到“ Cloud Function”面板,然后选中函数名称左侧的框。然后,在同一面板的右上角,单击“显示信息面板”-在屏幕中注意,要求进行身份验证。 (您必须从这里添加,而不是功能“权限”页面-您不能从此处添加新成员。) enter image description here

  6. 现在将服务帐户添加为新成员。将您先前复制的服务帐户电子邮件粘贴到红色框中的空白字段中。您必须输入电子邮件帐户,仅此名称将不起作用。对于“角色”-在下拉列表中,再次选择“云函数调用程序”。单击保存。 enter image description here

  7. 在Cloud Function的属性中,提供了HTTP触发器,将其复制并方便以后使用。 enter image description here

  8. 现在转到Google Cloud Scheduler并选择一个时间表。 (或者,如果您还没有一个,则创建一个。下面的屏幕显示已经制作的一个。) enter image description here

  9. 在“计划”复选框处于选中状态时,单击“编辑”,将显示以下屏幕。选择初始屏幕底部的“显示更多”以查看所有字段。有关权限的重要字段:

对于“ URL”-粘贴您在第6步中复制的触发器URL。
对于“ Auth Header”,请选择OIDC令牌。这些由您的项目的GCP管理,足以进行身份​​验证。
对于“服务帐户”,请粘贴上述步骤中的同一帐户。
“受众群体”将自动填充,无需在此处放置任何内容。 完成后,根据您的入口点单击“更新”或“保存”。 enter image description here

  1. 返回Cloud Scheduler仪表板,单击“立即运行”按钮运行功能。如果一切顺利,它将运行并且状态为“成功”。如果不是,请检查日志以查看发生了什么。 enter image description here

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

  3. 作为检查,请确保将HTTP触发URL粘贴到浏览器中,以确保它无法运行。您应该获得以下禁止信息: enter image description here