修复全量审查问题;设置接口PATCH化;回传指纹加固
CI / test (push) Successful in 32s

This commit is contained in:
2026-07-22 16:51:23 +08:00
parent 0614ef22af
commit f51fb6c722
66 changed files with 3997 additions and 687 deletions
+117
View File
@@ -0,0 +1,117 @@
<a id="top"></a>
<div align="center">
<img src="assets/logo.svg" width="88" alt="OCI Portal logo">
# OCI 调用者指纹评估
**OCI Portal 请求暴露面与多租户关联风险**
![OCI SDK](https://img.shields.io/badge/OCI-Go%20SDK-F80000?logo=oracle&logoColor=white)
![Auth](https://img.shields.io/badge/Auth-API%20Key-2563EB)
![Scope](https://img.shields.io/badge/Scope-Multi--tenant-0F9D58)
[结论速览](#summary) · [请求暴露面](#request-signals) · [项目指纹](#portal-signals) · [关联评估](#assessment) · [核验依据](#evidence)
</div>
> [!NOTE]
> 本文面向架构与隐私评估,说明 OCI Portal 调用 OCI Public API 时 Oracle
> 可见的信息及跨租户关联风险。结论基于当前源码,不代表 Oracle 实际采用的
> 风控规则。
<a id="summary"></a>
## 结论速览
> [!IMPORTANT]
> OCI Portal 的每次 API Key 请求都会在签名的 `keyId` 中携带
> `tenancy OCID / user OCID / fingerprint`。这能准确识别云身份,但不能单凭
> 一次请求证明调用方是 OCI Portal。
| 问题 | 结论 |
| --- | --- |
| Oracle 能识别单次请求的租户和用户吗? | **能。**签名身份、源 IP、目标服务、操作与时间均可见 |
| 通用 SDK 请求头能识别 OCI Portal 吗? | **不能。**默认 User-Agent、签名算法和 Go TLS 特征被大量客户端共享 |
| Oracle 能关联多个租户共用同一实例吗? | **具备能力。**需组合出口 IP、资源元数据、固定文本和调用序列 |
| 外部第三方能完成同等关联吗? | **通常不能。**其无法取得 Oracle 网关日志和租户内部资源元数据 |
<a id="request-signals"></a>
## 单次请求暴露面
当前项目统一通过 `common.NewRawConfigurationProvider` 使用 API Key
```text
Authorization: Signature version="1",
keyId="<tenancyOCID>/<userOCID>/<fingerprint>",
algorithm="rsa-sha256", ...
```
| 信号 | 默认形态 | 区分度 |
| --- | --- | :---: |
| 签名身份 | `tenancy / user / fingerprint` 明文位于 `keyId` | 身份强,软件弱 |
| User-Agent | 大多数 SDK 请求为 `Oracle-GoSDK/<版本> (...)` | 弱 |
| SDK 客户端信息 | SDK 生成的服务请求通常带 `opc-client-info: Oracle-GoSDK/<版本>` | 弱 |
| 请求元数据 | `Date``Host``request-target`;写请求另含 body 摘要 | 通用 |
| 网络特征 | 源 IP、TLS / ALPN、HTTP/2 行为 | 单次弱,跨租户组合后增强 |
| OCI 遥测头 | 显式启用 `OCI_INCLUDE_REQUEST_TELEMETRY_DATA=true` 时,SDK 操作可写 service / operation;直通请求未必携带 | 可选 |
项目没有构造 Instance Principal、Resource Principal 或 Session Token
鉴权,也没有主动覆盖 User-Agent 或为 `opc-request-id` 设置固定前缀。
`opc-client-info` 由 SDK 请求构造器写入,不含 OCI Portal 标记;手工构造的
请求可能不带该字段。少量手工签名请求绕过 `BaseClient.prepareRequest`
使用 Go `net/http` 的默认 User-Agent。
<a id="portal-signals"></a>
## OCI Portal 增量指纹
| 信号 | 当前行为 | 关联强度 |
| --- | --- | :---: |
| 出口 IP | 无租户级或全局代理时,走部署环境默认出口 / NAT | **强旁证(命中时)** |
| 日志回传资源名 | 按 tenancy 派生为 `<8hex>-audit*`,描述使用中性文案 | 弱 |
| GenAI Responses 请求头 | 同时写入 `CompartmentId``opc-compartment-id` | 中 / 弱 |
| API 调用序列 | 测活、账户画像、区域与资源查询存在稳定组合 | 辅助 |
SDK 默认 User-Agent、`opc-client-info` 与固定签名格式只说明“使用 OCI Go
SDK”,不是项目专属信号。
<a id="assessment"></a>
## 多租户关联评估
| 观察视角 | 结论 | 主要依据 |
| --- | --- | --- |
| Oracle 内部,跨租户数据 | **中** | 固定文本、出口 IP 与调用序列可组合比对 |
| Oracle 内部,单租户数据 | **低** | 能识别实现痕迹,但难证明多个租户共用同一实例 |
| 仅看 SDK 请求头 | **低** | 可识别云身份和 SDK 类型,不能可靠识别具体应用 |
| 外部第三方 | **通常不可行** | 缺少 OCI 网关日志、Sign-on Policy 与租户资源元数据 |
这些等级表达的是“可关联性”,不是 Oracle 已执行关联或据此采取处置。
同一出口 IP 也可能来自 NAT、代理或共享基础设施,必须与其他信号联合判断。
<a id="evidence"></a>
## 核验依据
### OCI 与 SDK
- [OCI Request Signatures](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/signingrequests.htm)
- [OCI API Signing Key](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm)
- [OCI Go SDK client.gov65.121.0](https://github.com/oracle/oci-go-sdk/blob/v65.121.0/common/client.go)
- [OCI Go SDK http_signer.gov65.121.0](https://github.com/oracle/oci-go-sdk/blob/v65.121.0/common/http_signer.go)
- [OCI Go SDK configuration.gov65.121.0](https://github.com/oracle/oci-go-sdk/blob/v65.121.0/common/configuration.go)
### 项目源码
- [API Key provider](../internal/oci/client.go#L237-L246)
- [手工签名请求](../internal/oci/account.go#L83-L97)
- [租户出站代理](../internal/oci/proxyhttp.go#L45-L65)
- [日志回传资源命名](../internal/oci/logrelay_names.go#L20-L55)
- [GenAI Responses 请求头](../internal/oci/genai_responses.go#L27-L38)
- [MFA justification](../internal/oci/signon.go#L223-L236)
- [审计与日志回传约束](../.trellis/spec/backend/oci-audit.md)
<p align="right"><a href="#top">返回顶部 ↑</a></p>
+305 -18
View File
@@ -608,7 +608,7 @@ const docTemplate = `{
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/internal_api.pagedResponse-oci-portal_internal_model_AiCallLog"
"$ref": "#/definitions/internal_api.pagedResponse-oci-portal_internal_model_AiContentLog"
}
}
}
@@ -780,7 +780,7 @@ const docTemplate = `{
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/internal_api.pagedResponse-oci-portal_internal_model_AiContentLog"
"$ref": "#/definitions/internal_api.pagedResponse-oci-portal_internal_model_AiCallLog"
}
}
}
@@ -930,8 +930,14 @@ const docTemplate = `{
}
],
"responses": {
"200": {
"description": "已更新,返回换发的新 token",
"schema": {
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"204": {
"description": "已更新,请重新登录"
"description": "已更新但新 token 签发失败,需重新登录"
},
"401": {
"description": "当前密码错误",
@@ -984,8 +990,14 @@ const docTemplate = `{
}
],
"responses": {
"200": {
"description": "已解绑,返回换发的新 token",
"schema": {
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"204": {
"description": "已解绑"
"description": "已解绑但新 token 签发失败,需重新登录"
},
"409": {
"description": "最后一个身份不可解绑",
@@ -1165,8 +1177,14 @@ const docTemplate = `{
}
],
"responses": {
"200": {
"description": "已保存,返回换发的新 token",
"schema": {
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"204": {
"description": "已保存"
"description": "已保存但新 token 签发失败,需重新登录"
},
"409": {
"description": "未绑定外部身份",
@@ -1242,8 +1260,14 @@ const docTemplate = `{
}
],
"responses": {
"200": {
"description": "已启用,返回换发的新 token",
"schema": {
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"204": {
"description": "已启用"
"description": "已启用但新 token 签发失败,需重新登录"
}
}
}
@@ -1271,8 +1295,14 @@ const docTemplate = `{
}
],
"responses": {
"200": {
"description": "已停用,返回换发的新 token",
"schema": {
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"204": {
"description": "已停用"
"description": "已停用但新 token 签发失败,需重新登录"
}
}
}
@@ -2473,6 +2503,15 @@ const docTemplate = `{
"schema": {
"$ref": "#/definitions/oci-portal_internal_oci.PAR"
}
},
"400": {
"description": "accessType 或 expiresHours 非法",
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
}
},
@@ -2522,8 +2561,17 @@ const docTemplate = `{
}
],
"responses": {
"200": {
"description": "all=1 时返回 {deleted: n}",
"schema": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
}
},
"204": {
"description": "删除成功,链接立即失效"
"description": "按 parId 删单条成功,链接立即失效"
}
}
}
@@ -2801,6 +2849,7 @@ const docTemplate = `{
"BearerAuth": []
}
],
"description": "创建禁用态 IdP;若 IdP 已创建但 JIT 后置配置失败且回滚无法确认,仍返回 201,并在 setupWarning 中标明部分成功",
"tags": [
"租户 IAM"
],
@@ -2833,7 +2882,7 @@ const docTemplate = `{
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/oci-portal_internal_oci.IdentityProviderInfo"
"$ref": "#/definitions/internal_api.createIdpResponse"
}
}
}
@@ -3010,6 +3059,128 @@ const docTemplate = `{
}
}
},
"/api/v1/oci-configs/{id}/idp-icons": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "上传到身份域公共图片存储(/storage/v1/Images),返回可填入 iconUrl 的公网地址",
"consumes": [
"multipart/form-data"
],
"tags": [
"租户 IAM"
],
"summary": "上传身份提供商图标",
"parameters": [
{
"type": "integer",
"description": "配置 ID",
"name": "id",
"in": "path",
"required": true
},
{
"type": "string",
"description": "身份域 OCID(缺省 Default 域)",
"name": "domainId",
"in": "query"
},
{
"type": "file",
"description": "图标文件(png/jpg/jpeg/gif/svg/webp/ico,≤1MB)",
"name": "file",
"in": "formData",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/internal_api.idpIconResponse"
}
},
"400": {
"description": "缺文件字段、文件为空或文件名非法",
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
},
"413": {
"description": "文件超过 1MB",
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
},
"415": {
"description": "扩展名不支持或与文件内容不符",
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
}
},
"delete": {
"security": [
{
"BearerAuth": []
}
],
"description": "使用上传响应中的 fileName 删除身份域公开图片;404 按已删除处理",
"tags": [
"租户 IAM"
],
"summary": "删除身份提供商图标",
"parameters": [
{
"type": "integer",
"description": "配置 ID",
"name": "id",
"in": "path",
"required": true
},
{
"type": "string",
"description": "身份域 OCID(缺省 Default 域)",
"name": "domainId",
"in": "query"
},
{
"type": "string",
"description": "上传响应返回的 IdP 图标存储标识(images/idp-icon-\u003c32hex\u003e.\u003cext\u003e)",
"name": "fileName",
"in": "query",
"required": true
}
],
"responses": {
"204": {
"description": "无内容"
},
"400": {
"description": "fileName 缺失或不是本服务生成的 IdP 图标标识",
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
}
}
},
"/api/v1/oci-configs/{id}/images": {
"get": {
"security": [
@@ -6711,7 +6882,7 @@ const docTemplate = `{
}
}
},
"put": {
"patch": {
"security": [
{
"BearerAuth": []
@@ -6720,10 +6891,10 @@ const docTemplate = `{
"tags": [
"设置"
],
"summary": "保存 OAuth provider 配置",
"summary": "部分更新 OAuth provider 配置",
"parameters": [
{
"description": "provider 配置",
"description": "出现的字段才会被更新",
"name": "body",
"in": "body",
"required": true,
@@ -6762,7 +6933,7 @@ const docTemplate = `{
}
}
},
"put": {
"patch": {
"security": [
{
"BearerAuth": []
@@ -6771,15 +6942,15 @@ const docTemplate = `{
"tags": [
"设置"
],
"summary": "保存安全设置并返回最新值",
"summary": "部分更新安全设置并返回最新值",
"parameters": [
{
"description": "请求体",
"description": "出现的字段才会被更新",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/oci-portal_internal_service.SecuritySettings"
"$ref": "#/definitions/oci-portal_internal_service.SecurityPatch"
}
}
],
@@ -7036,7 +7207,7 @@ const docTemplate = `{
"required": true
},
{
"description": "可更新字段",
"description": "可更新字段;抢机 payload 的 count 语义为目标台数",
"name": "body",
"in": "body",
"required": true,
@@ -7051,6 +7222,18 @@ const docTemplate = `{
"schema": {
"$ref": "#/definitions/oci-portal_internal_model.Task"
}
},
"400": {
"description": "参数非法或抢机目标不大于已完成数量",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"409": {
"description": "任务被并发修改,须刷新重试",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
},
@@ -7448,6 +7631,35 @@ const docTemplate = `{
}
}
},
"internal_api.createIdpResponse": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"id": {
"type": "string"
},
"jitEnabled": {
"type": "boolean"
},
"name": {
"type": "string"
},
"partnerProviderId": {
"type": "string"
},
"setupWarning": {
"$ref": "#/definitions/internal_api.idpSetupWarning"
},
"timeCreated": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"internal_api.createInstanceRequest": {
"type": "object",
"required": [
@@ -7759,6 +7971,34 @@ const docTemplate = `{
}
}
},
"internal_api.idpIconResponse": {
"type": "object",
"properties": {
"fileName": {
"type": "string"
},
"url": {
"type": "string"
}
}
},
"internal_api.idpSetupWarning": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"requestId": {
"type": "string"
},
"resourceCreated": {
"type": "boolean"
}
}
},
"internal_api.importRequest": {
"type": "object",
"required": [
@@ -11335,6 +11575,13 @@ const docTemplate = `{
"hasActiveTask": {
"type": "boolean"
},
"series": {
"description": "Series 按币种拆分的序列(合计降序);顶层 Currency/Total/Days 恒为首个\n(主)币种,多币种租户的其余币种只出现在 Series,不与主币种相加。",
"type": "array",
"items": {
"$ref": "#/definitions/oci-portal_internal_service.OverviewCostSeries"
}
},
"total": {
"type": "number"
}
@@ -11351,6 +11598,23 @@ const docTemplate = `{
}
}
},
"oci-portal_internal_service.OverviewCostSeries": {
"type": "object",
"properties": {
"currency": {
"type": "string"
},
"days": {
"type": "array",
"items": {
"$ref": "#/definitions/oci-portal_internal_service.OverviewCostDay"
}
},
"total": {
"type": "number"
}
}
},
"oci-portal_internal_service.OverviewTasks": {
"type": "object",
"properties": {
@@ -11525,6 +11789,29 @@ const docTemplate = `{
}
}
},
"oci-portal_internal_service.SecurityPatch": {
"type": "object",
"properties": {
"appUrl": {
"type": "string"
},
"ipRateBurst": {
"type": "integer"
},
"ipRateRps": {
"type": "integer"
},
"loginFailLimit": {
"type": "integer"
},
"loginLockMinutes": {
"type": "integer"
},
"realIpHeader": {
"type": "string"
}
}
},
"oci-portal_internal_service.SecuritySettings": {
"type": "object",
"properties": {
@@ -11639,7 +11926,7 @@ const docTemplate = `{
// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = &swag.Spec{
Version: "0.0.1",
Version: "0.8.0",
Host: "",
BasePath: "/",
Schemes: []string{},
+304 -17
View File
@@ -601,7 +601,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/internal_api.pagedResponse-oci-portal_internal_model_AiCallLog"
"$ref": "#/definitions/internal_api.pagedResponse-oci-portal_internal_model_AiContentLog"
}
}
}
@@ -773,7 +773,7 @@
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/internal_api.pagedResponse-oci-portal_internal_model_AiContentLog"
"$ref": "#/definitions/internal_api.pagedResponse-oci-portal_internal_model_AiCallLog"
}
}
}
@@ -923,8 +923,14 @@
}
],
"responses": {
"200": {
"description": "已更新,返回换发的新 token",
"schema": {
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"204": {
"description": "已更新,请重新登录"
"description": "已更新但新 token 签发失败,需重新登录"
},
"401": {
"description": "当前密码错误",
@@ -977,8 +983,14 @@
}
],
"responses": {
"200": {
"description": "已解绑,返回换发的新 token",
"schema": {
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"204": {
"description": "已解绑"
"description": "已解绑但新 token 签发失败,需重新登录"
},
"409": {
"description": "最后一个身份不可解绑",
@@ -1158,8 +1170,14 @@
}
],
"responses": {
"200": {
"description": "已保存,返回换发的新 token",
"schema": {
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"204": {
"description": "已保存"
"description": "已保存但新 token 签发失败,需重新登录"
},
"409": {
"description": "未绑定外部身份",
@@ -1235,8 +1253,14 @@
}
],
"responses": {
"200": {
"description": "已启用,返回换发的新 token",
"schema": {
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"204": {
"description": "已启用"
"description": "已启用但新 token 签发失败,需重新登录"
}
}
}
@@ -1264,8 +1288,14 @@
}
],
"responses": {
"200": {
"description": "已停用,返回换发的新 token",
"schema": {
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"204": {
"description": "已停用"
"description": "已停用但新 token 签发失败,需重新登录"
}
}
}
@@ -2466,6 +2496,15 @@
"schema": {
"$ref": "#/definitions/oci-portal_internal_oci.PAR"
}
},
"400": {
"description": "accessType 或 expiresHours 非法",
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
}
},
@@ -2515,8 +2554,17 @@
}
],
"responses": {
"200": {
"description": "all=1 时返回 {deleted: n}",
"schema": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
}
},
"204": {
"description": "删除成功,链接立即失效"
"description": "按 parId 删单条成功,链接立即失效"
}
}
}
@@ -2794,6 +2842,7 @@
"BearerAuth": []
}
],
"description": "创建禁用态 IdP;若 IdP 已创建但 JIT 后置配置失败且回滚无法确认,仍返回 201,并在 setupWarning 中标明部分成功",
"tags": [
"租户 IAM"
],
@@ -2826,7 +2875,7 @@
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/oci-portal_internal_oci.IdentityProviderInfo"
"$ref": "#/definitions/internal_api.createIdpResponse"
}
}
}
@@ -3003,6 +3052,128 @@
}
}
},
"/api/v1/oci-configs/{id}/idp-icons": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"description": "上传到身份域公共图片存储(/storage/v1/Images),返回可填入 iconUrl 的公网地址",
"consumes": [
"multipart/form-data"
],
"tags": [
"租户 IAM"
],
"summary": "上传身份提供商图标",
"parameters": [
{
"type": "integer",
"description": "配置 ID",
"name": "id",
"in": "path",
"required": true
},
{
"type": "string",
"description": "身份域 OCID(缺省 Default 域)",
"name": "domainId",
"in": "query"
},
{
"type": "file",
"description": "图标文件(png/jpg/jpeg/gif/svg/webp/ico,≤1MB)",
"name": "file",
"in": "formData",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/internal_api.idpIconResponse"
}
},
"400": {
"description": "缺文件字段、文件为空或文件名非法",
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
},
"413": {
"description": "文件超过 1MB",
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
},
"415": {
"description": "扩展名不支持或与文件内容不符",
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
}
},
"delete": {
"security": [
{
"BearerAuth": []
}
],
"description": "使用上传响应中的 fileName 删除身份域公开图片;404 按已删除处理",
"tags": [
"租户 IAM"
],
"summary": "删除身份提供商图标",
"parameters": [
{
"type": "integer",
"description": "配置 ID",
"name": "id",
"in": "path",
"required": true
},
{
"type": "string",
"description": "身份域 OCID(缺省 Default 域)",
"name": "domainId",
"in": "query"
},
{
"type": "string",
"description": "上传响应返回的 IdP 图标存储标识(images/idp-icon-\u003c32hex\u003e.\u003cext\u003e)",
"name": "fileName",
"in": "query",
"required": true
}
],
"responses": {
"204": {
"description": "无内容"
},
"400": {
"description": "fileName 缺失或不是本服务生成的 IdP 图标标识",
"schema": {
"type": "object",
"additionalProperties": {
"type": "string"
}
}
}
}
}
},
"/api/v1/oci-configs/{id}/images": {
"get": {
"security": [
@@ -6704,7 +6875,7 @@
}
}
},
"put": {
"patch": {
"security": [
{
"BearerAuth": []
@@ -6713,10 +6884,10 @@
"tags": [
"设置"
],
"summary": "保存 OAuth provider 配置",
"summary": "部分更新 OAuth provider 配置",
"parameters": [
{
"description": "provider 配置",
"description": "出现的字段才会被更新",
"name": "body",
"in": "body",
"required": true,
@@ -6755,7 +6926,7 @@
}
}
},
"put": {
"patch": {
"security": [
{
"BearerAuth": []
@@ -6764,15 +6935,15 @@
"tags": [
"设置"
],
"summary": "保存安全设置并返回最新值",
"summary": "部分更新安全设置并返回最新值",
"parameters": [
{
"description": "请求体",
"description": "出现的字段才会被更新",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/oci-portal_internal_service.SecuritySettings"
"$ref": "#/definitions/oci-portal_internal_service.SecurityPatch"
}
}
],
@@ -7029,7 +7200,7 @@
"required": true
},
{
"description": "可更新字段",
"description": "可更新字段;抢机 payload 的 count 语义为目标台数",
"name": "body",
"in": "body",
"required": true,
@@ -7044,6 +7215,18 @@
"schema": {
"$ref": "#/definitions/oci-portal_internal_model.Task"
}
},
"400": {
"description": "参数非法或抢机目标不大于已完成数量",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"409": {
"description": "任务被并发修改,须刷新重试",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
},
@@ -7441,6 +7624,35 @@
}
}
},
"internal_api.createIdpResponse": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"id": {
"type": "string"
},
"jitEnabled": {
"type": "boolean"
},
"name": {
"type": "string"
},
"partnerProviderId": {
"type": "string"
},
"setupWarning": {
"$ref": "#/definitions/internal_api.idpSetupWarning"
},
"timeCreated": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"internal_api.createInstanceRequest": {
"type": "object",
"required": [
@@ -7752,6 +7964,34 @@
}
}
},
"internal_api.idpIconResponse": {
"type": "object",
"properties": {
"fileName": {
"type": "string"
},
"url": {
"type": "string"
}
}
},
"internal_api.idpSetupWarning": {
"type": "object",
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string"
},
"requestId": {
"type": "string"
},
"resourceCreated": {
"type": "boolean"
}
}
},
"internal_api.importRequest": {
"type": "object",
"required": [
@@ -11328,6 +11568,13 @@
"hasActiveTask": {
"type": "boolean"
},
"series": {
"description": "Series 按币种拆分的序列(合计降序);顶层 Currency/Total/Days 恒为首个\n(主)币种,多币种租户的其余币种只出现在 Series,不与主币种相加。",
"type": "array",
"items": {
"$ref": "#/definitions/oci-portal_internal_service.OverviewCostSeries"
}
},
"total": {
"type": "number"
}
@@ -11344,6 +11591,23 @@
}
}
},
"oci-portal_internal_service.OverviewCostSeries": {
"type": "object",
"properties": {
"currency": {
"type": "string"
},
"days": {
"type": "array",
"items": {
"$ref": "#/definitions/oci-portal_internal_service.OverviewCostDay"
}
},
"total": {
"type": "number"
}
}
},
"oci-portal_internal_service.OverviewTasks": {
"type": "object",
"properties": {
@@ -11518,6 +11782,29 @@
}
}
},
"oci-portal_internal_service.SecurityPatch": {
"type": "object",
"properties": {
"appUrl": {
"type": "string"
},
"ipRateBurst": {
"type": "integer"
},
"ipRateRps": {
"type": "integer"
},
"loginFailLimit": {
"type": "integer"
},
"loginLockMinutes": {
"type": "integer"
},
"realIpHeader": {
"type": "string"
}
}
},
"oci-portal_internal_service.SecuritySettings": {
"type": "object",
"properties": {
+208 -17
View File
@@ -176,6 +176,25 @@ definitions:
- metadata
- name
type: object
internal_api.createIdpResponse:
properties:
enabled:
type: boolean
id:
type: string
jitEnabled:
type: boolean
name:
type: string
partnerProviderId:
type: string
setupWarning:
$ref: '#/definitions/internal_api.idpSetupWarning'
timeCreated:
type: string
type:
type: string
type: object
internal_api.createInstanceRequest:
properties:
assignIpv6:
@@ -385,6 +404,24 @@ definitions:
error:
type: string
type: object
internal_api.idpIconResponse:
properties:
fileName:
type: string
url:
type: string
type: object
internal_api.idpSetupWarning:
properties:
code:
type: string
message:
type: string
requestId:
type: string
resourceCreated:
type: boolean
type: object
internal_api.importRequest:
properties:
alias:
@@ -2744,6 +2781,13 @@ definitions:
type: array
hasActiveTask:
type: boolean
series:
description: |-
Series 按币种拆分的序列(合计降序);顶层 Currency/Total/Days 恒为首个
(主)币种,多币种租户的其余币种只出现在 Series,不与主币种相加。
items:
$ref: '#/definitions/oci-portal_internal_service.OverviewCostSeries'
type: array
total:
type: number
type: object
@@ -2754,6 +2798,17 @@ definitions:
day:
type: string
type: object
oci-portal_internal_service.OverviewCostSeries:
properties:
currency:
type: string
days:
items:
$ref: '#/definitions/oci-portal_internal_service.OverviewCostDay'
type: array
total:
type: number
type: object
oci-portal_internal_service.OverviewTasks:
properties:
active:
@@ -2869,6 +2924,21 @@ definitions:
webhook:
$ref: '#/definitions/oci-portal_internal_service.LogWebhookInfo'
type: object
oci-portal_internal_service.SecurityPatch:
properties:
appUrl:
type: string
ipRateBurst:
type: integer
ipRateRps:
type: integer
loginFailLimit:
type: integer
loginLockMinutes:
type: integer
realIpHeader:
type: string
type: object
oci-portal_internal_service.SecuritySettings:
properties:
appUrl:
@@ -3308,7 +3378,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/internal_api.pagedResponse-oci-portal_internal_model_AiCallLog'
$ref: '#/definitions/internal_api.pagedResponse-oci-portal_internal_model_AiContentLog'
security:
- BearerAuth: []
summary: 分页查询内容日志
@@ -3411,7 +3481,7 @@ paths:
"200":
description: OK
schema:
$ref: '#/definitions/internal_api.pagedResponse-oci-portal_internal_model_AiContentLog'
$ref: '#/definitions/internal_api.pagedResponse-oci-portal_internal_model_AiCallLog'
security:
- BearerAuth: []
summary: AI 调用日志列表
@@ -3498,8 +3568,12 @@ paths:
schema:
$ref: '#/definitions/oci-portal_internal_service.UpdateCredentialsInput'
responses:
"200":
description: 已更新,返回换发的新 token
schema:
$ref: '#/definitions/internal_api.tokenResponse'
"204":
description: 已更新,请重新登录
description: 已更新但新 token 签发失败,需重新登录
"401":
description: 当前密码错误
schema:
@@ -3530,8 +3604,12 @@ paths:
required: true
type: integer
responses:
"200":
description: 已解绑,返回换发的新 token
schema:
$ref: '#/definitions/internal_api.tokenResponse'
"204":
description: 已解绑
description: 已解绑但新 token 签发失败,需重新登录
"409":
description: 最后一个身份不可解绑
schema:
@@ -3644,8 +3722,12 @@ paths:
schema:
type: object
responses:
"200":
description: 已保存,返回换发的新 token
schema:
$ref: '#/definitions/internal_api.tokenResponse'
"204":
description: 已保存
description: 已保存但新 token 签发失败,需重新登录
"409":
description: 未绑定外部身份
schema:
@@ -3689,8 +3771,12 @@ paths:
schema:
type: object
responses:
"200":
description: 已启用,返回换发的新 token
schema:
$ref: '#/definitions/internal_api.tokenResponse'
"204":
description: 已启用
description: 已启用但新 token 签发失败,需重新登录
security:
- BearerAuth: []
summary: 激活两步验证
@@ -3706,8 +3792,12 @@ paths:
schema:
type: object
responses:
"200":
description: 已停用,返回换发的新 token
schema:
$ref: '#/definitions/internal_api.tokenResponse'
"204":
description: 已停用
description: 已停用但新 token 签发失败,需重新登录
security:
- BearerAuth: []
summary: 停用两步验证
@@ -4428,8 +4518,14 @@ paths:
name: region
type: string
responses:
"200":
description: 'all=1 时返回 {deleted: n}'
schema:
additionalProperties:
type: integer
type: object
"204":
description: 删除成功,链接立即失效
description: 按 parId 删单条成功,链接立即失效
security:
- BearerAuth: []
summary: 删除临时链接
@@ -4493,6 +4589,12 @@ paths:
description: fullUrl 仅创建响应返回,请立即保存
schema:
$ref: '#/definitions/oci-portal_internal_oci.PAR'
"400":
description: accessType 或 expiresHours 非法
schema:
additionalProperties:
type: string
type: object
security:
- BearerAuth: []
summary: 签发临时链接(PAR)
@@ -4665,6 +4767,8 @@ paths:
tags:
- 租户 IAM
post:
description: 创建禁用态 IdP;若 IdP 已创建但 JIT 后置配置失败且回滚无法确认,仍返回 201,并在 setupWarning
中标明部分成功
parameters:
- description: 配置 ID
in: path
@@ -4685,7 +4789,7 @@ paths:
"201":
description: Created
schema:
$ref: '#/definitions/oci-portal_internal_oci.IdentityProviderInfo'
$ref: '#/definitions/internal_api.createIdpResponse'
security:
- BearerAuth: []
summary: 创建身份提供商(SAML)
@@ -4798,6 +4902,85 @@ paths:
summary: 更新身份域设置
tags:
- 租户 IAM
/api/v1/oci-configs/{id}/idp-icons:
delete:
description: 使用上传响应中的 fileName 删除身份域公开图片;404 按已删除处理
parameters:
- description: 配置 ID
in: path
name: id
required: true
type: integer
- description: 身份域 OCID(缺省 Default 域)
in: query
name: domainId
type: string
- description: 上传响应返回的 IdP 图标存储标识(images/idp-icon-<32hex>.<ext>)
in: query
name: fileName
required: true
type: string
responses:
"204":
description: 无内容
"400":
description: fileName 缺失或不是本服务生成的 IdP 图标标识
schema:
additionalProperties:
type: string
type: object
security:
- BearerAuth: []
summary: 删除身份提供商图标
tags:
- 租户 IAM
post:
consumes:
- multipart/form-data
description: 上传到身份域公共图片存储(/storage/v1/Images),返回可填入 iconUrl 的公网地址
parameters:
- description: 配置 ID
in: path
name: id
required: true
type: integer
- description: 身份域 OCID(缺省 Default 域)
in: query
name: domainId
type: string
- description: 图标文件(png/jpg/jpeg/gif/svg/webp/ico,≤1MB)
in: formData
name: file
required: true
type: file
responses:
"200":
description: OK
schema:
$ref: '#/definitions/internal_api.idpIconResponse'
"400":
description: 缺文件字段、文件为空或文件名非法
schema:
additionalProperties:
type: string
type: object
"413":
description: 文件超过 1MB
schema:
additionalProperties:
type: string
type: object
"415":
description: 扩展名不支持或与文件内容不符
schema:
additionalProperties:
type: string
type: object
security:
- BearerAuth: []
summary: 上传身份提供商图标
tags:
- 租户 IAM
/api/v1/oci-configs/{id}/images:
get:
parameters:
@@ -7090,9 +7273,9 @@ paths:
summary: OAuth provider 配置
tags:
- 设置
put:
patch:
parameters:
- description: provider 配置
- description: 出现的字段才会被更新
in: body
name: body
required: true
@@ -7105,7 +7288,7 @@ paths:
$ref: '#/definitions/oci-portal_internal_service.OAuthProvidersView'
security:
- BearerAuth: []
summary: 保存 OAuth provider 配置
summary: 部分更新 OAuth provider 配置
tags:
- 设置
/api/v1/settings/security:
@@ -7120,14 +7303,14 @@ paths:
summary: 返回安全设置
tags:
- 设置
put:
patch:
parameters:
- description: 请求体
- description: 出现的字段才会被更新
in: body
name: body
required: true
schema:
$ref: '#/definitions/oci-portal_internal_service.SecuritySettings'
$ref: '#/definitions/oci-portal_internal_service.SecurityPatch'
responses:
"200":
description: OK
@@ -7135,7 +7318,7 @@ paths:
$ref: '#/definitions/oci-portal_internal_service.SecuritySettings'
security:
- BearerAuth: []
summary: 保存安全设置并返回最新值
summary: 部分更新安全设置并返回最新值
tags:
- 设置
/api/v1/settings/task:
@@ -7292,7 +7475,7 @@ paths:
name: id
required: true
type: integer
- description: 可更新字段
- description: 可更新字段;抢机 payload 的 count 语义为目标台数
in: body
name: body
required: true
@@ -7303,6 +7486,14 @@ paths:
description: OK
schema:
$ref: '#/definitions/oci-portal_internal_model.Task'
"400":
description: 参数非法或抢机目标不大于已完成数量
schema:
$ref: '#/definitions/internal_api.errorResponse'
"409":
description: 任务被并发修改,须刷新重试
schema:
$ref: '#/definitions/internal_api.errorResponse'
security:
- BearerAuth: []
summary: 更新任务