AdGuardDNS/internal/cmd/servergroup.go

164 lines
4.2 KiB
Go
Raw Normal View History

2022-08-26 14:18:35 +03:00
package cmd
import (
2024-11-08 16:26:22 +03:00
"context"
2022-08-26 14:18:35 +03:00
"fmt"
"github.com/AdguardTeam/AdGuardDNS/internal/agd"
2023-06-11 12:58:40 +03:00
"github.com/AdguardTeam/AdGuardDNS/internal/bindtodevice"
2022-08-26 14:18:35 +03:00
"github.com/AdguardTeam/AdGuardDNS/internal/dnsmsg"
2024-11-08 16:26:22 +03:00
"github.com/AdguardTeam/AdGuardDNS/internal/tlsconfig"
2024-06-07 14:27:46 +03:00
"github.com/AdguardTeam/golibs/container"
2022-08-26 14:18:35 +03:00
"github.com/AdguardTeam/golibs/errors"
)
// serverGroups are the DNS server groups. A valid instance of serverGroups has
// no nil items.
type serverGroups []*serverGroup
// toInternal returns the configuration for all server groups in the DNS
2024-10-14 17:44:24 +03:00
// service. srvGrps and other parts of the configuration must be valid.
2022-08-26 14:18:35 +03:00
func (srvGrps serverGroups) toInternal(
2024-11-08 16:26:22 +03:00
ctx context.Context,
2022-08-26 14:18:35 +03:00
messages *dnsmsg.Constructor,
2023-06-11 12:58:40 +03:00
btdMgr *bindtodevice.Manager,
2024-12-05 14:19:25 +03:00
tlsMgr tlsconfig.Manager,
2022-08-26 14:18:35 +03:00
fltGrps map[agd.FilteringGroupID]*agd.FilteringGroup,
2024-01-04 19:22:32 +03:00
ratelimitConf *rateLimitConfig,
dnsConf *dnsConfig,
2022-08-26 14:18:35 +03:00
) (svcSrvGrps []*agd.ServerGroup, err error) {
svcSrvGrps = make([]*agd.ServerGroup, len(srvGrps))
for i, g := range srvGrps {
fltGrpID := agd.FilteringGroupID(g.FilteringGroup)
_, ok := fltGrps[fltGrpID]
if !ok {
return nil, fmt.Errorf("server group %q: unknown filtering group %q", g.Name, fltGrpID)
}
2024-12-05 14:19:25 +03:00
var deviceDomains []string
deviceDomains, err = g.TLS.toInternal(ctx, tlsMgr)
2022-08-26 14:18:35 +03:00
if err != nil {
2024-12-05 14:19:25 +03:00
return nil, fmt.Errorf("tls %q: %w", g.Name, err)
2022-08-26 14:18:35 +03:00
}
svcSrvGrps[i] = &agd.ServerGroup{
2024-10-14 17:44:24 +03:00
DDR: g.DDR.toInternal(messages),
2024-12-05 14:19:25 +03:00
DeviceDomains: deviceDomains,
2024-10-14 17:44:24 +03:00
Name: agd.ServerGroupName(g.Name),
FilteringGroup: fltGrpID,
ProfilesEnabled: g.ProfilesEnabled,
2022-08-26 14:18:35 +03:00
}
2024-11-08 16:26:22 +03:00
svcSrvGrps[i].Servers, err = g.Servers.toInternal(
btdMgr,
2024-12-05 14:19:25 +03:00
tlsMgr,
2024-11-08 16:26:22 +03:00
ratelimitConf,
dnsConf,
2024-12-05 14:19:25 +03:00
deviceDomains,
2024-11-08 16:26:22 +03:00
)
2022-08-26 14:18:35 +03:00
if err != nil {
return nil, fmt.Errorf("server group %q: %w", g.Name, err)
}
}
return svcSrvGrps, nil
}
2024-10-14 17:44:24 +03:00
// type check
var _ validator = serverGroups(nil)
// validate implements the [validator] interface for serverGroups.
2022-08-26 14:18:35 +03:00
func (srvGrps serverGroups) validate() (err error) {
if len(srvGrps) == 0 {
2024-10-14 17:44:24 +03:00
return errors.ErrEmptyValue
2022-08-26 14:18:35 +03:00
}
2024-06-07 14:27:46 +03:00
names := container.NewMapSet[string]()
2022-08-26 14:18:35 +03:00
for i, g := range srvGrps {
err = g.validate()
if err != nil {
return fmt.Errorf("at index %d: %w", i, err)
}
if names.Has(g.Name) {
2024-12-05 14:19:25 +03:00
return fmt.Errorf("at index %d: name: %w: %q", i, errors.ErrDuplicated, g.Name)
2022-08-26 14:18:35 +03:00
}
names.Add(g.Name)
}
return nil
}
// serverGroup defines a group of DNS servers all of which use the same
// filtering settings.
//
// TODO(a.garipov): Think about more consistent naming, since this object is a
// configuration, but it also stores other configurations.
type serverGroup struct {
// DDR is the Discovery Of Designated Resolvers (DDR) configuration for this
// server group.
DDR *ddrConfig `yaml:"ddr"`
2024-03-11 12:21:07 +03:00
// TLS are the TLS settings for this server, if any.
TLS *tlsConfig `yaml:"tls"`
2022-08-26 14:18:35 +03:00
// Name is the unique name of the server group.
Name string `yaml:"name"`
// FilteringGroup is the name of the filtering group.
FilteringGroup string `yaml:"filtering_group"`
// Servers are the settings for servers.
Servers servers `yaml:"servers"`
2024-10-14 17:44:24 +03:00
// ProfilesEnabled, if true, enables recognition of user devices and
// profiles for this server group.
ProfilesEnabled bool `yaml:"profiles_enabled"`
2022-08-26 14:18:35 +03:00
}
2024-10-14 17:44:24 +03:00
// type check
var _ validator = (*serverGroup)(nil)
// validate implements the [validator] interface for *serverGroup.
2022-08-26 14:18:35 +03:00
func (g *serverGroup) validate() (err error) {
switch {
case g == nil:
2024-10-14 17:44:24 +03:00
return errors.ErrNoValue
2022-08-26 14:18:35 +03:00
case g.Name == "":
2024-10-14 17:44:24 +03:00
return fmt.Errorf("name: %w", errors.ErrEmptyValue)
2022-08-26 14:18:35 +03:00
case g.FilteringGroup == "":
2024-10-14 17:44:24 +03:00
return fmt.Errorf("filtering_group: %w", errors.ErrEmptyValue)
2022-08-26 14:18:35 +03:00
}
err = g.DDR.validate()
if err != nil {
return fmt.Errorf("ddr: %w", err)
}
needsTLS, err := g.Servers.validate()
if err != nil {
return fmt.Errorf("servers: %w", err)
}
err = g.TLS.validate(needsTLS)
if err != nil {
return fmt.Errorf("tls: %w", err)
}
return nil
}
2024-12-05 14:19:25 +03:00
// collectSessTicketPaths returns the list of unique session ticket file paths
// for all server groups.
func (srvGrps serverGroups) collectSessTicketPaths() (paths []string) {
set := container.NewSortedSliceSet[string]()
for _, g := range srvGrps {
for _, k := range g.TLS.SessionKeys {
set.Add(k)
}
}
return set.Values()
}