首页
/ JumpServer PAM 资产账号密码查询 Python SDK 集成指南:从 REST API 到 jms-pam 客户端实战

JumpServer PAM 资产账号密码查询 Python SDK 集成指南:从 REST API 到 jms-pam 客户端实战

2026-09-09 15:00:28作者:平淮齐Percy

本篇技术指南以 JumpServer 开源仓库中 Python 演示目录 的官方文档(README.ja.md)与示例代码为主体,系统讲解如何通过 RESTful API 查询 PAM 资产账号密码(Account Secret)、如何通过集成应用(Integration Application)机制获取 API 密钥并完成 HTTP 签名认证,以及官方 jms-pam Python 客户端(demo.py、jms_pam/main.py)的完整实现原理与使用方式。读完本文,你将能够独立编写基于 Python 的资产密码拉取脚本,并将其接入自己的运维自动化与 IT 工单系统。

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

在 JumpServer 的账号(accounts)应用模块中,官方为第三方系统提供了一组“集成应用”相关的 API。本文聚焦的核心接口用于查询 PAM 资产上指定账号的密码(Secret),它以 RESTful 风格对外提供,并以 JSON 格式返回数据。

  • 请求方式GET
  • 请求路径api/v1/accounts/integration-applications/account-secret/
  • 返回格式:JSON

从路由注册看,该接口对应源码中 apps/accounts/urls.py 注册的 integration-applications 路由,其具体实现位于 apps/accounts/api/account/application.pyIntegrationApplicationViewSet.get_account_secret 动作(url_path='account-secret'detail=False),因此最终拼出的访问地址即 api/v1/accounts/integration-applications/account-secret/。该动作通过 IntegrationAccountSecretSerializer 校验查询参数,并以 accounts.view_integrationapplication 作为 RBAC 权限点,意味着只有被授予相应权限的应用账号才能调用。

2. 环境要求

官方 Python 演示对运行环境提出了明确要求:

依赖项 版本要求 用途
Python 3.11+ 运行时
requests 2.31.0 HTTP 客户端
httpsig 1.3.0 HTTP 请求签名(HTTPSignature)

其中 requests 负责发起 HTTP 请求,httpsig 用于实现 HTTP Signature 认证——这是 JumpServer 集成应用鉴权的核心,稍后会在第 4 节详细展开。

安装依赖可通过 pip 完成:

pip install "requests==2.31.0" "httpsig==1.3.0"

此外,官方演示还提供了打包配置 apps/accounts/demos/python/setup.py,声明包名为 jms-pam(版本 0.0.1),并同样将 requestshttpsig 列为安装依赖,说明该目录既可作为独立脚本运行,也可作为 Python 包安装到你的项目中复用。

3. 请求参数与响应格式

3.1 请求参数

GET api/v1/accounts/integration-applications/account-secret/ 接口需要携带以下查询参数:

参数名 类型 必填 说明
asset str 资产名称
account str 账号名称

在源码层面,官方 SDK 的 SecretRequest 类(apps/accounts/demos/python/jms_pam/main.py)对参数校验做了更严格的定义,可以作为实战参考:

  • 当提供了 account_id 时,assetasset_idaccount 均不得再提供;
  • 当提供了 account 时,assetasset_id 至少提供其一;
  • account_idasset_id 不允许同时提供;
  • account_idasset_id 必须是合法 UUID,否则抛出 ValueError
  • assetasset_id 均未提供,抛出 RequestParamsError(['asset', 'asset_id']);若 account 未提供,抛出 RequestParamsError(['account', 'account_id'])

也就是说,除了按名称(asset + account)查询外,还支持按 ID(asset_id / account_id)精确查询,参数组合受严格约束。

3.2 响应示例

成功时接口返回 JSON:

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

字段说明:

  • id:集成应用(Integration Application)的 ID,也是发起请求的应用身份标识;
  • secret:目标资产账号的密码明文。

需要特别注意的是,返回密码与否受 JumpServer 全局安全配置 SECURITY_DISABLE_VIEW_SECRET 控制。从 apps/accounts/api/account/application.py 的源码可以看到:

secret = None if settings.SECURITY_DISABLE_VIEW_SECRET else account.secret

当系统开启“禁止查看密钥”策略时,secret 字段会返回 None。此外,每次查询都会记录安全审计日志,包含服务名称、服务 ID、账号(含用户名)、资产(含地址)与来源 IP 等信息,确保密码查询行为全程可追踪。

4. 集成应用与 API Key 获取(FAQ 核心问题)

Q:API Key 如何获取?

A:在 PAM 的“应用管理”中创建应用,即可生成 KEY_ID 与 KEY_SECRET。

