Add basic config

This commit is contained in:
Daniel Lundin
2019-05-08 20:26:13 +02:00
parent 879ff9acd0
commit 7653aec1a8
3 changed files with 132 additions and 109 deletions
+80
View File
@@ -0,0 +1,80 @@
package main
import (
"encoding/json"
"io/ioutil"
"os"
"github.com/mdlayher/wireguardctrl/wgtypes"
log "github.com/sirupsen/logrus"
)
type ServerConfig struct {
configPath string `json:"-"`
PrivateKey string
PublicKey string
Users map[string]*UserConfig
}
type UserConfig struct {
Name string
Devices map[string]*DeviceConfig
}
type DeviceConfig struct {
Name string
PrivateKey string
PublicKey string
}
func NewServerConfig(cfgPath string) *ServerConfig {
key, err := wgtypes.GeneratePrivateKey()
if err != nil {
log.Fatal(err)
}
cfg := &ServerConfig{
configPath: cfgPath,
PrivateKey: key.String(),
PublicKey: key.PublicKey().String(),
Users: make(map[string]*UserConfig),
}
f, err := os.Open(cfgPath)
if err == nil {
if err = json.NewDecoder(f).Decode(cfg); err != nil {
log.Fatal(err)
}
log.Debug("Read server config from file: ", cfgPath)
} else if os.IsNotExist(err) {
log.Debug("No config found. Creating new: ", cfgPath)
err = cfg.Write()
}
if err != nil {
log.Fatal(err)
}
return cfg
}
func (cfg *ServerConfig) Write() error {
data, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
return err
}
return ioutil.WriteFile(cfg.configPath, data, 0600)
}
func (cfg *ServerConfig) GetUserConfig(user string) *UserConfig {
c, ok := cfg.Users[user]
if !ok {
log.WithField("user", user).Info("No such user. Creating one.")
c = &UserConfig{
Name: user,
Devices: make(map[string]*DeviceConfig),
}
cfg.Users[user] = c
}
return c
}
+52 -15
View File
@@ -5,6 +5,7 @@ import (
"encoding/json"
"net/http"
"os"
"path"
"strings"
"github.com/dgrijalva/jwt-go"
@@ -20,6 +21,8 @@ import (
)
var (
dataDir = kingpin.Flag("data-dir", "Directory used for storage").Default("/var/lib/wireguard-ui").String()
listenAddr = kingpin.Flag("listen-address", "Address to listen to").Default(":8080").String()
natLink = kingpin.Flag("nat-device", "Network interface to masquerade").Default("wlp2s0").String()
@@ -30,8 +33,8 @@ var (
)
type Server struct {
storage *Storage
config *ServerConfig
serverConfigPath string
Config *ServerConfig
}
type WgLink struct {
@@ -56,14 +59,23 @@ func ifname(n string) []byte {
}
func NewServer() *Server {
storage := NewStorage()
server := &Server{
storage: storage,
config: storage.GetServerConfig(),
err := os.MkdirAll(*dataDir, 0700)
if err != nil {
log.WithError(err).Fatalf("Error initializing data directory: %s", *dataDir)
}
return server
cfgPath := path.Join(*dataDir, "config.json")
config := NewServerConfig(cfgPath)
log.Debug("Configuration loaded with public key: ", config.PublicKey)
s := Server{
serverConfigPath: cfgPath,
Config: config,
}
log.Debug("Server initialized: ", *dataDir)
return &s
}
func (s *Server) initInterface() error {
@@ -148,7 +160,7 @@ func (s *Server) initInterface() error {
}
log.Debug("Adding wireguard private key")
key, err := wgtypes.ParseKey(s.config.PrivateKey)
key, err := wgtypes.ParseKey(s.Config.PrivateKey)
if err != nil {
return err
}
@@ -171,6 +183,7 @@ func (s *Server) Start() error {
router := httprouter.New()
router.GET("/", s.Index)
router.GET("/api/v1/users/:user/devices", s.withAuth(s.GetDevices))
router.POST("/api/v1/users/:user/devices", s.withAuth(s.CreateDevice))
log.WithField("listenAddr", *listenAddr).Info("Starting server")
return http.ListenAndServe(*listenAddr, router)
@@ -218,6 +231,13 @@ func (s *Server) withAuth(handler httprouter.Handle) httprouter.Handle {
user := userFromJwtToken(r)
if user == "" {
user = "anonymous"
log.Info("Unauthenticated user: ", user)
}
if user != ps.ByName("user") {
log.WithField("user", user).WithField("path", r.URL.Path).Warn("Unauthorized access")
w.WriteHeader(http.StatusUnauthorized)
return
}
ctx := context.WithValue(r.Context(), "user", user)
@@ -232,12 +252,29 @@ func (s *Server) Index(w http.ResponseWriter, r *http.Request, _ httprouter.Para
func (s *Server) GetDevices(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
user := r.Context().Value("user")
if user != ps.ByName("user") {
log.WithField("user", user).WithField("path", r.URL.Path).Warn("Unauthorized access")
w.WriteHeader(http.StatusUnauthorized)
return
}
err := json.NewEncoder(w).Encode(s.config)
log.Debug(user)
err := json.NewEncoder(w).Encode(s.Config)
if err != nil {
log.Error(err)
w.WriteHeader(http.StatusInternalServerError)
}
}
func (s *Server) CreateDevice(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
user := r.Context().Value("user").(string)
log.WithField("user", user).Debug("CreateDevice")
c := s.Config.GetUserConfig(user)
log.Debugf("user config: %#v", c)
err := s.Config.Write()
if err != nil {
log.Error(err)
w.WriteHeader(http.StatusInternalServerError)
return
}
err = json.NewEncoder(w).Encode(c)
if err != nil {
log.Error(err)
w.WriteHeader(http.StatusInternalServerError)
-94
View File
@@ -1,94 +0,0 @@
package main
import (
"encoding/json"
"io/ioutil"
"os"
"path"
"github.com/mdlayher/wireguardctrl/wgtypes"
log "github.com/sirupsen/logrus"
"gopkg.in/alecthomas/kingpin.v2"
)
var (
dataDir = kingpin.Flag("data-dir", "Directory used for storage").Default("/var/lib/wireguard-ui").String()
)
type ServerConfig struct {
PrivateKey string
PublicKey string
Users []*UserConfig
}
type UserConfig struct {
Name string
Devices []*DeviceConfig
}
type DeviceConfig struct {
Name string
PrivateKey string
PublicKey string
}
type Storage struct {
serverConfigPath string
}
func NewStorage() *Storage {
err := os.MkdirAll(*dataDir, 0700)
if err != nil {
log.WithError(err).Fatalf("Error initializing data directory: %s", *dataDir)
}
s := Storage{
serverConfigPath: path.Join(*dataDir, "config.json"),
}
log.Debug("Storage initialized: ", *dataDir)
return &s
}
func NewServerConfig() *ServerConfig {
key, err := wgtypes.GeneratePrivateKey()
if err != nil {
log.Fatal(err)
}
cfg := ServerConfig{
PrivateKey: key.String(),
PublicKey: key.PublicKey().String(),
}
return &cfg
}
func (cfg *ServerConfig) WriteServerConfig(path string) error {
data, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
return err
}
return ioutil.WriteFile(path, data, 0600)
}
func (s *Storage) GetServerConfig() *ServerConfig {
config := NewServerConfig()
f, err := os.Open(s.serverConfigPath)
if err == nil {
if err = json.NewDecoder(f).Decode(config); err != nil {
log.Fatal(err)
}
log.Debug("Read server config from file: ", s.serverConfigPath)
} else if os.IsNotExist(err) {
log.Debug("No config found. Creating new: ", s.serverConfigPath)
err = config.WriteServerConfig(s.serverConfigPath)
}
if err != nil {
log.Fatal(err)
}
log.Debug("Configuration loaded with public key: ", config.PublicKey)
return config
}