prvng_platform/provisioning-server
2025-10-07 10:59:52 +01:00
..
2025-10-07 10:59:52 +01:00
2025-10-07 10:59:52 +01:00
2025-10-07 10:59:52 +01:00
2025-10-07 10:59:52 +01:00
2025-10-07 10:59:52 +01:00
2025-10-07 10:59:52 +01:00
2025-10-07 10:59:52 +01:00
2025-10-07 10:59:52 +01:00
2025-10-07 10:59:52 +01:00
2025-10-07 10:59:52 +01:00
2025-10-07 10:59:52 +01:00

Provisioning API Server

A comprehensive REST API server for remote provisioning operations, enabling thin clients and CI/CD pipeline integration.

Features

  • Comprehensive REST API: Complete provisioning operations via HTTP
  • JWT Authentication: Secure token-based authentication
  • RBAC System: Role-based access control (Admin, Operator, Developer, Viewer)
  • Async Operations: Long-running tasks with status tracking
  • Nushell Integration: Direct execution of provisioning CLI commands
  • Audit Logging: Complete operation tracking for compliance
  • Metrics: Prometheus-compatible metrics endpoint
  • CORS Support: Configurable cross-origin resource sharing
  • Health Checks: Built-in health and readiness endpoints

Architecture

┌─────────────────┐
│  REST Client    │
│  (curl, CI/CD)  │
└────────┬────────┘
         │ HTTPS/JWT
         ▼
┌─────────────────┐
│  API Gateway    │
│  - Routes       │
│  - Auth         │
│  - RBAC         │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ Async Task Mgr  │
│ - Queue         │
│ - Status        │
└────────┬────────┘
         │
         ▼
┌─────────────────┐
│ Nushell Exec    │
│ - CLI wrapper   │
│ - Timeout       │
└─────────────────┘

Installation

Building from Source

cd provisioning/platform/provisioning-server
cargo build --release

The binary will be at target/release/provisioning-server.

Using Docker

# Build image
docker build -t provisioning-server .

# Run container
docker run -d \
  -p 8083:8083 \
  -e JWT_SECRET="your-secret-here" \
  -e PROVISIONING_CLI_PATH="/usr/local/bin/provisioning" \
  provisioning-server

Using Docker Compose

# Start server
docker-compose up -d

# View logs
docker-compose logs -f

# Stop server
docker-compose down

Configuration

Configuration File

Create config.toml:

[server]
host = "0.0.0.0"
port = 8083
cors_enabled = true

[auth]
jwt_secret = "your-secret-key-here"
token_expiry_hours = 24
refresh_token_expiry_hours = 168

[provisioning]
cli_path = "/usr/local/bin/provisioning"
timeout_seconds = 300
max_concurrent_operations = 10

[logging]
level = "info"
json_format = false

Environment Variables

Alternatively, use environment variables:

export SERVER_HOST=0.0.0.0
export SERVER_PORT=8083
export JWT_SECRET="your-secret-key"
export PROVISIONING_CLI_PATH="/usr/local/bin/provisioning"
export LOG_LEVEL=info

See .env.example for all available variables.

Usage

Starting the Server

# Using config file
provisioning-server --config config.toml

# Using environment variables
provisioning-server

# Custom settings
provisioning-server \
  --host 0.0.0.0 \
  --port 8083 \
  --jwt-secret "my-secret" \
  --cli-path "/usr/local/bin/provisioning" \
  --log-level debug

Authentication

Login

curl -X POST http://localhost:8083/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "username": "admin",
    "password": "admin123"
  }'

Response:

{
  "token": "eyJhbGc...",
  "refresh_token": "eyJhbGc...",
  "expires_in": 86400
}

Using Token

Include the token in subsequent requests:

export TOKEN="eyJhbGc..."

curl -X GET http://localhost:8083/v1/servers \
  -H "Authorization: Bearer $TOKEN"

Refresh Token

