mirror of
https://github.com/psviderski/uncloud.git
synced 2026-08-26 19:13:34 +00:00
generate user key for new cluster and add it to peers on bootstrap machine
This commit is contained in:
+32
-9
@@ -9,6 +9,7 @@ import (
|
||||
"uncloud/internal/cli/config"
|
||||
"uncloud/internal/cmdexec"
|
||||
"uncloud/internal/machine"
|
||||
"uncloud/internal/machine/network"
|
||||
"uncloud/internal/secret"
|
||||
)
|
||||
|
||||
@@ -30,7 +31,7 @@ func (c *Cluster) toConfig() *config.Cluster {
|
||||
}
|
||||
}
|
||||
|
||||
func (cli *CLI) CreateCluster(name string, privateKey ed25519.PrivateKey) (*Cluster, error) {
|
||||
func (cli *CLI) CreateCluster(name string, privateKey ed25519.PrivateKey, userPrivateKey secret.Secret) (*Cluster, error) {
|
||||
if _, ok := cli.config.Clusters[name]; ok {
|
||||
return nil, fmt.Errorf("cluster %q already exists", name)
|
||||
}
|
||||
@@ -41,13 +42,22 @@ func (cli *CLI) CreateCluster(name string, privateKey ed25519.PrivateKey) (*Clus
|
||||
return nil, fmt.Errorf("generate cluster secret: %w", err)
|
||||
}
|
||||
}
|
||||
if userPrivateKey == nil {
|
||||
user, err := NewUser(nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("generate user: %w", err)
|
||||
}
|
||||
userPrivateKey = user.PrivateKey()
|
||||
}
|
||||
|
||||
c := &Cluster{
|
||||
Name: name,
|
||||
privateKey: privateKey,
|
||||
config: cli.config,
|
||||
}
|
||||
cli.config.Clusters[name] = c.toConfig()
|
||||
cfg := c.toConfig()
|
||||
cfg.UserKey = userPrivateKey
|
||||
cli.config.Clusters[name] = cfg
|
||||
if err := cli.config.Save(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -56,7 +66,7 @@ func (cli *CLI) CreateCluster(name string, privateKey ed25519.PrivateKey) (*Clus
|
||||
}
|
||||
|
||||
func (cli *CLI) CreateDefaultCluster() (*Cluster, error) {
|
||||
c, err := cli.CreateCluster("default", nil)
|
||||
c, err := cli.CreateCluster("default", nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -116,7 +126,19 @@ func (c *Cluster) AddMachine(ctx context.Context, name, user, host string, port
|
||||
_ = exec.Close()
|
||||
}()
|
||||
|
||||
mcfg, err := machine.NewBootstrapConfig(name, netip.Prefix{})
|
||||
wgUserKey := c.config.Clusters[c.Name].UserKey
|
||||
if wgUserKey == nil {
|
||||
return "", errors.New("cluster user_key must be set in the config")
|
||||
}
|
||||
wgUser, err := NewUser(wgUserKey)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("create user from key: %w", err)
|
||||
}
|
||||
userPeerCfg := network.PeerConfig{
|
||||
Subnet: netip.PrefixFrom(wgUser.Address(), 128),
|
||||
PublicKey: wgUser.PublicKey(),
|
||||
}
|
||||
mcfg, err := machine.NewBootstrapConfig(name, netip.Prefix{}, userPeerCfg)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("generate machine bootstrap config: %w", err)
|
||||
}
|
||||
@@ -153,13 +175,14 @@ func (c *Cluster) AddMachine(ctx context.Context, name, user, host string, port
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("start uncloudd: %w: %s", err, out)
|
||||
}
|
||||
fmt.Println("uncloudd started")
|
||||
fmt.Println("uncloudd daemon started")
|
||||
|
||||
connConfig := config.MachineConnection{
|
||||
User: user,
|
||||
Host: host,
|
||||
Port: port,
|
||||
SSHKey: sshKeyPath,
|
||||
User: user,
|
||||
Host: host,
|
||||
Port: port,
|
||||
SSHKey: sshKeyPath,
|
||||
PublicKey: mcfg.Network.PublicKey,
|
||||
}
|
||||
c.config.Clusters[c.Name].Machines = append(c.config.Clusters[c.Name].Machines, connConfig)
|
||||
if err = c.config.Save(); err != nil {
|
||||
|
||||
@@ -6,4 +6,6 @@ type Cluster struct {
|
||||
Name string `toml:"-"`
|
||||
Machines []MachineConnection `toml:"machines"`
|
||||
Secret secret.Secret `toml:"secret"`
|
||||
// UserKey is the user's WireGuard private key used to connect to cluster machines.
|
||||
UserKey secret.Secret `toml:"user_key"`
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package config
|
||||
|
||||
import "uncloud/internal/secret"
|
||||
|
||||
type MachineConnection struct {
|
||||
User string `toml:"user,omitempty"`
|
||||
Host string `toml:"host"`
|
||||
Port int `toml:"port"`
|
||||
SSHKey string `toml:"ssh_key,omitempty"`
|
||||
User string `toml:"user,omitempty"`
|
||||
Host string `toml:"host"`
|
||||
Port int `toml:"port"`
|
||||
SSHKey string `toml:"ssh_key,omitempty"`
|
||||
PublicKey secret.Secret `toml:"public_key,omitempty"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||
"net/netip"
|
||||
"uncloud/internal/secret"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
privateKey wgtypes.Key
|
||||
}
|
||||
|
||||
func NewUser(privateKey secret.Secret) (*User, error) {
|
||||
var (
|
||||
wgKey wgtypes.Key
|
||||
err error
|
||||
)
|
||||
if privateKey == nil {
|
||||
wgKey, err = wgtypes.GeneratePrivateKey()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("generate key for user: %w", err)
|
||||
}
|
||||
privateKey = wgKey[:]
|
||||
} else {
|
||||
wgKey, err = wgtypes.NewKey(privateKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid key: %w", err)
|
||||
}
|
||||
privateKey = wgKey[:]
|
||||
}
|
||||
return &User{
|
||||
privateKey: wgKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (u *User) PrivateKey() secret.Secret {
|
||||
return u.privateKey[:]
|
||||
}
|
||||
|
||||
func (u *User) PublicKey() secret.Secret {
|
||||
pubKey := u.privateKey.PublicKey()
|
||||
return pubKey[:]
|
||||
}
|
||||
|
||||
func (u *User) Address() netip.Addr {
|
||||
pubKey := u.PublicKey()
|
||||
bytes := [16]byte{0xfd, 0xcc}
|
||||
copy(bytes[2:], pubKey[:14])
|
||||
return netip.AddrFrom16(bytes)
|
||||
}
|
||||
Reference in New Issue
Block a user