Skip to content

feat(jumpserver): add bastionhost v4.10.16 service#228

Open
Hoy11 wants to merge 1 commit into
chaitin:mainfrom
Hoy11:feature/jumpserver-bastionhost
Open

feat(jumpserver): add bastionhost v4.10.16 service#228
Hoy11 wants to merge 1 commit into
chaitin:mainfrom
Hoy11:feature/jumpserver-bastionhost

Conversation

@Hoy11

@Hoy11 Hoy11 commented Jun 25, 2026

Copy link
Copy Markdown

feat(jumpserver): add bastionhost v4.10.16 service

接入设备

JumpServer 堡垒机(JumpServer Bastionhost)V4.10.16,堡垒机 / 网关接入平台,提供资产、用户、在线会话等安全运营常用数据查询能力。服务包 services/jumpserver__bastionhost_v4-10-16,proto 包 JumpServer_Bastionhost_V41016

设备版本

JumpServer V4.10.16,REST API 基础路径 http://<ip>/api/v1。本次验证环境使用 Docker 镜像 jumpserver/jms_all:v4.10.16 部署,API 文档地址为 /api/docs/,OpenAPI JSON 地址为 /api/swagger.json

认证方式

支持两种认证方式:

  1. Bearer Token 认证

    • 配置 secret.tokensecret.authorization
    • 请求头携带 Authorization: Bearer <token> 或完整 Authorization
  2. 用户名 / 密码登录认证

    • 配置 secret.username / secret.password
    • 每次 RPC 调用前请求 POST /api/v1/authentication/auth/
    • 从响应中获取 keywordtoken
    • 后续数据接口携带 Authorization: Bearer <token>

私有化部署或自签名 HTTPS 场景可通过 config.rejectUnauthorized: false 跳过证书校验。默认超时时间由 config.timeoutMs 控制。

实现方法

方式:RPC(gRPC / Connect RPC / MCP,4 个方法)

方法 类型 上游端点 说明
ListAssets GET /api/v1/assets/assets/ 查询 JumpServer 资产列表,支持 limitoffsetsearchplatform
GetAsset GET /api/v1/assets/assets/{id}/ 根据资产 ID 查询单个资产详情
ListUsers GET /api/v1/users/users/ 查询 JumpServer 用户列表,支持 limitoffsetsearch
ListOnlineSessions GET /api/v1/terminal/sessions/?is_finished=false 查询当前在线终端会话

错误映射:

  • 参数缺失或非法:INVALID_ARGUMENT
  • 认证失败或 Token 无效:UNAUTHENTICATED
  • 权限不足或 HTTP 403:PERMISSION_DENIED
  • HTTP 5xx 或网络错误:UNAVAILABLE
  • 非 JSON 响应或未知响应:UNKNOWN

风险边界:

  • 当前版本仅实现只读查询能力。
  • 不创建、更新、删除、禁用、解锁、终止 JumpServer 资源。
  • 不执行会话断开、用户禁用、资产删除等高风险写操作。
  • 后续如增加写操作,需要补充默认参数、幂等语义、回滚方式和 JumpServer 审计字段。

测试命令

cd services
npm run validate -- --service-dir jumpserver__bastionhost_v4-10-16
npm test -- --service-dir jumpserver__bastionhost_v4-10-16
npm run pack:check

本地验证结果:

  • validate: passed
  • test: 22/22 pass
  • pack:check: passed

OctoBus 导入与调用验证

npx -y @chaitin-ai/octobus serve \
  --data-dir work/jumpserver-octobus-data-v41016 \
  --addr 127.0.0.1:19016

npx -y @chaitin-ai/octobus --addr 127.0.0.1:19016 \
  service import jumpserver-bastionhost-v4-10-16 \
  ./services//jumpserver__bastionhost_v4-10-16