curl -X POST http://localhost:8083/v1/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{
    "refresh_token": "eyJhbGc..."
  }'

Default Users

Username Password Role
admin admin123 admin
operator operator123 operator
developer dev123 developer

⚠️ IMPORTANT: Change these credentials in production!

API Endpoints

Authentication

  • POST /v1/auth/login - User login
  • POST /v1/auth/refresh - Refresh access token

Servers

  • GET /v1/servers - List all servers
  • POST /v1/servers/create - Create new server
  • DELETE /v1/servers/{id} - Delete server
  • GET /v1/servers/{id}/status - Get server status

Create Server Example

curl -X POST http://localhost:8083/v1/servers/create \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "workspace": "production",
    "provider": "upcloud",
    "plan": "2xCPU-4GB",
    "hostname": "web-01",
    "zone": "de-fra1",
    "check_mode": false,
    "tags": ["web", "production"]
  }'

Response:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "pending",
  "created_at": "2025-10-06T12:00:00Z",
  "updated_at": "2025-10-06T12:00:00Z",
  "result": null,
  "error": null
}

Taskservs

  • GET /v1/taskservs - List all taskservs
  • POST /v1/taskservs/create - Create taskserv
  • DELETE /v1/taskservs/{id} - Delete taskserv
  • GET /v1/taskservs/{id}/status - Get taskserv status

Create Taskserv Example

curl -X POST http://localhost:8083/v1/taskservs/create \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "workspace": "production",
    "name": "kubernetes",
    "servers": ["web-01", "web-02"],
    "check_mode": false
  }'

Workflows

  • POST /v1/workflows/submit - Submit workflow
  • GET /v1/workflows/{id} - Get workflow details
  • GET /v1/workflows/{id}/status - Get workflow status
  • POST /v1/workflows/{id}/cancel - Cancel workflow

Submit Workflow Example

curl -X POST http://localhost:8083/v1/workflows/submit \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "workspace": "production",
    "workflow_type": "cluster_create",
    "parameters": {
      "cluster_name": "k8s-prod",
      "node_count": 3
    }
  }'

Operations

  • GET /v1/operations - List all operations
  • GET /v1/operations/{id} - Get operation status
  • POST /v1/operations/{id}/cancel - Cancel operation

Check Operation Status

curl -X GET http://localhost:8083/v1/operations/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer $TOKEN"

Response:

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "created_at": "2025-10-06T12:00:00Z",
  "updated_at": "2025-10-06T12:05:00Z",
  "result": {
    "server_id": "srv-abc123",
    "ip_address": "10.0.0.1"
  },
  "error": null
}

Workspaces

  • GET /v1/workspaces - List workspaces
  • POST /v1/workspaces/create - Create workspace
  • GET /v1/workspaces/{name} - Get workspace details

System

  • GET /health - Health check (no auth required)
  • GET /v1/version - Version information
  • GET /v1/metrics - Prometheus metrics (requires auth)

RBAC Permissions

Admin Role

Full system access including:

  • All server operations
  • All taskserv operations
  • All cluster operations
  • Workspace management
  • Workflow management
  • System administration
  • Audit log access

Operator Role

Infrastructure operations:

  • Create/delete/read servers
  • Create/delete/read taskservs
  • Create/delete/read clusters
  • Submit/cancel workflows
  • View operations

Developer Role

Read access plus SSH:

  • Read servers/taskservs/clusters
  • SSH to servers
  • View workflows
  • View operations

Viewer Role

Read-only access:

  • List all resources
  • View status
  • System health checks

Security Best Practices

Production Deployment

  1. Change Default Credentials: Update all default usernames/passwords
  2. Use Strong JWT Secret: Generate a secure random string (32+ characters)
  3. Enable TLS: Use HTTPS in production
  4. Restrict CORS: Configure specific allowed origins
  5. Enable mTLS: For client certificate authentication
  6. Regular Token Rotation: Implement token refresh strategy
  7. Audit Logging: Enable audit logs for compliance

