feat: set and get derp map

This commit is contained in:
Johan Siebens
2022-05-20 14:33:16 +02:00
parent 557c43192a
commit c04a5e26d1
10 changed files with 744 additions and 131 deletions
+15
View File
@@ -2,6 +2,7 @@ package broker
import (
"sync"
"tailscale.com/tailcfg"
"tailscale.com/types/key"
)
@@ -15,6 +16,7 @@ type Signal struct {
PeersRemoved []uint64
ACLUpdated bool
DNSUpdated bool
derpMap *tailcfg.DERPMap
}
type Broker interface {
@@ -26,6 +28,7 @@ type Broker interface {
SignalPeersRemoved([]uint64)
SignalDNSUpdated()
SignalACLUpdated()
SignalDERPMapUpdated(c *tailcfg.DERPMap)
IsConnected(uint64) bool
}
@@ -47,6 +50,14 @@ func (m *BrokerPool) Get(tailnetID uint64) Broker {
return b
}
func (m *BrokerPool) SignalDERPMapUpdated(c *tailcfg.DERPMap) {
m.lock.Lock()
defer m.lock.Unlock()
for _, b := range m.store {
b.SignalDERPMapUpdated(c)
}
}
func newBroker(tailnetID uint64) Broker {
b := &broker{
tailnetID: tailnetID,
@@ -103,6 +114,10 @@ func (h *broker) SignalACLUpdated() {
h.signalChannel <- &Signal{ACLUpdated: true}
}
func (h *broker) SignalDERPMapUpdated(c *tailcfg.DERPMap) {
h.signalChannel <- &Signal{derpMap: c}
}
func (h *broker) listen() {
for {
select {
+125
View File
@@ -0,0 +1,125 @@
package cmd
import (
"context"
"encoding/json"
"fmt"
"github.com/jsiebens/ionscale/pkg/gen/api"
"github.com/muesli/coral"
"gopkg.in/yaml.v2"
"io/ioutil"
"tailscale.com/tailcfg"
)
func derpMapCommand() *coral.Command {
command := &coral.Command{
Use: "derp-map",
Short: "Manage DERP Map configuration",
}
command.AddCommand(getDERPMap())
command.AddCommand(setDERPMap())
return command
}
func getDERPMap() *coral.Command {
command := &coral.Command{
Use: "get",
Short: "Get the DERP Map configuration",
SilenceUsage: true,
}
var asJson bool
var target = Target{}
target.prepareCommand(command)
command.Flags().BoolVar(&asJson, "json", false, "")
command.RunE = func(command *coral.Command, args []string) error {
client, c, err := target.createGRPCClient()
if err != nil {
return err
}
defer safeClose(c)
resp, err := client.GetDERPMap(context.Background(), &api.GetDERPMapRequest{})
if err != nil {
return err
}
var derpMap struct {
Regions map[int]*tailcfg.DERPRegion
}
if err := json.Unmarshal(resp.Value, &derpMap); err != nil {
return err
}
if asJson {
marshal, err := json.MarshalIndent(derpMap, "", " ")
if err != nil {
return err
}
fmt.Println()
fmt.Println(string(marshal))
} else {
marshal, err := yaml.Marshal(derpMap)
if err != nil {
return err
}
fmt.Println()
fmt.Println(string(marshal))
}
return nil
}
return command
}
func setDERPMap() *coral.Command {
command := &coral.Command{
Use: "set",
Short: "Set the DERP Map configuration",
SilenceUsage: true,
}
var file string
var target = Target{}
target.prepareCommand(command)
command.Flags().StringVar(&file, "file", "", "")
command.RunE = func(command *coral.Command, args []string) error {
grpcClient, c, err := target.createGRPCClient()
if err != nil {
return err
}
defer safeClose(c)
rawJson, err := ioutil.ReadFile(file)
if err != nil {
return err
}
resp, err := grpcClient.SetDERPMap(context.Background(), &api.SetDERPMapRequest{Value: rawJson})
if err != nil {
return err
}
var derpMap tailcfg.DERPMap
if err := json.Unmarshal(resp.Value, &derpMap); err != nil {
return err
}
fmt.Println()
fmt.Println("DERP Map updated successfully")
return nil
}
return command
}
+1
View File
@@ -7,6 +7,7 @@ import (
func Command() *coral.Command {
rootCmd := rootCommand()
rootCmd.AddCommand(keyCommand())
rootCmd.AddCommand(derpMapCommand())
rootCmd.AddCommand(serverCommand())
rootCmd.AddCommand(versionCommand())
rootCmd.AddCommand(tailnetCommand())
+4 -3
View File
@@ -119,9 +119,6 @@ func (h *PollNetMapHandler) handleUpdate(c echo.Context, binder bind.Binder, m *
keepAliveTicker := time.NewTicker(keepAliveInterval)
syncTicker := time.NewTicker(5 * time.Second)
var latestSync = time.Now()
var latestUpdate = latestSync
c.Response().WriteHeader(http.StatusOK)
if _, err := c.Response().Write(response); err != nil {
@@ -137,6 +134,9 @@ func (h *PollNetMapHandler) handleUpdate(c echo.Context, binder bind.Binder, m *
h.scheduleOfflineMessage(tailnetID, machineID)
}()
var latestSync = time.Now()
var latestUpdate = latestSync
for {
select {
case s := <-updateChan:
@@ -292,6 +292,7 @@ func (h *PollNetMapHandler) createMapResponse(m *domain.Machine, binder bind.Bin
} else {
mapResponse = &tailcfg.MapResponse{
PacketFilter: rules,
DERPMap: derpMap,
PeersChanged: changedPeers,
PeersRemoved: removedPeers,
UserProfiles: mapping.ToUserProfiles(users),
+38
View File
@@ -0,0 +1,38 @@
package service
import (
"context"
"encoding/json"
"github.com/jsiebens/ionscale/pkg/gen/api"
"tailscale.com/tailcfg"
)
func (s *Service) GetDERPMap(ctx context.Context, req *api.GetDERPMapRequest) (*api.GetDERPMapResponse, error) {
derpMap, err := s.repository.GetDERPMap(ctx)
if err != nil {
return nil, err
}
raw, err := json.Marshal(derpMap)
if err != nil {
return nil, err
}
return &api.GetDERPMapResponse{Value: raw}, nil
}
func (s *Service) SetDERPMap(ctx context.Context, req *api.SetDERPMapRequest) (*api.SetDERPMapResponse, error) {
var derpMap tailcfg.DERPMap
err := json.Unmarshal(req.Value, &derpMap)
if err != nil {
return nil, err
}
if err := s.repository.SetDERPMap(ctx, &derpMap); err != nil {
return nil, err
}
s.brokerPool.SignalDERPMapUpdated(&derpMap)
return &api.SetDERPMapResponse{Value: req.Value}, nil
}