Google Cloud Endpoints元数据服务器身份验证

时间:2018-04-13 07:40:50

标签: google-cloud-platform jwt google-cloud-endpoints grpc

背景:

对于我正在处理的项目,我根据说明here使用可扩展服务代理(ESP)后面的gRPC API的服务帐户设置服务以进行服务身份验证。作为参考,我的身份验证配置如下所示

authentication:
  providers:
    - id: google_service_account
      issuer: <service-account-email>
      jwks_uri: https://www.googleapis.com/robot/v1/metadata/x509/<service-account-email>
  rules:
    - selector: "*"
      requirements:
        - provider_id: google_service_account

然后我有一个ruby客户端,它从磁盘读取服务帐户密钥(通过GCP控制台获得),并使用googleauth gem生成一个JWT,用于通过API进行身份验证。

module Authenticated
  def credentials
    @credentials ||= Google::Auth::ServiceAccountJwtHeaderCredentials
      .make_creds(json_key_io: service_account_json_io)
      .apply(jwt_aud_uri: ENV.fetch('SERVICE_NAME'))
  end

  def self.service_account
    @service_account ||= StringIO.new(
      File.read('/etc/secrets/service-account.json'),
    )
  end

  private

  def service_account_json_io
    Authenticated.service_account.tap(&:rewind)
  end
end

目前处于工作状态,客户端可以使用ESP进行身份验证。

问题:

自从实现上述功能后,我有另一个客户端应用程序需要重用相同的API。这意味着必须生成新的服务帐户密钥并将其安装到新的应用程序中以进行身份​​验证。最终,如果我创建更多客户端,则必须安全地存储许多服务帐户密钥容易出错且存在潜在的安全风险。相反,我想使用GCE元数据服务器从默认计算引擎服务帐户生成JWT(虽然我可能稍后使用其他帐户)并将其传递给ESP。

到目前为止,我所尝试的是更改ESP身份验证配置,如下所示

authentication:
  providers:
    - id: google_service_account
      issuer: https://accounts.google.com
      jwks_uri: https://www.googleapis.com/robot/v1/metadata/x509/<gce-default-service-account-email>
  rules:
    - selector: "*"
      requirements:
        - provider_id: google_service_account

并更新ruby客户端以从元数据服务器请求JWT,如下所示

module Authenticated
  METADATA_SERVER_IDENTITY_URI = 'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?format=full&audience='.freeze

  def credentials
    { authorization: "Bearer #{identity_jwt}" }
  end

  private

  def identity_jwt
    http = Net::HTTP.new(identity_uri.hostname)
    http.request(identity_request).body
  end

  def identity_request
    Net::HTTP::Get.new(identity_uri).tap do |req|
      req.add_field('Metadata-Flavor', 'Google')
    end
  end

  def identity_uri
    URI.parse("#{METADATA_SERVER_IDENTITY_URI}https://#{ENV['SERVICE_NAME']}")
  end
end

这次再次生成JWT,但这次将发行者设置为https://accounts.google.com(如ESP身份验证配置中所反映的)。但是,这次客户端无法通过ESP报告Error: KEY_RETRIEVAL_ERROR

进行身份验证

问题......最后:

是否可以使用通过GCE元数据服务器生成的JWT对ESP进行身份验证?什么是配置步骤?

2 个答案:

答案 0 :(得分:0)

通过从Google Cloud Endpoints配置yaml中删除jwks密钥,它会强制ESP使用OpenID发现来获取将用于获取正确jwks_uri的{​​{1}}。这可以在api manager configuration

中看到

如果问题(JWK)中定义了相同的发布者,代码将生成包含accounts.google.com的{​​{3}}的网址。 ESP使用此处指定的jwks_uri来验证JWT。

答案 1 :(得分:0)

是的,在第二种情况下,检索到的JWT是谷歌签名(“iss”是https://accounts.google.com)JWT,而不是签署的服务帐户(“iss”是服务帐户电子邮件)JWT。因此JWT URI需要相应更新。 以前的jwks-uri(https://www.googleapis.com/robot/v1/metadata/x509/)仅适用于签名为JWT的服务帐户。