npx -y @chaitin-ai/octobus --addr 127.0.0.1:19016 \
  instance create jumpserver-real-v41016 \
  --service jumpserver-bastionhost-v4-10-16 \
  --config-json '{"endpoint":"http://10.2.36.xxx","apiPrefix":"/api/v1","timeoutMs":10000,"rejectUnauthorized":false}' \
  --secret-json '{"username":"admin","password":"******"}'

npx -y @chaitin-ai/octobus --addr 127.0.0.1:19016 \
  capset create jumpserver-real-v41016 \
  --name 'JumpServer Real V4.10.16'

npx -y @chaitin-ai/octobus --addr 127.0.0.1:19016 \
  capset add-instance jumpserver-real-v41016 jumpserver-real-v41016

Connect RPC 调用示例:

curl -sS -X POST \
  'http://127.0.0.1:19016/capsets/jumpserver-real-v41016/connect/jumpserver-real-v41016/JumpServer_Bastionhost_V41016.JumpServer_Bastionhost_V41016/ListAssets' \
  -H 'Content-Type: application/json' \
  -d '{"limit":5}'

验证结果:

  • ListUsers: 返回 2 条用户
  • ListAssets: 返回 3 条资产
  • GetAsset: 返回指定资产详情
  • ListOnlineSessions: 接口调用成功,当前在线会话为空

已知限制

  • 当前适配器为只读版本,不包含资产创建、用户禁用、会话终止等写操作。
  • 用户名 / 密码认证模式下,每次 RPC 调用都会登录获取 Token,暂未做 Token 缓存。
  • JumpServer 不同部署可能启用 HTTPS、自签名证书或反向代理路径,需要按实际环境配置 endpointapiPrefixrejectUnauthorized
  • JumpServer 列表接口可能返回分页对象或数组,本包已兼容两种结构。
  • ListOnlineSessions 仅查询 is_finished=false 的当前在线会话;无在线会话时返回空列表。

真实设备验证

以下联调证据来自 JumpServer V4.10.16 测试实例。敏感信息已脱敏:Token、Cookie、密码、真实内网地址、邮箱、部分资产地址均使用 ******10.2.36.xxx 替代,保留完整请求路径、状态码和响应结构。

联调证据:认证接口 跑通

# Request
POST http://10.2.36.xxx/api/v1/authentication/auth/
Content-Type: application/json

{
  "username": "admin",
  "password": "******"
}

# Response   HTTP/1.1 201 Created
Content-Type: application/json
Set-Cookie: SESSION_COOKIE_NAME_PREFIX=******; Path=/
Set-Cookie: jms_sessionid=******; HttpOnly; Path=/; SameSite=Lax

{
  "token": "******",
  "keyword": "Bearer",
  "date_expired": "2026/06/26 15:32:02 +0800",
  "user": {
    "id": "f2358d92-6564-49a7-8cc4-d98b3f0c7623",
    "name": "Administrator",
    "username": "admin",
    "email": "******",
    "wechat": "",
    "phone": {
      "code": "+86",
      "phone": ""
    },
    "mfa_level": {
      "value": 0,
      "label": "Disabled"
    },
    "source": {
      "value": "local",
      "label": "Local"
    },
    "wecom_id": null,
    "dingtalk_id": null,
    "feishu_id": null,
    "lark_id": null,
    "slack_id": null,
    "org_roles": [
      {
        "id": "00000000-0000-0000-0000-000000000005",
        "display_name": "Organization Admin",
        "name": "OrgAdmin"
      }
    ],
    "avatar_url": "/static/img/avatar/admin.png",
    "groups": [],
    "system_roles": [
      {
        "id": "00000000-0000-0000-0000-000000000001",
        "display_name": "System Admin"
      }
    ],
    "labels": [],
    "password_strategy": {
      "value": "email",
      "label": "Reset link will be generated and sent to the user"
    },
    "public_key_comment": "",
    "public_key_hash_md5": "",
    "guide_url": "",
    "lang": "en",
    "receive_backends": [
      "site_msg",
      "email"
    ],
    "is_org_admin": true,
    "is_superuser": true,
    "is_service_account": false,
    "is_valid": true,
    "is_expired": false,
    "is_active": true,
    "is_otp_secret_key_bound": false,
    "can_public_key_auth": true,
    "mfa_enabled": false,
    "need_update_password": false,
    "is_face_code_set": false,
    "mfa_force_enabled": false,
    "is_first_login": false,
    "login_blocked": false,
    "date_expired": "2096/06/07 14:17:16 +0800",
    "date_joined": "2026/06/25 14:17:16 +0800",
    "last_login": "2026/06/25 15:32:02 +0800",
    "date_updated": "2026/06/25 14:22:30 +0800",
    "date_api_key_last_used": "2026/06/25 15:30:23 +0800",
    "date_password_last_updated": "2026/06/25 14:20:42 +0800",
    "created_by": "System",
    "updated_by": "System",
    "comment": null
  }
}

