99 lines
1.9 KiB
Go
99 lines
1.9 KiB
Go
package security
|
|
|
|
import (
|
|
"errors"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
RiskLow = 1
|
|
RiskMedium = 2
|
|
RiskHigh = 3
|
|
)
|
|
|
|
type DevicePolicy struct {
|
|
Mode string
|
|
}
|
|
|
|
type PolicySnapshot struct {
|
|
Version uint64
|
|
GlobalRisk int
|
|
Devices map[string]DevicePolicy
|
|
CreatedAt time.Time
|
|
}
|
|
|
|
type Snapshot struct {
|
|
mu sync.RWMutex
|
|
data PolicySnapshot
|
|
}
|
|
|
|
func New(globalRisk int, devices map[string]DevicePolicy, version uint64) *Snapshot {
|
|
if globalRisk < RiskLow || globalRisk > RiskHigh {
|
|
globalRisk = RiskMedium
|
|
}
|
|
cp := make(map[string]DevicePolicy, len(devices))
|
|
for k, v := range devices {
|
|
cp[k] = v
|
|
}
|
|
return &Snapshot{data: PolicySnapshot{
|
|
Version: version, GlobalRisk: globalRisk, Devices: cp, CreatedAt: time.Now(),
|
|
}}
|
|
}
|
|
|
|
func (s *Snapshot) Current() PolicySnapshot {
|
|
s.mu.RLock()
|
|
defer s.mu.RUnlock()
|
|
cp := make(map[string]DevicePolicy, len(s.data.Devices))
|
|
for k, v := range s.data.Devices {
|
|
cp[k] = v
|
|
}
|
|
snap := s.data
|
|
snap.Devices = cp
|
|
return snap
|
|
}
|
|
|
|
func (s *Snapshot) Publish(globalRisk int, devices map[string]DevicePolicy, version uint64) error {
|
|
if globalRisk < RiskLow || globalRisk > RiskHigh {
|
|
return errors.New("invalid global risk")
|
|
}
|
|
cp := make(map[string]DevicePolicy, len(devices))
|
|
for k, v := range devices {
|
|
cp[k] = v
|
|
}
|
|
s.mu.Lock()
|
|
if version < s.data.Version {
|
|
s.mu.Unlock()
|
|
return errors.New("policy version regression")
|
|
}
|
|
s.data = PolicySnapshot{
|
|
Version: version, GlobalRisk: globalRisk, Devices: cp, CreatedAt: time.Now(),
|
|
}
|
|
s.mu.Unlock()
|
|
return nil
|
|
}
|
|
|
|
func (s *Snapshot) EffectiveRisk(device string) int {
|
|
s.mu.RLock()
|
|
defer s.mu.RUnlock()
|
|
if p, ok := s.data.Devices[device]; ok {
|
|
if risk := ModeRisk(p.Mode); risk != 0 {
|
|
return risk
|
|
}
|
|
}
|
|
return s.data.GlobalRisk
|
|
}
|
|
|
|
func ModeRisk(mode string) int {
|
|
switch mode {
|
|
case "low":
|
|
return RiskLow
|
|
case "medium":
|
|
return RiskMedium
|
|
case "high":
|
|
return RiskHigh
|
|
default:
|
|
return 0
|
|
}
|
|
}
|