- 后端
- 企业应用
- 运维
【免费下载链接】bk-cmdb
蓝鲸智云配置平台(BlueKing CMDB)
本文围绕蓝鲸智云配置平台(BlueKing CMDB)API 网关开放接口search_objects(查询对象模型,Query models)展开,该接口允许调用方按可选条件(创建人、分类、模型 ID、名称、排序等)检索 CMDB 中的模型元数据,要求具备「模型查看」权限。读完本文,你将掌握该接口的完整请求/响应参数、API 网关侧的限流与鉴权配置,以及从 topo_server 路由到 core service 存储层、再到 IAM 权限校验的完整源码调用链,便于在实际集成中正确调用并排查问题。
一、接口概览
search_objects是 CMDB 通过 API 网关对外暴露的模型查询接口,其基本信息可从网关资源定义文件 bk_apigw_resources_bk-cmdb.yaml 中确认(operationId: search_objects,description 为「查询模型」,descriptionEn: Search objects):
| 项目 | 取值 | 说明 |
|---|---|---|
| 请求方法 | POST | 网关 backend method 为 post |
| 请求路径 | /api/v3/find/object | 网关 path 与 backend path 一致 |
| 鉴权 | 需要 API 网关鉴权 | isPublic: false、allowApplyPermission: true,需在网关申请该资源权限 |
| 业务权限 | 模型查看权限 | 命中结果后还会做逐模型 IAM 鉴权(见第四节) |
| 限流 | 100 tokens / 1s | 通过bk-rate-limit插件配置period: 1, tokens: 100 |
| 用户实名 | 不强制 | authConfig.userVerifiedRequired: false |
该接口与同目录下其他 150+ 个开放接口文档(如 search_object_topo.md、search_classifications.md)共同构成 CMDB 的开放 API 体系,对应源码实现位于场景服务 topo_server。
二、请求参数
所有请求参数均为可选,参数以 JSON 对象作为请求体提交。官方接口文档(search_objects.md)定义的参数如下:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
creator | string | 否 | 数据创建人 |
modifier | string | 否 | 数据最后修改人 |
bk_classification_id | string | 否 | 模型分类 ID,只能使用字母序列命名 |
bk_obj_id | string | 否 | 对象模型 ID,只能使用字母序列命名 |
bk_obj_name | string | 否 | 对象模型名称,用于展示,可为任意人类可读语言 |
obj_sort_number | int | 否 | 对象模型在对应模型分组内的排序序号 |
请求示例
{ "creator": "user", "modifier": "user", "bk_classification_id": "test", "bk_obj_id": "biz", "bk_obj_name": "aaa", "obj_sort_number": 1 }调用示例(通过网关访问):
curl -X POST 'https://{api-gateway-host}/api/v3/find/object' \ -H 'X-Api-Gw-Required: true' \ -H 'Content-Type: application/json' \ -d '{"bk_obj_id": "biz"}'提示:多个字段同时出现时,服务端将其作为「与(AND)」条件组合过滤;不传任何参数时等同于全量查询(受分页限制,见第四节
QueryCondition说明)。
三、响应结构与参数
响应示例
{ "result": true, "code": 0, "message": "", "permission": null, "data": [ { "bk_classification_id": "bk_organization", "create_time": "2018-03-08T11:30:28.005+08:00", "creator": "cc_system", "description": "", "id": 4, "bk_ispaused": false, "ispre": true, "last_time": null, "modifier": "", "bk_obj_icon": "icon-XXX", "bk_obj_id": "XX", "bk_obj_name": "XXX", "position": "{\"test_obj\":{\"x\":-253,\"y\":137}}", "bk_supplier_account": "0", "obj_sort_number": 1 } ] }响应字段
| 字段 | 类型 | 说明 |
|---|---|---|
result | bool | 请求是否成功,true成功、false失败 |
code | int | 错误码,0表示成功,>0表示失败 |
message | string | 失败时返回的错误信息 |
permission | object | 权限信息(无权限时返回缺少的权限点描述) |
data | object | 请求返回数据(模型列表) |
data 列表元素字段
| 字段 | 类型 | 说明 |
|---|---|---|
id | int | 数据记录 ID |
creator | string | 数据创建人 |
modifier | string | 数据最后修改人 |
bk_classification_id | string | 模型分类 ID,只能使用字母序列命名 |
bk_obj_id | string | 对象模型 ID,只能使用字母序列命名 |
bk_obj_name | string | 对象模型名称,用于展示 |
bk_supplier_account | string | 厂商账号 |
bk_ispaused | bool | 是否已停用 |
ispre | bool | 是否为预定义(内置)模型,预定义模型一般不允许删除 |
bk_obj_icon | string | 对象模型图标信息,供前端展示,取值可参考前端图标资源定义(如icon-XXX) |
position | json object string | 前端展示用的画布坐标(JSON 字符串,如{"test_obj":{"x":-253,"y":137}}) |
description | string | 数据描述 |
obj_sort_number | int | 模型在对应模型分组内的排序序号 |
上述字段与源码中的Object结构体一一对应,见 object.go:
// Object object metadata definition type Object struct { ID int64 `field:"id" json:"id" bson:"id" mapstructure:"id"` ObjCls string `field:"bk_classification_id" json:"bk_classification_id" bson:"bk_classification_id" mapstructure:"bk_classification_id"` ObjIcon string `field:"bk_obj_icon" json:"bk_obj_icon" bson:"bk_obj_icon" mapstructure:"bk_obj_icon"` ObjectID string `field:"bk_obj_id" json:"bk_obj_id" bson:"bk_obj_id" mapstructure:"bk_obj_id"` ObjectName string `field:"bk_obj_name" json:"bk_obj_name" bson:"bk_obj_name" mapstructure:"bk_obj_name"` IsHidden bool `field:"bk_ishidden" json:"bk_ishidden" ...` // 为 true 时前端不展示 IsPre bool `field:"ispre" json:"ispre" ...` IsPaused bool `field:"bk_ispaused" json:"bk_ispaused" ...` Position string `field:"position" json:"position" ...` OwnerID string `field:"bk_supplier_account" json:"bk_supplier_account" ...` Description string `field:"description" json:"description" ...` Creator string `field:"creator" json:"creator" ...` Modifier string `field:"modifier" json:"modifier" ...` CreateTime *Time `field:"create_time" json:"create_time" ...` LastTime *Time `field:"last_time" json:"last_time" ...` ObjSortNumber int64 `field:"obj_sort_number" json:"obj_sort_number" ...` }可以推断,position与bk_obj_icon、obj_sort_number这类字段主要服务于前端模型管理画布:position记录各模型节点在画布上的坐标,obj_sort_number决定模型在分组中的排列顺序,二者通常由「更新定义」等写接口维护。
四、源码实现链路
4.1 topo_server 路由注册与 SearchObject 处理
topo_server 在 service_business_initfunc.go 中注册该路由:
utility.AddHandler(rest.Action{Verb: http.MethodPost, Path: "/find/object", Handler: s.SearchObject})SearchObject的完整实现见 object.go:
// SearchObject search some objects by condition func (s *Service) SearchObject(ctx *rest.Contexts) { data := mapstr.New() if err := ctx.DecodeInto(&data); err != nil { ctx.RespAutoError(err) return } query := &metadata.QueryCondition{Condition: data, DisableCounter: true} resp, err := s.Engine.CoreAPI.CoreService().Model().ReadModel(ctx.Kit.Ctx, ctx.Kit.Header, query) if err != nil { ctx.RespAutoError(err) return } // authorize ids := make([]int64, len(resp.Info)) for k, v := range resp.Info { ids[k] = v.ID } authResp, authorized, err := s.AuthManager.HasFindModelAuthUseID(ctx.Kit, ids) if err != nil { ctx.RespAutoError(err) return } if !authorized { ctx.RespNoAuth(authResp) return } ctx.RespEntity(resp.Info) }从这段实现可以看出几个关键点:
- 请求体直接作为精确匹配条件:整个 JSON 请求体被解码进
mapstr,再原样塞入QueryCondition.Condition,与「所有参数均为可选、多参数 AND 组合」的接口描述一致; DisableCounter: true:跳过 count 统计,data直接返回列表而不附带总数;- 先查询、后鉴权:拿到结果后用命中的模型 ID 集合调用 IAM 鉴权,无权限时通过
RespNoAuth返回,此时响应中的permission字段会携带缺失的权限信息——这正是响应结构里permission字段的来源。
4.2 到 core service 的 ReadModel 调用
ReadModel是 topo_server 通过 apimachinery 客户端访问 core service 的入口,见 model/api.go:
// ReadModel search object func (m *model) ReadModel(ctx context.Context, h http.Header, input *metadata.QueryCondition) ( *metadata.QueryModelDataResult, error) { resp := new(metadata.ReadModelResult) subPath := "/read/model" err := m.client.Post(). WithContext(ctx). Body(input). SubResourcef(subPath). WithHeaders(h). Do(). Into(resp) ... return &resp.Data, err }对应地,core service 在 service_initfunc.go 中注册了POST /read/model → SearchModel(实现位于 service/model.go),完成元数据检索。集成测试 model_test.go 也验证了该内部路径的调用方式:client.POST("http://127.0.0.1:3308/api/v3/read/model", ...)。
4.3 QueryCondition:分页与条件语义
QueryCondition定义在 query.go:
type QueryCondition struct { Fields []string `json:"fields"` Page BasePage `json:"page"` Condition mapstr.MapStr `json:"condition"` // 非必填,只能用来查时间,且与Condition是与关系 TimeCondition *TimeCondition `json:"time_condition,omitempty"` DisableCounter bool `json:"disable_counter"` } // IsIllegal limit is illegal, if limit = 0; change to default page size func (qc *QueryCondition) IsIllegal() bool { if qc.Page.Limit == 0 { qc.Page.Limit = common.BKDefaultLimit } if qc.Page.Limit > common.BKMaxPageSize && qc.Page.Limit != common.BKNoLimit { return true } return false }需要注意:search_objects的公开入参仅支持第二节列出的六个字段,分页参数(page)由QueryCondition框架承载、服务端内部控制,limit为 0 时回落到默认页大小BKDefaultLimit,超过BKMaxPageSize的取值会被判定为非法——也就是说该接口单次返回条数受平台默认分页上限约束,大规模拉取建议按bk_classification_id等条件分批查询。
4.4 权限校验:HasFindModelAuthUseID
search_objects声明的业务权限为「模型查看权限」,其实现位于 ac/extensions/model.go:
// HasFindModelAuthUseID use the id parameter to determine whether you have permission to find the model func (am *AuthManager) HasFindModelAuthUseID(kit *rest.Kit, ids []int64) (*metadata.BaseResp, bool, error) { if !am.Enabled() { return nil, true, nil } if len(ids) == 0 { return nil, true, nil } models, err := am.getSkipFindAttrAuthModelID(kit) ... }从源码结构看,鉴权流程为:IAM 关闭时直接放行;查询结果为空时直接放行;否则先剔除免鉴权的内置模型 ID,再对剩余 ID 逐个校验「模型查看」权限,任一失败即整体拒绝。因此调用方若看到permission字段非空,通常是申请了对应模型的资源级查看权限即可恢复。
五、使用建议与注意事项
- 参数均为精确匹配:
bk_obj_name等字段按QueryCondition.Condition的精确匹配语义工作,不是模糊搜索;如需按分类聚合查看,可组合search_classifications(POST /api/v3/find/objectclassification,见 search_classifications.md)先拿到分类再按bk_classification_id过滤。 - 命名约束:
bk_obj_id、bk_classification_id只能使用字母序列命名,这是模型写接口与读接口的共同约束;bk_obj_name则允许中文等多语言名称,仅用于展示。 ispre字段的实际含义:ispre: true表示预定义(内置)模型,如biz、set、host等核心模型,调用方在消费返回数据时应识别该标记,避免对内置模型做变更类操作。- 网关侧限流:资源级
bk-rate-limit配置为每秒 100 tokens(见 bk_apigw_resources_bk-cmdb.yaml),批量任务应控制调用频率,避免触发限流。 - 无权限排查:由于鉴权发生在查询之后,
code != 0且permission有值时,优先检查调用方账号在 IAM 中是否拥有对应模型的查看权限;permission为空而失败时再考虑参数或网关鉴权问题。
六、相关接口
围绕模型元数据,topo_server 在同一路由文件(service_business_initfunc.go)中还注册了若干近邻接口,可作为search_objects的补充:
| 接口 | 路径 | 用途 |
|---|---|---|
| 查询模型(含属性) | POST /api/v3/find/object/model | 模型 + 属性一并返回,见 SearchModel |
| 查询对象拓扑 | POST /api/v3/find/objecttopology | 查询模型间关联拓扑,见 search_object_topo.md |
| 查询分类 | POST /api/v3/find/objectclassification | 查询模型分类列表,见 search_classifications.md |
| 查询属性 | POST /api/v3/find/objectattr | 按模型查询其属性定义,见 SearchObjectAttribute |
如需查看该接口的权威参数定义,可直接阅读仓库中的接口文档 search_objects.md(英文)与 search_objects.md(中文),二者内容同源。
- 后端
- 企业应用
- 运维
【免费下载链接】bk-cmdb
蓝鲸智云配置平台(BlueKing CMDB)
相关推荐
蓝鲸配置平台(BlueKing CMDB)业务集容器查询接口 list_kube_container_in_biz_set 详解与源码剖析
蓝鲸配置平台(BlueKing CMDB)业务集容器查询接口 list_kube_container_in_biz_set 详解与源码剖析 本篇介绍 bk cm
后端企业应用运维蓝鲸配置平台 CMDB 批量查询模块实例 API(find_module_batch)接口详解与源码实现分析
蓝鲸配置平台 CMDB 批量查询模块实例 API(find_module_batch)接口详解与源码实现分析 本指南围绕蓝鲸智云配置平台(bk cmdb)开放
后端企业应用运维蓝鲸配置平台 bk-cmdb 模型实例关联关系数量查询接口全解析
蓝鲸配置平台 bk cmdb 模型实例关联关系数量查询接口全解析 count_instance_associations 是蓝鲸配置平台(bk cmdb)对外开
后端企业应用运维
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考