联调证据:ListUsers 跑通

# Request
GET http://10.2.36.xxx/api/v1/users/users/?limit=5
Authorization: Bearer ******
Accept: application/json

# Response   HTTP/1.1 200 OK
Content-Type: application/json

{
  "count": 2,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "b8d7e1c7-e3f0-4a91-a310-faabd9704528",
      "name": "11",
      "username": "admin1",
      "email": "******",
      "wechat": "",
      "phone": {
        "code": "+86",
        "phone": ""
      },
      "mfa_level": {
        "value": 0,
        "label": "Disabled"
      },
      "source": {
        "value": "local",
        "label": "Local"
      },
      "avatar_url": "/static/img/avatar/user.png",
      "groups": [],
      "system_roles": [
        {
          "id": "00000000-0000-0000-0000-000000000003",
          "display_name": "User"
        }
      ],
      "labels": [],
      "password_strategy": {
        "value": "email",
        "label": "Reset link will be generated and sent to the user"
      },
      "is_superuser": false,
      "is_service_account": false,
      "is_valid": true,
      "is_expired": false,
      "is_active": true,
      "is_otp_secret_key_bound": false,
      "can_public_key_auth": true,
      "mfa_enabled": false,
      "need_update_password": true,
      "is_face_code_set": false,
      "mfa_force_enabled": false,
      "is_first_login": true,
      "login_blocked": false,
      "date_expired": "2096/06/07 14:36:37 +0800",
      "date_joined": "2026/06/25 14:36:53 +0800",
      "last_login": null,
      "date_updated": "2026/06/25 14:36:53 +0800",
      "date_api_key_last_used": null,
      "date_password_last_updated": "2026/06/25 14:36:53 +0800",
      "created_by": "Administrator",
      "updated_by": "Administrator",
      "comment": null
    },
    {
      "id": "f2358d92-6564-49a7-8cc4-d98b3f0c7623",
      "name": "Administrator",
      "username": "admin",
      "email": "******",
      "wechat": "",
      "phone": {
        "code": "+86",
        "phone": ""
      },
      "mfa_level": {
        "value": 0,
        "label": "Disabled"
      },
      "source": {
        "value": "local",
        "label": "Local"
      },
      "avatar_url": "/static/img/avatar/admin.png",
      "groups": [],
      "system_roles": [
        {
          "id": "00000000-0000-0000-0000-000000000001",
          "display_name": "System Admin"
        }
      ],
      "labels": [],
      "password_strategy": {
        "value": "email",
        "label": "Reset link will be generated and sent to the user"
      },
      "is_superuser": true,
      "is_service_account": false,
      "is_valid": true,
      "is_expired": false,
      "is_active": true,
      "is_otp_secret_key_bound": false,
      "can_public_key_auth": true,
      "mfa_enabled": false,
      "need_update_password": false,
      "is_face_code_set": false,
      "mfa_force_enabled": false,
      "is_first_login": false,
      "login_blocked": false,
      "date_expired": "2096/06/07 14:17:16 +0800",
      "date_joined": "2026/06/25 14:17:16 +0800",
      "last_login": "2026/06/25 14:52:21 +0800",
      "date_updated": "2026/06/25 14:22:30 +0800",
      "date_api_key_last_used": "2026/06/25 14:49:23 +0800",
      "date_password_last_updated": "2026/06/25 14:20:42 +0800",
      "created_by": "System",
      "updated_by": "Administrator",
      "comment": null
    }
  ]
}

