Control Plane¶
Overview¶
The Control Plane is the multi-tenant management layer for JustIAM. It provides a centralized UI and API for operators to manage tenants, licensing, infrastructure, worker configurations, and agent pools.
The control plane is only used in multi-tenant deployments. Single-tenant deployments are managed directly through the tenant admin UI and docker-compose configuration.
Architecture¶
┌─────────────────────┐
│ Control Plane UI │
│ (React / TypeScript) │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ Control Plane API │
│ (Go) │
└──────────┬──────────┘
│
┌──────────────────────┼──────────────────────┐
│ │ │
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ Tenant A │ │ Tenant B │ │ Tenant C │
│ (backend) │ │ (backend) │ │ (backend) │
└───────────┘ └───────────┘ └───────────┘
Dashboard¶
The control plane dashboard shows a high-level overview of the deployment:
- Total tenants, active users, and license status
- Recent activity and alerts
Tenant management¶
Creating a tenant¶
Navigate to Tenants → New Tenant or use the API:
This creates:
- A new PostgreSQL database for the tenant
- A Kubernetes Secret with the tenant's connection string and JWT secret
- An entry in the tenant registry ConfigMap
Tenant detail¶
Each tenant page provides:
| Section | Operations |
|---|---|
| Overview | Stats (users, groups, apps), status, backend version |
| Admin password | View or reset the initial admin password |
| Database | Connection info, migrations |
| Backups | List backups, trigger a new backup, download |
| Secrets | Rotate JWT secret, login-worker token, proxy token |
| Worker config | Set worker mode (inline/agent), login-worker mode, concurrency limits |
| Bootstrap token | Manage the Terraform bootstrap token |
| CP token | Rotate the control-plane-to-tenant API token |
Deleting a tenant¶
Danger
This drops the tenant's database and removes all associated Kubernetes resources. This action is irreversible.
License management¶
The control plane manages the license for the entire deployment.
Activate a license¶
When activated, the license is fanned out to all tenants automatically.
View license status¶
Returns the current license status, limits, expiry, and per-tenant allocation.
Clear the license¶
Reverts all tenants to free-tier mode.
Per-tenant allocation¶
Allocate a specific user cap to a tenant:
Renewal¶
If the license has a renewal_url, this fetches a replacement license immediately.
See Licensing for the full license lifecycle.
Worker configuration¶
The control plane manages how each tenant executes tasks and login scripts.
Task worker mode¶
| Mode | Description |
|---|---|
inline |
Tasks run in the backend process (default) |
agent |
Tasks dispatched to external gRPC agents |
Task concurrency limit¶
Login worker mode¶
PUT /tenants/:slug/login-worker
Content-Type: application/json
{
"mode": "shared",
"url": "http://login-worker-shared.justiam-mt.svc:8090",
"max_concurrent": 5
}
| Mode | Description |
|---|---|
inline |
Post-render scripts run in the backend process |
shared |
Scripts run in a shared login-worker deployment |
dedicated |
Scripts run in a per-tenant login-worker pod |
Agent pools¶
Agent pools group external task workers. Tenants are assigned to pools, and tasks are dispatched to agents in the assigned pool.
Create a pool¶
POST /pools
Content-Type: application/json
{
"name": "compute-heavy",
"labels": ["gpu", "compute"]
}
Assign a tenant to a pool¶
Shared agent pool¶
The control plane can manage a shared agent pool for tenants that don't need dedicated agents:
- Initialize: Creates the shared pool with HMAC registration
- Scale: Adjust the number of agents
- Rotate key: Rotate the HMAC self-registration key
POST /shared-agent-pool/init
POST /shared-agent-pool/scale
Content-Type: application/json
{
"replicas": 5
}
Infrastructure¶
The Infrastructure page shows the status of all deployed components:
- Backend pods and versions
- Login worker pods (shared and dedicated)
- Agent pools and connected agents
- Database status
Worker version upgrades¶
Settings¶
SMTP¶
Configure the SMTP relay used by all tenants for password reset and notification emails:
PUT /settings/smtp
Content-Type: application/json
{
"host": "smtp.example.com",
"port": 587,
"username": "noreply@example.com",
"password": "smtp-password",
"from": "noreply@example.com"
}
Test SMTP:
Alerts¶
Configure alert rules for operational events:
PUT /settings/alerts
Content-Type: application/json
{
"license_expiring": true,
"capacity_warnings": true,
"daily_reports": true,
"alert_email": "ops@example.com"
}
Audit log¶
The control plane maintains its own audit log, separate from tenant audit logs. It tracks:
- Tenant creation and deletion
- License changes
- Worker configuration changes
- Secret rotations
- Admin actions
Authentication¶
The control plane UI authenticates operators via OIDC:
GET /auth/login— initiates the login flowGET /auth/callback— handles the OIDC callbackPOST /auth/logout— ends the session
API tokens¶
Operators can create API tokens for automation:
POST /me/tokens
Content-Type: application/json
{
"name": "terraform-automation",
"expires_in_days": 90
}
Deployment¶
The control plane is deployed as two separate services:
| Component | Manifest |
|---|---|
| CP Backend | k8s-mt/cp-backend.yaml |
| CP Frontend | k8s-mt/controlplane/ |
Both are deployed in the justiam-mt namespace alongside the main backend and frontend.