返回所有博客/google-meet

Google Meet 现在会把加入请求分成已验证队列和高风险队列。数据中心里的 bot 全部落入后者。本文介绍我们如何用 SAML 让 bot 登录真实的 Workspace 账户,以及具体怎么配置。

AAmr El Shimy
··6 min read
已认证的 Google Meet Bot:摆脱高风险队列

2026 年 4 月,Google Meet 开始把加入请求分成两个队列。受邀者和组织成员进入已验证队列,直接放行。其他所有人落入第二个队列,主持人看到的标签是「存在潜在威胁」,默认按钮是「拒绝」而不是「允许」。

录制 bot 运行在数据中心 IP 上。它们无一例外都落入第二个队列。

我们先试了最直接的办法。住宅代理在这里行不通:IP 池是共享的,信誉早就被消耗光了,Google 照样会标记它们。真正能把 bot 送进已验证队列的只有一件事:成为真实组织里真实的 Google Workspace 用户。

所以我们就做了这件事。现在 bot 可以登录你自己的 Workspace 账户,并以该用户的身份加入会议。

这是按 bot 选择启用的功能。只要不在 request 中传 meet_config,一切照旧:你的 bot 仍然像以前一样匿名加入。

让人意外的一点

大家都以为「已认证 bot」意味着 OAuth,以为要把 Google 账户的访问权交给我们。事实并非如此。

底层机制是 SAML。你的 Workspace 配置一个 Legacy SSO 配置文件,指向我们的登录 endpoint。当 bot 在 Google 登录页输入邮箱时,Google 发现这个域名已经联合认证,于是重定向到我们这里。我们用与你上传到自己 Workspace 的证书相匹配的私钥签署一份 SAML 断言,浏览器把它 POST 回 Google,bot 就登录成功了。

你从未授予 MeetingBaaS 任何 Google API 的访问权限。 你把一份公开证书上传到自己掌控的 Workspace。我们持有对应的私钥,并且只用它做这一件事。

大家通常设想的三种方案都行不通:

方案为什么行不通
用户名和密码会遇到 2FA 提示、密码轮换、验证码,以及「异常登录位置」验证。无头浏览器全都过不去。
Google OAuth(3LO)每个账户都需要一个交互式的同意对话框。没有人在那里点击它。
服务账户根本无法以参会者身份加入 Meet 通话。

SAML 绕开了上面每一个问题。没有第二重验证需要满足,因为断言本身就是认证。

匿名的数据中心 bot 默认落入威胁队列;已签名的 SAML 断言可将同一个 bot 作为真实 Workspace 用户移入已验证队列

两个资源,而不是一个

API 分成 workspaces 和 logins 两部分,这个划分不是随意的。

Google 的 Legacy SSO 配置文件每个 Workspace 只保存一份验证证书,该 Workspace 内的所有用户共用。如果我们把证书建模在 login 上,那么新增一个 bot 账户就只剩两种选择:要么生成新的密钥对并覆盖 Google Admin 中的证书,这会立刻让所有已按旧证书注册的 login 失效;要么手工把同一份证书和密钥粘贴到每一次创建调用里。

所以证书归属于 workspace,各个身份挂在它下面。

/v2/meet-workspaces   → domain + SAML certificate and private key
/v2/meet-logins       → the Workspace users, attached via workspace_id

Workspaces

POST   /v2/meet-workspaces
GET    /v2/meet-workspaces
GET    /v2/meet-workspaces/:workspace_id
PATCH  /v2/meet-workspaces/:workspace_id
DELETE /v2/meet-workspaces/:workspace_id

创建方式有两种。可以让我们生成密钥对:

{
  "name": "Acme Production",
  "domain": "bots.acme.com",
  "generate_keypair": true
}

也可以自带:

{
  "name": "Acme Production",
  "domain": "bots.acme.com",
  "cert_pem": "-----BEGIN CERTIFICATE-----...",
  "private_key_pem": "-----BEGIN PRIVATE KEY-----..."
}

两者只能选其一。同时传或者都不传都会报验证错误。创建时我们会检查证书和密钥能否正常解析、密钥是否与证书匹配,以及域名是否为有效主机名且你尚未注册过。

无论你走哪条路径,response 中都会包含 cert_pem,因为这正是你需要粘贴到 Google Admin 里的值。private_key_pem 永远不会返回,任何 endpoint 都不会。

domain 创建后不可修改。其余内容都可以通过 patch 更新,包括同时轮换证书和密钥。

Logins

POST   /v2/meet-logins
GET    /v2/meet-logins
GET    /v2/meet-logins/utilization
GET    /v2/meet-logins/:credential_id
PATCH  /v2/meet-logins/:credential_id
DELETE /v2/meet-logins/:credential_id
{
  "workspace_id": "f0e1d2c3-b4a5-6789-0123-456789abcdef",
  "name": "Production Bot Pool — Account 1",
  "email": "bot1@bots.acme.com",
  "email_group": "bots@bots.acme.com"
}

邮箱域名必须与父 workspace 的域名一致,或者是它的子域名。emailworkspace_id 不可修改:要迁移一个 login,请先删除再新建一个。

email_group 是可选的,但值得设置。共享同一分组的 login 会组成一个轮询池;如果你把这个分组地址放进日历邀请,被分配到的 bot 就是受邀者,这是通过等候室最快的路径。

两种资源都接受一个 extra 对象来存放你自己的元数据,之后可以按它过滤:

GET /v2/meet-logins?extra=environment:production

在 bot 上使用

