From e56780fdd4dd7da2635da2ed611d90ae85121dc5 Mon Sep 17 00:00:00 2001 From: Tim Beatham Date: Mon, 30 Oct 2023 19:02:28 +0000 Subject: [PATCH 1/2] Added ability to query the JSON data store --- cmd/wg-mesh/main.go | 21 +++++++++++++++++++++ cmd/wgmeshd/configuration.yaml | 2 +- go.mod | 1 + pkg/automerge/automerge.go | 4 ---- pkg/automerge/types.go | 14 +++++++------- pkg/ctrlserver/ctrlserver.go | 4 ++++ pkg/ctrlserver/ctrltypes.go | 12 +++++------- pkg/ipc/ipc.go | 6 ++++++ pkg/robin/requester.go | 11 +++++++++++ 9 files changed, 56 insertions(+), 19 deletions(-) diff --git a/cmd/wg-mesh/main.go b/cmd/wg-mesh/main.go index 97473b8..70f78b4 100644 --- a/cmd/wg-mesh/main.go +++ b/cmd/wg-mesh/main.go @@ -144,6 +144,19 @@ func getGraph(client *ipcRpc.Client, meshId string) { fmt.Println(reply) } +func queryMesh(client *ipcRpc.Client, meshId, query string) { + var reply string + + err := client.Call("IpcHandler.Query", &ipc.QueryMesh{MeshId: meshId, Query: query}, &reply) + + if err != nil { + fmt.Println(err.Error()) + return + } + + fmt.Println(reply) +} + func main() { parser := argparse.NewParser("wg-mesh", "wg-mesh Manipulate WireGuard meshes") @@ -155,6 +168,7 @@ func main() { enableInterfaceCmd := parser.NewCommand("enable-interface", "Enable A Specific Mesh Interface") getGraphCmd := parser.NewCommand("get-graph", "Convert a mesh into DOT format") leaveMeshCmd := parser.NewCommand("leave-mesh", "Leave a mesh network") + queryMeshCmd := parser.NewCommand("query-mesh", "Query a mesh network using JMESPath") var newMeshIfName *string = newMeshCmd.String("f", "ifname", &argparse.Options{Required: true}) var newMeshPort *int = newMeshCmd.Int("p", "wgport", &argparse.Options{Required: true}) @@ -172,6 +186,9 @@ func main() { var leaveMeshMeshId *string = leaveMeshCmd.String("m", "mesh", &argparse.Options{Required: true}) + var queryMeshMeshId *string = queryMeshCmd.String("m", "mesh", &argparse.Options{Required: true}) + var queryMeshQuery *string = queryMeshCmd.String("q", "query", &argparse.Options{Required: true}) + err := parser.Parse(os.Args) if err != nil { @@ -224,4 +241,8 @@ func main() { if leaveMeshCmd.Happened() { leaveMesh(client, *leaveMeshMeshId) } + + if queryMeshCmd.Happened() { + queryMesh(client, *queryMeshMeshId, *queryMeshQuery) + } } diff --git a/cmd/wgmeshd/configuration.yaml b/cmd/wgmeshd/configuration.yaml index 96a5c94..fc74dfd 100644 --- a/cmd/wgmeshd/configuration.yaml +++ b/cmd/wgmeshd/configuration.yaml @@ -3,4 +3,4 @@ privateKeyPath: "/wgmesh/cert/priv.pem" caCertificatePath: "/wgmesh/cert/cacert.pem" skipCertVerification: true gRPCPort: "8080" -advertiseRoutes: true +advertiseRoutes: true \ No newline at end of file diff --git a/go.mod b/go.mod index 8025b72..f6805d8 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( require ( github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.5.9 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/native v1.1.0 // indirect github.com/mdlayher/genetlink v1.3.2 // indirect github.com/mdlayher/netlink v1.7.2 // indirect diff --git a/pkg/automerge/automerge.go b/pkg/automerge/automerge.go index c45a7d4..0bba122 100644 --- a/pkg/automerge/automerge.go +++ b/pkg/automerge/automerge.go @@ -139,10 +139,6 @@ func (m *CrdtMeshManager) HasChanges() bool { return len(changes) > 0 } -func (m *CrdtMeshManager) HasFailed(endpoint string) bool { - return false -} - func (m *CrdtMeshManager) SaveChanges() { hashes := m.doc.Heads() hash := hashes[len(hashes)-1] diff --git a/pkg/automerge/types.go b/pkg/automerge/types.go index 81b10f4..7f399e6 100644 --- a/pkg/automerge/types.go +++ b/pkg/automerge/types.go @@ -2,15 +2,15 @@ package crdt // MeshNodeCrdt: Represents a CRDT for a mesh nodes type MeshNodeCrdt struct { - HostEndpoint string `automerge:"hostEndpoint"` - WgEndpoint string `automerge:"wgEndpoint"` - PublicKey string `automerge:"publicKey"` - WgHost string `automerge:"wgHost"` - Timestamp int64 `automerge:"timestamp"` - Routes map[string]interface{} `automerge:"routes"` + HostEndpoint string `automerge:"hostEndpoint" json:"hostEndpoint"` + WgEndpoint string `automerge:"wgEndpoint" json:"wgEndpoint"` + PublicKey string `automerge:"publicKey" json:"publicKey"` + WgHost string `automerge:"wgHost" json:"wgHost"` + Timestamp int64 `automerge:"timestamp" json:"timestamp"` + Routes map[string]interface{} `automerge:"routes" json:"routes"` } // MeshCrdt: Represents the mesh network as a whole type MeshCrdt struct { - Nodes map[string]MeshNodeCrdt `automerge:"nodes"` + Nodes map[string]MeshNodeCrdt `automerge:"nodes" json:"nodes"` } diff --git a/pkg/ctrlserver/ctrlserver.go b/pkg/ctrlserver/ctrlserver.go index 9ed485f..f0bf0db 100644 --- a/pkg/ctrlserver/ctrlserver.go +++ b/pkg/ctrlserver/ctrlserver.go @@ -7,6 +7,7 @@ import ( "github.com/tim-beatham/wgmesh/pkg/ip" "github.com/tim-beatham/wgmesh/pkg/lib" "github.com/tim-beatham/wgmesh/pkg/mesh" + "github.com/tim-beatham/wgmesh/pkg/query" "github.com/tim-beatham/wgmesh/pkg/rpc" "github.com/tim-beatham/wgmesh/pkg/wg" "golang.zx2c4.com/wireguard/wgctrl" @@ -19,6 +20,7 @@ type NewCtrlServerParams struct { AuthProvider rpc.AuthenticationServer CtrlProvider rpc.MeshCtrlServerServer SyncProvider rpc.SyncServiceServer + Querier query.Querier } // Create a new instance of the MeshCtrlServer or error if the @@ -73,7 +75,9 @@ func NewCtrlServer(params *NewCtrlServerParams) (*MeshCtrlServer, error) { return nil, err } + ctrlServer.Querier = query.NewJmesQuerier(ctrlServer.MeshManager) ctrlServer.ConnectionServer = connServer + return ctrlServer, nil } diff --git a/pkg/ctrlserver/ctrltypes.go b/pkg/ctrlserver/ctrltypes.go index d107139..0a32e87 100644 --- a/pkg/ctrlserver/ctrltypes.go +++ b/pkg/ctrlserver/ctrltypes.go @@ -4,13 +4,12 @@ import ( "github.com/tim-beatham/wgmesh/pkg/conf" "github.com/tim-beatham/wgmesh/pkg/conn" "github.com/tim-beatham/wgmesh/pkg/mesh" + "github.com/tim-beatham/wgmesh/pkg/query" "golang.zx2c4.com/wireguard/wgctrl" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) -/* - * Represents a WireGuard node - */ +// Represents a WireGuard MeshNode type MeshNode struct { HostEndpoint string WgEndpoint string @@ -20,19 +19,18 @@ type MeshNode struct { Routes []string } +// Represents a WireGuard Mesh type Mesh struct { SharedKey *wgtypes.Key Nodes map[string]MeshNode } -/* - * Defines the mesh control server this node - * is running - */ +// Represents a ctrlserver to be used in WireGuard type MeshCtrlServer struct { Client *wgctrl.Client MeshManager *mesh.MeshManager ConnectionManager conn.ConnectionManager ConnectionServer *conn.ConnectionServer Conf *conf.WgMeshConfiguration + Querier query.Querier } diff --git a/pkg/ipc/ipc.go b/pkg/ipc/ipc.go index 6f4a8db..7cc7dd7 100644 --- a/pkg/ipc/ipc.go +++ b/pkg/ipc/ipc.go @@ -42,6 +42,11 @@ type ListMeshReply struct { Meshes []string } +type QueryMesh struct { + MeshId string + Query string +} + type MeshIpc interface { CreateMesh(args *NewMeshArgs, reply *string) error ListMeshes(name string, reply *ListMeshReply) error @@ -50,6 +55,7 @@ type MeshIpc interface { GetMesh(meshId string, reply *GetMeshReply) error EnableInterface(meshId string, reply *string) error GetDOT(meshId string, reply *string) error + Query(query QueryMesh, reply *string) error } const SockAddr = "/tmp/wgmesh_ipc.sock" diff --git a/pkg/robin/requester.go b/pkg/robin/requester.go index eb14aa2..41bb4f3 100644 --- a/pkg/robin/requester.go +++ b/pkg/robin/requester.go @@ -176,6 +176,17 @@ func (n *IpcHandler) GetDOT(meshId string, reply *string) error { return nil } +func (n *IpcHandler) Query(params ipc.QueryMesh, reply *string) error { + queryResponse, err := n.Server.Querier.Query(params.MeshId, params.Query) + + if err != nil { + return err + } + + *reply = string(queryResponse) + return nil +} + type RobinIpcParams struct { CtrlServer *ctrlserver.MeshCtrlServer } From aa3d40f82cd32fd321e78bd7c80124ee9e685465 Mon Sep 17 00:00:00 2001 From: Tim Beatham Date: Tue, 31 Oct 2023 10:34:09 +0000 Subject: [PATCH 2/2] Added JMESpath to query the state of specific meshes. --- pkg/automerge/types.go | 14 +++++++------- pkg/lib/conv.go | 12 ++++++++++++ pkg/sync/syncservice.go | 2 ++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/pkg/automerge/types.go b/pkg/automerge/types.go index 7f399e6..81b10f4 100644 --- a/pkg/automerge/types.go +++ b/pkg/automerge/types.go @@ -2,15 +2,15 @@ package crdt // MeshNodeCrdt: Represents a CRDT for a mesh nodes type MeshNodeCrdt struct { - HostEndpoint string `automerge:"hostEndpoint" json:"hostEndpoint"` - WgEndpoint string `automerge:"wgEndpoint" json:"wgEndpoint"` - PublicKey string `automerge:"publicKey" json:"publicKey"` - WgHost string `automerge:"wgHost" json:"wgHost"` - Timestamp int64 `automerge:"timestamp" json:"timestamp"` - Routes map[string]interface{} `automerge:"routes" json:"routes"` + HostEndpoint string `automerge:"hostEndpoint"` + WgEndpoint string `automerge:"wgEndpoint"` + PublicKey string `automerge:"publicKey"` + WgHost string `automerge:"wgHost"` + Timestamp int64 `automerge:"timestamp"` + Routes map[string]interface{} `automerge:"routes"` } // MeshCrdt: Represents the mesh network as a whole type MeshCrdt struct { - Nodes map[string]MeshNodeCrdt `automerge:"nodes" json:"nodes"` + Nodes map[string]MeshNodeCrdt `automerge:"nodes"` } diff --git a/pkg/lib/conv.go b/pkg/lib/conv.go index 1f115aa..0536ae4 100644 --- a/pkg/lib/conv.go +++ b/pkg/lib/conv.go @@ -43,3 +43,15 @@ func MapKeys[K comparable, V any](m map[K]V) []K { return values } + +type convert[V1 any, V2 any] func(V1) V2 + +func Map[V1 any, V2 any](list []V1, f convert[V1, V2]) []V2 { + newList := make([]V2, len(list)) + + for i, elem := range list { + newList[i] = f(elem) + } + + return newList +} diff --git a/pkg/sync/syncservice.go b/pkg/sync/syncservice.go index f2e9b67..7ebc1d8 100644 --- a/pkg/sync/syncservice.go +++ b/pkg/sync/syncservice.go @@ -87,10 +87,12 @@ func (s *SyncServiceImpl) SyncMesh(stream rpc.SyncService_SyncMeshServer) error if syncer != nil { syncer.Complete() } + return nil } } } + func NewSyncService(server *ctrlserver.MeshCtrlServer) *SyncServiceImpl { return &SyncServiceImpl{Server: server} }