【问题标题】:Access Cloud Function via HTTP from ruby client, using google auth gem使用 google auth gem 从 ruby​​ 客户端通过 HTTP 访问 Cloud Function
【发布时间】:2021-03-29 19:51:30
【问题描述】:

我正在尝试使用 ruby​​ googleauth gem 来验证服务帐户以对云函数进行 HTTP 调用,但没有成功。

测试代码:

require 'googleauth'

class TestService
  include HTTParty
  format :json
  debug_output $stdout

  def test
    authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
      json_key_io: File.open(ENV['GOOGLE_APPLICATION_CREDENTIALS']),
      scope: 'https://www.googleapis.com/auth/cloud-platform')
    options =
      {
        headers:
          {
            accept: 'application/json',
            authorization: "Bearer #{authorizer.fetch_access_token!['access_token']}"
          },
        query:
          {
            foo: 'bar'
          }
      }

    self.class.get('https://us-east1-xx-beta.cloudfunctions.net/my-cloud-function', options)
  end
end

TestService.new.test

(我想知道是否应该指定audience 而不是scope,但我一直无法做到这一点。)

我将 GOOGLE_APPLICATION_CREDENTIALS env var 设置为有效 GCP 服务帐户密钥文件的路径,并确保相关服务帐户列在此 Cloud Functions 的 Cloud Functions 权限中调用者角色。

访问失败,输出如下。

opening connection to us-east1-xx-beta.cloudfunctions.net:443...
opened
starting SSL for us-east1-xx-beta.cloudfunctions.net:443...
SSL established, protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384
<- "GET /my-cloud-function?foo=bar HTTP/1.1\r\nAccept: application/json\r\nAuthorization: Bearer ya29.c.Kp8B-QfKOgrA5jwGxc3tK8MkX2RJqe0LcQqKtjo1hMDJawXJZWTOq3nZyOHkfHZMJpm5hbFr11T7LFTzbP4bnxX1SIUXJt-papBSKYU0lOKXXiqdwa9s5yN-oHD45qSp6bSOIMwzhG9GJC8ZqeOrbyJAhd5oqmZUgqDg_2cgGusA5wVViaJZtiBFC_TaMmBK06MUmGT2a1q4UGLIyH4nyug1\r\nAccept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3\r\nUser-Agent: Ruby\r\nConnection: close\r\nHost: us-east1-xx-beta.cloudfunctions.net\r\n\r\n"
-> "HTTP/1.1 401 Unauthorized\r\n"
-> "WWW-Authenticate: Bearer error=\"invalid_token\" error_description=\"The access token could not be verified\"\r\n"
-> "Date: Mon, 29 Mar 2021 19:42:21 GMT\r\n"
-> "Content-Type: text/html; charset=UTF-8\r\n"
-> "Server: Google Frontend\r\n"
-> "Content-Length: 315\r\n"
-> "Alt-Svc: h3-29=\":443\"; ma=2592000,h3-T051=\":443\"; ma=2592000,h3-Q050=\":443\"; ma=2592000,h3-Q046=\":443\"; ma=2592000,h3-Q043=\":443\"; ma=2592000,quic=\":443\"; ma=2592000; v=\"46,43\"\r\n"
-> "Connection: close\r\n"
-> "\r\n"
reading 315 bytes...
-> "\n<html><head>\n<meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n<title>401 Unauthorized</title>\n</head>\n<body text=#000000 bgcolor=#ffffff>\n<h1>Error: Unauthorized</h1>\n<h2>Your client does not have permission to the requested URL <code>/my-cloud-function?foo=bar</code>.</h2>\n<h2></h2>\n</body></html>\n"
read 315 bytes
Conn close

【问题讨论】:

  • Cloud Functions 需要一个 OAuth 身份令牌,并将受众设置为函数 URL。您正在发送 OAuth 访问令牌。
  • @JohnHanley 这就是我所怀疑的,但我还没有完全弄清楚如何使用 googleauth gem 来解决这个问题。但感谢朝那个方向轻推,我会继续努力的。函数 URL 是完整的 URL,对吗?包括参数?
  • 只是函数URL,不是查询参数。

标签: ruby google-cloud-functions google-authentication google-auth-library google-auth-library-ruby


【解决方案1】:

正如 John Hanley 所提到的,您正在使用访问令牌作为函数的授权,但您需要 Identity Token 才能成功调用该函数。您可以在程序中通过将scope 更改为target_audience 来做到这一点:

authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
  json_key_io: File.open(ENV['GOOGLE_APPLICATION_CREDENTIALS']),
  target_audience: "GCF-TRIGGER-URL")

然后使用以下方法获取 ID 令牌:

authorizer.fetch_access_token!["id_token"]

make_creds()(查看源代码)中有一条线索表明同时指定 scope 和 target_audience 会引发 ArgumentError。测试该库将显示指定 scope 返回访问令牌,而指定 target_audience 将返回 ID 令牌。

【讨论】:

    猜你喜欢
    • 2016-03-23
    • 2021-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-16
    • 2012-02-29
    • 2022-09-28
    相关资源
    最近更新 更多