feat: generate and store control keys

This commit is contained in:
Johan Siebens
2022-05-17 21:11:50 +02:00
parent 6365869da2
commit b1974d7f83
8 changed files with 84 additions and 38 deletions
+7 -24
View File
@@ -37,8 +37,7 @@ const (
httpsListenAddrKey = "IONSCALE_HTTPS_LISTEN_ADDR"
serverUrlKey = "IONSCALE_SERVER_URL"
keysSystemAdminKeyKey = "IONSCALE_SYSTEM_ADMIN_KEY"
keysControlKeyKey = "IONSCALE_CONTROL_KEY"
keysLegacyControlKeyKey = "IONSCALE_LEGACY_CONTROL_KEY"
keysEncryptionKeyKey = "IONSCALE_ENCRYPTION_KEY"
databaseUrlKey = "IONSCALE_DB_URL"
tlsDisableKey = "IONSCALE_TLS_DISABLE"
tlsCertFileKey = "IONSCALE_TLS_CERT_FILE"
@@ -60,9 +59,8 @@ func defaultConfig() *Config {
MetricsListenAddr: GetString(metricsListenAddrKey, ":8081"),
ServerUrl: GetString(serverUrlKey, "https://localhost:8443"),
Keys: Keys{
SystemAdminKey: GetString(keysSystemAdminKeyKey, ""),
ControlKey: GetString(keysControlKeyKey, ""),
LegacyControlKey: GetString(keysLegacyControlKeyKey, ""),
SystemAdminKey: GetString(keysSystemAdminKeyKey, ""),
EncryptionKey: GetString(keysEncryptionKeyKey, ""),
},
Database: Database{
Url: GetString(databaseUrlKey, "ionscale.db"),
@@ -85,9 +83,7 @@ func defaultConfig() *Config {
}
type ServerKeys struct {
SystemAdminKey key.MachinePrivate
ControlKey key.MachinePrivate
LegacyControlKey key.MachinePrivate
SystemAdminKey key.MachinePrivate
}
type Config struct {
@@ -122,9 +118,8 @@ type Database struct {
}
type Keys struct {
SystemAdminKey string `yaml:"system_admin_key"`
ControlKey string `yaml:"control_key"`
LegacyControlKey string `yaml:"legacy_control_key"`
SystemAdminKey string `yaml:"system_admin_key"`
EncryptionKey string `yaml:"encryption_key"`
}
func (c *Config) CreateUrl(format string, a ...interface{}) string {
@@ -138,19 +133,7 @@ func (c *Config) ReadServerKeys() (*ServerKeys, error) {
return nil, fmt.Errorf("error reading system admin key: %v", err)
}
controlKey, err := util.ParseMachinePrivateKey(c.Keys.ControlKey)
if err != nil {
return nil, fmt.Errorf("error reading control key: %v", err)
}
legacyControlKey, err := util.ParseMachinePrivateKey(c.Keys.LegacyControlKey)
if err != nil {
return nil, fmt.Errorf("error reading legacy control key: %v", err)
}
return &ServerKeys{
SystemAdminKey: *systemAdminKey,
ControlKey: *controlKey,
LegacyControlKey: *legacyControlKey,
SystemAdminKey: *systemAdminKey,
}, nil
}
+20
View File
@@ -8,6 +8,7 @@ import (
"github.com/hashicorp/go-hclog"
"net/http"
"tailscale.com/tailcfg"
"tailscale.com/types/key"
"time"
"github.com/jsiebens/ionscale/internal/config"
@@ -53,6 +54,10 @@ func migrate(db *gorm.DB, repository domain.Repository) error {
return err
}
if err := initializeControlKeys(repository); err != nil {
return err
}
if err := initializeDERPMap(repository); err != nil {
return err
}
@@ -93,6 +98,21 @@ func initializeDERPMap(repository domain.Repository) error {
return nil
}
func initializeControlKeys(repository domain.Repository) error {
ctx := context.Background()
keys, err := repository.GetControlKeys(ctx)
if keys != nil || err != nil {
return err
}
keys = &domain.ControlKeys{
ControlKey: key.NewMachine(),
LegacyControlKey: key.NewMachine(),
}
return repository.SetControlKeys(ctx, keys)
}
type GormLoggerAdapter struct {
logger hclog.Logger
}
+3
View File
@@ -8,6 +8,9 @@ import (
)
type Repository interface {
GetControlKeys(ctx context.Context) (*ControlKeys, error)
SetControlKeys(ctx context.Context, v *ControlKeys) error
GetDERPMap(ctx context.Context) (*tailcfg.DERPMap, error)
SetDERPMap(ctx context.Context, v *tailcfg.DERPMap) error
+38 -4
View File
@@ -6,16 +6,50 @@ import (
"errors"
"gorm.io/gorm"
"tailscale.com/tailcfg"
"tailscale.com/types/key"
)
type configKey string
const (
controlKeysConfigKey configKey = "control_keys"
derpMapConfigKey configKey = "derp_map"
)
type ControlKeys struct {
ControlKey key.MachinePrivate
LegacyControlKey key.MachinePrivate
}
type ServerConfig struct {
Key string `gorm:"primary_key"`
Key configKey `gorm:"primary_key"`
Value []byte
}
func (r *repository) GetControlKeys(ctx context.Context) (*ControlKeys, error) {
var m ControlKeys
err := r.getServerConfig(ctx, controlKeysConfigKey, &m)
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
if err != nil {
return nil, err
}
return &m, nil
}
func (r *repository) SetControlKeys(ctx context.Context, v *ControlKeys) error {
return r.setServerConfig(ctx, controlKeysConfigKey, v)
}
func (r *repository) GetDERPMap(ctx context.Context) (*tailcfg.DERPMap, error) {
var m tailcfg.DERPMap
err := r.getServerConfig(ctx, "derp_map", &m)
err := r.getServerConfig(ctx, derpMapConfigKey, &m)
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
@@ -32,7 +66,7 @@ func (r *repository) SetDERPMap(ctx context.Context, v *tailcfg.DERPMap) error {
return r.setServerConfig(ctx, "derp_map", v)
}
func (r *repository) getServerConfig(ctx context.Context, s string, v interface{}) error {
func (r *repository) getServerConfig(ctx context.Context, s configKey, v interface{}) error {
var m ServerConfig
tx := r.withContext(ctx).Take(&m, "key = ?", s)
@@ -48,7 +82,7 @@ func (r *repository) getServerConfig(ctx context.Context, s string, v interface{
return nil
}
func (r *repository) setServerConfig(ctx context.Context, s string, v interface{}) error {
func (r *repository) setServerConfig(ctx context.Context, s configKey, v interface{}) error {
marshal, err := json.Marshal(v)
if err != nil {
return err
+2 -2
View File
@@ -1,7 +1,6 @@
package handlers
import (
"fmt"
"github.com/jsiebens/ionscale/internal/version"
"github.com/labstack/echo/v4"
)
@@ -10,7 +9,8 @@ func IndexHandler(code int) echo.HandlerFunc {
return func(c echo.Context) error {
info, s := version.GetReleaseInfo()
data := map[string]interface{}{
"Version": fmt.Sprintf("%s - %s", info, s),
"Version": info,
"Revision": s,
}
return c.Render(code, "index.html", data)
}
+2 -2
View File
@@ -1,7 +1,7 @@
package handlers
import (
"github.com/jsiebens/ionscale/internal/config"
"github.com/jsiebens/ionscale/internal/domain"
"github.com/labstack/echo/v4"
"net/http"
"strconv"
@@ -12,7 +12,7 @@ const (
NoiseCapabilityVersion = 28
)
func KeyHandler(keys *config.ServerKeys) echo.HandlerFunc {
func KeyHandler(keys *domain.ControlKeys) echo.HandlerFunc {
legacyPublicKey := keys.LegacyControlKey.Public()
publicKey := keys.ControlKey.Public()
+10 -5
View File
@@ -39,12 +39,17 @@ func Start(config *config.Config) error {
logger.Info("Starting ionscale server")
serverKey, err := config.ReadServerKeys()
if err != nil {
return err
}
_, repository, err := database.OpenDB(&config.Database, logger)
if err != nil {
return err
}
serverKey, err := config.ReadServerKeys()
controlKeys, err := repository.GetControlKeys(context.Background())
if err != nil {
return err
}
@@ -88,9 +93,9 @@ func Start(config *config.Config) error {
return e
}
noiseHandlers := handlers.NewNoiseHandlers(serverKey.ControlKey, createPeerHandler)
registrationHandlers := handlers.NewRegistrationHandlers(bind.BoxBinder(serverKey.LegacyControlKey), config, repository, pendingMachineRegistrationRequests)
pollNetMapHandler := handlers.NewPollNetMapHandler(bind.BoxBinder(serverKey.LegacyControlKey), brokers, repository, offlineTimers)
noiseHandlers := handlers.NewNoiseHandlers(controlKeys.ControlKey, createPeerHandler)
registrationHandlers := handlers.NewRegistrationHandlers(bind.BoxBinder(controlKeys.LegacyControlKey), config, repository, pendingMachineRegistrationRequests)
pollNetMapHandler := handlers.NewPollNetMapHandler(bind.BoxBinder(controlKeys.LegacyControlKey), brokers, repository, offlineTimers)
authenticationHandlers := handlers.NewAuthenticationHandlers(
config,
repository,
@@ -118,7 +123,7 @@ func Start(config *config.Config) error {
tlsAppHandler.Any("/*", handlers.IndexHandler(http.StatusNotFound))
tlsAppHandler.Any("/", handlers.IndexHandler(http.StatusOK))
tlsAppHandler.GET("/version", handlers.Version)
tlsAppHandler.GET("/key", handlers.KeyHandler(serverKey))
tlsAppHandler.GET("/key", handlers.KeyHandler(controlKeys))
tlsAppHandler.POST("/ts2021", noiseHandlers.Upgrade)
tlsAppHandler.POST("/machine/:id", registrationHandlers.Register)
tlsAppHandler.POST("/machine/:id/map", pollNetMapHandler.PollNetMap)
+2 -1
View File
@@ -56,7 +56,8 @@
<div class="wrapper">
<div style="text-align: center">
<p><b>ionscale</b></p>
<small>{{.Version}}</small>
<p><small>{{.Version}}</small></p>
<p><small>{{.Revision}}</small></p>
</div>
</div>
</body>