Teleport PagerDuty 访问请求插件:把权限审批变成故障事件通知与自动放行
2026/9/20 19:29:13 网站建设 项目流程
  • 网络安全
  • 认证鉴权
  • 运维
  • 后端

【免费下载链接】teleport

The easiest, and most secure way to access and protect all of your infrastructure.

项目地址:https://gitcode.com/gh_mirrors/tel/teleport
点击查看免费下载

Teleport 的 PagerDuty 访问请求插件(Access Request Plugin)将 Teleport 中的资源/角色访问请求(Access Request)与 PagerDuty 故障事件(Incident)打通:每当用户发起权限提升请求,插件自动在指定 PagerDuty 服务上创建一条 Incident 并通知值班团队,审批人可以直接跟进,而插件还会在请求被批准、拒绝、过期后同步关闭对应 Incident;更进一步,它还可以根据 PagerDuty 的 on-call 排班表自动批准请求,让正在处理事故的值班工程师无需等待人工审批即可拿到基础设施权限。读完本文,你将掌握该插件的架构原理、配置项含义、RBAC 资源定义、部署与运行方式,以及如何借助仓库内的源码与测试理解其内部行为。

插件是什么:以事件驱动权限审批

根据 integrations/access/pagerduty/README.md 的定位,Teleport Access API 提供了一款 PagerDuty 访问请求插件,它允许你:

  • 把 Teleport 的资源/角色访问请求视为 PagerDuty Incident;
  • 将 Incident 通知发送给合适的团队(尤其是值班团队);
  • 通过 PagerDuty 侧的操作直接批准或拒绝请求(以及自动批准)。

该插件位于仓库的integrations/access/pagerduty目录,属于 Teleport Access API 的官方集成之一。官方配置指南(见 docs/pages/identity-governance/access-requests/plugins/pagerduty.mdx)强调其典型价值:工程师在解决故障时,可以按需获取基础设施权限,而不需要常驻管理员权限,从而缩小攻击面。

架构与工作流程

插件自身是一个独立进程,运行在你的私有网络中,通过 Teleport Identity File(身份文件)与 Teleport 集群建立 gRPC 连接;同时通过 REST API 与 PagerDuty API 交互。整体架构如下:

从图中可以看到三条关键链路:

  1. 插件通过反向隧道监听来自 Teleport Auth Service 的访问请求事件(LISTEN FOR ACCESS REQUESTS),并回写请求状态(MODIFY ACCESS REQUESTS);
  2. 插件调用 PagerDuty API 发送通知、读取 Incident 状态(SEND NOTIFICATIONS AND GET INCIDENT STATUS);
  3. Teleport 集群内部,Proxy Service 与 Auth Service 之间通过 gRPC 通信完成身份认证与访问控制。

