Files
oci-portal/docs/OCI调用者指纹评估.md
2026-07-22 16:51:23 +08:00

118 lines
5.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<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>