{
  "meeting_url": "https://meet.google.com/abc-defg-hij",
  "bot_name": "Recording Bot",
  "meet_config": {
    "email_group": "bots@bots.acme.com",
    "fallback": "fail"
  }
}

meet_config 的解析规则:

你传入的内容实际行为
null(默认值)匿名 bot。不登录、不走 SAML,与现有行为一致。
{ "email_group": "X" }在分组 X 内的活跃 login 之间轮询。
{ "credential_id": "Y" }固定使用 login Y。
两者都传,且分组非空email_group 优先,credential_id 被忽略。
只传 { "email_group": "" }在团队全部活跃 login 之间轮询,不做分组过滤。
{ "email_group": "", "credential_id": "Y" }固定使用 login Y。空分组不算分组,所以 credential_id 生效。

分配时会挑选活跃会话最少的 login,数量相同就选最久未使用的,并通过一次原子条件更新占住名额,这样两个同时创建的 bot 不会抢到同一个。

当池子占满时,由 fallback 决定。默认值 "fail" 会返回 FST_ERR_MEET_LOGIN_UNAVAILABLE"anonymous" 则静默回退到未认证加入。如果拿到某种录像比拿到一份已验证的录像更重要,这就是正确的选择。

容量

每个 login 都带一个并发会话上限,默认是 20。这个数字刻意低于业界认为 Google 开始限流的水平,它只是一个下限,等你测过自己的流量之后可以调高。

GET /v2/meet-logins/utilization 一次调用就给你完整的全貌:

{
  "logins_total": 5,
  "logins_active": 5,
  "logins_invalid": 0,
  "concurrent_sessions": 47,
  "concurrent_capacity": 100,
  "utilization_pct": 47,
  "by_email_group": [
    { "email_group": "bots@bots.acme.com", "logins": 5, "concurrent": 47, "capacity": 100 }
  ]
}

盯住 utilization_pct。如果它经常高于 70,说明你需要更多 Workspace 用户,因为流量的尾部已经在触发 fallback 了。

当一个 login 出问题时

workspace 和 login 都有一个 state 字段,取值为 activeinvalid。只有系统会设置 invalid,而且只在 bot 登录失败且注定会一直失败时才设置:SAML 断言被拒绝,通常意味着 Google Admin 中的证书和我们的不再匹配;或者 Workspace 用户被停用、被删除。临时性超时不会改变任何状态。

被置为无效的 login 不再接受分配,并会记录 last_error_messagelast_error_at,以及一个包含触发它的 bot 的 failure_data 对象。重新启用刻意设计成手动操作,等你修复了根本原因之后再执行:

PATCH /v2/meet-logins/:credential_id
{ "state": "active" }

PATCH 只接受 "active"。你自己尝试设置 "invalid" 会被 request 校验拒绝,返回 400。

删除仍有会话在进行的 login 或 workspace 会返回 409,而不是把凭据从运行中的 bot 脚下抽走。删除 workspace 会级联删除它下面的 login。

配置步骤

准备一个专用的 Workspace 或子域名

使用单独的 Google Workspace,至少也要用一个专用子域名,例如 bots.acme.com。不要用你的主组织。

Google Admin 中的 SSO 配置是组织级的。如果在员工登录用的 Workspace 上把它指向我们,他们的登录也会被一并重定向。这里需要付费套餐,因为免费版没有 SSO 配置文件。

创建 workspace

curl -X POST https://api.meetingbaas.com/v2/meet-workspaces \
  -H "x-meeting-baas-api-key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain": "bots.acme.com", "generate_keypair": true}'

保存 response 中的 cert_pem

在 Google Admin 中配置 SSO

安全(Security)→ 使用第三方 IdP 设置单点登录(Set up single sign-on with a third party IdP)→ 添加 SAML 配置文件(Add SAML profile)→ 旧版 SSO 配置文件(Legacy SSO profile)。

字段
登录页 URL(Sign-in page URL)https://api.meetingbaas.com/v2/meet-sso/sign-in
登出页 URL(Sign-out page URL)https://api.meetingbaas.com/v2/meet-sso/sign-out
验证证书(Verification certificate)第 2 步得到的 cert_pem
使用域名专属颁发者(Use a domain-specific issuer)

启用这个配置文件,然后在「管理 SSO 配置文件分配」(Manage SSO profile assignments)中完成分配。

创建 Workspace 用户

并发 bot 池的每个名额对应一个 Google Workspace 用户。

每个账户都必须先交互式地完成一次 Google 的「欢迎使用 Google Workspace」引导流程,之后才能正常工作。这一步最容易被跳过,它导致的登录失败看起来像证书问题,其实不是。顺手在 myaccount.google.com 把账户语言设为英语(美国)。

你也可以创建一个 Google 群组,把 bot 用户放进去,再把这个群组加到日历邀请里。

注册每个 login

curl -X POST https://api.meetingbaas.com/v2/meet-logins \
  -H "x-meeting-baas-api-key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workspace_id": "...",
    "name": "bot1",
    "email": "bot1@bots.acme.com",
    "email_group": "bots@bots.acme.com"
  }'

发一个 bot 试试

POST /v2/bots 调用中加上 meet_config,然后看着它径直走进会议。

一个值得提前知道的限制

Google 在参会者列表中显示 Workspace 用户本人的名字,会覆盖你传入的 bot_name。如果显示名称对你很重要,目前唯一的变通办法是:想显示几个名字,就配几个 Workspace 用户,这显然扩展不了多远。我们正在研究这个问题。

相关阅读

想知道自己的流量该配多大的 login 池?或者不确定专用子域名在你的环境里够不够?联系我们

相关博客google-meet