Tenant Isolation
Tenant isolation network policies ensure that workloads running in different tenant namespaces cannot communicate with each other. This is a critical security boundary in the MATIH multi-tenant architecture, preventing data leakage and unauthorized access between tenant environments.
Isolation Model
The MATIH platform supports two tenant isolation levels:
| Level | Network Isolation | Compute Isolation | Data Isolation |
|---|---|---|---|
| Namespace-isolated | NetworkPolicy per namespace | Shared nodes, resource quotas | Separate databases/schemas |
| Dedicated | NetworkPolicy + dedicated nodes | Dedicated node pool | Dedicated database instances |
Default Deny Policy
Each tenant namespace starts with a default deny-all policy:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: tenant-acme
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress: []
egress: []This ensures that no traffic flows to or from the tenant namespace until explicit allow rules are created.
Tenant-to-Shared-Service Access
Tenant workloads can access shared platform services through explicit egress rules:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-shared-services
namespace: tenant-acme
spec:
podSelector: {}
policyTypes:
- Egress
egress:
# DNS
- to:
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
# API Gateway
- to:
- namespaceSelector:
matchLabels:
name: matih-system
podSelector:
matchLabels:
app: api-gateway
ports:
- protocol: TCP
port: 8080
# AI Service
- to:
- namespaceSelector:
matchLabels:
name: matih-data-plane
podSelector:
matchLabels:
app: ai-service
ports:
- protocol: TCP
port: 8000Cross-Tenant Denial
The critical isolation rule prevents any tenant from reaching another tenant namespace:
| Source | Destination | Allowed |
|---|---|---|
| tenant-acme | tenant-acme | Yes (intra-namespace) |
| tenant-acme | tenant-beta | No (blocked) |
| tenant-acme | matih-system | Limited (API Gateway only) |
| tenant-acme | matih-data-plane | Limited (shared services only) |
| tenant-acme | matih-monitoring | No |
| matih-data-plane | tenant-acme | Limited (ingress controller only) |
Ingress to Tenant Services
Tenant-specific services receive traffic only through the dedicated tenant ingress controller:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-tenant-ingress
namespace: tenant-acme
spec:
podSelector:
matchLabels:
app: tenant-frontend
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: tenant-acme
podSelector:
matchLabels:
app: ingress-nginx
ports:
- protocol: TCP
port: 3000Label Requirements
Tenant isolation depends on correct namespace labels:
| Label | Purpose | Example |
|---|---|---|
name | Namespace name reference | name: tenant-acme |
matih.io/tenant-id | Tenant identifier | matih.io/tenant-id: acme |
matih.io/namespace-type | Namespace category | matih.io/namespace-type: tenant |
matih.io/isolation-level | Isolation tier | matih.io/isolation-level: namespace |
Provisioning Integration
Network policies are created automatically during tenant provisioning:
- Tenant Service creates the namespace with required labels
- Default deny policy is applied
- Shared service egress rules are created
- Tenant ingress policy is created
- Connectivity is validated
Verification
Tenant isolation can be verified using the validation script:
./scripts/tools/validate-tenant-ingress.sh --tenant acmeTroubleshooting
| Issue | Symptom | Resolution |
|---|---|---|
| Tenant cannot access AI service | Connection timeout | Verify egress rule to matih-data-plane |
| Cross-tenant data leak | Unauthorized namespace access | Check default-deny policy exists |
| Missing namespace labels | Policies not matching | Verify namespace labels with expected values |
| Ingress not working | Tenant frontend unreachable | Check ingress controller pod labels |