talos/cmd/talosctl/pkg/mgmt/helpers/wireguard.go
Dmitriy Matrenichev dad9c40c73
chore: simplify code
- replace `interface{}` with `any` using `gofmt -r 'interface{} -> any -w'`
- replace `a = []T{}` with `var a []T` where possible.
- replace `a = []T{}` with `a = make([]T, 0, len(b))` where possible.

Signed-off-by: Dmitriy Matrenichev <dmitry.matrenichev@siderolabs.com>
2024-07-08 18:14:00 +03:00

119 lines
3.2 KiB
Go

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
package helpers
import (
"fmt"
"net/netip"
"strings"
"time"
sideronet "github.com/siderolabs/net"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"github.com/siderolabs/talos/pkg/machinery/config"
"github.com/siderolabs/talos/pkg/machinery/config/container"
"github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1"
)
// NewWireguardConfigBundle creates a new Wireguard config bundle.
func NewWireguardConfigBundle(ips []netip.Addr, wireguardCidr string, listenPort, mastersCount int) (*WireguardConfigBundle, error) {
configs := map[string]*v1alpha1.Device{}
keys := make([]wgtypes.Key, len(ips))
peers := make([]*v1alpha1.DeviceWireguardPeer, len(ips))
for i, ip := range ips {
key, err := wgtypes.GeneratePrivateKey()
if err != nil {
return nil, err
}
keys[i] = key
peers[i] = &v1alpha1.DeviceWireguardPeer{
WireguardAllowedIPs: []string{
wireguardCidr,
},
WireguardPublicKey: key.PublicKey().String(),
WireguardPersistentKeepaliveInterval: time.Second * 5,
}
if i < mastersCount {
peers[i].WireguardEndpoint = fmt.Sprintf("%s:%d", ip.String(), listenPort)
}
}
parts := strings.Split(wireguardCidr, "/")
networkNumber := parts[1]
network, err := netip.ParsePrefix(wireguardCidr)
if err != nil {
return nil, err
}
for i, nodeIP := range ips {
wgIP, err := sideronet.NthIPInNetwork(network, i+2)
if err != nil {
return nil, err
}
config := &v1alpha1.DeviceWireguardConfig{}
var currentPeers []*v1alpha1.DeviceWireguardPeer
// add all peers except self
for _, peer := range peers {
if peer.PublicKey() != keys[i].PublicKey().String() {
currentPeers = append(currentPeers, peer)
}
}
config.WireguardPeers = currentPeers
config.WireguardPrivateKey = keys[i].String()
device := &v1alpha1.Device{
DeviceInterface: "wg0",
DeviceAddresses: []string{fmt.Sprintf("%s/%s", wgIP.String(), networkNumber)},
DeviceWireguardConfig: config,
DeviceMTU: 1500,
}
if i < mastersCount {
config.WireguardListenPort = listenPort
}
configs[nodeIP.String()] = device
}
return &WireguardConfigBundle{
configs: configs,
}, nil
}
// WireguardConfigBundle allows assembling wireguard network configuration with first controlplane being listen node.
type WireguardConfigBundle struct {
configs map[string]*v1alpha1.Device
}
// PatchConfig generates config patch for a node and patches the configuration data.
func (w *WireguardConfigBundle) PatchConfig(ip fmt.Stringer, cfg config.Provider) (config.Provider, error) {
config := cfg.RawV1Alpha1().DeepCopy()
if config.MachineConfig.MachineNetwork == nil {
config.MachineConfig.MachineNetwork = &v1alpha1.NetworkConfig{
NetworkInterfaces: []*v1alpha1.Device{},
}
}
device, ok := w.configs[ip.String()]
if !ok {
return nil, fmt.Errorf("failed to get wireguard config for node %s", ip.String())
}
config.MachineConfig.MachineNetwork.NetworkInterfaces = append(config.MachineConfig.MachineNetwork.NetworkInterfaces, device)
return container.New(config)
}