Files
brianmcgee e3a7790e57
buildbot/nix-eval Build done.
PR Size Review Check / pr-size-review-gate (pull_request) Successful in 24s
sizelint / sizelint (pull_request) Successful in 2m12s
buildbot/nix-build Build done.
gitea-mq Already up to date with target branch
fix breaks in gofumpt and golangci-lint from updating nixpkgs
2026-07-07 16:32:14 +01:00

78 lines
2.4 KiB
Go

package config
import (
"fmt"
"log/slog"
"time"
dmcrypto "git.clan.lol/clan/data-mesher/pkg/crypto"
"github.com/libp2p/go-libp2p/core/peer"
)
// MinPushPullInterval specifies the minimum interval between push-pull operations in seconds.
const MinPushPullInterval = 5 * time.Second
// Cluster represents the configuration for a cluster using libp2p.
type Cluster struct {
Port uint16 `mapstructure:"port"`
Interfaces []string `mapstructure:"interfaces"`
BootstrapPeers []peer.AddrInfo `mapstructure:"bootstrap_peers"`
PushPullInterval time.Duration `mapstructure:"push_pull_interval"`
// Certificate-based authentication
IdentityKey *dmcrypto.PrivateKey `mapstructure:"identity_key"`
IdentityCert *dmcrypto.Certificate `mapstructure:"identity_cert"`
}
// Validate checks the cluster configuration for valid values.
func (c *Cluster) Validate(network *dmcrypto.PublicKey) error {
if c.Port == 0 {
return fmt.Errorf("%w: cluster port must be between 1 and 65535", ErrInvalidConfig)
}
if len(c.BootstrapPeers) == 0 {
return fmt.Errorf("%w: at least one bootstrap peer is required", ErrInvalidConfig)
}
// we don't want push/pull to happen too frequently
if c.PushPullInterval < MinPushPullInterval {
return fmt.Errorf("%w: cluster push pull interval must be >= %v seconds", ErrInvalidConfig, MinPushPullInterval)
}
if c.IdentityKey == nil {
return fmt.Errorf("%w: identity key is required", ErrInvalidConfig)
}
peerID, err := c.IdentityKey.PeerID()
if err != nil {
// this shouldn't really happen
return fmt.Errorf("%w: failed to derive peer ID from identity key", ErrInvalidConfig)
}
if c.IdentityCert == nil {
return fmt.Errorf("%w: identity certificate is required", ErrInvalidConfig)
}
// verify the certificate's public key matches the identity key
if !c.IdentityCert.IdentityKey.Equal(c.IdentityKey.Public) {
return fmt.Errorf("%w: identity certificate public key does not match identity key", ErrInvalidConfig)
}
// verify the certificate is signed by this node's home network
if err = c.IdentityCert.Verify(network); err != nil {
return fmt.Errorf("%w: identity certificate not signed by network certificate authority", ErrInvalidConfig)
}
slog.Debug(
"cluster config",
"port", c.Port,
"interfaces", c.Interfaces,
"bootstrap_peers", c.BootstrapPeers,
"push_pull_interval", c.PushPullInterval,
"peer_id", peerID,
)
return nil
}