news 2026/9/11 3:03:40

JumpServer PAM 账号密钥查询 API 实战:Go 语言集成开发指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JumpServer PAM 账号密钥查询 API 实战:Go 语言集成开发指南

JumpServer PAM 账号密钥查询 API 实战:Go 语言集成开发指南

【免费下载链接】jumpserverJumpServer is an open-source Privileged Access Management (PAM) platform that provides DevOps and IT teams with on-demand and secure access to SSH, RDP, Kubernetes, Database and RemoteApp endpoints through a web browser.项目地址: https://gitcode.com/GitHub_Trending/ju/jumpserver

导读

本文以 JumpServer 仓库内置的 Go 语言 SDK 示例为线索,系统讲解 PAM 资产账号密码(Secret)查询服务的完整集成方案:从 RESTful 接口的请求规范、HMAC-SHA256 签名认证原理,到 Go 代码的逐段实现与常见问题排查。读完本文,你将掌握使用 Go 安全调用 JumpServer 账号密钥接口的完整能力,包括签名请求构造、参数校验、错误处理与结果解析,并能直接复用仓库提供的现成代码。

1. 接口概览:PAM 账号密码查询服务

JumpServer 作为开源特权访问管理(PAM)平台,允许第三方系统(如运维平台、工单系统、自动化脚本)通过 RESTful API 按需获取资产账号的密码,用于自动登录、批量巡检等场景。该能力由IntegrationApplication(集成应用)机制提供:管理员先在 JumpServer 中创建"应用",绑定账号并生成密钥对,第三方服务持密钥调用接口换取账号密码,全程无需把密码明文存储在自己的系统中。

