mirror of
https://codeberg.org/cunicu/cunicu.git
synced 2025-09-26 21:01:14 +08:00
249 lines
5.2 KiB
Go
249 lines
5.2 KiB
Go
// SPDX-FileCopyrightText: 2023-2025 Steffen Vogel <post@steffenvogel.de>
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
//go:build linux
|
|
|
|
package daemon_test
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
|
|
g "cunicu.li/gont/v2/pkg"
|
|
"golang.zx2c4.com/wireguard/wgctrl"
|
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
|
|
|
"cunicu.li/cunicu/pkg/crypto"
|
|
"cunicu.li/cunicu/pkg/daemon"
|
|
"cunicu.li/cunicu/pkg/device"
|
|
"cunicu.li/cunicu/test"
|
|
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
var _ = Describe("watcher", func() {
|
|
var err error
|
|
var c *wgctrl.Client
|
|
var w *daemon.Watcher
|
|
var devUser bool
|
|
var h *daemon.EventsHandler
|
|
var ns *g.Namespace
|
|
var devName string
|
|
|
|
JustBeforeEach(OncePerOrdered, func() {
|
|
By("Creating net namespace")
|
|
|
|
nsName := fmt.Sprintf("wg-test-ns-%d", rand.Intn(1000)) //nolint:gosec
|
|
ns, err = g.NewNamespace(nsName)
|
|
Expect(err).To(Succeed())
|
|
|
|
func() {
|
|
exit, err := ns.Enter()
|
|
Expect(err).To(Succeed())
|
|
|
|
defer exit()
|
|
|
|
c, err = wgctrl.New()
|
|
Expect(err).To(Succeed())
|
|
}()
|
|
|
|
By("Creating watcher")
|
|
|
|
w, err = daemon.NewWatcher(c, 0, func(dev string) bool { return dev == devName })
|
|
Expect(err).To(Succeed())
|
|
|
|
h = daemon.NewEventsHandler(16)
|
|
|
|
w.AddAllHandler(h)
|
|
|
|
go func() {
|
|
exit, _ := ns.Enter()
|
|
defer exit()
|
|
|
|
w.Watch()
|
|
}()
|
|
})
|
|
|
|
JustAfterEach(OncePerOrdered, func() {
|
|
err := w.Close()
|
|
Expect(err).To(Succeed())
|
|
|
|
err = ns.Close()
|
|
Expect(err).To(Succeed())
|
|
})
|
|
|
|
// Overload It() to enter/exit namespace
|
|
It := func(name string, function func()) {
|
|
It(name, Offset(1), func() {
|
|
exit, err := ns.Enter()
|
|
Expect(err).To(Succeed())
|
|
|
|
function()
|
|
exit()
|
|
})
|
|
}
|
|
|
|
TestSync := func() {
|
|
var i *daemon.Interface
|
|
var p *daemon.Peer
|
|
var d device.Device
|
|
|
|
It("adding interface", func() {
|
|
d, err = device.NewDevice(devName, devUser)
|
|
Expect(err).To(Succeed())
|
|
|
|
err = w.Sync()
|
|
Expect(err).To(Succeed())
|
|
|
|
var ie daemon.InterfaceAddedEvent
|
|
Expect(h.Events).To(test.ReceiveEvent(&ie))
|
|
|
|
i = ie.Interface
|
|
|
|
Expect(ie.Interface).NotTo(BeNil())
|
|
Expect(ie.Interface.Name()).To(Equal(devName))
|
|
})
|
|
|
|
It("modifying the interface", func() {
|
|
oldListenPort := i.ListenPort
|
|
newListenPort := oldListenPort + 1
|
|
|
|
err = c.ConfigureDevice(devName, wgtypes.Config{
|
|
ListenPort: &newListenPort,
|
|
})
|
|
Expect(err).To(Succeed())
|
|
|
|
err = w.Sync()
|
|
Expect(err).To(Succeed())
|
|
|
|
var ie daemon.InterfaceModifiedEvent
|
|
Expect(h.Events).To(test.ReceiveEvent(&ie))
|
|
|
|
Expect(ie.Interface).NotTo(BeNil())
|
|
Expect(ie.Interface.Name()).To(Equal(devName))
|
|
Expect(ie.Modified & daemon.InterfaceModifiedListenPort).NotTo(BeZero())
|
|
Expect(ie.Interface.ListenPort).To(Equal(newListenPort))
|
|
Expect(ie.Old.ListenPort).To(Equal(oldListenPort))
|
|
})
|
|
|
|
It("adding a peer", func() {
|
|
sk, err := crypto.GenerateKey()
|
|
Expect(err).To(Succeed())
|
|
|
|
err = c.ConfigureDevice(i.Name(), wgtypes.Config{
|
|
Peers: []wgtypes.PeerConfig{
|
|
{
|
|
PublicKey: wgtypes.Key(sk.PublicKey()),
|
|
},
|
|
},
|
|
})
|
|
Expect(err).To(Succeed())
|
|
|
|
err = w.Sync()
|
|
Expect(err).To(Succeed())
|
|
|
|
var ie daemon.InterfaceModifiedEvent
|
|
Expect(h.Events).To(test.ReceiveEvent(&ie))
|
|
|
|
Expect(ie.Modified & daemon.InterfaceModifiedPeers).NotTo(BeZero())
|
|
|
|
var pe daemon.PeerAddedEvent
|
|
Expect(h.Events).To(test.ReceiveEvent(&pe))
|
|
|
|
// Remember peer for further test subjects
|
|
p = pe.Peer
|
|
|
|
Expect(pe.Peer.PublicKey()).To(Equal(sk.PublicKey()))
|
|
})
|
|
|
|
It("modifying a peer", func() {
|
|
psk, err := crypto.GeneratePrivateKey()
|
|
Expect(err).To(Succeed())
|
|
|
|
err = p.SetPresharedKey(&psk)
|
|
Expect(err).To(Succeed())
|
|
|
|
err = w.Sync()
|
|
Expect(err).To(Succeed())
|
|
|
|
var pe daemon.PeerModifiedEvent
|
|
Expect(h.Events).To(test.ReceiveEvent(&pe))
|
|
|
|
Expect(pe.Peer.PublicKey()).To(Equal(p.PublicKey()))
|
|
Expect(pe.Modified & daemon.PeerModifiedPresharedKey).NotTo(BeZero())
|
|
Expect(pe.Peer.PresharedKey()).To(Equal(psk))
|
|
})
|
|
|
|
It("removing a peer", func() {
|
|
err = c.ConfigureDevice(i.Name(), wgtypes.Config{
|
|
Peers: []wgtypes.PeerConfig{
|
|
{
|
|
PublicKey: wgtypes.Key(p.PublicKey()),
|
|
Remove: true,
|
|
},
|
|
},
|
|
})
|
|
Expect(err).To(Succeed())
|
|
|
|
err = w.Sync()
|
|
Expect(err).To(Succeed())
|
|
|
|
var ie daemon.InterfaceModifiedEvent
|
|
Expect(h.Events).To(test.ReceiveEvent(&ie))
|
|
|
|
Expect(ie.Modified & daemon.InterfaceModifiedPeers).NotTo(BeZero())
|
|
|
|
var pe daemon.PeerRemovedEvent
|
|
Expect(h.Events).To(test.ReceiveEvent(&pe))
|
|
|
|
Expect(pe.Peer.PublicKey()).To(Equal(p.PublicKey()))
|
|
})
|
|
|
|
It("removing an interface", func() {
|
|
err = d.Close()
|
|
Expect(err).To(Succeed())
|
|
|
|
err = w.Sync()
|
|
Expect(err).To(Succeed())
|
|
|
|
var ie daemon.InterfaceRemovedEvent
|
|
Expect(h.Events).To(test.ReceiveEvent(&ie))
|
|
|
|
Expect(ie.Interface).NotTo(BeNil())
|
|
Expect(ie.Interface.Name()).To(Equal(devName))
|
|
})
|
|
}
|
|
|
|
Context("sync", func() {
|
|
Context("kernel", Ordered, func() {
|
|
BeforeAll(func() {
|
|
devName = "wg-kernel"
|
|
devUser = false
|
|
})
|
|
|
|
TestSync()
|
|
})
|
|
|
|
Context("user", Ordered, func() {
|
|
BeforeAll(func() {
|
|
devName = fmt.Sprintf("wg-user-%d", rand.Intn(1000)) //nolint:gosec
|
|
devUser = true
|
|
})
|
|
|
|
TestSync()
|
|
})
|
|
})
|
|
|
|
Context("watch", Pending, func() {
|
|
Context("periodic", func() {
|
|
})
|
|
|
|
Context("user", func() {
|
|
})
|
|
|
|
Context("kernel", func() {
|
|
})
|
|
})
|
|
})
|