JWT Secret Generation

# Generate secure random secret
openssl rand -base64 32

TLS Configuration

[server]
tls_cert = "/path/to/cert.pem"
tls_key = "/path/to/key.pem"

mTLS Configuration

[auth]
mtls_enabled = true
mtls_ca_cert = "/path/to/ca.pem"

Monitoring

Health Check

curl http://localhost:8083/health

Response:

{
  "status": "healthy",
  "version": "0.1.0",
  "uptime_seconds": 3600
}

Metrics

curl http://localhost:8083/v1/metrics \
  -H "Authorization: Bearer $TOKEN"

Response:

{
  "uptime_seconds": 3600,
  "tasks": {
    "total": 42,
    "running": 3
  }
}

Development

Running Tests

cargo test

Running with Debug Logging

RUST_LOG=debug provisioning-server

Code Structure

src/
├── main.rs              # Application entry point
├── lib.rs               # Library exports
├── config.rs            # Configuration management
├── error.rs             # Error types
├── models/              # Request/response models
├── auth/                # Authentication & authorization
│   ├── jwt.rs           # JWT token handling
│   ├── rbac.rs          # Role-based access control
│   └── mod.rs           # Auth module exports
├── executor/            # Command execution
│   ├── nushell.rs       # Nushell CLI wrapper
│   ├── async_task.rs    # Async task manager
│   └── mod.rs           # Executor exports
└── api/                 # API endpoints
    ├── routes.rs        # Route definitions
    ├── servers.rs       # Server endpoints
    ├── taskservs.rs     # Taskserv endpoints
    ├── workflows.rs     # Workflow endpoints
    ├── operations.rs    # Operation endpoints
    ├── workspaces.rs    # Workspace endpoints
    ├── auth.rs          # Auth endpoints
    ├── system.rs        # System endpoints
    └── mod.rs           # API module exports

CI/CD Integration

GitHub Actions Example

name: Deploy Infrastructure

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Login
        run: |
          TOKEN=$(curl -X POST https://api.example.com/v1/auth/login \
            -H "Content-Type: application/json" \
            -d '{"username":"${{ secrets.API_USER }}","password":"${{ secrets.API_PASS }}"}' \
            | jq -r '.token')
          echo "TOKEN=$TOKEN" >> $GITHUB_ENV

      - name: Create Server
        run: |
          curl -X POST https://api.example.com/v1/servers/create \
            -H "Authorization: Bearer $TOKEN" \
            -H "Content-Type: application/json" \
            -d '{
              "workspace": "production",
              "provider": "upcloud",
              "plan": "2xCPU-4GB",
              "hostname": "web-${{ github.run_number }}"
            }'

GitLab CI Example

deploy:
  stage: deploy
  script:
    - |
      TOKEN=$(curl -X POST $API_URL/v1/auth/login \
        -H "Content-Type: application/json" \
        -d "{\"username\":\"$API_USER\",\"password\":\"$API_PASS\"}" \
        | jq -r '.token')
    - |
      curl -X POST $API_URL/v1/workflows/submit \
        -H "Authorization: Bearer $TOKEN" \
        -H "Content-Type: application/json" \
        -d @workflow.json
  only:
    - main

Troubleshooting

Common Issues

Authentication Failed

  • Check JWT secret configuration
  • Verify username/password
  • Check token expiration

Operation Timeout

  • Increase timeout_seconds in config
  • Check provisioning CLI accessibility
  • Verify network connectivity

Permission Denied

  • Check user role assignments
  • Verify RBAC permissions
  • Review audit logs

Server Not Starting

  • Check port availability
  • Verify configuration file
  • Check log output

Debug Mode

Enable detailed logging:

RUST_LOG=debug provisioning-server --log-level debug

License

See project root LICENSE file.

Support

For issues and questions:

  • Check documentation: /docs
  • Review API reference: /v1/health
  • Contact: infrastructure team