# Tenant Network Model Design

**Date:** 2025-12-08  
**Task:** T015 S2  
**Status:** Design Complete

## 1. Overview

PlasmaVMCのマルチテナントネットワーク分離モデル。OVNを基盤として、組織（org）とプロジェクト（project）の2階層でネットワークを分離する。

## 2. Tenant Hierarchy

```
Organization (org_id)
  └── Project (project_id)
       └── VPC (Virtual Private Cloud)
            └── Subnet(s)
                 └── VM Port(s)
```

### 2.1 Organization Level
- **目的**: 企業/組織レベルの分離
- **ネットワーク分離**: 完全に分離（デフォルトでは通信不可）
- **用途**: マルチテナント環境での組織間分離

### 2.2 Project Level
- **目的**: プロジェクト/アプリケーションレベルの分離
- **ネットワーク分離**: プロジェクトごとに独立したVPC
- **用途**: 同一組織内の異なるプロジェクト間の分離

## 3. VPC (Virtual Private Cloud) Model

### 3.1 VPC per Project

各プロジェクトは1つのVPCを持つ（1:1関係）。

**VPC識別子:**
```
vpc_id = "{org_id}/{project_id}"
```

**OVNマッピング:**
- OVN Logical Router: プロジェクトVPCのルーター
- OVN Logical Switches: VPC内のサブネット（複数可）

### 3.2 VPC CIDR Allocation

**戦略**: プロジェクト作成時に自動割り当て

**CIDRプール:**
- デフォルト: `10.0.0.0/8` を分割
- プロジェクトごと: `/16` サブネット（65,536 IP）
- 例: 
  - Project 1: `10.1.0.0/16`
  - Project 2: `10.2.0.0/16`
  - Project 3: `10.3.0.0/16`

**割り当て方法:**
1. プロジェクト作成時に未使用の`/16`を割り当て
2. ChainFireに割り当て状態を保存
3. プロジェクト削除時にCIDRを解放

**CIDR管理キー（ChainFire）:**
```
/networks/cidr/allocations/{org_id}/{project_id} = "10.X.0.0/16"
/networks/cidr/pool/used = ["10.1.0.0/16", "10.2.0.0/16", ...]
```

## 4. Subnet Model

### 4.1 Subnet per VPC

各VPCは1つ以上のサブネットを持つ。

**サブネット識別子:**
```
subnet_id = "{org_id}/{project_id}/{subnet_name}"
```

**デフォルトサブネット:**
- プロジェクト作成時に自動作成
- 名前: `default`
- CIDR: VPC CIDR内の`/24`（256 IP）
- 例: VPC `10.1.0.0/16` → サブネット `10.1.0.0/24`

**追加サブネット:**
- ユーザーが作成可能
- VPC CIDR内で任意の`/24`を割り当て
- 例: `10.1.1.0/24`, `10.1.2.0/24`

**OVNマッピング:**
- OVN Logical Switch: 各サブネット

### 4.2 Subnet Attributes

```rust
pub struct Subnet {
    pub id: String,              // "{org_id}/{project_id}/{subnet_name}"
    pub org_id: String,
    pub project_id: String,
    pub name: String,
    pub cidr: String,            // "10.1.0.0/24"
    pub gateway_ip: String,      // "10.1.0.1"
    pub dns_servers: Vec<String>, // ["8.8.8.8", "8.8.4.4"]
    pub dhcp_enabled: bool,
    pub created_at: u64,
}
```

## 5. Network Isolation

### 5.1 Inter-Tenant Isolation

**組織間:**
- デフォルト: 完全に分離（通信不可）
- 例外: 明示的なピアリング設定が必要

**プロジェクト間（同一組織）:**
- デフォルト: 分離（通信不可）
- 例外: VPCピアリングまたは共有ネットワークで接続可能

### 5.2 Intra-Tenant Communication

**同一プロジェクト内:**
- 同一サブネット: L2通信（直接）
- 異なるサブネット: L3ルーティング（Logical Router経由）

