mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-28 19:41:17 +00:00
Implements proper least-privilege model for RPC methods. Previously,
any UID in allowed_peer_uids could call privileged methods, meaning
another service's UID would inherit full host-level control.
Capability System:
- Three levels: read, write, admin
- Per-UID capability assignment via allowed_peers config
- Privileged methods require admin capability
- Backwards compatible with legacy allowed_peer_uids format
Configuration:
allowed_peers:
- uid: 0
capabilities: [read, write, admin] # Root gets all
- uid: 1000
capabilities: [read] # Docker: read-only
- uid: 1001
capabilities: [read, write] # Temps but not key distribution
Security benefit: Services can be granted only the capabilities they
need, preventing unintended privilege escalation.
Related to security audit 2025-11-07.
Co-authored-by: Codex <codex@openai.com>
35 lines
705 B
Go
35 lines
705 B
Go
package main
|
|
|
|
import "strings"
|
|
|
|
// Capability represents a permission bit granted to a peer.
|
|
type Capability uint32
|
|
|
|
const (
|
|
CapabilityRead Capability = 1 << iota
|
|
CapabilityWrite
|
|
CapabilityAdmin
|
|
capabilityLegacyAll = CapabilityRead | CapabilityWrite | CapabilityAdmin
|
|
)
|
|
|
|
func (c Capability) Has(flag Capability) bool {
|
|
return c&flag == flag
|
|
}
|
|
|
|
func parseCapabilityList(values []string) Capability {
|
|
if len(values) == 0 {
|
|
return CapabilityRead
|
|
}
|
|
var caps Capability
|
|
for _, raw := range values {
|
|
switch strings.ToLower(strings.TrimSpace(raw)) {
|
|
case "read":
|
|
caps |= CapabilityRead
|
|
case "write":
|
|
caps |= CapabilityWrite
|
|
case "admin":
|
|
caps |= CapabilityAdmin
|
|
}
|
|
}
|
|
return caps
|
|
}
|