【发布时间】:2021-08-16 09:59:00
【问题描述】:
我通过firebase deploy --only functions 部署了简单的测试可调用函数。
这里是内容:
export const test = region('europe-west1').https.onCall((data, context) => {
logger.debug('test call info', data, context);
return 'hello, world!';
});
我可以通过对https://europe-west1-{project}.cloudfunctions.net/test 进行HTTP 调用并接收{"result": "hello, world!"} 来成功调用它。
现在想通过 IAM 策略保护这个函数。
- 我创建新的服务帐户并加载它的凭据 json。
- 我转到控制台并从
allUsers中删除 Cloud Functions Invoker 角色,并添加在 #1 中创建的具有 Cloud Functions Invoker 角色的服务帐户。 - 我在我的 PC 上使用我的服务帐户创建 id-token
const auth = new GoogleAuth({keyFile: './key.json'});
targetAudience = new URL('https://europe-west1-{project}.cloudfunctions.net/test');
const client = await auth.getIdTokenClient(targetAudience as string);
const idToken = await client.idTokenProvider.fetchIdToken(targetAudience as string);
console.log(idToken);
- 我验证我的令牌是正确的,并通过
https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={{id-token}}为正确的服务帐户颁发。 - 我用
Authorization: Bearer {{id-token}}标头调用我的端点。 - 我收到 401 未经授权的错误,JSON 告诉我
{
"error": {
"message": "Unauthenticated",
"status": "UNAUTHENTICATED"
}
}
UPD1:向@DazWilkin 提供附加信息
1.
gcloud auth activate-service-account cloud-functions-invoker@{project-id}.iam.gserviceaccount.com --key-file="key.json"
Activated service account credentials for: [cloud-functions-invoker@{project-id}.iam.gserviceaccount.com]
gcloud projects get-iam-policy {project-id}
...
- members:
- serviceAccount:cloud-functions-admin@{project-id}.iam.gserviceaccount.com
- serviceAccount:cloud-functions-invoker@{project-id}.iam.gserviceaccount.com
role: roles/cloudfunctions.invoker
...
- 我复制这个值
gcloud auth print-identity-token | clip - 这是我致电
https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={{id-token}}后得到的信息
{
"aud": "32555940559.apps.googleusercontent.com",
"azp": "cloud-functions-invoker@{project-id}.iam.gserviceaccount.com",
"email": "cloud-functions-invoker@{project-id}.iam.gserviceaccount.com",
"email_verified": "true",
"exp": "1629157648",
"iat": "1629154048",
"iss": "https://accounts.google.com",
"sub": "114693730231812960252",
"alg": "RS256",
"kid": "6ef4bd908591f697a8a9b893b03e6a77eb04e51f",
"typ": "JWT"
}
- 我做了这个卷曲(从邮递员那里复制)。我也用命令行尝试了同样的 curl - 得到了同样的结果。
curl --location --request POST 'https://europe-west1-{project-id}.cloudfunctions.net/test' \
--header 'Authorization: Bearer
{token}
' \
--header 'Content-Type: application/json' \
--data-raw '{
"data": {
"goodbye": "world:("
}
}'
UPD2:新输入
这种行为仅在 callable 函数https.onCall() 中观察到。如果我使用https.onRequest() 一切正常,但我仍然对onCall 的行为感到困惑,因为我似乎正确地实现了protocol(参见我的curl)。
【问题讨论】:
-
看来 (!?) 正确。您可以在
gcloud auth activate-service-account@](cloud.google.com/sdk/gcloud/reference/auth/…) 之后使用gcloud到 [gcloud auth print-identity-token](cloud.google.com/sdk/gcloud/reference/auth/print-identity-token)。这将消除您的客户端生成的身份令牌是否不正确。尽管您使用端点进行的检查确实提供了一种很好的检查方式。 -
您无需删除现有账户,只需将新创建的账户添加到 IAM 调用者角色即可
-
可能包含(编辑)
gcloud projects get-iam-policy的结果,以便项目确认调用程序绑定。 -
IAM 政策看起来不错!
-
如果您只是使用
{token}代替您问题中的值,那么我不明白为什么它不起作用!
标签: firebase authentication google-cloud-functions gcloud google-iam