Org and account

0 阅读7分钟

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.orchestratorAccount
  • packages/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

  1. useCloudOrganizationAccountsData()

    • 获取所有组织和账户数据
    • 返回 organizationsDatasingleAccountsData
  2. useCloudAccount(accountId)

    • 获取单个 CloudProviderAccount 对象
    • accountsStorage 中查找
  3. useOrganizationsAndAccountsRows()

    • 将组织和账户数据转换为表格行数据
    • 返回 CloudOrganizationAccountRowData[]

关键函数

  1. parseOrganizationsAndAccountsResponse(response)

    • 解析后端 API 响应
    • 返回 [organizationsData, singleAccountsData]
  2. parseCloudOrganizationAccountsToRows(...)

    • 将组织数据转换为行数据
    • 包含 orgData 的填充

注意事项

  1. 术语混淆:

    • Organization (Upwind) vs CloudOrganization (云提供商)
    • CloudOrganizationAccount (组织视图) vs CloudProviderAccount (系统对象)
  2. 数据来源:

    • CloudOrganizationCloudOrganizationAccount 来自 API 响应,存储在组件 state
    • CloudProviderAccount 存储在 accountsStorage
  3. 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 中查找账户对象
  4. 可选字段:

    • cloudOrganizationIdCloudProviderAccount 中是可选的 (独立账户没有)
    • orgDataCloudOrganizationAccountRowData 中对于独立账户是 null