这是 README 文档 FAQ 中明确给出的答案,也是使用本接口的前提:集成应用是 JumpServer 面向第三方系统开放的“服务身份”。创建应用后获得的一对密钥:

  • KEY_ID:应用 ID,作为签名请求中的身份标识,对应响应中的 id 字段;
  • KEY_SECRET:应用密钥,用于计算 HMAC 签名,任何情况下都不应泄露。

apps/accounts/demos/python/demo.py 中,官方将这两个值通过环境变量注入:

KEY_ID = os.getenv("API_KEY_ID", "72b0b0aa-ad82-4182-a631-ae4865e8ae0e")
KEY_SECRET = os.getenv("API_KEY_SECRET", "6fuSO7P1m4cj8SSlgaYdblOjNAmnxDVD7tr8")

从源码结构看,IntegrationApplicationViewSet 还提供了另外两个与密钥生命周期相关的动作:

  • GET .../integration-applications/<id>/secret/get_once_secret):一次性查看应用自身的 Secret,需要 MFA 二次确认(UserConfirmation.require(ConfirmType.MFA));
  • GET .../integration-applications/<id>/refresh-secret/refresh_secret):刷新应用 Secret,调用后旧的 KEY_SECRET 立即失效,用于密钥轮换场景。

这两个接口与 get_account_secret 一起,构成了集成应用密钥从“创建 → 查看 → 轮换”的完整闭环,可用于编写密钥管理脚本。

5. HTTP 签名认证原理与 Header 约定

调用该接口必须使用 HTTP Signature(httpsig)认证,而不是简单的 Bearer Token。签名过程在 apps/accounts/demos/python/demo.pyapps/accounts/demos/python/jms_pam/main.py 中都有完整实现,其核心逻辑一致:

from httpsig.requests_auth import HTTPSignatureAuth

auth = HTTPSignatureAuth(
    key_id=KEY_ID, secret=KEY_SECRET,
    algorithm='hmac-sha256',
    headers=['(request-target)', 'accept', 'date', 'x-jms-org']  # demo.py 版本
)

要点说明:

  • 算法hmac-sha256,以 KEY_SECRET 为密钥对选定的 Header 做 HMAC 签名;
  • 签名覆盖范围:demo.py 将 (request-target)acceptdatex-jms-org 纳入签名;而 jms_pam 包内实现(main.py 的 _get_auth)签名的 Header 为 ['(request-target)', 'accept', 'date']。两种签名范围都包含请求目标与时间戳,可有效防止请求被篡改或重放;
  • Date 时间戳:必须使用 RFC 1123 GMT 格式,例如 Wed, 09 Sep 2026 02:37:44 GMT,且应与服务器时间保持同步,否则签名校验可能失败。

请求必须携带的 Header 汇总如下:

Header 示例值 说明
Accept application/json 期望响应格式
Date Wed, 09 Sep 2026 02:37:44 GMT 签名时间戳(RFC 1123 GMT)
X-JMS-ORG 00000000-0000-0000-0000-000000000002 目标组织 ID
X-Source jms-pam 调用方标识

其中 X-JMS-ORG 用于指定查询所属组织,demo.py 中默认值为 00000000-0000-0000-0000-000000000002,可通过环境变量 ORG_ID 覆盖;X-Source 标记调用来源,便于服务端审计区分不同调用方。

6. 完整 Python 实战:两种调用方式

6.1 方式一:基于 requests + httpsig 的最小实现(demo.py)

官方提供了开箱即用的示例脚本 apps/accounts/demos/python/demo.py,其核心是一个 APIClient 类:

import requests
import os
from datetime import datetime
from httpsig.requests_auth import HTTPSignatureAuth

API_URL = os.getenv("API_URL", "http://127.0.0.1:8080")
KEY_ID = os.getenv("API_KEY_ID", "72b0b0aa-ad82-4182-a631-ae4865e8ae0e")
KEY_SECRET = os.getenv("API_KEY_SECRET", "6fuSO7P1m4cj8SSlgaYdblOjNAmnxDVD7tr8")
ORG_ID = os.getenv("ORG_ID", "00000000-0000-0000-0000-000000000002")


class APIClient:
    def __init__(self):
        self.session = requests.Session()
        self.auth = HTTPSignatureAuth(
            key_id=KEY_ID, secret=KEY_SECRET,
            algorithm='hmac-sha256', headers=['(request-target)', 'accept', 'date', 'x-jms-org']
        )

    def get_account_secret(self, asset, account):
        url = f"{API_URL}/api/v1/accounts/integration-applications/account-secret/"
        headers = {
            'Accept': 'application/json',
            'X-JMS-ORG': ORG_ID,
            'Date': datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT'),
            'X-Source': 'jms-pam'
        }
        params = {"asset": asset, "account": account}

        try:
            response = self.session.get(url, auth=self.auth, headers=headers, params=params, timeout=10)
            response.raise_for_status()
            return response.json()
        except requests.RequestException as e:
            print(f"API request failed: {e}")
            return None