联调证据:ListAssets 跑通

# Request
GET http://10.2.36.xxx/api/v1/assets/assets/?limit=5
Authorization: Bearer ******
Accept: application/json

# Response   HTTP/1.1 200 OK
Content-Type: application/json

{
  "count": 3,
  "next": null,
  "previous": null,
  "results": [
    {
      "id": "df3f5e8a-f929-4dfd-89b1-02acb7391665",
      "name": "1",
      "address": "******",
      "zone": null,
      "platform": {
        "id": 1,
        "name": "Linux",
        "type": "linux"
      },
      "nodes": [
        {
          "id": "cde3b14e-12f7-4fba-ac74-e634592b946c",
          "name": "DEFAULT"
        }
      ],
      "labels": [],
      "protocols": [
        {
          "name": "sftp",
          "port": 22
        },
        {
          "name": "ssh",
          "port": 22
        }
      ],
      "nodes_display": [
        "/DEFAULT"
      ],
      "directory_services": [],
      "accounts_amount": 0,
      "category": {
        "value": "host",
        "label": "Host"
      },
      "type": {
        "value": "linux",
        "label": "Linux"
      },
      "connectivity": {
        "value": "-",
        "label": "Unknown"
      },
      "org_id": "00000000-0000-0000-0000-000000000002",
      "org_name": "DEFAULT",
      "gathered_info": {},
      "spec_info": {},
      "is_active": true,
      "date_verified": null,
      "date_created": "2026/06/25 14:37:19 +0800",
      "date_updated": "2026/06/25 14:37:19 +0800",
      "comment": "",
      "created_by": "Administrator"
    },
    {
      "id": "d9d07abc-af31-4f10-85ef-9ef96d70a6bd",
      "name": "2",
      "address": "******",
      "zone": null,
      "platform": {
        "id": 16,
        "name": "H3C",
        "type": "general"
      },
      "nodes": [
        {
          "id": "cde3b14e-12f7-4fba-ac74-e634592b946c",
          "name": "DEFAULT"
        }
      ],
      "labels": [],
      "protocols": [
        {
          "name": "ssh",
          "port": 22
        }
      ],
      "nodes_display": [
        "/DEFAULT"
      ],
      "directory_services": [],
      "accounts_amount": 0,
      "category": {
        "value": "device",
        "label": "Device"
      },
      "type": {
        "value": "general",
        "label": "General"
      },
      "connectivity": {
        "value": "-",
        "label": "Unknown"
      },
      "org_id": "00000000-0000-0000-0000-000000000002",
      "org_name": "DEFAULT",
      "gathered_info": {},
      "spec_info": {},
      "is_active": true,
      "date_verified": null,
      "date_created": "2026/06/25 14:37:37 +0800",
      "date_updated": "2026/06/25 14:37:37 +0800",
      "comment": "",
      "created_by": "Administrator"
    },
    {
      "id": "cc4222cf-7010-466e-9125-fa00d7c3eb1d",
      "name": "3",
      "address": "******",
      "zone": null,
      "platform": {
        "id": 18,
        "name": "MariaDB",
        "type": "mariadb"
      },
      "nodes": [
        {
          "id": "cde3b14e-12f7-4fba-ac74-e634592b946c",
          "name": "DEFAULT"
        }
      ],
      "labels": [],
      "protocols": [
        {
          "name": "mariadb",
          "port": 3306
        }
      ],
      "nodes_display": [
        "/DEFAULT"
      ],
      "directory_services": [],
      "accounts_amount": 0,
      "category": {
        "value": "database",
        "label": "Database"
      },
      "type": {
        "value": "mariadb",
        "label": "MariaDB"
      },
      "connectivity": {
        "value": "-",
        "label": "Unknown"
      },
      "org_id": "00000000-0000-0000-0000-000000000002",
      "org_name": "DEFAULT",
      "gathered_info": {},
      "spec_info": {
        "db_name": "",
        "use_ssl": false,
        "allow_invalid_cert": false,
        "pg_ssl_mode": "prefer"
      },
      "is_active": true,
      "date_verified": null,
      "date_created": "2026/06/25 14:37:49 +0800",
      "date_updated": "2026/06/25 14:37:49 +0800",
      "comment": "",
      "created_by": "Administrator"
    }
  ]
}