**OVN実装:**
- Logical Switch内: L2 forwarding（MACアドレスベース）
- Logical Router: L3 forwarding（IPアドレスベース）

## 6. IP Address Management (IPAM)

### 6.1 IP Allocation Strategy

**VM作成時のIP割り当て:**

1. **自動割り当て（DHCP）**: デフォルト
   - サブネット内の未使用IPを自動選択
   - DHCPサーバー（OVN統合）がIPを割り当て

2. **静的割り当て**: オプション
   - ユーザー指定のIPアドレス
   - サブネットCIDR内である必要がある
   - 重複チェックが必要

**IP割り当てキー（ChainFire）:**
```
/networks/ipam/{org_id}/{project_id}/{subnet_name}/allocated = ["10.1.0.10", "10.1.0.11", ...]
/networks/ipam/{org_id}/{project_id}/{subnet_name}/reserved = ["10.1.0.1", "10.1.0.254"] // gateway, broadcast
```

### 6.2 DHCP Configuration

**OVN DHCP Options:**

```rust
pub struct DhcpOptions {
    pub subnet_id: String,
    pub gateway_ip: String,
    pub dns_servers: Vec<String>,
    pub domain_name: Option<String>,
    pub ntp_servers: Vec<String>,
    pub lease_time: u32, // seconds
}
```

**OVN実装:**
- OVN Logical SwitchにDHCP Optionsを設定
- OVNがDHCPサーバーとして機能
- VMはDHCP経由でIP、ゲートウェイ、DNSを取得

## 7. Security Groups

### 7.1 Security Group Model

**セキュリティグループ識別子:**
```
sg_id = "{org_id}/{project_id}/{sg_name}"
```

**デフォルトセキュリティグループ:**
- プロジェクト作成時に自動作成
- 名前: `default`
- ルール: 
  - Ingress: 同一セキュリティグループ内からの全トラフィック許可
  - Egress: 全トラフィック許可

**セキュリティグループ構造:**
```rust
pub struct SecurityGroup {
    pub id: String,              // "{org_id}/{project_id}/{sg_name}"
    pub org_id: String,
    pub project_id: String,
    pub name: String,
    pub description: String,
    pub ingress_rules: Vec<SecurityRule>,
    pub egress_rules: Vec<SecurityRule>,
    pub created_at: u64,
}

pub struct SecurityRule {
    pub protocol: Protocol,      // TCP, UDP, ICMP, etc.
    pub port_range: Option<(u16, u16)>, // (min, max) or None for all
    pub source_type: SourceType,
    pub source: String,          // CIDR or security_group_id
}

pub enum Protocol {
    Tcp,
    Udp,
    Icmp,
    All,
}

pub enum SourceType {
    Cidr,           // "10.1.0.0/24"
    SecurityGroup,  // "{org_id}/{project_id}/{sg_name}"
}
```

### 7.2 OVN ACL Implementation

**OVN ACL (Access Control List):**
- Logical Switch PortにACLを適用
- 方向: `from-lport` (egress), `to-lport` (ingress)
- アクション: `allow`, `drop`, `reject`

**ACL例:**
```
# Ingress rule: Allow TCP port 80 from security group "web"
from-lport 1000 "tcp && tcp.dst == 80 && ip4.src == $sg_web" allow-related

# Egress rule: Allow all
to-lport 1000 "1" allow
```

## 8. NAT (Network Address Translation)

### 8.1 SNAT (Source NAT)

**目的**: プライベートIPから外部（インターネット）への通信

**実装:**
- OVN Logical RouterにSNATルールを設定
- プロジェクトVPCの全トラフィックを外部IPに変換

**設定:**
```rust
pub struct SnatConfig {
    pub vpc_id: String,
    pub external_ip: String,    // 外部IPアドレス
    pub enabled: bool,
}
```

**OVN実装:**
- Logical RouterにSNATルールを追加
- `ovn-nbctl lr-nat-add <router> snat <external_ip> <internal_cidr>`

### 8.2 DNAT (Destination NAT)

**目的**: 外部から特定VMへの通信（ポートフォワーディング）