if __name__ == "__main__":
    client = APIClient()
    result = client.get_account_secret(asset="ubuntu_docker", account="root")
    print(result)

使用步骤:

  1. 设置环境变量 API_URLAPI_KEY_IDAPI_KEY_SECRETORG_ID 可选);
  2. 实例化 APIClient
  3. 调用 get_account_secret(asset="ubuntu_docker", account="root") 查询指定资产上 root 账号的密码。

脚本内置 10 秒超时并对 RequestException 做了兜底处理,查询失败时返回 None 而非抛出异常,便于在自动化流程中做容错。

6.2 方式二:官方 jms-pam SDK(jms_pam 包)

apps/accounts/demos/python/jms_pam/ 目录封装了一个更完整的 SDK 雏形,包含三个核心类:

  • SecretRequest:请求参数对象,负责 UUID 校验与参数互斥校验(见第 3.1 节),并提供 get_url()get_query() 生成请求地址与查询串;
  • Secret:响应结果对象,valid 属性表示请求是否成功,失败时 desc 携带错误描述;from_response 会将非 200 响应的错误字段拼接为可读文本;
  • JumpServerPAM:客户端主体,构造函数接收 endpointkey_idkey_secretorg_id,内部懒加载 HTTPSignatureAuth,通过 send(secret_request) 完成一次签名请求。

JumpServerPAM 的请求地址由 SecretRequest.get_url() 固定为 /api/v1/accounts/service-integrations/account-secret/,与 README 文档中提到的 integration-applications 路径略有出入——从源码结构看,前者应是该 SDK 早期约定的路由,实际使用时应以当前版本 api/v1/accounts/integration-applications/account-secret/ 为准。这一点也提醒使用者:将 demo 接入生产环境前,务必先在本仓库 apps/accounts/urls.py 中核对当前版本的接口路径。

使用 jms_pam 的示例:

from jms_pam import JumpServerPAM, SecretRequest

client = JumpServerPAM(
    endpoint="http://127.0.0.1:8080",
    key_id="72b0b0aa-ad82-4182-a631-ae4865e8ae0e",
    key_secret="6fuSO7P1m4cj8SSlgaYdblOjNAmnxDVD7tr8",
    org_id="00000000-0000-0000-0000-000000000002",
)

req = SecretRequest(asset="ubuntu_docker", account="root")
result = client.send(req)
print(result.secret, result.valid, result.desc)

该封装适合需要将密码查询能力复用到多个业务场景(如 CI/CD 发布、数据库巡检、工单系统取密)的团队:只需初始化一次客户端,用不同的 SecretRequest 即可反复查询。

6.3 集成应用密钥的生命周期管理

结合第 4 节的源码分析,可将集成应用密钥管理归纳为三步:

  1. 创建:在 Web 控制台「PAM → 应用管理」中创建应用,获得 KEY_ID / KEY_SECRET;
  2. 查询:通过 get_account_secret 查询资产账号密码,请求携带签名 Header;
  3. 轮换:定期调用 refresh-secret 刷新应用 Secret,降低密钥泄露风险;密钥泄露时可用 get_once_secret(需 MFA 确认)查看当前 Secret 以便核对。

7. 常见问题(FAQ)

Q:API Key 如何获取?

A:在 PAM 的「应用管理」中创建应用,即可生成 KEY_ID 与 KEY_SECRET。创建完成后,将两者配置到环境变量 API_KEY_IDAPI_KEY_SECRET 中即可开始调用。

Q:返回的 secret 为什么是 null?

A:当 JumpServer 开启了 SECURITY_DISABLE_VIEW_SECRET(禁止查看密钥)配置时,接口会返回 secret: null。需要联系管理员评估该策略后调整。

Q:签名校验失败怎么办?

A:检查三点:1) KEY_ID / KEY_SECRET 是否正确且未过期;2) 本机时间与服务器时间是否同步(Date 头参与签名);3) 签名覆盖的 Header 是否与实现一致,特别是 X-JMS-ORG 是否在签名范围内。

Q:如何限制调用权限?

A:get_account_secret 的 RBAC 权限点为 accounts.view_integrationapplication,可在角色权限中为指定应用/用户授予或回收该权限,实现最小权限控制。

8. 版本历史(Changelog)

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

9. 延伸阅读

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
docsdocs
暂无描述
Markdown
899
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
924
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
599
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
525
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
394