云 运行 - 通过服务帐户进行 gRPC 身份验证 - NodeJS
Cloud Run - gRPC authentication through service account - NodeJS
我必须向云 运行 服务发出经过身份验证的请求,该服务使用 HTTP/2 方法通过 grpc 进行通信。
服务 returns 一个文件的 signedURL 并且在未经身份验证的情况下部署时它会成功地执行相同的操作。
我在从客户端发出请求时将 JWT 令牌添加到元数据中。但是 grpc 服务器给出了以下错误 -
code: 16,
metadata: Metadata {
_internal_repr: {
'www-authenticate': [Array],
date: [Array],
server: [Array],
'x-envoy-upstream-service-time': [Array],
'content-length': [Array]
},
flags: 0
Your client does not have permission to the requested URL
在云 运行 上,我在连接选项卡中启用了 HTTP/2。与此 Cloud 运行 服务关联的服务帐户也具有 Cloud 运行 Invoker 权限。
下面是实例化grpc server的代码-
const grpc = require('grpc')
const protoLoader = require('@grpc/proto-loader')
const packageDefinition = protoLoader.loadSync(
`${__dirname}/${proto_file}`,
{
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
})
const Proto = grpc.loadPackageDefinition(packageDefinition)
function main () {
const server = new grpc.Server()
server.addService(Proto.${service_name}.service, { ${function_name} })
server.bindAsync(`0.0.0.0:${PORT}`, grpc.ServerCredentials.createInsecure(), (error, port) => {
if (error) {
throw error
}
server.start()
console.log('gRPC Server running!')
})
}
main()
以下是发出经过身份验证的请求的客户端代码 -
const grpc = require('grpc')
const protoLoader = require('@grpc/proto-loader')
const {GoogleAuth} = require('google-auth-library');
const auth = new GoogleAuth();
const packageDefinition = protoLoader.loadSync(
`${__dirname}/${proto_file}`, {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
})
//* Or make the changes for authenticated call to CDN here
const Proto = grpc.loadPackageDefinition(packageDefinition)
async function request() {
return auth.getIdTokenClient(targetAudience);
}
const metadata = new grpc.Metadata();
request().then((token)=> {
metadata.add('Authorization', `Bearer ${token}`);
})
function getFileLink (projectId, fileId, plaintext = null) {
const serverAddress = config.server_address
let credentials
if (plaintext) {
credentials = grpc.credentials.createInsecure()
} else {
credentials = grpc.credentials.createSsl()
}
const cdn = new cdnProto.CDN(serverAddress, grpc.credentials.createSsl())
const request = {
project_id: projectId,
file_id: fileId
}
return new Promise((resolve, reject) => {
cdn.GetFileLink(request, metadata, (error, response) => {
if (error) {
console.log(error)
resolve(null)
} else {
resolve(response)
}
})
})
}
我已经解决了这个问题。我的做法是对的,但是我获取token的方式不对。要获得所需的 auth Token,我还必须调用另一个方法。
async function request() {
client = await auth.getIdTokenClient(targetAudience);
return client.idTokenProvider.fetchIdToken(targetAudience)
}
我必须向云 运行 服务发出经过身份验证的请求,该服务使用 HTTP/2 方法通过 grpc 进行通信。 服务 returns 一个文件的 signedURL 并且在未经身份验证的情况下部署时它会成功地执行相同的操作。 我在从客户端发出请求时将 JWT 令牌添加到元数据中。但是 grpc 服务器给出了以下错误 -
code: 16,
metadata: Metadata {
_internal_repr: {
'www-authenticate': [Array],
date: [Array],
server: [Array],
'x-envoy-upstream-service-time': [Array],
'content-length': [Array]
},
flags: 0
Your client does not have permission to the requested URL
在云 运行 上,我在连接选项卡中启用了 HTTP/2。与此 Cloud 运行 服务关联的服务帐户也具有 Cloud 运行 Invoker 权限。 下面是实例化grpc server的代码-
const grpc = require('grpc')
const protoLoader = require('@grpc/proto-loader')
const packageDefinition = protoLoader.loadSync(
`${__dirname}/${proto_file}`,
{
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
})
const Proto = grpc.loadPackageDefinition(packageDefinition)
function main () {
const server = new grpc.Server()
server.addService(Proto.${service_name}.service, { ${function_name} })
server.bindAsync(`0.0.0.0:${PORT}`, grpc.ServerCredentials.createInsecure(), (error, port) => {
if (error) {
throw error
}
server.start()
console.log('gRPC Server running!')
})
}
main()
以下是发出经过身份验证的请求的客户端代码 -
const grpc = require('grpc')
const protoLoader = require('@grpc/proto-loader')
const {GoogleAuth} = require('google-auth-library');
const auth = new GoogleAuth();
const packageDefinition = protoLoader.loadSync(
`${__dirname}/${proto_file}`, {
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
})
//* Or make the changes for authenticated call to CDN here
const Proto = grpc.loadPackageDefinition(packageDefinition)
async function request() {
return auth.getIdTokenClient(targetAudience);
}
const metadata = new grpc.Metadata();
request().then((token)=> {
metadata.add('Authorization', `Bearer ${token}`);
})
function getFileLink (projectId, fileId, plaintext = null) {
const serverAddress = config.server_address
let credentials
if (plaintext) {
credentials = grpc.credentials.createInsecure()
} else {
credentials = grpc.credentials.createSsl()
}
const cdn = new cdnProto.CDN(serverAddress, grpc.credentials.createSsl())
const request = {
project_id: projectId,
file_id: fileId
}
return new Promise((resolve, reject) => {
cdn.GetFileLink(request, metadata, (error, response) => {
if (error) {
console.log(error)
resolve(null)
} else {
resolve(response)
}
})
})
}
我已经解决了这个问题。我的做法是对的,但是我获取token的方式不对。要获得所需的 auth Token,我还必须调用另一个方法。
async function request() {
client = await auth.getIdTokenClient(targetAudience);
return client.idTokenProvider.fetchIdToken(targetAudience)
}