State CA signing key in secrets store, eliminate admin bundle
This commit is contained in:
parent
9d5c8ea4db
commit
d2710db8f1
@ -1,37 +0,0 @@
|
|||||||
// Package admin deals with the parsing and creation of admin.json files.
|
|
||||||
package admin
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"io"
|
|
||||||
"isle/nebula"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CreationParams are general parameters used when creating a new network. These
|
|
||||||
// are available to all hosts within the network via their bootstrap files.
|
|
||||||
type CreationParams struct {
|
|
||||||
ID string
|
|
||||||
Name string
|
|
||||||
Domain string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Admin is used for accessing all information contained within an admin.json.
|
|
||||||
type Admin struct {
|
|
||||||
CreationParams CreationParams
|
|
||||||
|
|
||||||
Nebula struct {
|
|
||||||
CACredentials nebula.CACredentials
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromReader reads an admin.json from the given io.Reader.
|
|
||||||
func FromReader(r io.Reader) (Admin, error) {
|
|
||||||
var a Admin
|
|
||||||
err := json.NewDecoder(r).Decode(&a)
|
|
||||||
return a, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteTo writes the Admin as an admin.json to the given io.Writer.
|
|
||||||
func (a Admin) WriteTo(into io.Writer) error {
|
|
||||||
return json.NewEncoder(into).Encode(a)
|
|
||||||
}
|
|
@ -6,7 +6,6 @@ import (
|
|||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"isle/admin"
|
|
||||||
"isle/nebula"
|
"isle/nebula"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -25,11 +24,19 @@ func AppDirPath(appDirPath string) string {
|
|||||||
return filepath.Join(appDirPath, "share/bootstrap.json")
|
return filepath.Join(appDirPath, "share/bootstrap.json")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CreationParams are general parameters used when creating a new network. These
|
||||||
|
// are available to all hosts within the network via their bootstrap files.
|
||||||
|
type CreationParams struct {
|
||||||
|
ID string
|
||||||
|
Name string
|
||||||
|
Domain string
|
||||||
|
}
|
||||||
|
|
||||||
// Bootstrap contains all information which is needed by a host daemon to join a
|
// Bootstrap contains all information which is needed by a host daemon to join a
|
||||||
// network on boot.
|
// network on boot.
|
||||||
type Bootstrap struct {
|
type Bootstrap struct {
|
||||||
AdminCreationParams admin.CreationParams
|
NetworkCreationParams CreationParams
|
||||||
CAPublicCredentials nebula.CAPublicCredentials
|
CAPublicCredentials nebula.CAPublicCredentials
|
||||||
|
|
||||||
PrivateCredentials nebula.HostPrivateCredentials
|
PrivateCredentials nebula.HostPrivateCredentials
|
||||||
HostAssigned `json:"-"`
|
HostAssigned `json:"-"`
|
||||||
@ -42,7 +49,7 @@ type Bootstrap struct {
|
|||||||
// function assigns Hosts an empty map.
|
// function assigns Hosts an empty map.
|
||||||
func New(
|
func New(
|
||||||
caCreds nebula.CACredentials,
|
caCreds nebula.CACredentials,
|
||||||
adminCreationParams admin.CreationParams,
|
adminCreationParams CreationParams,
|
||||||
name nebula.HostName,
|
name nebula.HostName,
|
||||||
ip netip.Addr,
|
ip netip.Addr,
|
||||||
) (
|
) (
|
||||||
@ -66,12 +73,12 @@ func New(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Bootstrap{
|
return Bootstrap{
|
||||||
AdminCreationParams: adminCreationParams,
|
NetworkCreationParams: adminCreationParams,
|
||||||
CAPublicCredentials: caCreds.Public,
|
CAPublicCredentials: caCreds.Public,
|
||||||
PrivateCredentials: hostPrivCreds,
|
PrivateCredentials: hostPrivCreds,
|
||||||
HostAssigned: assigned,
|
HostAssigned: assigned,
|
||||||
SignedHostAssigned: signedAssigned,
|
SignedHostAssigned: signedAssigned,
|
||||||
Hosts: map[nebula.HostName]Host{},
|
Hosts: map[nebula.HostName]Host{},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"isle/admin"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
func readAdmin(path string) (admin.Admin, error) {
|
|
||||||
|
|
||||||
if path == "-" {
|
|
||||||
|
|
||||||
adm, err := admin.FromReader(os.Stdin)
|
|
||||||
if err != nil {
|
|
||||||
return admin.Admin{}, fmt.Errorf("parsing admin.json from stdin: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return adm, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
f, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
return admin.Admin{}, fmt.Errorf("opening file: %w", err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
return admin.FromReader(f)
|
|
||||||
}
|
|
@ -33,35 +33,22 @@ var subCmdHostsCreate = subCmd{
|
|||||||
textUnmarshalerFlag{&ip}, "ip", "i", "IP of the new host",
|
textUnmarshalerFlag{&ip}, "ip", "i", "IP of the new host",
|
||||||
)
|
)
|
||||||
|
|
||||||
adminPath := flags.StringP(
|
|
||||||
"admin-path", "a", "",
|
|
||||||
`Path to admin.json file. If the given path is "-" then stdin is used.`,
|
|
||||||
)
|
|
||||||
|
|
||||||
if err := flags.Parse(subCmdCtx.args); err != nil {
|
if err := flags.Parse(subCmdCtx.args); err != nil {
|
||||||
return fmt.Errorf("parsing flags: %w", err)
|
return fmt.Errorf("parsing flags: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !hostNameF.Changed ||
|
if !hostNameF.Changed || !ipF.Changed {
|
||||||
!ipF.Changed ||
|
return errors.New("--hostname and --ip are required")
|
||||||
*adminPath == "" {
|
|
||||||
return errors.New("--hostname, --ip, and --admin-path are required")
|
|
||||||
}
|
|
||||||
|
|
||||||
adm, err := readAdmin(*adminPath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("reading admin.json with --admin-path of %q: %w", *adminPath, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var res daemon.CreateHostResult
|
var res daemon.CreateHostResult
|
||||||
err = subCmdCtx.daemonRCPClient.Call(
|
err := subCmdCtx.daemonRCPClient.Call(
|
||||||
subCmdCtx.ctx,
|
subCmdCtx.ctx,
|
||||||
&res,
|
&res,
|
||||||
"CreateHost",
|
"CreateHost",
|
||||||
daemon.CreateHostRequest{
|
daemon.CreateHostRequest{
|
||||||
CASigningPrivateKey: adm.Nebula.CACredentials.SigningPrivateKey,
|
HostName: hostName,
|
||||||
HostName: hostName,
|
IP: ip,
|
||||||
IP: ip,
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -24,11 +24,6 @@ var subCmdNebulaCreateCert = subCmd{
|
|||||||
"Name of the host to generate a certificate for",
|
"Name of the host to generate a certificate for",
|
||||||
)
|
)
|
||||||
|
|
||||||
adminPath := flags.StringP(
|
|
||||||
"admin-path", "a", "",
|
|
||||||
`Path to admin.json file. If the given path is "-" then stdin is used.`,
|
|
||||||
)
|
|
||||||
|
|
||||||
pubKeyPath := flags.StringP(
|
pubKeyPath := flags.StringP(
|
||||||
"public-key-path", "p", "",
|
"public-key-path", "p", "",
|
||||||
`Path to PEM file containing public key which will be embedded in the cert.`,
|
`Path to PEM file containing public key which will be embedded in the cert.`,
|
||||||
@ -38,17 +33,10 @@ var subCmdNebulaCreateCert = subCmd{
|
|||||||
return fmt.Errorf("parsing flags: %w", err)
|
return fmt.Errorf("parsing flags: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !hostNameF.Changed ||
|
if !hostNameF.Changed || *pubKeyPath == "" {
|
||||||
*adminPath == "" ||
|
|
||||||
*pubKeyPath == "" {
|
|
||||||
return errors.New("--hostname, --admin-path, and --pub-key-path are required")
|
return errors.New("--hostname, --admin-path, and --pub-key-path are required")
|
||||||
}
|
}
|
||||||
|
|
||||||
adm, err := readAdmin(*adminPath)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("reading admin.json with --admin-path of %q: %w", *adminPath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
hostPubPEM, err := os.ReadFile(*pubKeyPath)
|
hostPubPEM, err := os.ReadFile(*pubKeyPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("reading public key from %q: %w", *pubKeyPath, err)
|
return fmt.Errorf("reading public key from %q: %w", *pubKeyPath, err)
|
||||||
@ -65,7 +53,6 @@ var subCmdNebulaCreateCert = subCmd{
|
|||||||
&res,
|
&res,
|
||||||
"CreateNebulaCertificate",
|
"CreateNebulaCertificate",
|
||||||
daemon.CreateNebulaCertificateRequest{
|
daemon.CreateNebulaCertificateRequest{
|
||||||
CASigningPrivateKey: adm.Nebula.CACredentials.SigningPrivateKey,
|
|
||||||
HostName: hostName,
|
HostName: hostName,
|
||||||
HostEncryptingPublicKey: hostPub,
|
HostEncryptingPublicKey: hostPub,
|
||||||
},
|
},
|
||||||
|
@ -3,15 +3,13 @@ package main
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"isle/admin"
|
|
||||||
"isle/daemon"
|
"isle/daemon"
|
||||||
"isle/jsonutil"
|
"isle/jsonutil"
|
||||||
"os"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var subCmdNetworkCreate = subCmd{
|
var subCmdNetworkCreate = subCmd{
|
||||||
name: "create",
|
name: "create",
|
||||||
descr: "Create's a new network, with this host being the first host in that network. The resulting admin.json is output to stdout.",
|
descr: "Create's a new network, with this host being the first host in that network.",
|
||||||
do: func(subCmdCtx subCmdCtx) error {
|
do: func(subCmdCtx subCmdCtx) error {
|
||||||
var (
|
var (
|
||||||
ctx = subCmdCtx.ctx
|
ctx = subCmdCtx.ctx
|
||||||
@ -53,16 +51,11 @@ var subCmdNetworkCreate = subCmd{
|
|||||||
return errors.New("--name, --domain, --ip-net, and --hostname are required")
|
return errors.New("--name, --domain, --ip-net, and --hostname are required")
|
||||||
}
|
}
|
||||||
|
|
||||||
var adm admin.Admin
|
err := subCmdCtx.daemonRCPClient.Call(ctx, nil, "CreateNetwork", req)
|
||||||
err := subCmdCtx.daemonRCPClient.Call(ctx, &adm, "CreateNetwork", req)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("creating network: %w", err)
|
return fmt.Errorf("creating network: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := adm.WriteTo(os.Stdout); err != nil {
|
|
||||||
return fmt.Errorf("writing admin.json to stdout")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ func dnsmasqPmuxProcConfig(
|
|||||||
|
|
||||||
confData := dnsmasq.ConfData{
|
confData := dnsmasq.ConfData{
|
||||||
Resolvers: daemonConfig.DNS.Resolvers,
|
Resolvers: daemonConfig.DNS.Resolvers,
|
||||||
Domain: hostBootstrap.AdminCreationParams.Domain,
|
Domain: hostBootstrap.NetworkCreationParams.Domain,
|
||||||
IP: hostBootstrap.ThisHost().IP().String(),
|
IP: hostBootstrap.ThisHost().IP().String(),
|
||||||
Hosts: hostsSlice,
|
Hosts: hostsSlice,
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"isle/admin"
|
|
||||||
"isle/bootstrap"
|
"isle/bootstrap"
|
||||||
"isle/jsonutil"
|
"isle/jsonutil"
|
||||||
"isle/nebula"
|
"isle/nebula"
|
||||||
@ -35,15 +34,13 @@ type Daemon interface {
|
|||||||
// become this first host's IP.
|
// become this first host's IP.
|
||||||
// - hostName: The name of this first host in the network.
|
// - hostName: The name of this first host in the network.
|
||||||
//
|
//
|
||||||
// An Admin instance is returned, which is necessary to perform admin
|
// The daemon on which this is called will become the first host in the
|
||||||
// actions in the future.
|
// network, and will have full administrative privileges.
|
||||||
CreateNetwork(
|
CreateNetwork(
|
||||||
ctx context.Context, name, domain string,
|
ctx context.Context, name, domain string,
|
||||||
ipNet nebula.IPNet,
|
ipNet nebula.IPNet,
|
||||||
hostName nebula.HostName,
|
hostName nebula.HostName,
|
||||||
) (
|
) error
|
||||||
admin.Admin, error,
|
|
||||||
)
|
|
||||||
|
|
||||||
// JoinNetwork joins the Daemon to an existing network using the given
|
// JoinNetwork joins the Daemon to an existing network using the given
|
||||||
// Bootstrap.
|
// Bootstrap.
|
||||||
@ -66,7 +63,6 @@ type Daemon interface {
|
|||||||
// address.
|
// address.
|
||||||
CreateHost(
|
CreateHost(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
caSigningPrivateKey nebula.SigningPrivateKey, // TODO load from secrets storage
|
|
||||||
hostName nebula.HostName,
|
hostName nebula.HostName,
|
||||||
ip netip.Addr, // TODO automatically choose IP address
|
ip netip.Addr, // TODO automatically choose IP address
|
||||||
) (
|
) (
|
||||||
@ -81,7 +77,6 @@ type Daemon interface {
|
|||||||
// - ErrHostNotFound
|
// - ErrHostNotFound
|
||||||
CreateNebulaCertificate(
|
CreateNebulaCertificate(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
caSigningPrivateKey nebula.SigningPrivateKey, // TODO load from secrets storage
|
|
||||||
hostName nebula.HostName,
|
hostName nebula.HostName,
|
||||||
hostPubKey nebula.EncryptingPublicKey,
|
hostPubKey nebula.EncryptingPublicKey,
|
||||||
) (
|
) (
|
||||||
@ -519,21 +514,17 @@ func (d *daemon) restartLoop(ctx context.Context, readyCh chan<- struct{}) {
|
|||||||
func (d *daemon) CreateNetwork(
|
func (d *daemon) CreateNetwork(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
name, domain string, ipNet nebula.IPNet, hostName nebula.HostName,
|
name, domain string, ipNet nebula.IPNet, hostName nebula.HostName,
|
||||||
) (
|
) error {
|
||||||
admin.Admin, error,
|
|
||||||
) {
|
|
||||||
nebulaCACreds, err := nebula.NewCACredentials(domain, ipNet)
|
nebulaCACreds, err := nebula.NewCACredentials(domain, ipNet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return admin.Admin{}, fmt.Errorf("creating nebula CA cert: %w", err)
|
return fmt.Errorf("creating nebula CA cert: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
adm = admin.Admin{
|
creationParams = bootstrap.CreationParams{
|
||||||
CreationParams: admin.CreationParams{
|
ID: randStr(32),
|
||||||
ID: randStr(32),
|
Name: name,
|
||||||
Name: name,
|
Domain: domain,
|
||||||
Domain: domain,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
garageRPCSecret = randStr(32)
|
garageRPCSecret = randStr(32)
|
||||||
@ -541,29 +532,34 @@ func (d *daemon) CreateNetwork(
|
|||||||
|
|
||||||
err = setGarageRPCSecret(ctx, d.secretsStore, garageRPCSecret)
|
err = setGarageRPCSecret(ctx, d.secretsStore, garageRPCSecret)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return admin.Admin{}, fmt.Errorf("storing garage RPC secret: %w", err)
|
return fmt.Errorf("setting garage RPC secret: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = setNebulaCASigningPrivateKey(ctx, d.secretsStore, nebulaCACreds.SigningPrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("setting nebula CA signing key secret: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
hostBootstrap, err := bootstrap.New(
|
hostBootstrap, err := bootstrap.New(
|
||||||
nebulaCACreds,
|
nebulaCACreds,
|
||||||
adm.CreationParams,
|
creationParams,
|
||||||
hostName,
|
hostName,
|
||||||
ipNet.FirstAddr(),
|
ipNet.FirstAddr(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return adm, fmt.Errorf("initializing bootstrap data: %w", err)
|
return fmt.Errorf("initializing bootstrap data: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.l.Lock()
|
d.l.Lock()
|
||||||
|
|
||||||
if d.state != daemonStateNoNetwork {
|
if d.state != daemonStateNoNetwork {
|
||||||
d.l.Unlock()
|
d.l.Unlock()
|
||||||
return adm, ErrAlreadyJoined
|
return ErrAlreadyJoined
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(d.daemonConfig.Storage.Allocations) < 3 {
|
if len(d.daemonConfig.Storage.Allocations) < 3 {
|
||||||
d.l.Unlock()
|
d.l.Unlock()
|
||||||
return adm, ErrInvalidConfig.WithData(
|
return ErrInvalidConfig.WithData(
|
||||||
"At least three storage allocations are required.",
|
"At least three storage allocations are required.",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -573,18 +569,16 @@ func (d *daemon) CreateNetwork(
|
|||||||
err = d.initialize(hostBootstrap, readyCh)
|
err = d.initialize(hostBootstrap, readyCh)
|
||||||
d.l.Unlock()
|
d.l.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return adm, fmt.Errorf("initializing daemon: %w", err)
|
return fmt.Errorf("initializing daemon: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-readyCh:
|
case <-readyCh:
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return adm, ctx.Err()
|
return ctx.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
adm.Nebula.CACredentials = nebulaCACreds
|
return nil
|
||||||
|
|
||||||
return adm, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *daemon) JoinNetwork(
|
func (d *daemon) JoinNetwork(
|
||||||
@ -674,7 +668,6 @@ func makeCACreds(
|
|||||||
|
|
||||||
func (d *daemon) CreateHost(
|
func (d *daemon) CreateHost(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
caSigningPrivateKey nebula.SigningPrivateKey,
|
|
||||||
hostName nebula.HostName,
|
hostName nebula.HostName,
|
||||||
ip netip.Addr,
|
ip netip.Addr,
|
||||||
) (
|
) (
|
||||||
@ -685,14 +678,17 @@ func (d *daemon) CreateHost(
|
|||||||
) (
|
) (
|
||||||
JoiningBootstrap, error,
|
JoiningBootstrap, error,
|
||||||
) {
|
) {
|
||||||
var (
|
caSigningPrivateKey, err := getNebulaCASigningPrivateKey(
|
||||||
joiningBootstrap JoiningBootstrap
|
ctx, d.secretsStore,
|
||||||
err error
|
|
||||||
)
|
)
|
||||||
|
if err != nil {
|
||||||
|
return JoiningBootstrap{}, fmt.Errorf("getting CA signing key: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var joiningBootstrap JoiningBootstrap
|
||||||
joiningBootstrap.Bootstrap, err = bootstrap.New(
|
joiningBootstrap.Bootstrap, err = bootstrap.New(
|
||||||
makeCACreds(currBootstrap, caSigningPrivateKey),
|
makeCACreds(currBootstrap, caSigningPrivateKey),
|
||||||
currBootstrap.AdminCreationParams,
|
currBootstrap.NetworkCreationParams,
|
||||||
hostName,
|
hostName,
|
||||||
ip,
|
ip,
|
||||||
)
|
)
|
||||||
@ -722,7 +718,6 @@ func (d *daemon) CreateHost(
|
|||||||
|
|
||||||
func (d *daemon) CreateNebulaCertificate(
|
func (d *daemon) CreateNebulaCertificate(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
caSigningPrivateKey nebula.SigningPrivateKey,
|
|
||||||
hostName nebula.HostName,
|
hostName nebula.HostName,
|
||||||
hostPubKey nebula.EncryptingPublicKey,
|
hostPubKey nebula.EncryptingPublicKey,
|
||||||
) (
|
) (
|
||||||
@ -738,6 +733,13 @@ func (d *daemon) CreateNebulaCertificate(
|
|||||||
return nebula.Certificate{}, ErrHostNotFound
|
return nebula.Certificate{}, ErrHostNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
caSigningPrivateKey, err := getNebulaCASigningPrivateKey(
|
||||||
|
ctx, d.secretsStore,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nebula.Certificate{}, fmt.Errorf("getting CA signing key: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
caCreds := makeCACreds(currBootstrap, caSigningPrivateKey)
|
caCreds := makeCACreds(currBootstrap, caSigningPrivateKey)
|
||||||
|
|
||||||
return nebula.NewHostCert(caCreds, hostPubKey, hostName, host.IP())
|
return nebula.NewHostCert(caCreds, hostPubKey, hostName, host.IP())
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"cmp"
|
"cmp"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"isle/admin"
|
|
||||||
"isle/bootstrap"
|
"isle/bootstrap"
|
||||||
"isle/nebula"
|
"isle/nebula"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
@ -47,9 +46,9 @@ type CreateNetworkRequest struct {
|
|||||||
func (r *RPC) CreateNetwork(
|
func (r *RPC) CreateNetwork(
|
||||||
ctx context.Context, req CreateNetworkRequest,
|
ctx context.Context, req CreateNetworkRequest,
|
||||||
) (
|
) (
|
||||||
admin.Admin, error,
|
struct{}, error,
|
||||||
) {
|
) {
|
||||||
return r.daemon.CreateNetwork(
|
return struct{}{}, r.daemon.CreateNetwork(
|
||||||
ctx, req.Name, req.Domain, req.IPNet, req.HostName,
|
ctx, req.Name, req.Domain, req.IPNet, req.HostName,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -130,9 +129,8 @@ func (r *RPC) RemoveHost(ctx context.Context, req RemoveHostRequest) (struct{},
|
|||||||
//
|
//
|
||||||
// All fields are required.
|
// All fields are required.
|
||||||
type CreateHostRequest struct {
|
type CreateHostRequest struct {
|
||||||
CASigningPrivateKey nebula.SigningPrivateKey // TODO load from secrets storage
|
HostName nebula.HostName
|
||||||
HostName nebula.HostName
|
IP netip.Addr
|
||||||
IP netip.Addr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateHostResult wraps the results from the CreateHost RPC method.
|
// CreateHostResult wraps the results from the CreateHost RPC method.
|
||||||
@ -148,7 +146,7 @@ func (r *RPC) CreateHost(
|
|||||||
CreateHostResult, error,
|
CreateHostResult, error,
|
||||||
) {
|
) {
|
||||||
joiningBootstrap, err := r.daemon.CreateHost(
|
joiningBootstrap, err := r.daemon.CreateHost(
|
||||||
ctx, req.CASigningPrivateKey, req.HostName, req.IP,
|
ctx, req.HostName, req.IP,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return CreateHostResult{}, err
|
return CreateHostResult{}, err
|
||||||
@ -162,7 +160,6 @@ func (r *RPC) CreateHost(
|
|||||||
//
|
//
|
||||||
// All fields are required.
|
// All fields are required.
|
||||||
type CreateNebulaCertificateRequest struct {
|
type CreateNebulaCertificateRequest struct {
|
||||||
CASigningPrivateKey nebula.SigningPrivateKey // TODO load from secrets storage
|
|
||||||
HostName nebula.HostName
|
HostName nebula.HostName
|
||||||
HostEncryptingPublicKey nebula.EncryptingPublicKey
|
HostEncryptingPublicKey nebula.EncryptingPublicKey
|
||||||
}
|
}
|
||||||
@ -181,7 +178,7 @@ func (r *RPC) CreateNebulaCertificate(
|
|||||||
CreateNebulaCertificateResult, error,
|
CreateNebulaCertificateResult, error,
|
||||||
) {
|
) {
|
||||||
cert, err := r.daemon.CreateNebulaCertificate(
|
cert, err := r.daemon.CreateNebulaCertificate(
|
||||||
ctx, req.CASigningPrivateKey, req.HostName, req.HostEncryptingPublicKey,
|
ctx, req.HostName, req.HostEncryptingPublicKey,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return CreateNebulaCertificateResult{}, err
|
return CreateNebulaCertificateResult{}, err
|
||||||
|
@ -3,13 +3,26 @@ package daemon
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"isle/garage"
|
"isle/garage"
|
||||||
|
"isle/nebula"
|
||||||
"isle/secrets"
|
"isle/secrets"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
secretsNSNebula = "nebula"
|
||||||
secretsNSGarage = "garage"
|
secretsNSGarage = "garage"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Nebula-related secrets
|
||||||
|
|
||||||
|
var (
|
||||||
|
nebulaCASigningPrivateKeySecretID = secrets.NewID(secretsNSNebula, "ca-signing-private-key")
|
||||||
|
)
|
||||||
|
|
||||||
|
var getNebulaCASigningPrivateKey, setNebulaCASigningPrivateKey = secrets.GetSetFunctions[nebula.SigningPrivateKey](
|
||||||
|
nebulaCASigningPrivateKeySecretID,
|
||||||
|
)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Garage-related secrets
|
// Garage-related secrets
|
||||||
|
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
package nebula
|
|
||||||
|
|
||||||
import (
|
|
||||||
"isle/secrets"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
caSigningPrivateKeySecretID = secrets.NewID("nebula", "ca-signing-private-key")
|
|
||||||
)
|
|
||||||
|
|
||||||
// Get/Set functions for the CA SigningPrivateKey secret.
|
|
||||||
var GetCASigningPrivateKey, SetCASigningPrivateKey = secrets.GetSetFunctions[SigningPrivateKey](
|
|
||||||
caSigningPrivateKeySecretID,
|
|
||||||
)
|
|
@ -4,7 +4,8 @@ source "$UTILS"/with-1-data-1-empty-node-network.sh
|
|||||||
adminBS="$XDG_STATE_HOME"/isle/bootstrap.json
|
adminBS="$XDG_STATE_HOME"/isle/bootstrap.json
|
||||||
bs="$secondus_bootstrap" # set in with-1-data-1-empty-node-network.sh
|
bs="$secondus_bootstrap" # set in with-1-data-1-empty-node-network.sh
|
||||||
|
|
||||||
[ "$(jq -r <"$bs" '.Bootstrap.AdminCreationParams')" = "$(jq -r <admin.json '.CreationParams')" ]
|
[ "$(jq -r <"$bs" '.Bootstrap.NetworkCreationParams.Domain')" = "shared.test" ]
|
||||||
|
[ "$(jq -r <"$bs" '.Bootstrap.NetworkCreationParams.Name')" = "testing" ]
|
||||||
[ "$(jq -r <"$bs" '.Bootstrap.SignedHostAssigned.Body.Name')" = "secondus" ]
|
[ "$(jq -r <"$bs" '.Bootstrap.SignedHostAssigned.Body.Name')" = "secondus" ]
|
||||||
|
|
||||||
[ "$(jq -r <"$bs" '.Bootstrap.Hosts.primus.PublicCredentials')" \
|
[ "$(jq -r <"$bs" '.Bootstrap.Hosts.primus.PublicCredentials')" \
|
||||||
|
@ -6,14 +6,12 @@ cat pubkey
|
|||||||
|
|
||||||
(
|
(
|
||||||
isle nebula create-cert \
|
isle nebula create-cert \
|
||||||
--admin-path admin.json \
|
|
||||||
--hostname non-esiste \
|
--hostname non-esiste \
|
||||||
--public-key-path pubkey \
|
--public-key-path pubkey \
|
||||||
2>&1 || true \
|
2>&1 || true \
|
||||||
) | grep '\[6\] Host not found'
|
) | grep '\[6\] Host not found'
|
||||||
|
|
||||||
isle nebula create-cert \
|
isle nebula create-cert \
|
||||||
--admin-path admin.json \
|
|
||||||
--hostname primus \
|
--hostname primus \
|
||||||
--public-key-path pubkey \
|
--public-key-path pubkey \
|
||||||
| grep -- '-----BEGIN NEBULA CERTIFICATE-----'
|
| grep -- '-----BEGIN NEBULA CERTIFICATE-----'
|
||||||
|
@ -5,10 +5,8 @@ source "$UTILS"/with-1-data-1-empty-node-network.sh
|
|||||||
[ "$(cat b/meta/isle/rpc_port)" = "3910" ]
|
[ "$(cat b/meta/isle/rpc_port)" = "3910" ]
|
||||||
[ "$(cat c/meta/isle/rpc_port)" = "3920" ]
|
[ "$(cat c/meta/isle/rpc_port)" = "3920" ]
|
||||||
|
|
||||||
[ "$(jq -r <admin.json '.CreationParams.ID')" != "" ]
|
[ "$(jq -r <"$BOOTSTRAP_FILE" '.NetworkCreationParams.ID')" != "" ]
|
||||||
[ "$(jq -r <admin.json '.CreationParams.Name')" = "testing" ]
|
[ "$(jq -r <"$BOOTSTRAP_FILE" '.NetworkCreationParams.Name')" = "testing" ]
|
||||||
[ "$(jq -r <admin.json '.CreationParams.Domain')" = "shared.test" ]
|
[ "$(jq -r <"$BOOTSTRAP_FILE" '.NetworkCreationParams.Domain')" = "shared.test" ]
|
||||||
|
|
||||||
[ "$(jq -rc <"$BOOTSTRAP_FILE" '.AdminCreationParams')" = "$(jq -rc <admin.json '.CreationParams')" ]
|
|
||||||
[ "$(jq -rc <"$BOOTSTRAP_FILE" '.CAPublicCredentials')" = "$(jq -rc <admin.json '.Nebula.CACredentials.Public')" ]
|
|
||||||
[ "$(jq -r <"$BOOTSTRAP_FILE" '.SignedHostAssigned.Body.Name')" = "primus" ]
|
[ "$(jq -r <"$BOOTSTRAP_FILE" '.SignedHostAssigned.Body.Name')" = "primus" ]
|
||||||
|
@ -63,12 +63,10 @@ EOF
|
|||||||
--domain shared.test \
|
--domain shared.test \
|
||||||
--hostname primus \
|
--hostname primus \
|
||||||
--ip-net "$ipNet" \
|
--ip-net "$ipNet" \
|
||||||
--name "testing" \
|
--name "testing"
|
||||||
> admin.json
|
|
||||||
|
|
||||||
echo "Creating secondus bootstrap"
|
echo "Creating secondus bootstrap"
|
||||||
isle hosts create \
|
isle hosts create \
|
||||||
--admin-path admin.json \
|
|
||||||
--hostname secondus \
|
--hostname secondus \
|
||||||
--ip "$secondus_ip" \
|
--ip "$secondus_ip" \
|
||||||
> "$secondus_bootstrap"
|
> "$secondus_bootstrap"
|
||||||
|
Loading…
Reference in New Issue
Block a user