83 lines
2.3 KiB
Go
83 lines
2.3 KiB
Go
// Package clientpolicy defines fixed credential-level limits that can be
|
|
// enforced before an extraction reaches the activity-pool store.
|
|
package clientpolicy
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
)
|
|
|
|
var ErrInvalidPolicy = errors.New("invalid client policy")
|
|
|
|
// Policy limits an authenticated client's extraction request. Zero values
|
|
// preserve the existing unrestricted listener behavior.
|
|
type Policy struct {
|
|
MaxExtractCount int `yaml:"maxExtractCount"`
|
|
AllowedUpstreams []string `yaml:"allowedUpstreams"`
|
|
AllowedRegions []string `yaml:"allowedRegions"`
|
|
}
|
|
|
|
func (policy Policy) IsZero() bool {
|
|
return policy.MaxExtractCount == 0 && len(policy.AllowedUpstreams) == 0 && len(policy.AllowedRegions) == 0
|
|
}
|
|
|
|
func (policy Policy) Validate() error {
|
|
if policy.MaxExtractCount < 0 ||
|
|
!validUniqueValues(policy.AllowedUpstreams) ||
|
|
!validUniqueValues(policy.AllowedRegions) {
|
|
return ErrInvalidPolicy
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (policy Policy) Clone() Policy {
|
|
policy.AllowedUpstreams = append([]string(nil), policy.AllowedUpstreams...)
|
|
policy.AllowedRegions = append([]string(nil), policy.AllowedRegions...)
|
|
return policy
|
|
}
|
|
|
|
func (policy Policy) AllowsExtractCount(count int) bool {
|
|
return policy.MaxExtractCount == 0 || count <= policy.MaxExtractCount
|
|
}
|
|
|
|
func (policy Policy) RestrictUpstreams(requested []string) ([]string, bool) {
|
|
return restrict(requested, policy.AllowedUpstreams)
|
|
}
|
|
|
|
func (policy Policy) RestrictRegions(requested []string) ([]string, bool) {
|
|
return restrict(requested, policy.AllowedRegions)
|
|
}
|
|
|
|
func restrict(requested, allowed []string) ([]string, bool) {
|
|
if len(allowed) == 0 {
|
|
return append([]string(nil), requested...), true
|
|
}
|
|
if len(requested) == 0 {
|
|
return append([]string(nil), allowed...), true
|
|
}
|
|
allowedSet := make(map[string]struct{}, len(allowed))
|
|
for _, value := range allowed {
|
|
allowedSet[value] = struct{}{}
|
|
}
|
|
for _, value := range requested {
|
|
if _, ok := allowedSet[value]; !ok {
|
|
return nil, false
|
|
}
|
|
}
|
|
return append([]string(nil), requested...), true
|
|
}
|
|
|
|
func validUniqueValues(values []string) bool {
|
|
seen := make(map[string]struct{}, len(values))
|
|
for _, value := range values {
|
|
if value == "" || strings.TrimSpace(value) != value {
|
|
return false
|
|
}
|
|
if _, exists := seen[value]; exists {
|
|
return false
|
|
}
|
|
seen[value] = struct{}{}
|
|
}
|
|
return true
|
|
}
|