mirror of
https://github.com/netbirdio/netbird.git
synced 2024-11-22 08:03:30 +01:00
4587f7686e
* feat: basic management service implementation [FAILING TESTS] * test: fix healthcheck test * test: #39 add peer registration endpoint test * feat: #39 add setup key handling * feat: #39 add peer management store persistence * refactor: extract config read/write to the utility package * refactor: move file contents copy to the utility package * refactor: use Accounts instead of Users in the Store * feature: add management server Docker file * refactor: introduce datadir instead of config * chore: use filepath.Join to concat filepaths instead of string concat * refactor: move stop channel to the root * refactor: move stop channel to the root * review: fix PR review notes Co-authored-by: braginini <hello@wiretrustee.com>
121 lines
2.8 KiB
Go
121 lines
2.8 KiB
Go
package management
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/wiretrustee/wiretrustee/util"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
// storeFileName Store file name. Stored in the datadir
|
|
const storeFileName = "store.json"
|
|
|
|
// Account represents a unique account of the system
|
|
type Account struct {
|
|
Id string
|
|
SetupKeys map[string]*SetupKey
|
|
Peers map[string]*Peer
|
|
}
|
|
|
|
// SetupKey represents a pre-authorized key used to register machines (peers)
|
|
// One key might have multiple machines
|
|
type SetupKey struct {
|
|
Key string
|
|
}
|
|
|
|
// Peer represents a machine connected to the network.
|
|
// The Peer is a Wireguard peer identified by a public key
|
|
type Peer struct {
|
|
// Wireguard public key
|
|
Key string
|
|
// A setup key this peer was registered with
|
|
SetupKey *SetupKey
|
|
}
|
|
|
|
// Store represents an account storage
|
|
type Store struct {
|
|
Accounts map[string]*Account
|
|
|
|
// mutex to synchronise Store read/write operations
|
|
mux sync.Mutex `json:"-"`
|
|
storeFile string `json:"-"`
|
|
}
|
|
|
|
// NewStore restores a store from the file located in the datadir
|
|
func NewStore(dataDir string) (*Store, error) {
|
|
return restore(filepath.Join(dataDir, storeFileName))
|
|
}
|
|
|
|
// restore restores the state of the store from the file.
|
|
// Creates a new empty store file if doesn't exist
|
|
func restore(file string) (*Store, error) {
|
|
|
|
if _, err := os.Stat(file); os.IsNotExist(err) {
|
|
// create a new Store if previously didn't exist (e.g. first run)
|
|
s := &Store{
|
|
Accounts: make(map[string]*Account),
|
|
mux: sync.Mutex{},
|
|
storeFile: file,
|
|
}
|
|
|
|
err = s.persist(file)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return s, nil
|
|
}
|
|
|
|
read, err := util.ReadJson(file, &Store{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
read.(*Store).storeFile = file
|
|
|
|
return read.(*Store), nil
|
|
}
|
|
|
|
// persist persists account data to a file
|
|
// It is recommended to call it with locking Store,mux
|
|
func (s *Store) persist(file string) error {
|
|
return util.WriteJson(file, s)
|
|
}
|
|
|
|
// AddPeer adds peer to the store and associates it with a Account and a SetupKey. Returns related Account
|
|
// Each Account has a list of pre-authorised SetupKey and if no Account has a given key nil will be returned, meaning the key is invalid
|
|
func (s *Store) AddPeer(setupKey string, peerKey string) error {
|
|
s.mux.Lock()
|
|
defer s.mux.Unlock()
|
|
|
|
for _, u := range s.Accounts {
|
|
for _, key := range u.SetupKeys {
|
|
if key.Key == strings.ToLower(setupKey) {
|
|
u.Peers[peerKey] = &Peer{Key: peerKey, SetupKey: key}
|
|
err := s.persist(s.storeFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
}
|
|
|
|
return fmt.Errorf("invalid setup key")
|
|
}
|
|
|
|
// AddAccount adds new account to the store.
|
|
func (s *Store) AddAccount(account *Account) error {
|
|
s.mux.Lock()
|
|
defer s.mux.Unlock()
|
|
// todo will override, handle existing keys
|
|
s.Accounts[account.Id] = account
|
|
err := s.persist(s.storeFile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|