1 parent
289a8cc2d8
commit
66f36cfac6
19 files changed
+1905
-817
No files matched your search
@@ -46,14 +46,44 @@ func convertGroup(u *unstructured.Unstructured) (group, error) {
|
||||
return groupFromSpec(u.GetName(), s)
|
||||
}
|
||||
|
||||
// FieldError is a validation failure tied to one field of a ClientGroup, so an
|
||||
// editor can show the message next to the input that caused it. Field is the
|
||||
// JSON path inside the group ("policy", "match.cidrs", "rate_limit"); "name"
|
||||
// and "match" are used for the whole-object cases.
|
||||
type FieldError struct {
|
||||
Field string
|
||||
Msg string
|
||||
}
|
||||
|
||||
func (e FieldError) Error() string { return e.Msg }
|
||||
|
||||
// CheckGroup validates a ClientGroup spec the way the runtime will, so an
|
||||
// editor can refuse a bad one before it is written.
|
||||
// editor can refuse a bad one before it is written. It reports the first
|
||||
// problem; CheckGroupAll reports every one.
|
||||
func CheckGroup(name string, s ClientGroupSpec) (config.Group, error) {
|
||||
g, err := groupFromSpec(name, s)
|
||||
return g.cfg, err
|
||||
g, errs := checkGroup(name, s)
|
||||
if len(errs) > 0 {
|
||||
return g.cfg, errs[0]
|
||||
}
|
||||
return g.cfg, nil
|
||||
}
|
||||
|
||||
// CheckGroupAll is CheckGroup for an editor that wants to show every problem
|
||||
// at once instead of one per save.
|
||||
func CheckGroupAll(name string, s ClientGroupSpec) []FieldError {
|
||||
_, errs := checkGroup(name, s)
|
||||
return errs
|
||||
}
|
||||
|
||||
func groupFromSpec(name string, s ClientGroupSpec) (group, error) {
|
||||
g, errs := checkGroup(name, s)
|
||||
if len(errs) > 0 {
|
||||
return group{}, errs[0]
|
||||
}
|
||||
return g, nil
|
||||
}
|
||||
|
||||
func checkGroup(name string, s ClientGroupSpec) (group, []FieldError) {
|
||||
g := config.Group{
|
||||
Name: name,
|
||||
Comment: s.Comment,
|
||||
@@ -68,14 +98,18 @@ func groupFromSpec(name string, s ClientGroupSpec) (group, error) {
|
||||
LogQueries: s.LogQueries,
|
||||
Upstreams: s.Upstreams,
|
||||
}
|
||||
var errs []FieldError
|
||||
bad := func(field, format string, args ...any) {
|
||||
errs = append(errs, FieldError{Field: field, Msg: fmt.Sprintf(format, args...)})
|
||||
}
|
||||
switch g.Policy {
|
||||
case "allow", "deny", "block_only":
|
||||
default:
|
||||
return group{}, fmt.Errorf("policy must be allow, deny or block_only (got %q)", g.Policy)
|
||||
bad("policy", "policy must be allow, deny or block_only (got %q)", g.Policy)
|
||||
}
|
||||
for _, cidr := range g.Match.CIDRs {
|
||||
if _, _, err := net.ParseCIDR(cidr); err != nil {
|
||||
return group{}, fmt.Errorf("bad CIDR %q", cidr)
|
||||
bad("match.cidrs", "bad CIDR %q", cidr)
|
||||
}
|
||||
}
|
||||
// Copy before normalising: the slice belongs to the decoded object.
|
||||
@@ -85,18 +119,22 @@ func groupFromSpec(name string, s ClientGroupSpec) (group, error) {
|
||||
g.Match.PTRSuffixes[i] = s + "."
|
||||
}
|
||||
}
|
||||
if !g.Match.Any && len(g.Match.CIDRs) == 0 && len(g.Match.PTRSuffixes) == 0 && len(g.Match.Tags) == 0 {
|
||||
return group{}, fmt.Errorf("match selects no clients: set cidrs, ptr_suffixes, tags or any")
|
||||
}
|
||||
if g.Match.Any && len(g.Match.CIDRs) == 0 && len(g.Match.PTRSuffixes) == 0 && len(g.Match.Tags) == 0 {
|
||||
selectsSomething := len(g.Match.CIDRs) > 0 || len(g.Match.PTRSuffixes) > 0 || len(g.Match.Tags) > 0
|
||||
switch {
|
||||
case !g.Match.Any && !selectsSomething:
|
||||
bad("match", "match selects no clients: set cidrs, ptr_suffixes, tags or any")
|
||||
case g.Match.Any && !selectsSomething:
|
||||
// config.Validate refuses this shape for every group. Refusing it here
|
||||
// rejects one object instead of the whole merged configuration.
|
||||
return group{}, fmt.Errorf("match.any alone is not accepted; use a catch-all in the YAML acl.groups")
|
||||
bad("match.any", "match.any alone is not accepted; use a catch-all in the YAML acl.groups")
|
||||
}
|
||||
if g.RateLimit < 0 || g.MaxConcurrent < 0 {
|
||||
return group{}, fmt.Errorf("rate_limit and max_concurrent must not be negative")
|
||||
if g.RateLimit < 0 {
|
||||
bad("rate_limit", "rate_limit must not be negative")
|
||||
}
|
||||
return group{cfg: g, priority: s.Priority}, nil
|
||||
if g.MaxConcurrent < 0 {
|
||||
bad("max_concurrent", "max_concurrent must not be negative")
|
||||
}
|
||||
return group{cfg: g, priority: s.Priority}, errs
|
||||
}
|
||||
|
||||
func convertList(u *unstructured.Unstructured) (config.ListSource, error) {
|
||||
|
||||
Reference in new issue
Block a user