从源码看,app.go 中的App.run会启动一个 watcher,订阅KindAccessRequestKindAccessMonitoringRule两类事件(app.go#L115-L118),随后根据事件类型分别处理。插件的核心状态机在 app.go 中体现为:

  • onPendingRequest:请求进入 PENDING 状态时,先尝试创建通知 Incident,再尝试自动批准;
  • onResolvedRequest:请求被批准/拒绝/升级时,向 Incident 追加评审与结论 Note,并关闭 Incident;
  • onDeletedRequest:请求过期被删除时,以expired标记关闭对应 Incident。

一次完整的请求生命周期

结合源码与官方文档,一次典型的交互流程如下:

  1. 用户(例如myuser)发起访问editor角色的请求;
  2. Teleport Auth Service 根据用户角色的annotations为请求打上系统注解;
  3. 插件监听到 PENDING 请求,读取pagerduty_notify_service注解定位目标服务,调用 CreateIncident 创建标题为Access request from <user>incident_keyteleport-access-request/<reqID>的 Incident;
  4. 审批人(或自动批准逻辑)在 Teleport 侧评审/批准/拒绝请求;
  5. 插件通过 ResolveIncident 将 Incident 状态置为resolved,并追加一条说明“Access request has been approved/denied/expired”的 Note。

运行后,你可以在 PagerDuty 控制台看到形如下图的 Incident:

仓库中的插件实现结构

integrations/access/pagerduty目录是插件的完整 Go 实现,关键文件如下:

文件职责
cmd/teleport-pagerduty/main.go命令行入口,提供configureversionstart三个子命令
cmd/teleport-pagerduty/example_config.toml随二进制嵌入的示例配置,teleport-pagerduty configure直接输出它
config.go配置结构定义、默认值填充与校验
app.go核心业务逻辑:事件处理、创建/关闭 Incident、自动批准
client.go基于 resty 封装的 PagerDuty REST API 客户端
types.goPagerDuty API 的请求/响应类型定义
plugindata.go插件状态数据(PluginData)的编解码
testlib/集成测试套件与 Fake PagerDuty 服务

从 main.go#L41-L71 可以看到命令行行为:teleport-pagerduty configure打印示例 TOML 配置;start通过--config(默认/etc/teleport-pagerduty.toml)加载配置并启动,-d开启调试日志。

配置详解

最小配置示例

插件使用 TOML 格式配置文件,官方示例见 examples/resources/plugins/teleport-pagerduty-cloud.toml:

# example teleport-pagerduty configuration TOML file [teleport] auth_server = "myinstance.teleport.sh:443" # Teleport Cloud proxy HTTPS address identity = "/var/lib/teleport/plugins/pagerduty/identity" # Identity file path refresh_identity = true # Refresh identity file periodically [pagerduty] api_key = "key" # PagerDuty API Key user_email = "me@example.com" # PagerDuty bot user email (Could be admin email) [log] output = "stderr" # Logger output. Could be "stdout", "stderr" or "/var/lib/teleport/pagerduty.log" severity = "INFO" # Logger severity. Could be "INFO", "ERROR", "DEBUG" or "WARN".

配置字段与默认值

config.go 中的Config.CheckAndSetDefaults定义了完整的默认值逻辑:

  • pagerduty.api_key:必填。如果以/开头,会被当作文件路径,从该文件读取密钥(config.go#L111-L116),便于密钥落盘管理;
  • pagerduty.user_email:必填,PagerDuty 机器人用户的邮箱。创建 Incident 时该用户被记录为创建者(对应 client.go#L185 的From请求头);
  • pagerduty.notify_service:可选的注解名,默认pagerduty_notify_service,用于指定“收到新请求时通知哪个服务”;
  • pagerduty.services:可选的注解名,默认pagerduty_services,用于指定“哪些服务的值班成员可以自动批准”;
  • API 端点默认https://api.pagerduty.com
  • log.output默认stderrlog.severity默认info

[teleport]段的连接方式有两种(详见 example_config.toml 中的注释):

  • --format=file:使用identity身份文件,可配refresh_identity = true周期性刷新;
  • --format=tls:使用client_keyclient_crtroot_cas三件套证书。

addr指向 Auth Server(默认端口 3025)或 Proxy(3080/443);Teleport Cloud 场景下形如your-account.teleport.sh:443

核心机制一:基于注解的通知路由

插件不依赖固定的服务名,而是读取访问请求上的系统注解来决定行为。官方部署指南在 pagerduty.mdx 中给出了角色定义示例:

kind: role version: v5 metadata: name: editor-requester spec: allow: request: roles: ['editor'] thresholds: - approve: 1 deny: 1 annotations: pagerduty_notify_service: ["Teleport Access Request Notifications"]

当用户以该角色发起请求时,Auth Service 会把注解写入请求的系统注解(system annotations)。插件在 getNotifyServiceName 中读取pagerduty_notify_service注解的第一个值,再通过 FindServiceByName(大小写不敏感)定位 PagerDuty 服务并创建 Incident。

若注解缺失或为空,插件会跳过通知(以errSkip静默处理,app.go#L315-L318),因此没有配置通知的服务不会产生噪音。

核心机制二:基于 on-call 排班的自动批准

对于应急场景,插件支持“谁值班谁放行”:当请求注解pagerduty_services列出的服务中,有某个服务的升级策略(Escalation Policy)里包含当前请求用户,且该用户处于 on-call 状态时,插件会自动以插件用户身份提交一条 APPROVED 评审。

官方文档的示例角色如下(pagerduty.mdx#L149-L181):

kind: role version: v5 metadata: name: demo-role-requester spec: allow: request: roles: ['demo-role'] thresholds: - approve: 1 deny: 1 annotations: pagerduty_services: ["My Critical Service"]

自动批准的前提条件(来自源码 tryApproveRequest):

  1. 请求注解pagerduty_services必须存在;
  2. 请求用户的 Teleport 用户名必须是合法邮箱,且能在 PagerDuty 中按邮箱找到对应用户(FindUserByEmail);
  3. 该用户在注解列出的某个服务的升级策略中处于 on-call(FilterOnCallPolicies 通过/oncalls接口分页校验);
  4. 插件用户必须拥有评审这些请求的权限(见下文 RBAC)。

满足条件后,插件提交的评审理由形如:

Access requested by user <name> (<email>) who is on call in service(s) <service1,service2>

值得注意的是,插件会跳过“不是为注解中列出的服务值班”的用户:即使该用户在其他服务的升级策略中 on-call,也不会触发批准(这正是 suite.go 中TestAutoApprovalWhenOnCallInSomeOtherPolicy的测试意图)。

核心机制三:Incident 状态同步与评审回填

请求被批准、拒绝或过期后,插件会自动同步 PagerDuty 侧状态:

  • onResolvedRequest(app.go#L325-L342)根据请求最终状态(APPROVED / DENIED / PROMOTED)构造Resolution
  • ResolveIncident 先向 Incident 追加一条结论 Note(如Access request has been approved,附上原因),再把 Incident 的status更新为resolved
  • 请求过期被删除时,onDeletedRequestexpired标记关闭 Incident(app.go#L344-L346)。

此外,多人评审场景下,插件的 postReviewNotes 会把每一位评审人的结论追加为 Incident Note,内容格式见 client.go#L57-L65:

<Author> reviewed the request at <time>. Resolution: APPROVED. Reason: <reason>.

评审进度的去重依赖插件数据(PluginData)中的reviews_count计数,避免重复追加 Note。

插件状态存储:PluginData

插件会把每个请求的关联状态(创建的 Incident ID、服务 ID、用户、角色、创建时间、评审计数、最终决议)写入 Teleport 的 access request plugin data。定义与编解码见 plugindata.go:

  • RequestData:user、roles、created、request_reason、reviews_count、resolution 等字段;
  • PagerdutyData:service_id、incident_id。

写入通过modifyPluginData(app.go#L639-L675)执行“读取-比较-交换”的乐观锁更新(compare-and-swap),冲突时使用指数退避重试,保证并发场景下(例如多个事件同时到达)PluginData 的一致性。测试套件中的TestRace正是通过大量并发请求验证这一行为。

部署:从 RBAC 到运行

1. 定义 RBAC 资源

除请求者角色外,还需要为插件本身准备账号。官方文档(pagerduty.mdx#L199-L321)定义了两个角色和一个用户:

kind: role version: v5 metadata: name: access-plugin spec: allow: rules: - resources: ['access_request'] verbs: ['list', 'read'] - resources: ['access_plugin_data'] verbs: ['update'] review_requests: roles: ['demo-role'] where: 'contains(request.system_annotations["pagerduty_services"], "My Critical Service")' --- kind: user metadata: name: access-plugin spec: roles: ['access-plugin'] version: v2

其中review_requests.where谓词表达式限制了插件只能评审“注解pagerduty_services包含My Critical Service”的请求,这是一种最小权限约束。

kind: role version: v5 metadata: name: access-plugin-impersonator spec: allow: impersonate: roles: - access-plugin users: - access-plugin

然后使用tctl create -f ...创建以上资源,并把自己账号加入editor-revieweraccess-plugin-impersonatordemo-role-requester等角色,最后创建用于演示的请求者用户:

$ tctl create -f editor-request-rbac.yaml $ tctl create -f demo-role-requester.yaml $ tctl create -f access-plugin.yaml $ tctl create -f access-plugin-impersonator.yaml $ tctl users add myuser --roles=editor-requester

2. 导出插件身份

插件需要一个 Teleport 身份文件来认证。生产环境推荐使用 Machine ID(tbot)签发短期身份文件,演示环境也可以用tctl导出长期身份文件,具体以 tbot-identity.mdx 与 identity-export.mdx 两个 include 文档为准。

3. 生成 PagerDuty API Key

在 PagerDuty 控制台进入Integrations → API Access Keys创建 API Key(不要勾选 Read-only)。账号需要具备 “Admin”、“Global Admin” 或 “Account Owner” 基础角色,以便列出和查询用户资料。Key 将填入配置文件的pagerduty.api_key

4. 生成并编辑配置

在插件主机上执行:

$ teleport-pagerduty configure > teleport-pagerduty.toml $ sudo mv teleport-pagerduty.toml /etc

插件默认读取/etc/teleport-pagerduty.toml,也可用--config覆盖。编辑后填入 Auth/Proxy 地址、身份文件路径与 PagerDuty 凭据。若使用 Helm 部署,则通过teleport-plugin-pagerdutyChart 的 values 文件配置teleport.addressteleport.identitySecretNamepagerduty.apiKeypagerduty.userEmail(参见 examples/resources/plugins/teleport-pagerduty-helm-cloud.yaml 与 Helm 参考文档 teleport-plugin-pagerduty.mdx)。

5. 启动与验证

可执行文件方式直接运行:

$ teleport-pagerduty start -d

Docker 方式:

$ docker run -v <path-to-config>:/etc/teleport-pagerduty.toml public.ecr.aws/gravitational/teleport-plugin-pagerduty:(=teleport.version=) start

启动日志会依次输出版本检查、请求 watcher 启动、PagerDuty API 健康检查(调用/abilities,见 HealthCheck)与 watcher 连接成功。健康检查失败会提示“check your credentials and service_id settings”(app.go#L210)。

6. systemd 托管

生产环境建议用 systemd 托管,仓库提供了官方 unit 文件 examples/systemd/plugins/teleport-pagerduty.service:

[Unit] Description=Teleport Pagerduty Plugin After=network.target [Service] Type=simple Restart=on-failure ExecStart=/usr/local/bin/teleport-pagerduty start --config=/etc/teleport-pagerduty.toml ExecReload=/bin/kill -HUP $MAINPID PIDFile=/run/teleport-pagerduty.pid [Install] WantedBy=multi-user.target

保存到/usr/lib/systemd/system/后执行:

$ sudo systemctl enable teleport-pagerduty $ sudo systemctl start teleport-pagerduty

用测试理解行为边界

integrations/access/pagerduty/testlib提供了非常完整的测试套件,可作为理解插件行为的“活文档”:

  • TestIncidentCreation:验证 Incident 创建到注解指定服务,incident_keyteleport-access-request/<reqID>,初始状态triggered,且 Incident ID 回写 PluginData;
  • TestApproval/TestDenial:验证请求被批准/拒绝后,Incident 追加相应 Note 并变为resolved
  • TestExpiration:验证请求被删除(模拟过期)后,Incident 以expired说明关闭;
  • TestAutoApprovalWhenOnCall/TestAutoApprovalWhenNotOnCall/TestAutoApprovalWhenOnCallInSomeOtherPolicy:分别验证 on-call 自动批准、非 on-call 不批准、以及“在无关服务值班也不批准”的边界;
  • TestRecipientsFromAccessMonitoringRule:验证访问监控规则(Access Monitoring Rule)也能作为通知服务来源;
  • TestRace:并发风暴下插件数据的最终一致性。

其中测试断言(如 Note 内容必须包含 “Access request has been approved”、“Reason: okay”)直接对应 client.go 中的三个模板:incident body、review note、resolution note。

延伸:访问监控规则作为通知来源

除了角色注解,插件还支持通过 Access Monitoring Rule 指定通知对象。在 app.go#L178-L193 中,插件为accessmonitoring.RuleHandler配置了FetchRecipientCallback,将规则中的接收者(schedule 类型)映射为 PagerDuty 服务名。当请求命中规则时,RecipientsFromAccessMonitoringRules返回的服务名优先级高于角色注解(app.go#L348-L371)。这与仓库文档 access-monitoring-rules.mdx 中描述的机制一致,可让管理员用统一规则集中管理通知策略。

小结

Teleport PagerDuty 访问请求插件把“权限审批”无缝嵌入事故响应流程:通过pagerduty_notify_service注解路由通知、通过pagerduty_services注解结合 on-call 排班实现自动批准、通过 Incident Note 回填评审过程、通过 PluginData 保证状态一致性。如果要在自己的 Teleport 集群中落地这套审批流,可以直接参考 docs/pages/identity-governance/access-requests/plugins/pagerduty.mdx 的八步部署指南,并结合本文的配置项与源码分析调整细节。

  • 网络安全
  • 认证鉴权
  • 运维
  • 后端

【免费下载链接】teleport

The easiest, and most secure way to access and protect all of your infrastructure.

项目地址:https://gitcode.com/gh_mirrors/tel/teleport
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询