Google Cloud Endpoints 元数据服务器身份验证
Google Cloud Endpoints Metadata Server Authentication
上下文:
对于我正在处理的项目,我根据说明 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 进行身份验证?配置步骤是什么?
通过从 Google Cloud Endpoints 配置 yaml 中删除 jwks
密钥,它会强制 ESP 使用 OpenID 发现来获取 jwks_uri
,它将用于获取正确的 JWK
。这可以在 api manager configuration.
中看到
给定问题中定义的相同发行人 (accounts.google.com
),代码将生成 URL 到 https://accounts.google.com/.well-known/openid-configuration,其中包含 jwks_uri
。 ESP 使用此处指定的 jwks
来验证 JWT。
是的,在第二种情况下,检索到的 JWT 是 Google 签名的("iss" 是 https://accounts.google.com)JWT,而不是服务帐户签名的("iss" 是服务帐户电子邮件)智威汤逊。因此 JWT URI 需要相应地更新。
以前的 jwks-uri (https://www.googleapis.com/robot/v1/metadata/x509/) 仅适用于服务帐户签名的 JWT。
上下文:
对于我正在处理的项目,我根据说明 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 进行身份验证?配置步骤是什么?
通过从 Google Cloud Endpoints 配置 yaml 中删除 jwks
密钥,它会强制 ESP 使用 OpenID 发现来获取 jwks_uri
,它将用于获取正确的 JWK
。这可以在 api manager configuration.
给定问题中定义的相同发行人 (accounts.google.com
),代码将生成 URL 到 https://accounts.google.com/.well-known/openid-configuration,其中包含 jwks_uri
。 ESP 使用此处指定的 jwks
来验证 JWT。
是的,在第二种情况下,检索到的 JWT 是 Google 签名的("iss" 是 https://accounts.google.com)JWT,而不是服务帐户签名的("iss" 是服务帐户电子邮件)智威汤逊。因此 JWT URI 需要相应地更新。 以前的 jwks-uri (https://www.googleapis.com/robot/v1/metadata/x509/) 仅适用于服务帐户签名的 JWT。