仓库中该功能的核心实现位于:

  • 接口视图:apps/accounts/api/account/application.py
  • 数据模型:apps/accounts/models/application.py
  • 参数校验序列化器:apps/accounts/serializers/account/service.py
  • 路由注册:apps/accounts/urls.py(router.register(r'integration-applications', ...)
  • 官方 SDK 示例:Go 版位于 apps/accounts/demos/go/

1.1 接口基本信息

项目内容
请求方式GET
接口路径api/v1/accounts/integration-applications/account-secret/
返回格式JSON
认证方式HTTP Signature(HMAC-SHA256)
请求参数asset(资产名称,必填)、account(账号名称,必填)

响应示例

{ "id": "72b0b0aa-ad82-4182-a631-ae4865e8ae0e", "secret": "123456" }

其中id为发起请求的集成应用(服务)ID,secret为查询到的账号密码明文。

1.2 服务端参数校验:不止 asset 与 account

值得注意的是,从源码看,服务端实际支持的查询参数比原文档列出的两个更丰富。序列化器 IntegrationAccountSecretSerializer 定义了四个可选字段:

参数类型必填说明
assetstr条件必填资产名称
asset_idUUID条件必填资产 ID
accountstr条件必填账号名称
account_idUUID条件必填账号 ID

校验规则为:account_id一旦提供即直接通过;否则asset/asset_id至少提供一个、account/account_id至少提供一个,否则返回 400 与提示At least one of the following fields must be provided: ...。因此使用asset+account名称组合是最直观的调用方式,而account_id则提供了更精确的定位手段(demo.go 与 jms_pam.go 中均有体现)。

服务端在 get_account_secret 动作中的完整处理流程为:校验参数 → 调用service.get_account(**data)定位账号(对应模型方法 get_account,支持按名称或 ID 组合查询,且账号必须在该应用的accounts绑定列表中)→ 写入审计日志IntegrationApplicationLog→ 依据全局开关SECURITY_DISABLE_VIEW_SECRET决定是否返回密码明文。

2. 环境要求与准备工作

2.1 环境要求

编写 Go 版本 SDK 客户端需要:

  • Go 1.16+
  • 标准库:crypto/hmaccrypto/sha256encoding/base64net/http
  • 可选第三方库:github.com/google/uuid(UUID 校验)、gopkg.in/twindagger/httpsig.v1(HTTP Signature 签名,jms_pam.go 使用)

2.2 获取 API Key(KEY_ID 与 KEY_SECRET)

在 JumpServer 的PAM → 应用管理中创建集成应用,系统会生成一对凭证:

  • KEY_ID:应用 ID(形如72b0b0aa-ad82-4182-a631-ae4865e8ae0e的 UUID)
  • KEY_SECRET:应用密钥(36 位随机字符串)

创建时需绑定允许访问的账号(模型中的accounts字段),并将来源 IP 加入ip_group白名单(默认['*'],见 IntegrationApplicationSerializer)。密钥可随时在应用中刷新:服务端提供GET api/v1/accounts/integration-applications/{id}/refresh-secret/动作,调用模型方法refresh_secret()重新生成 36 位随机串(application.py)。

2.3 配置项

仓库示例通过环境变量注入配置,均有默认值(demo.go):

环境变量默认值说明
API_URLhttp://127.0.0.1:8080JumpServer 服务地址
API_KEY_ID示例 UUID应用 ID
API_KEY_SECRET示例密钥应用密钥
ORG_ID00000000-0000-0000-0000-000000000002组织 ID,通过X-JMS-ORG请求头传递

生产环境务必通过环境变量覆盖默认值,切勿使用仓库中的示例凭证。

3. 签名认证:HMAC-SHA256 HTTP Signature

JumpServer 的账号密钥接口采用 HTTP Signature 方案做请求签名,防篡改、防重放。核心思想是:将请求方法、目标路径与若干请求头拼接成待签名字符串,用KEY_SECRET做 HMAC-SHA256 计算,Base64 编码后放入Authorization头。

3.1 签名串构造规则

以 demo.go 为例,签名过程分五步:

第一步:准备参与签名的请求头。示例固定签名以下字段:

(request-target) accept date x-jms-org

第二步:构造待签名字符串。每行格式为字段名: 值,行间以换行符拼接:

(request-target): get /api/v1/accounts/integration-applications/account-secret/?asset=ubuntu_docker&account=root accept: application/json date: Mon, 09 Sep 2026 02:12:25 GMT x-jms-org: 00000000-0000-0000-0000-000000000002

关键细节:

  • (request-target)为小写请求方法 + 空格 + 完整 URI(必须包含 query 参数);
  • date使用 RFC 1123 GMT 格式(Go 布局字符串Mon, 02 Jan 2006 15:04:05 GMT);
  • x-jms-org为组织 ID,需与请求头一致。

第三步:计算签名

mac := hmac.New(sha256.New, []byte(c.KeySecret)) mac.Write([]byte(signatureString)) signatureB64 := base64.StdEncoding.EncodeToString(mac.Sum(nil))

第四步:拼装 Authorization 头

authHeader := fmt.Sprintf( `Signature keyId="%s",algorithm="hmac-sha256",headers="%s",signature="%s"`, c.KeyID, strings.Join(headersList, " "), signatureB64, )

headers字段声明参与签名的头列表,服务端据此重建签名串。

第五步:发送请求,同时携带Accept: application/jsonDateX-JMS-ORGX-Source: jms-pam头(X-Source用于标识调用来源)。

3.2 利用第三方库简化签名

仓库还提供了使用httpsig库的精简实现 jms_pam.go:

func (c *JumpServerPAM) SignRequest(r *http.Request) error { headers := []string{"(request-target)", "date"} signer, err := httpsig.NewRequestSigner(c.KeyID, c.KeySecret, "hmac-sha256") if err != nil { return err } return signer.SignRequest(r, headers, nil) }

该版本只需签名(request-target)date两个字段,库会自动生成Authorization头,代码更简洁;而 demo.go 的手写版本完整展示了签名原理,更适合学习与无外部依赖的场景。

4. Go 代码实战:从最小示例到完整 SDK

4.1 最小可运行示例(demo.go)

demo.go 是开箱即用的完整示例,核心调用逻辑如下:

func (c *APIClient) GetAccountSecret(asset, account string) (map[string]interface{}, error) { u, err := url.Parse(c.APIURL) // ... u.Path = "/api/v1/accounts/integration-applications/account-secret/" q := u.Query() q.Add("asset", asset) q.Add("account", account) u.RawQuery = q.Encode() req, err := http.NewRequest("GET", u.String(), nil) // ... 设置 Accept / X-JMS-ORG / Date / X-Source 头 // ... 按第 3 节构造签名并写入 Authorization 头 resp, err := c.Client.Do(req) // ... if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("API returned non-200 status: %d", resp.StatusCode) } var result map[string]interface{} if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { return nil, fmt.Errorf("failed to decode response: %v", err) } return result, nil } func main() { client := NewAPIClient() result, err := client.GetAccountSecret("ubuntu_docker", "root") if err != nil { log.Fatalf("Error: %v", err) } fmt.Printf("Result: %+v\n", result) }

运行方式

cd apps/accounts/demos/go API_URL=http://your-jumpserver:8080 \ API_KEY_ID=your-key-id \ API_KEY_SECRET=your-key-secret \ ORG_ID=your-org-id \ go run demo.go

4.2 完整 SDK 封装(jms_pam.go)

jms_pam.go 提供了更工程化的封装,适合集成进大型项目,包含三个核心抽象:

(1)请求对象SecretRequest:封装参数与校验逻辑。NewSecretRequest 接收assetassetIDaccountaccountID四个参数,默认Method为 GET;validate 实现服务端同样的校验规则——accountID提供则直接通过(须为合法 UUID),否则要求资产与账号的名称/ID 至少各提供一个,非法 UUID 会返回invalid UUID错误。GetQuery 将非空参数编码进 query。

(2)响应对象Secret:统一结果解析。FromResponse 在状态码为 200 时解码secret并置valid = true;非 200 时将原始错误体原样存入Desc,便于上层展示服务端错误信息(如Account not found)。

(3)客户端JumpServerPAM:通过NewJumpServerPAM(endpoint, keyID, keySecret, orgID)构造(jms_pam.go),orgID为空时默认使用00000000-0000-0000-0000-000000000002Send方法负责拼接 URL、设置请求头、签名并发送,网络错误同样写入Desc返回而非中断调用。

典型调用示例

client := NewJumpServerPAM("http://your-jumpserver:8080", keyID, keySecret, "") req, _ := NewSecretRequest("ubuntu_docker", "", "root", "") secret, err := client.Send(req) if err != nil { log.Fatal(err) } fmt.Printf("secret=%s valid=%v\n", secret.Secret, secret.Valid)

4.3 与服务端实现对照

客户端 SDK 的行为与服务端源码一一对应:

  • IntegrationApplicationViewSet.get_account_secret要求RBACPermission权限,即调用方必须是通过X-JMS-ORG指定组织内的有效集成应用(模型 is_authenticated 返回is_active);
  • 请求成功会写入 IntegrationApplicationLog,记录来源 IP、服务名、账号与资产信息,便于审计追溯;
  • settings.SECURITY_DISABLE_VIEW_SECRET开启,接口返回的secretNone——这是全局"禁用查看密钥"策略,调用方需据此调整业务逻辑。

5. 常见问题(FAQ)

Q: API Key 如何获取?

A: 在 JumpServer 的PAM → 应用管理中创建应用,即可生成KEY_IDKEY_SECRET。创建后需在应用中绑定目标账号,并确保调用方 IP 在ip_group白名单内。

Q: 请求返回 400 "At least one of the following fields must be provided"?

A: 未满足参数组合要求。检查是否提供了asset/asset_idaccount/account_id(名称与 ID 组合亦可,但至少各一个)。另外,若传了account_id但格式非法(非 UUID),会提示invalid UUID

Q: 返回 "Account not found"?

A: 账号不存在,或该账号未绑定到当前集成应用。请确认应用管理中的绑定账号列表,以及asset名称是否与资产名称完全一致。

Q: 签名校验失败(401)?

A: 重点核对三点:date头是否为 RFC 1123 GMT 格式;(request-target)是否包含完整 query 且方法为小写getheaders声明顺序与签名串中头的顺序、取值是否完全一致。建议先对照 demo.sh 用 curl 打通,再用 Go 复现。

Q: 响应中 secret 为 null?

A: JumpServer 开启了全局SECURITY_DISABLE_VIEW_SECRET安全策略,密钥查看被禁用,需要管理员在系统设置中调整。

6. 版本历史(Changelog)

版本号变更内容日期
1.0.0初始版本2025-02-11

7. 延伸阅读

本主题在仓库中还提供了其他语言的等价示例,可对照阅读:

  • Python:apps/accounts/demos/python/demo.py 与 apps/accounts/demos/python/jms_pam/main.py
  • Java:apps/accounts/demos/java/demo.java
  • Node.js:apps/accounts/demos/node/demo.js
  • curl:apps/accounts/demos/curl/demo.sh(最适合先验证签名链路)

各语言示例的 README 与代码文件结构一致,签名规则完全相同,理解了本文的 Go 实现即可举一反三。

【免费下载链接】jumpserverJumpServer is an open-source Privileged Access Management (PAM) platform that provides DevOps and IT teams with on-demand and secure access to SSH, RDP, Kubernetes, Database and RemoteApp endpoints through a web browser.项目地址: https://gitcode.com/GitHub_Trending/ju/jumpserver

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 3:00:08

基于serpi.c的Linux 16550 UART自定义驱动开发指南

简介:一份面向Linux内核驱动开发与嵌入式串口通信学习者的16550 UART驱动源码包。资源共11个文件,以C源文件、Shell脚本、头文件为主,附Makefile、说明文档及编译好的ko模块,压缩包仅13KB,结构精简,适合通读…

作者头像 李华
网站建设 2026/9/11 2:58:56

AI编程真实水位线:30天后你该补哪三块能力短板

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 2:58:38

MBA论文写作AI工具实测:从文献检索到降重的完整方案

1. 测评背景与维度设计 1.1 为什么会有这篇全维度测评 先说背景。我自己当年写MBA毕业论文的时候,白天上班晚上写论文,连续三个月几乎没有完整休息日。最崩溃的不是没思路,而是思路明明很清楚,但写到文献综述、理论框架、数据分析…

作者头像 李华
网站建设 2026/9/11 2:57:50

Intel工业网卡技术解析:确定性通信的硬件根基

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 2:52:29

基于FastAPI与订单状态机的虚拟商品自动发货系统实践

1. 项目定位与整体设计思路先说结论:这个项目解决的是“没有营业执照、没有企业资质、也不想走第三方支付平台审核”的卖家,如何低成本搭建一个能自动发货、能管理订单的虚拟商品交易系统。我做这个系统时,最核心的取舍就是:不接微…

作者头像 李华