**実装:**
- OVN Logical RouterにDNATルールを設定
- 外部IP:ポート → 内部IP:ポートのマッピング

**設定:**
```rust
pub struct DnatConfig {
    pub vpc_id: String,
    pub external_ip: String,
    pub external_port: u16,
    pub internal_ip: String,
    pub internal_port: u16,
    pub protocol: Protocol,      // TCP or UDP
}
```

**OVN実装:**
- `ovn-nbctl lr-nat-add <router> dnat <external_ip> <internal_ip>`

## 9. Network Policies

### 9.1 Network Policy Model

**ネットワークポリシー:**
- セキュリティグループより細かい制御
- プロジェクト/サブネットレベルでのポリシー

**ポリシータイプ:**
1. **Ingress Policy**: 受信トラフィック制御
2. **Egress Policy**: 送信トラフィック制御
3. **Isolation Policy**: ネットワーク間の分離設定

**実装:**
- OVN ACLで実現
- セキュリティグループと組み合わせて適用

## 10. API Sketch

### 10.1 Network Service API

```protobuf
service NetworkService {
  // VPC operations
  rpc CreateVpc(CreateVpcRequest) returns (Vpc);
  rpc GetVpc(GetVpcRequest) returns (Vpc);
  rpc ListVpcs(ListVpcsRequest) returns (ListVpcsResponse);
  rpc DeleteVpc(DeleteVpcRequest) returns (Empty);

  // Subnet operations
  rpc CreateSubnet(CreateSubnetRequest) returns (Subnet);
  rpc GetSubnet(GetSubnetRequest) returns (Subnet);
  rpc ListSubnets(ListSubnetsRequest) returns (ListSubnetsResponse);
  rpc DeleteSubnet(DeleteSubnetRequest) returns (Empty);

  // Port operations (VM NIC attachment)
  rpc CreatePort(CreatePortRequest) returns (Port);
  rpc GetPort(GetPortRequest) returns (Port);
  rpc ListPorts(ListPortsRequest) returns (ListPortsResponse);
  rpc DeletePort(DeletePortRequest) returns (Empty);
  rpc AttachPort(AttachPortRequest) returns (Port);
  rpc DetachPort(DetachPortRequest) returns (Empty);

  // Security Group operations
  rpc CreateSecurityGroup(CreateSecurityGroupRequest) returns (SecurityGroup);
  rpc GetSecurityGroup(GetSecurityGroupRequest) returns (SecurityGroup);
  rpc ListSecurityGroups(ListSecurityGroupsRequest) returns (ListSecurityGroupsResponse);
  rpc UpdateSecurityGroup(UpdateSecurityGroupRequest) returns (SecurityGroup);
  rpc DeleteSecurityGroup(DeleteSecurityGroupRequest) returns (Empty);

  // NAT operations
  rpc CreateSnat(CreateSnatRequest) returns (SnatConfig);
  rpc DeleteSnat(DeleteSnatRequest) returns (Empty);
  rpc CreateDnat(CreateDnatRequest) returns (DnatConfig);
  rpc DeleteDnat(DeleteDnatRequest) returns (Empty);
}
```

### 10.2 Key Request/Response Types

```protobuf
message CreateVpcRequest {
  string org_id = 1;
  string project_id = 2;
  string name = 3;
  string cidr = 4;  // Optional, auto-allocated if not specified
}

message CreateSubnetRequest {
  string org_id = 1;
  string project_id = 2;
  string vpc_id = 3;
  string name = 4;
  string cidr = 5;  // Must be within VPC CIDR
  bool dhcp_enabled = 6;
  repeated string dns_servers = 7;
}

message CreatePortRequest {
  string org_id = 1;
  string project_id = 2;
  string subnet_id = 3;
  string vm_id = 4;
  string mac_address = 5;  // Optional, auto-generated if not specified
  string ip_address = 6;   // Optional, DHCP if not specified
  repeated string security_group_ids = 7;
}

message CreateSecurityGroupRequest {
  string org_id = 1;
  string project_id = 2;
  string name = 3;
  string description = 4;
  repeated SecurityRule ingress_rules = 5;
  repeated SecurityRule egress_rules = 6;
}
```

