Cloud Organization 和 Account 术语梳理
本文档详细解释 Upwind Console 中与云组织和账户相关的所有术语及其关系。
核心概念层级
Upwind Organization (用户组织)
│
├── CloudOrganization (云提供商组织)
│ │
│ ├── Orchestrator Account (编排账户)
│ ├── Management Account (AWS 管理账户,仅 AWS)
│ ├── CloudOrganizationAccount (组织内账户)
│ │ └── CloudProviderAccount (Upwind 系统中的账户对象)
│ └── CloudOrganizationUnit (组织单元/管理组)
│
└── Single Account (独立账户,不属于任何组织)
└── CloudProviderAccount (Upwind 系统中的账户对象)
术语详解
1. Organization (Upwind Organization)
定义: Upwind 平台上的用户组织,是 Upwind 系统的顶层概念。
特点:
- 每个 Upwind 用户属于一个 Organization
- Organization ID 用于标识用户在 Upwind 平台上的组织
- 一个 Organization 可以连接多个云提供商的账户和组织
代码位置:
packages/console/src/types/Organization.ts- 通过
authenticationService.getOrganizationId()获取
示例:
const orgId = authenticationService.getOrganizationId(); // "org_abc123"
2. CloudOrganization (云提供商组织)
定义: 云提供商的原生组织结构,对应:
- AWS: AWS Organizations
- Azure: Management Groups (管理组)
- GCP: GCP Organizations
特点:
- 一个 CloudOrganization 属于一个云提供商 (AWS/Azure/GCP)
- 一个 Upwind Organization 可以连接多个 CloudOrganization
- 包含多个账户 (CloudOrganizationAccount)
- 有层级结构 (通过 CloudOrganizationUnit)
数据结构:
type CloudOrganizationAttributes = {
cloudOrganizationId: string; // 云组织的唯一标识
orgDisplayName?: string; // 显示名称
cloudProvider: CloudProviderType; // AWS | AZURE | GCP
connectedAccounts: number; // 已连接的账户数
totalAccounts: number; // 总账户数
orchestratorAccount: string; // 编排账户 ID
awsManagementAccount?: string; // AWS 管理账户 (仅 AWS)
awsRootId?: string; // AWS Root OU ID (仅 AWS)
discoveryRole: string; // 发现角色
accounts: Record<string, CloudOrganizationAccountAttributes>;
byOu: Record<string, CloudOrganizationalUnitAttributes>;
}
代码位置:
packages/console/src/DataModel/OrganizationsAndAccounts/CloudOrganization.ts- API 响应:
CloudOrganizationResponseItem
3. Orchestrator Account (编排账户)
定义: 用于部署和管理 Upwind Cloud Scanner 基础设施的账户。
特点:
- 每个 CloudOrganization 必须有一个 Orchestrator Account
- Orchestrator Account 本身也是 CloudOrganizationAccount 之一
- 在 CloudOrganization 中通过
orchestratorAccount字段标识
代码位置:
CloudOrganizationAttributes.orchestratorAccountpackages/console/src/pages/NewOnboarding/OnboardingViews/Utils/onboardingTooltips.ts(工具提示说明)
UI 标识:
- 在账户列表中会显示 "Orchestrator" badge
- 在 CloudOrganizationSidePane 的 header 中会显示 AccountObjectVerticalDotsOptions
4. Management Account (管理账户,仅 AWS)
定义: AWS Organizations 的根账户,拥有组织的完全控制权。
特点:
- 仅适用于 AWS
- 是 AWS Organizations 的创建者账户
- 拥有组织的最高权限
- 可以创建和管理其他账户
- 在 CloudOrganization 中通过
awsManagementAccount字段标识
代码位置:
CloudOrganizationAttributes.awsManagementAccount
与 Orchestrator Account 的关系:
- Management Account 和 Orchestrator Account 可以是同一个账户,也可以是不同的账户
- 通常 Orchestrator Account 是 Management Account 的子账户
5. CloudOrganizationAccount (组织内账户)
定义: 属于某个 CloudOrganization 的账户,是云提供商组织中的成员账户。
特点:
- 属于某个 CloudOrganization (
cloudOrgId) - 有连接状态 (
connectionStatus) - 可能属于某个 Organizational Unit (
ou) - 在 Upwind 系统中对应一个
CloudProviderAccount对象
数据结构:
type CloudOrganizationAccountAttributes = {
accountId: string; // 云账户 ID (AWS Account ID / Azure Subscription ID / GCP Project ID)
accountDisplayName: string; // 显示名称
ou: string; // 所属组织单元 ID
connectedAt?: number; // 连接时间
connectionStatus: CloudOrganizationAccountConnectionStatus;
cloudProvider: CloudProviderType;
cloudOrgId?: string; // 所属云组织 ID
errorMessage?: string; // 错误消息
exceptionMessage?: string; // 异常消息
errorCode?: string; // 错误代码
}
与 CloudProviderAccount 的关联:
accountId字段对应云账户 ID(如 AWS Account ID),不是CloudProviderAccount的 credentials ID- 要通过
accountId查找对应的CloudProviderAccount,需要使用getAccountByCloudAccountId(accountId) - 示例:
// CloudOrganizationAccount 中的 accountId const orgAccount: CloudOrganizationAccountAttributes = { accountId: "123456789012", // AWS Account ID // ... }; // 查找对应的 CloudProviderAccount const cloudProviderAccount = sharedModel.getAccountByCloudAccountId( orgAccount.accountId // 使用 accountId 查找 ); // 或者使用 hook const [cloudAccount] = useCloudAccount(orgAccount.accountId); // 获取 CloudProviderAccount 的 credentials ID const credentialsId = cloudProviderAccount?.getId();
代码位置:
packages/console/src/DataModel/OrganizationsAndAccounts/CloudOrganizationAccount.ts- API 响应:
CloudOrganizationAccountResponseItem
6. CloudProviderAccount (Upwind 系统中的账户对象)
定义: Upwind 系统中表示云账户的对象,是系统内部的数据模型。
特点:
- 存储在
accountsStorage中 - 可以是组织内账户,也可以是独立账户
- 通过
cloudOrganizationId关联到 CloudOrganization (可选) - 通过
cloudOrganizationUnitId关联到 Organizational Unit (可选) - 有状态 (
status):CONNECTED,DISCONNECTED,ERROR等
数据结构:
type CloudProviderAccountAttributes = {
id: string; // Upwind 系统中的唯一 ID (credentials ID)
name: string; // 账户名称
provider: AwsProvider | AzureProvider | GcpProvider | ByocProvider;
status: CloudProviderStatus;
cloudApiEnabled?: boolean;
cloudScannerEnabled?: boolean;
createdAt?: number;
cloudOrganizationId?: string; // 所属云组织 ID (可选,独立账户没有)
cloudOrganizationUnitId?: string; // 所属组织单元 ID (可选)
}
与 CloudOrganizationAccount 的关系:
- 一个
CloudOrganizationAccount对应一个CloudProviderAccount CloudProviderAccount是 Upwind 系统的内部表示CloudOrganizationAccount是组织视图中的表示- 关联方式: 通过
CloudOrganizationAccount.accountId(云账户 ID)使
---
### 7. Single Account (独立账户)
**定义**: 不属于任何 CloudOrganization 的独立账户。
**特点**:
- `cloudOrganizationId` 为 `null` 或 `undefined`
- 在 UI 中会显示在 "Single Accounts" 分组中
- 仍然对应一个 `CloudProviderAccount` 对象
- 在 `CloudOrganizationAccountRowData` 中,`orgData` 为 `null`
**代码位置**:
- API 响应: `CloudSingleAccountWrapperResponseItem`
- 解析后存储在 `singleAccountsData` 数组中
**示例**:
```typescript
// 独立账户的 CloudOrganizationAccountAttributes
{
accountId: "123456789012",
accountDisplayName: "Standalone Account",
cloudOrgId: undefined, // 没有所属组织
connectionStatus: "connected",
cloudProvider: "AWS"
}
8. CloudOrganizationUnit (组织单元)
定义: 云提供商组织中的层级结构单元。
不同云提供商的对应:
- AWS: Organizational Unit (OU)
- Azure: Management Group (管理组)
- GCP: Folder (文件夹)
特点:
- 属于某个 CloudOrganization
- 可以有父子关系 (
ouParentId) - 包含多个账户
- 用于组织和管理账户
数据结构:
type CloudOrganizationalUnitAttributes = {
id: string;
organizationId: string; // 所属云组织 ID
organizationUnitId: string; // 组织单元 ID
ouName: string | null; // 显示名称
cloudProvider: CloudProviderType;
ouParentId?: string; // 父组织单元 ID
}
代码位置:
packages/console/src/DataModel/Objects/CloudOrganizationUnit.ts- API 响应:
CloudOrganizationalUnitResponseItem
示例:
// AWS OU
{
organizationUnitId: "ou-1234-567890",
ouName: "Production",
organizationId: "o-1234567890",
cloudProvider: "AWS"
}
// Azure Management Group
{
organizationUnitId: "/providers/Microsoft.Management/managementGroups/Prod",
ouName: "Production",
organizationId: "/providers/Microsoft.Management/managementGroups/root",
cloudProvider: "AZURE"
}
数据流和关系
1. 从后端 API 到前端的数据流
Backend API
↓
getCloudOrganizationsAndAccounts()
↓
CloudOrganizationsAndAccountsResponse
├── organizational_accounts: Record<string, CloudOrganizationResponseItem>
│ └── 包含 CloudOrganization 及其所有账户
└── single_accounts: CloudSingleAccountWrapperResponseItem[]
└── 包含独立账户
↓
parseOrganizationsAndAccountsResponse()
↓
[organizationsData, singleAccountsData]
├── organizationsData: Record<string, CloudOrganizationAttributes>
└── singleAccountsData: CloudOrganizationAccountAttributes[]
↓
useCloudOrganizationAccountsData()
↓
useOrganizationsAndAccountsRows()
↓
CloudOrganizationAccountRowData[]
2. 账户查找流程
通过 CloudAccountId 查找 CloudProviderAccount:
// 1. 从 accountsStorage 中查找
const account = accountsStorage.getAccountByCloudAccountId(cloudAccountId);
// 2. 或使用 hook
const account = useCloudAccount(cloudAccountId);
通过 CloudOrganizationId 查找 CloudOrganization:
// 从 organizationsData 中查找
const organization = organizationsData[cloudOrganizationId];
查找 Orchestrator Account:
// 1. 从 CloudOrganization 获取 orchestratorAccount ID
const orchestratorAccountId = organizationData?.orchestratorAccount;
// 2. 从 accountsStorage 中查找对应的 CloudProviderAccount
const orchestratorAccount = accountsStorage.getAccountByCloudAccountId(
orchestratorAccountId
);
3. 账户和组织的关系判断
判断账户是否属于组织:
const isPartOfOrganization = (account: CloudProviderAccount): boolean => {
return !!account.getOrganizationId(); // cloudOrganizationId 不为空
};
判断账户是否为 Orchestrator:
const isOrchestrator = (
account: CloudProviderAccount,
organization: CloudOrganizationAttributes
): boolean => {
const accountId = account.getCloudAccountId();
return accountId === organization.orchestratorAccount;
};
判断账户是否为 AWS Management Account:
const isAwsManagement = (
account: CloudProviderAccount,
organization: CloudOrganizationAttributes
): boolean => {
if (account.getCloudProvider() !== CLOUD_PROVIDER_TYPE.AWS) {
return false;
}
const accountId = account.getCloudAccountId();
return accountId === organization.awsManagementAccount;
};
常见场景
场景 1: 显示 CloudOrganization 的详细信息
// 1. 获取组织数据
const { organizationsData } = useCloudOrganizationAccountsData();
const organization = organizationsData[cloudOrganizationId];
// 2. 获取 Orchestrator Account
const orchestratorAccountId = organization?.orchestratorAccount;
const orchestratorAccount = useCloudAccount(orchestratorAccountId);
// 3. 显示信息
<CloudOrganizationSidePane
sidePaneItemId={cloudOrganizationId}
// organization 包含所有组织信息
// orchestratorAccount 用于显示 header 中的操作按钮
/>
场景 2: 显示单个账户的详细信息
// 1. 获取账户对象
const cloudAccount = useCloudAccount(cloudAccountId);
// 2. 判断是否属于组织
const isPartOfOrg = !!cloudAccount?.getOrganizationId();
// 3. 如果属于组织,获取组织信息
const orgId = cloudAccount?.getOrganizationId();
const organization = organizationsData[orgId || ""];
// 4. 显示信息
<CloudAccountSidePane
sidePaneItemId={cloudAccountId}
// cloudAccount 包含账户的所有信息
// organization 用于显示组织相关信息(如果需要)
/>
场景 3: 查找账户在组织中的位置
// 1. 获取账户和组织数据
const cloudAccount = useCloudAccount(cloudAccountId);
const orgId = cloudAccount?.getOrganizationId();
const organization = organizationsData[orgId || ""];
// 2. 查找账户在组织中的信息
const accountInOrg = organization?.accounts[cloudAccountId];
// 3. 获取组织单元信息
const ouId = accountInOrg?.ou;
const ou = organization?.byOu[ouId || ""];
代码中的关键 Hook 和函数
Hooks
-
useCloudOrganizationAccountsData()- 获取所有组织和账户数据
- 返回
organizationsData和singleAccountsData
-
useCloudAccount(accountId)- 获取单个
CloudProviderAccount对象 - 从
accountsStorage中查找
- 获取单个
-
useOrganizationsAndAccountsRows()- 将组织和账户数据转换为表格行数据
- 返回
CloudOrganizationAccountRowData[]
关键函数
-
parseOrganizationsAndAccountsResponse(response)- 解析后端 API 响应
- 返回
[organizationsData, singleAccountsData]
-
parseCloudOrganizationAccountsToRows(...)- 将组织数据转换为行数据
- 包含
orgData的填充
注意事项
-
术语混淆:
Organization(Upwind) vsCloudOrganization(云提供商)CloudOrganizationAccount(组织视图) vsCloudProviderAccount(系统对象)
-
数据来源:
CloudOrganization和CloudOrganizationAccount来自 API 响应,存储在组件 stateCloudProviderAccount存储在accountsStorage中
-
ID 类型:
cloudOrganizationId: 云组织的 ID (如 AWS Org ID)cloudAccountId: 云账户的 ID (如 AWS Account ID / Azure Subscription ID / GCP Project ID)id(credentials ID): Upwind 系统中的账户对象 ID,用于在accountsStorage中查找CloudProviderAccount对象- 重要:
AccountObjectVerticalDotsOptions组件中的id参数就是这个 credentials ID - 通过
account.getId()获取 - 通过
getAccountById(id)从accountsStorage中查找账户对象
- 重要:
-
可选字段:
cloudOrganizationId在CloudProviderAccount中是可选的 (独立账户没有)orgData在CloudOrganizationAccountRowData中对于独立账户是null