联调证据:GetAsset 跑通

# Request
GET http://10.2.36.xxx/api/v1/assets/assets/df3f5e8a-f929-4dfd-89b1-02acb7391665/
Authorization: Bearer ******
Accept: application/json

# Response   HTTP/1.1 200 OK
Content-Type: application/json

{
  "id": "df3f5e8a-f929-4dfd-89b1-02acb7391665",
  "name": "1",
  "address": "******",
  "zone": null,
  "platform": {
    "id": 1,
    "name": "Linux",
    "type": "linux"
  },
  "nodes": [
    {
      "id": "cde3b14e-12f7-4fba-ac74-e634592b946c",
      "name": "DEFAULT"
    }
  ],
  "labels": [],
  "protocols": [
    {
      "name": "sftp",
      "port": 22
    },
    {
      "name": "ssh",
      "port": 22
    }
  ],
  "nodes_display": [
    "/DEFAULT"
  ],
  "accounts": [],
  "directory_services": [],
  "accounts_amount": 0,
  "category": {
    "value": "host",
    "label": "Host"
  },
  "type": {
    "value": "linux",
    "label": "Linux"
  },
  "connectivity": {
    "value": "-",
    "label": "Unknown"
  },
  "auto_config": {
    "su_enabled": true,
    "gateway_enabled": true,
    "ansible_enabled": true,
    "id": 1,
    "ansible_config": {
      "ansible_connection": "smart"
    },
    "ping_enabled": true,
    "ping_method": "posix_ping",
    "ping_params": {},
    "gather_facts_enabled": true,
    "gather_facts_method": "gather_facts_posix",
    "gather_facts_params": {},
    "change_secret_enabled": true,
    "change_secret_method": "change_secret_posix",
    "change_secret_params": {},
    "push_account_enabled": true,
    "push_account_method": "push_account_posix",
    "push_account_params": {
      "home": "",
      "sudo": "/bin/whoami",
      "shell": "/bin/bash",
      "groups": ""
    },
    "verify_account_enabled": true,
    "verify_account_method": "verify_account_posix",
    "verify_account_params": {},
    "gather_accounts_enabled": true,
    "gather_accounts_method": "gather_accounts_posix",
    "gather_accounts_params": {},
    "remove_account_enabled": true,
    "remove_account_method": "remove_account_posix",
    "remove_account_params": {},
    "platform": 1
  },
  "org_id": "00000000-0000-0000-0000-000000000002",
  "org_name": "DEFAULT",
  "gathered_info": {},
  "spec_info": {},
  "is_active": true,
  "date_verified": null,
  "date_created": "2026/06/25 14:37:19 +0800",
  "date_updated": "2026/06/25 14:37:19 +0800",
  "comment": "",
  "created_by": "Administrator"
}

联调证据:ListOnlineSessions 跑通

# Request
GET http://10.2.36.xxx/api/v1/terminal/sessions/?is_finished=false&limit=5
Authorization: Bearer ******
Accept: application/json

# Response   HTTP/1.1 200 OK
Content-Type: application/json

{
  "count": 0,
  "next": null,
  "previous": null,
  "results": []
}

@Hoy11 Hoy11 marked this pull request as draft June 25, 2026 07:40
@Hoy11 Hoy11 marked this pull request as ready for review June 25, 2026 07:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant