320 lines
7.1 KiB
Markdown
320 lines
7.1 KiB
Markdown
|
|
# Proxmox API Token Management
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
This document describes the management of Proxmox API tokens for the Crossplane provider. API tokens provide secure, programmatic access to Proxmox clusters without requiring password authentication.
|
||
|
|
|
||
|
|
## Token Architecture
|
||
|
|
|
||
|
|
### Token Structure
|
||
|
|
|
||
|
|
Proxmox API tokens follow the format:
|
||
|
|
```
|
||
|
|
{username}@{realm}!{token-id}={token-secret}
|
||
|
|
```
|
||
|
|
|
||
|
|
Example:
|
||
|
|
```
|
||
|
|
root@pam!crossplane-instance-1=abc123-def456-ghi789
|
||
|
|
```
|
||
|
|
|
||
|
|
### Token Components
|
||
|
|
|
||
|
|
- **Username**: User account (e.g., `root`, `service-account`)
|
||
|
|
- **Realm**: Authentication realm (e.g., `pam`, `ldap`)
|
||
|
|
- **Token ID**: Unique identifier for the token
|
||
|
|
- **Token Secret**: Secret value (never log or expose)
|
||
|
|
|
||
|
|
## Token Creation
|
||
|
|
|
||
|
|
### Via Proxmox Web UI
|
||
|
|
|
||
|
|
1. **Navigate to**: Datacenter → Permissions → API Tokens
|
||
|
|
2. **Click**: "Add" → "API Token"
|
||
|
|
3. **Configure**:
|
||
|
|
- **Token ID**: `crossplane-instance-1`
|
||
|
|
- **User**: `root@pam` (or dedicated service account)
|
||
|
|
- **Comment**: "Crossplane provider for Instance 1"
|
||
|
|
- **Expiration**: Set expiration date (recommended)
|
||
|
|
- **Privilege Separation**: Enable if using dedicated user
|
||
|
|
4. **Save** and copy the token secret immediately
|
||
|
|
|
||
|
|
### Via Proxmox CLI
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Create token via pvesh
|
||
|
|
pvesh create /access/users/{user}/token/{token-id} \
|
||
|
|
--privsep 1 \
|
||
|
|
--expire {timestamp} \
|
||
|
|
--comment "Crossplane provider token"
|
||
|
|
```
|
||
|
|
|
||
|
|
### Via Proxmox API
|
||
|
|
|
||
|
|
```bash
|
||
|
|
curl -X POST "https://ml110-01.sankofa.nexus:8006/api2/json/access/users/root@pam/token/crossplane-instance-1" \
|
||
|
|
-H "Authorization: PVEAPIToken root@pam!existing-token=secret" \
|
||
|
|
-d 'privsep=1&expire=1735689600&comment=Crossplane provider'
|
||
|
|
```
|
||
|
|
|
||
|
|
## Token Permissions
|
||
|
|
|
||
|
|
### Principle of Least Privilege
|
||
|
|
|
||
|
|
Tokens should have **minimum required permissions**:
|
||
|
|
|
||
|
|
#### Recommended Permissions
|
||
|
|
|
||
|
|
**For VM Management**:
|
||
|
|
- `VM.Allocate` - Create VMs
|
||
|
|
- `VM.Clone` - Clone VMs
|
||
|
|
- `VM.Config.Disk` - Manage VM disks
|
||
|
|
- `VM.Config.Network` - Manage VM networks
|
||
|
|
- `VM.Monitor` - Monitor VM status
|
||
|
|
- `VM.PowerMgmt` - Start/stop VMs
|
||
|
|
- `VM.Snapshot` - Create snapshots
|
||
|
|
|
||
|
|
**For Storage Management**:
|
||
|
|
- `Datastore.Allocate` - Allocate storage
|
||
|
|
- `Datastore.Audit` - Audit storage
|
||
|
|
|
||
|
|
**For Node Management**:
|
||
|
|
- `Sys.Audit` - System audit
|
||
|
|
- `Sys.Modify` - System modification (if needed)
|
||
|
|
|
||
|
|
#### Full Administrator (Not Recommended)
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
# ⚠️ Only for development/testing
|
||
|
|
Permissions: Administrator
|
||
|
|
```
|
||
|
|
|
||
|
|
**Risks**:
|
||
|
|
- Full cluster access
|
||
|
|
- Can delete critical resources
|
||
|
|
- Security risk if compromised
|
||
|
|
|
||
|
|
### Permission Configuration
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Set token permissions via pvesh
|
||
|
|
pvesh set /access/acl \
|
||
|
|
--path / \
|
||
|
|
--roles Administrator \
|
||
|
|
--users root@pam!crossplane-instance-1
|
||
|
|
```
|
||
|
|
|
||
|
|
## Token Storage
|
||
|
|
|
||
|
|
### Kubernetes Secrets
|
||
|
|
|
||
|
|
**Never store tokens in code or config files!**
|
||
|
|
|
||
|
|
Store tokens in Kubernetes secrets:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Create secret with token
|
||
|
|
kubectl create secret generic proxmox-credentials \
|
||
|
|
--from-literal=credentials.json='{"username":"root@pam","token":"root@pam!crossplane-instance-1=abc123..."}' \
|
||
|
|
-n crossplane-system
|
||
|
|
```
|
||
|
|
|
||
|
|
### Secret Structure
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"username": "root@pam",
|
||
|
|
"token": "root@pam!crossplane-instance-1=abc123-def456-ghi789"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### ProviderConfig Reference
|
||
|
|
|
||
|
|
```yaml
|
||
|
|
apiVersion: proxmox.sankofa.nexus/v1alpha1
|
||
|
|
kind: ProviderConfig
|
||
|
|
metadata:
|
||
|
|
name: proxmox-provider-config
|
||
|
|
spec:
|
||
|
|
credentials:
|
||
|
|
source: Secret
|
||
|
|
secretRef:
|
||
|
|
name: proxmox-credentials
|
||
|
|
namespace: crossplane-system
|
||
|
|
key: credentials.json
|
||
|
|
```
|
||
|
|
|
||
|
|
## Token Rotation
|
||
|
|
|
||
|
|
### Rotation Schedule
|
||
|
|
|
||
|
|
- **Production**: Rotate every 90 days
|
||
|
|
- **Staging**: Rotate every 180 days
|
||
|
|
- **Development**: Rotate as needed
|
||
|
|
|
||
|
|
### Rotation Procedure
|
||
|
|
|
||
|
|
1. **Create New Token**
|
||
|
|
```bash
|
||
|
|
# Create new token with new ID
|
||
|
|
pvesh create /access/users/root@pam/token/crossplane-instance-1-v2
|
||
|
|
```
|
||
|
|
|
||
|
|
2. **Update Kubernetes Secret**
|
||
|
|
```bash
|
||
|
|
kubectl create secret generic proxmox-credentials \
|
||
|
|
--from-literal=credentials.json='{"token":"new-token"}' \
|
||
|
|
-n crossplane-system \
|
||
|
|
--dry-run=client -o yaml | kubectl apply -f -
|
||
|
|
```
|
||
|
|
|
||
|
|
3. **Verify Provider Works**
|
||
|
|
- Check provider logs
|
||
|
|
- Test VM operations
|
||
|
|
- Verify no authentication errors
|
||
|
|
|
||
|
|
4. **Revoke Old Token**
|
||
|
|
```bash
|
||
|
|
pvesh delete /access/users/root@pam/token/crossplane-instance-1
|
||
|
|
```
|
||
|
|
|
||
|
|
5. **Update Documentation**
|
||
|
|
- Update token inventory
|
||
|
|
- Record rotation date
|
||
|
|
- Update expiration dates
|
||
|
|
|
||
|
|
### Automated Rotation
|
||
|
|
|
||
|
|
Consider implementing automated token rotation:
|
||
|
|
- Kubernetes CronJob
|
||
|
|
- External secret manager (e.g., HashiCorp Vault)
|
||
|
|
- Proxmox API integration
|
||
|
|
|
||
|
|
## Token Inventory
|
||
|
|
|
||
|
|
### Current Tokens
|
||
|
|
|
||
|
|
| Token ID | User | Realm | Expiration | Purpose | Status |
|
||
|
|
|----------|------|-------|------------|---------|--------|
|
||
|
|
| crossplane-instance-1 | root | pam | TBD | Instance 1 provider | Active |
|
||
|
|
| crossplane-instance-2 | root | pam | TBD | Instance 2 provider | Active |
|
||
|
|
|
||
|
|
### Token Tracking
|
||
|
|
|
||
|
|
Maintain a token inventory with:
|
||
|
|
- Token ID
|
||
|
|
- Associated user
|
||
|
|
- Creation date
|
||
|
|
- Expiration date
|
||
|
|
- Purpose/comment
|
||
|
|
- Last rotation date
|
||
|
|
- Status (active/revoked)
|
||
|
|
|
||
|
|
## Security Best Practices
|
||
|
|
|
||
|
|
### ✅ Do
|
||
|
|
|
||
|
|
- Use dedicated service accounts for tokens
|
||
|
|
- Set token expiration dates
|
||
|
|
- Rotate tokens regularly
|
||
|
|
- Store tokens in Kubernetes secrets
|
||
|
|
- Use principle of least privilege
|
||
|
|
- Monitor token usage
|
||
|
|
- Audit token access logs
|
||
|
|
- Revoke unused tokens immediately
|
||
|
|
|
||
|
|
### ❌ Don't
|
||
|
|
|
||
|
|
- Store tokens in code or config files
|
||
|
|
- Commit tokens to git
|
||
|
|
- Share tokens between environments
|
||
|
|
- Use administrator tokens unnecessarily
|
||
|
|
- Set tokens to never expire
|
||
|
|
- Log token secrets
|
||
|
|
- Expose tokens in error messages
|
||
|
|
|
||
|
|
## Token Monitoring
|
||
|
|
|
||
|
|
### Usage Monitoring
|
||
|
|
|
||
|
|
Monitor token usage via Proxmox audit logs:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# View API token usage
|
||
|
|
pvesh get /api2/json/access/token/{token-id}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Audit Logs
|
||
|
|
|
||
|
|
Review Proxmox audit logs for:
|
||
|
|
- Token creation/deletion
|
||
|
|
- Token usage patterns
|
||
|
|
- Failed authentication attempts
|
||
|
|
- Unusual access patterns
|
||
|
|
|
||
|
|
### Alerting
|
||
|
|
|
||
|
|
Set up alerts for:
|
||
|
|
- Token expiration (30 days before)
|
||
|
|
- Failed authentication attempts
|
||
|
|
- Unusual API usage patterns
|
||
|
|
- Token rotation due dates
|
||
|
|
|
||
|
|
## Troubleshooting
|
||
|
|
|
||
|
|
### Error: "authentication failed"
|
||
|
|
|
||
|
|
**Causes**:
|
||
|
|
- Token expired
|
||
|
|
- Token revoked
|
||
|
|
- Incorrect token format
|
||
|
|
- Token secret mismatch
|
||
|
|
|
||
|
|
**Solutions**:
|
||
|
|
1. Verify token is active: `pvesh get /access/users/{user}/token/{token-id}`
|
||
|
|
2. Check token expiration date
|
||
|
|
3. Verify token secret in Kubernetes secret
|
||
|
|
4. Recreate token if needed
|
||
|
|
|
||
|
|
### Error: "permission denied"
|
||
|
|
|
||
|
|
**Causes**:
|
||
|
|
- Insufficient permissions
|
||
|
|
- Token permissions changed
|
||
|
|
- Resource access restrictions
|
||
|
|
|
||
|
|
**Solutions**:
|
||
|
|
1. Review token permissions
|
||
|
|
2. Check ACL rules
|
||
|
|
3. Verify user permissions
|
||
|
|
4. Update token permissions if needed
|
||
|
|
|
||
|
|
## Compliance
|
||
|
|
|
||
|
|
### SOC 2 Requirements
|
||
|
|
|
||
|
|
- ✅ Token rotation procedures
|
||
|
|
- ✅ Token expiration policies
|
||
|
|
- ✅ Access logging and monitoring
|
||
|
|
- ✅ Principle of least privilege
|
||
|
|
|
||
|
|
### ISO 27001 Requirements
|
||
|
|
|
||
|
|
- ✅ Token management procedures
|
||
|
|
- ✅ Access control policies
|
||
|
|
- ✅ Audit logging
|
||
|
|
- ✅ Security incident response
|
||
|
|
|
||
|
|
## Related Documentation
|
||
|
|
|
||
|
|
- [Provider Configuration](./PROVIDER_CONFIG.md)
|
||
|
|
- [Security Audit](./SECURITY_AUDIT.md)
|
||
|
|
- [TLS Configuration](./TLS_CONFIGURATION.md)
|
||
|
|
|
||
|
|
## Last Updated
|
||
|
|
|
||
|
|
- **Date**: 2024-12-19
|
||
|
|
- **Next Rotation**: TBD
|
||
|
|
- **Review Date**: 2025-01-19
|
||
|
|
|