224 lines
4.4 KiB
Markdown
224 lines
4.4 KiB
Markdown
|
|
# Tenant Management Guide
|
||
|
|
|
||
|
|
Comprehensive guide for managing multi-tenant operations in Sankofa Phoenix - Superior to Azure.
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
Sankofa Phoenix provides advanced multi-tenancy capabilities that exceed Azure's offerings:
|
||
|
|
|
||
|
|
- **More flexible than Azure**: Custom domains per tenant, cross-tenant resource sharing
|
||
|
|
- **Finer-grained permissions**: Beyond Azure RBAC with JSON-based permissions
|
||
|
|
- **Better isolation**: Database-level RLS policies, network isolation options
|
||
|
|
- **Sovereign identity**: Keycloak-based (no Azure dependencies)
|
||
|
|
|
||
|
|
## Tenant Tiers
|
||
|
|
|
||
|
|
### FREE
|
||
|
|
- Basic resource quotas
|
||
|
|
- Community support
|
||
|
|
- Standard SLA
|
||
|
|
|
||
|
|
### STANDARD
|
||
|
|
- Increased resource quotas
|
||
|
|
- Email support
|
||
|
|
- Enhanced SLA
|
||
|
|
|
||
|
|
### ENTERPRISE
|
||
|
|
- Custom resource quotas
|
||
|
|
- Priority support
|
||
|
|
- Custom SLA
|
||
|
|
- Dedicated resources available
|
||
|
|
|
||
|
|
### SOVEREIGN
|
||
|
|
- Complete isolation
|
||
|
|
- Dedicated infrastructure
|
||
|
|
- Custom compliance requirements
|
||
|
|
- Sovereign data residency
|
||
|
|
|
||
|
|
## Creating Tenants
|
||
|
|
|
||
|
|
### Via GraphQL API
|
||
|
|
|
||
|
|
```graphql
|
||
|
|
mutation {
|
||
|
|
createTenant(input: {
|
||
|
|
name: "acme-corp"
|
||
|
|
domain: "acme.sankofa.nexus"
|
||
|
|
tier: ENTERPRISE
|
||
|
|
quotaLimits: {
|
||
|
|
compute: { vcpu: 100, memory: 512, instances: 50 }
|
||
|
|
storage: { total: 10000, perInstance: 500 }
|
||
|
|
network: { bandwidth: 1000, egress: 5000 }
|
||
|
|
}
|
||
|
|
metadata: {
|
||
|
|
contact: "admin@acme.com"
|
||
|
|
region: "us-west"
|
||
|
|
}
|
||
|
|
}) {
|
||
|
|
id
|
||
|
|
name
|
||
|
|
billingAccountId
|
||
|
|
status
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Via API Service
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { tenantService } from './services/tenant'
|
||
|
|
|
||
|
|
const tenant = await tenantService.createTenant({
|
||
|
|
name: 'acme-corp',
|
||
|
|
domain: 'acme.sankofa.nexus',
|
||
|
|
tier: 'ENTERPRISE',
|
||
|
|
quotaLimits: {
|
||
|
|
compute: { vcpu: 100, memory: 512, instances: 50 },
|
||
|
|
storage: { total: 10000, perInstance: 500 },
|
||
|
|
network: { bandwidth: 1000, egress: 5000 },
|
||
|
|
},
|
||
|
|
})
|
||
|
|
```
|
||
|
|
|
||
|
|
## Managing Tenant Users
|
||
|
|
|
||
|
|
### Adding Users to Tenant
|
||
|
|
|
||
|
|
```graphql
|
||
|
|
mutation {
|
||
|
|
addUserToTenant(
|
||
|
|
tenantId: "tenant-id"
|
||
|
|
userId: "user-id"
|
||
|
|
role: TENANT_ADMIN
|
||
|
|
permissions: {
|
||
|
|
canCreateVMs: true
|
||
|
|
canDeleteVMs: false
|
||
|
|
maxVMs: 10
|
||
|
|
}
|
||
|
|
)
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Tenant Roles
|
||
|
|
|
||
|
|
- **TENANT_OWNER**: Full control over tenant
|
||
|
|
- **TENANT_ADMIN**: Administrative access (more granular than Azure)
|
||
|
|
- **TENANT_USER**: Standard user access
|
||
|
|
- **TENANT_VIEWER**: Read-only access
|
||
|
|
- **TENANT_BILLING_ADMIN**: Billing management access
|
||
|
|
|
||
|
|
## Tenant Quotas
|
||
|
|
|
||
|
|
Quotas are more flexible than Azure:
|
||
|
|
|
||
|
|
```graphql
|
||
|
|
mutation {
|
||
|
|
updateTenantQuotas(
|
||
|
|
tenantId: "tenant-id"
|
||
|
|
quotas: {
|
||
|
|
compute: {
|
||
|
|
vcpu: 200
|
||
|
|
memory: 1024
|
||
|
|
instances: 100
|
||
|
|
}
|
||
|
|
storage: {
|
||
|
|
total: 20000
|
||
|
|
perInstance: 1000
|
||
|
|
}
|
||
|
|
network: {
|
||
|
|
bandwidth: 2000
|
||
|
|
egress: 10000
|
||
|
|
}
|
||
|
|
custom: {
|
||
|
|
gpu: 4
|
||
|
|
specialFeatures: ["ai-inference"]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
) {
|
||
|
|
id
|
||
|
|
quotaLimits
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Custom Domains
|
||
|
|
|
||
|
|
Each tenant can have a custom domain (better than Azure):
|
||
|
|
|
||
|
|
```graphql
|
||
|
|
mutation {
|
||
|
|
updateTenant(
|
||
|
|
id: "tenant-id"
|
||
|
|
input: {
|
||
|
|
domain: "acme.sankofa.nexus"
|
||
|
|
}
|
||
|
|
) {
|
||
|
|
id
|
||
|
|
domain
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Cross-Tenant Resource Sharing
|
||
|
|
|
||
|
|
Share resources across tenants (more flexible than Azure):
|
||
|
|
|
||
|
|
```graphql
|
||
|
|
mutation {
|
||
|
|
shareResourceAcrossTenants(
|
||
|
|
resourceId: "resource-id"
|
||
|
|
targetTenants: ["tenant-1", "tenant-2"]
|
||
|
|
)
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Tenant Status Management
|
||
|
|
|
||
|
|
### Suspend Tenant
|
||
|
|
|
||
|
|
```graphql
|
||
|
|
mutation {
|
||
|
|
suspendTenant(
|
||
|
|
id: "tenant-id"
|
||
|
|
reason: "Payment overdue"
|
||
|
|
)
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Activate Tenant
|
||
|
|
|
||
|
|
```graphql
|
||
|
|
mutation {
|
||
|
|
activateTenant(id: "tenant-id")
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Keycloak Integration
|
||
|
|
|
||
|
|
Each tenant can have its own Keycloak realm for complete isolation:
|
||
|
|
|
||
|
|
1. Set `KEYCLOAK_MULTI_REALM=true`
|
||
|
|
2. Realm is automatically created when tenant is created
|
||
|
|
3. Users authenticate to tenant-specific realm
|
||
|
|
4. Complete isolation between tenants
|
||
|
|
|
||
|
|
## Best Practices
|
||
|
|
|
||
|
|
1. **Use appropriate tier**: Match tier to tenant needs
|
||
|
|
2. **Set realistic quotas**: Prevent resource exhaustion
|
||
|
|
3. **Monitor usage**: Use billing alerts to track spending
|
||
|
|
4. **Regular audits**: Review tenant access and permissions
|
||
|
|
5. **Backup policies**: Configure per-tenant backup policies
|
||
|
|
|
||
|
|
## Comparison to Azure
|
||
|
|
|
||
|
|
| Feature | Azure | Sankofa Phoenix |
|
||
|
|
|---------|-------|-----------------|
|
||
|
|
| Custom Domains | Limited | Full support per tenant |
|
||
|
|
| Permissions | RBAC only | RBAC + JSON permissions |
|
||
|
|
| Resource Sharing | Limited | Cross-tenant sharing |
|
||
|
|
| Billing Granularity | Hourly | Per-second |
|
||
|
|
| Identity | Azure AD only | Keycloak (sovereign) |
|
||
|
|
| Isolation | Logical | Logical + optional physical |
|
||
|
|
|