- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
Google Cloud Platform 引入了 Identity Aware Proxy,以保护 App Engine 柔性环境实例免受公共(public)访问。
但是,尚不完全清楚这是否可以或应该用于访问 GAE 托管 API 端点的 Google Cloud Functions。
documentation (使用 Python 和 Java 示例)指示 IAP 身份验证工作流程,包括 1) 生成 JWT token ,2) 创建 OpenID token ,3) 然后使用 Authorization: Bearer TOKEN
向 Google App Engine 提交请求标题。
如果每次调用函数时都必须进行授权,这对于运行云函数来说似乎相当复杂。
Google 云函数是否有其他方式访问安全的 GAE 端点?
最佳答案
如果您想从 GCF 调用受 IAP 保护的应用程序,您确实应该使用 ID token 。 Nodejs 中没有示例,所以我使用 this 做了一个作为引用(样式可能是错误的,因为那是我第一次接触nodejs)。与常规 JWT 声明集不同,它不应该包含范围并且具有 target_audience。
/**
* Make IAP request
*
*/
exports.CfToIAP = function CfToIAP (req, res) {
var crypto = require('crypto'),
request = require('request');
var token_URL = "https://www.googleapis.com/oauth2/v4/token";
// service account private key (copied from service_account.json)
var key = "-----BEGIN PRIVATE KEY-----\nMIIEvQexsQ1DBNe12345GRwAZM=\n-----END PRIVATE KEY-----\n";
// craft JWT
var JWT_header = new Buffer(JSON.stringify({ alg: "RS256", typ: "JWT" })).toString('base64');
// prepare claims set
var iss = "12345@12345.iam.gserviceaccount.com"; // service account email address (copied from service_account.json)
var aud = "https://www.googleapis.com/oauth2/v4/token";
var iat = Math.floor(new Date().getTime() / 1000);
var exp = iat + 120; // no need for a long linved token since it's not cached
var target_audience = "12345.apps.googleusercontent.com"; // this is the IAP client ID that can be obtained by clicking 3 dots -> Edit OAuth Client in IAP configuration page
var claims = {
iss: iss,
aud: aud,
iat: iat,
exp: exp,
target_audience: target_audience
};
var JWT_claimset = new Buffer(JSON.stringify(claims)).toString('base64');
// concatenate header and claimset
var unsignedJWT = [JWT_header, JWT_claimset].join('.');
// sign JWT
var JWT_signature = crypto.createSign('RSA-SHA256').update(unsignedJWT).sign(key, 'base64');
var signedJWT = [unsignedJWT, JWT_signature].join('.');
// get id_token and make IAP request
request.post({url:token_URL, form: {grant_type:'urn:ietf:params:oauth:grant-type:jwt-bearer', assertion:signedJWT}}, function(err,res,body){
var data = JSON.parse(body);
var bearer = ['Bearer', data.id_token].join(' ');
var options = {
url: 'https://1234.appspot.com/', // IAP protected GAE app
headers: {
'User-Agent': 'cf2IAP',
'Authorization': bearer
}
};
request(options, function (err, res, body) {
console.log('error:', err);
});
});
res.send('done');
};
/**
* package.json
*
*/
{
"name": "IAP-test",
"version": "0.0.1",
"dependencies": {
"request": ">=2.83"
}
}
更新:不推荐捆绑服务帐户 key ,因此更好的选择是使用元数据服务器。要使以下示例正常工作,应启用 Google 身份和访问管理 (IAM) API,并且 App Engine 默认服务帐户应具有服务帐户参与者角色(默认编辑器还不够):
/**
* Make request from CF to a GAE app behind IAP:
* 1) get access token from the metadata server.
* 2) prepare JWT and use IAM APIs projects.serviceAccounts.signBlob method to avoid bundling service account key.
* 3) 'exchange' JWT for ID token.
* 4) make request with ID token.
*
*/
exports.CfToIAP = function CfToIAP (req, res) {
// imports and constants
const request = require('request');
const user_agent = '<user_agent_to_identify_your_CF_call>';
const token_URL = "https://www.googleapis.com/oauth2/v4/token";
const project_id = '<project_ID_where_CF_is_deployed>';
const service_account = [project_id,
'@appspot.gserviceaccount.com'].join(''); // app default service account for CF project
const target_audience = '<IAP_client_ID>';
const IAP_GAE_app = '<IAP_protected_GAE_app_URL>';
// prepare request options and make metadata server access token request
var meta_req_opts = {
url: ['http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/',
service_account,
'/token'].join(''),
headers: {
'User-Agent': user_agent,
'Metadata-Flavor': 'Google'
}
};
request(meta_req_opts, function (err, res, body) {
// get access token from response
var meta_resp_data = JSON.parse(body);
var access_token = meta_resp_data.access_token;
// prepare JWT that is {Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature}
// https://developers.google.com/identity/protocols/OAuth2ServiceAccount for more info
var JWT_header = new Buffer(JSON.stringify({ alg: "RS256", typ: "JWT" })).toString('base64');
var iat = Math.floor(new Date().getTime() / 1000);
// prepare claims set and base64 encode it
var claims = {
iss: service_account,
aud: token_URL,
iat: iat,
exp: iat + 60, // no need for a long lived token since it's not cached
target_audience: target_audience
};
var JWT_claimset = new Buffer(JSON.stringify(claims)).toString('base64');
// concatenate JWT header and claims set and get signature usign IAM APIs projects.serviceAccounts.signBlob method
var to_sign = [JWT_header, JWT_claimset].join('.');
// sign JWT using IAM APIs projects.serviceAccounts.signBlob method
var signature_req_opts = {
url: ['https://iam.googleapis.com/v1/projects/',
project_id,
'/serviceAccounts/',
service_account,
':signBlob'].join(''),
method: "POST",
json: {
"bytesToSign": new Buffer(to_sign).toString('base64')
},
headers: {
'User-Agent': user_agent,
'Authorization': ['Bearer', access_token].join(' ')
}
};
request(signature_req_opts, function (err, res, body) {
// get signature from response and form JWT
var JWT_signature = body.signature;
var JWT = [JWT_header, JWT_claimset, JWT_signature].join('.');
// obtain ID token
request.post({url:token_URL, form: {grant_type:'urn:ietf:params:oauth:grant-type:jwt-bearer', assertion:JWT}}, function(err, res, body){
// use ID token to make a request to the IAP protected GAE app
var ID_token_resp_data = JSON.parse(body);
var ID_token = ID_token_resp_data.id_token;
var IAP_req_opts = {
url: IAP_GAE_app,
headers: {
'User-Agent': user_agent,
'Authorization': ['Bearer', ID_token].join(' ')
}
};
request(IAP_req_opts, function (err, res, body) {
console.log('error:', err);
});
});
});
});
res.send('done');
};
关于google-app-engine - 如何验证谷歌云功能以访问安全应用引擎端点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45787676/
以下代码: if (!(ep = engOpen("\0"))) { fprintf(stderr, "\nCan't start MATLAB engine\n");
我在谈论一些网络事物,例如 http://uservoice.com/ 你能推荐任何其他类似的服务、网站,或者可能是(甚至更好)一个现成的引擎来部署在自己的服务器上? 实际上,更多关于系统的问题,可以
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我正在寻找一个矩阵表达式解析器/引擎。例如, 3 * A + B * C 其中 A、B、C 是矩阵是一个典型的表达式。这应该类似于(单值)数学表达式解析器/引擎,但应该处理矩阵值和变量。我已经用谷歌搜
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 5年前关闭。 Improve this qu
是否有基于 .net 的 cometd 引擎?比如 Ajax 推送引擎 那是免费和开源的吗? 最佳答案 轨道式 Orbited是一个 HTTP 守护进程,针对长期 cometd 连接进行了优化。它旨在
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
我正在寻找支持以下功能的 haml javascript“端口”: 存储在文件中的模板。 JSON 输入。 支持“集合”[{Booking},{Booking},{Booking}] 进行迭代处理。
我在 IronPython 中托管 IronPython。我没有找到使用等效的命令行参数初始化它的方法:-X:FullFrames . 我的代码有点像这样: import clr clr.AddRef
我想将我工作的公司的所有松散信息整合到一个知识库中。 Wiki 似乎是一种可行的方法,但大部分相关信息都隐藏在 PST 文件中,并且需要很长时间才能说服人们将他们的电子邮件(包括附件)手动翻译成 Wi
我已经使用缓存的 flutter 引擎 flutter 到现有的 native 应用程序(添加到应用程序)中。 override fun onCreate(savedInstanceState: Bu
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我正在使用 Django Cassandra我已经定义了我的模型,我可以用它来命名一个表: class Meta: db_table = "table_name" 但是,Cassand
类似于 NoSQL 数据库,但适用于 OLAP。当然是开源的:) 编辑: OLAP 引擎在幕后使用关系数据库。例如 SAPBW 可以使用 Oracle 等。我的意思是一个没有这个底层关系数据库的 OL
我正在使用以下片段来 enable Razor templating in my solution (在 ASP.NET MVC3 之外)。是否可以轻松实现布局? 背景资料: 我在这一点上(模板编译成
我们目前使用闭源知识库解决方案,所见即所得创建文章是TinyMCE(看起来可能是修改/简化的)。 他们目前根本不允许更改它(添加插件等,除非您可以以某种方式注入(inject)插件)。 我确实拥有对
我正在评估我们的高性能电信应用程序的 BPEL 引擎,但性能似乎很差。我们评估了 Apache Ode、SunBPEL 引擎、Active BPEL 等。您知道任何更快的 BPEL 引擎实现或 C/C
Elastic / Lucene真的需要在文档中存储所有索引数据吗?您难道不就通过通过传递数据,以便Lucene may index the words into its hash table并为每个
我是 3D 游戏新手?我正在使用 Libgdx。如何计算像 Tetromino Revolution 游戏这样的透视相机的参数?请给我任何想法。 看图片:http://www.terminalstud
我是一名优秀的程序员,十分优秀!