### 10.3 Integration with PlasmaVMC VmService

**VM作成時のネットワーク設定:**

```rust
// VmSpecにネットワーク情報を追加（既存のNetworkSpecを拡張）
pub struct NetworkSpec {
    pub id: String,
    pub network_id: String,        // subnet_id: "{org_id}/{project_id}/{subnet_name}"
    pub mac_address: Option<String>,
    pub ip_address: Option<String>, // None = DHCP
    pub model: NicModel,
    pub security_groups: Vec<String>, // security_group_ids
}

// VM作成フロー
1. VmService.create_vm() が呼ばれる
2. NetworkService.create_port() でOVN Logical Portを作成
3. OVNがIPアドレスを割り当て（DHCPまたは静的）
4. セキュリティグループをポートに適用
5. VMのNICにポートをアタッチ（TAPインターフェース経由）
```

## 11. Data Flow

### 11.1 VM Creation Flow

```
1. User → VmService.create_vm()
   └── NetworkSpec: {network_id: "org1/proj1/default", security_groups: ["sg1"]}

2. VmService → NetworkService.create_port()
   └── Creates OVN Logical Port
   └── Allocates IP address (DHCP or static)
   └── Applies security groups (OVN ACLs)

3. VmService → HypervisorBackend.create()
   └── Creates TAP interface
   └── Attaches to OVN port

4. OVN → Updates Logical Switch
   └── Port appears in Logical Switch
   └── DHCP server ready to serve IP
```

### 11.2 Packet Flow (Intra-Subnet)

```
VM1 (10.1.0.10) → VM2 (10.1.0.11)

1. VM1 sends packet to 10.1.0.11
2. TAP interface → OVS bridge
3. OVS → OVN Logical Switch (L2 forwarding)
4. OVN ACL check (security groups)
5. Packet forwarded to VM2's TAP interface
6. VM2 receives packet
```

### 11.3 Packet Flow (Inter-Subnet)

```
VM1 (10.1.0.10) → VM2 (10.1.1.10)

1. VM1 sends packet to 10.1.1.10
2. TAP interface → OVS bridge
3. OVS → OVN Logical Switch (L2, no match)
4. OVN → Logical Router (L3 forwarding)
5. Logical Router → Destination Logical Switch
6. OVN ACL check
7. Packet forwarded to VM2's TAP interface
8. VM2 receives packet
```

## 12. Storage Schema

### 12.1 ChainFire Keys

```
# VPC
/networks/vpcs/{org_id}/{project_id} = Vpc (JSON)

# Subnet
/networks/subnets/{org_id}/{project_id}/{subnet_name} = Subnet (JSON)

# Port
/networks/ports/{org_id}/{project_id}/{port_id} = Port (JSON)

# Security Group
/networks/security_groups/{org_id}/{project_id}/{sg_name} = SecurityGroup (JSON)

# IPAM
/networks/ipam/{org_id}/{project_id}/{subnet_name}/allocated = ["10.1.0.10", ...] (JSON)

# CIDR Allocation
/networks/cidr/allocations/{org_id}/{project_id} = "10.1.0.0/16" (string)
```

## 13. Security Considerations

### 13.1 Tenant Isolation

- **L2分離**: Logical Switchごとに完全分離
- **L3分離**: Logical Routerでルーティング制御
- **ACL強制**: OVN ACLでセキュリティグループを強制

### 13.2 IP Spoofing Prevention

- OVNが送信元IPアドレスの検証を実施
- ポートに割り当てられたIP以外からの送信をブロック

### 13.3 ARP Spoofing Prevention

- OVNがARPテーブルを管理
- 不正なARP応答をブロック

## 14. Future Enhancements

1. **VPC Peering**: プロジェクト間のVPC接続
2. **VPN Gateway**: サイト間VPN接続
3. **Load Balancer Integration**: FiberLBとの統合
4. **Network Monitoring**: トラフィック分析と可観測性
5. **QoS Policies**: 帯域幅制限と優先度制御
