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"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"isle/admin"
|
||||
"isle/nebula"
|
||||
"net/netip"
|
||||
"path/filepath"
|
||||
@ -25,10 +24,18 @@ func AppDirPath(appDirPath string) string {
|
||||
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
|
||||
// network on boot.
|
||||
type Bootstrap struct {
|
||||
AdminCreationParams admin.CreationParams
|
||||
NetworkCreationParams CreationParams
|
||||
CAPublicCredentials nebula.CAPublicCredentials
|
||||
|
||||
PrivateCredentials nebula.HostPrivateCredentials
|
||||
@ -42,7 +49,7 @@ type Bootstrap struct {
|
||||
// function assigns Hosts an empty map.
|
||||
func New(
|
||||
caCreds nebula.CACredentials,
|
||||
adminCreationParams admin.CreationParams,
|
||||
adminCreationParams CreationParams,
|
||||
name nebula.HostName,
|
||||
ip netip.Addr,
|
||||
) (
|
||||
@ -66,7 +73,7 @@ func New(
|
||||
}
|
||||
|
||||
return Bootstrap{
|
||||
AdminCreationParams: adminCreationParams,
|
||||
NetworkCreationParams: adminCreationParams,
|
||||
CAPublicCredentials: caCreds.Public,
|
||||
PrivateCredentials: hostPrivCreds,
|
||||
HostAssigned: assigned,
|
||||
|
@ -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,33 +33,20 @@ var subCmdHostsCreate = subCmd{
|
||||
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 {
|
||||
return fmt.Errorf("parsing flags: %w", err)
|
||||
}
|
||||
|
||||
if !hostNameF.Changed ||
|
||||
!ipF.Changed ||
|
||||
*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)
|
||||
if !hostNameF.Changed || !ipF.Changed {
|
||||
return errors.New("--hostname and --ip are required")
|
||||
}
|
||||
|
||||
var res daemon.CreateHostResult
|
||||
err = subCmdCtx.daemonRCPClient.Call(
|
||||
err := subCmdCtx.daemonRCPClient.Call(
|
||||
subCmdCtx.ctx,
|
||||
&res,
|
||||
"CreateHost",
|
||||
daemon.CreateHostRequest{
|
||||
CASigningPrivateKey: adm.Nebula.CACredentials.SigningPrivateKey,
|
||||
HostName: hostName,
|
||||
IP: ip,
|
||||
},
|
||||
|
@ -24,11 +24,6 @@ var subCmdNebulaCreateCert = subCmd{
|
||||
"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(
|
||||
"public-key-path", "p", "",
|
||||
`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)
|
||||
}
|
||||
|
||||
if !hostNameF.Changed ||
|
||||
*adminPath == "" ||
|
||||
*pubKeyPath == "" {
|
||||
if !hostNameF.Changed || *pubKeyPath == "" {
|
||||
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)
|
||||
if err != nil {
|
||||
return fmt.Errorf("reading public key from %q: %w", *pubKeyPath, err)
|
||||
@ -65,7 +53,6 @@ var subCmdNebulaCreateCert = subCmd{
|
||||
&res,
|
||||
"CreateNebulaCertificate",
|
||||
daemon.CreateNebulaCertificateRequest{
|
||||
CASigningPrivateKey: adm.Nebula.CACredentials.SigningPrivateKey,
|
||||
HostName: hostName,
|
||||
HostEncryptingPublicKey: hostPub,
|
||||
},
|
||||
|
@ -3,15 +3,13 @@ package main
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"isle/admin"
|
||||
"isle/daemon"
|
||||
"isle/jsonutil"
|
||||
"os"
|
||||
)
|
||||
|
||||
var subCmdNetworkCreate = subCmd{
|
||||
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 {
|
||||
var (
|
||||
ctx = subCmdCtx.ctx
|
||||
@ -53,16 +51,11 @@ var subCmdNetworkCreate = subCmd{
|
||||
return errors.New("--name, --domain, --ip-net, and --hostname are required")
|
||||
}
|
||||
|
||||
var adm admin.Admin
|
||||
err := subCmdCtx.daemonRCPClient.Call(ctx, &adm, "CreateNetwork", req)
|
||||
err := subCmdCtx.daemonRCPClient.Call(ctx, nil, "CreateNetwork", req)
|
||||
if err != nil {
|
||||
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
|
||||
},
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ func dnsmasqPmuxProcConfig(
|
||||
|
||||
confData := dnsmasq.ConfData{
|
||||
Resolvers: daemonConfig.DNS.Resolvers,
|
||||
Domain: hostBootstrap.AdminCreationParams.Domain,
|
||||
Domain: hostBootstrap.NetworkCreationParams.Domain,
|
||||
IP: hostBootstrap.ThisHost().IP().String(),
|
||||
Hosts: hostsSlice,
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"isle/admin"
|
||||
"isle/bootstrap"
|
||||
"isle/jsonutil"
|
||||
"isle/nebula"
|
||||
@ -35,15 +34,13 @@ type Daemon interface {
|
||||
// become this first host's IP.
|
||||
// - hostName: The name of this first host in the network.
|
||||
//
|
||||
// An Admin instance is returned, which is necessary to perform admin
|
||||
// actions in the future.
|
||||
// The daemon on which this is called will become the first host in the
|
||||
// network, and will have full administrative privileges.
|
||||
CreateNetwork(
|
||||
ctx context.Context, name, domain string,
|
||||
ipNet nebula.IPNet,
|
||||
hostName nebula.HostName,
|
||||
) (
|
||||
admin.Admin, error,
|
||||
)
|
||||
) error
|
||||
|
||||
// JoinNetwork joins the Daemon to an existing network using the given
|
||||
// Bootstrap.
|
||||
@ -66,7 +63,6 @@ type Daemon interface {
|
||||
// address.
|
||||
CreateHost(
|
||||
ctx context.Context,
|
||||
caSigningPrivateKey nebula.SigningPrivateKey, // TODO load from secrets storage
|
||||
hostName nebula.HostName,
|
||||
ip netip.Addr, // TODO automatically choose IP address
|
||||
) (
|
||||
@ -81,7 +77,6 @@ type Daemon interface {
|
||||
// - ErrHostNotFound
|
||||
CreateNebulaCertificate(
|
||||
ctx context.Context,
|
||||
caSigningPrivateKey nebula.SigningPrivateKey, // TODO load from secrets storage
|
||||
hostName nebula.HostName,
|
||||
hostPubKey nebula.EncryptingPublicKey,
|
||||
) (
|
||||
@ -519,21 +514,17 @@ func (d *daemon) restartLoop(ctx context.Context, readyCh chan<- struct{}) {
|
||||
func (d *daemon) CreateNetwork(
|
||||
ctx context.Context,
|
||||
name, domain string, ipNet nebula.IPNet, hostName nebula.HostName,
|
||||
) (
|
||||
admin.Admin, error,
|
||||
) {
|
||||
) error {
|
||||
nebulaCACreds, err := nebula.NewCACredentials(domain, ipNet)
|
||||
if err != nil {
|
||||
return admin.Admin{}, fmt.Errorf("creating nebula CA cert: %w", err)
|
||||
return fmt.Errorf("creating nebula CA cert: %w", err)
|
||||
}
|
||||
|
||||
var (
|
||||
adm = admin.Admin{
|
||||
CreationParams: admin.CreationParams{
|
||||
creationParams = bootstrap.CreationParams{
|
||||
ID: randStr(32),
|
||||
Name: name,
|
||||
Domain: domain,
|
||||
},
|
||||
}
|
||||
|
||||
garageRPCSecret = randStr(32)
|
||||
@ -541,29 +532,34 @@ func (d *daemon) CreateNetwork(
|
||||
|
||||
err = setGarageRPCSecret(ctx, d.secretsStore, garageRPCSecret)
|
||||
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(
|
||||
nebulaCACreds,
|
||||
adm.CreationParams,
|
||||
creationParams,
|
||||
hostName,
|
||||
ipNet.FirstAddr(),
|
||||
)
|
||||
if err != nil {
|
||||
return adm, fmt.Errorf("initializing bootstrap data: %w", err)
|
||||
return fmt.Errorf("initializing bootstrap data: %w", err)
|
||||
}
|
||||
|
||||
d.l.Lock()
|
||||
|
||||
if d.state != daemonStateNoNetwork {
|
||||
d.l.Unlock()
|
||||
return adm, ErrAlreadyJoined
|
||||
return ErrAlreadyJoined
|
||||
}
|
||||
|
||||
if len(d.daemonConfig.Storage.Allocations) < 3 {
|
||||
d.l.Unlock()
|
||||
return adm, ErrInvalidConfig.WithData(
|
||||
return ErrInvalidConfig.WithData(
|
||||
"At least three storage allocations are required.",
|
||||
)
|
||||
}
|
||||
@ -573,18 +569,16 @@ func (d *daemon) CreateNetwork(
|
||||
err = d.initialize(hostBootstrap, readyCh)
|
||||
d.l.Unlock()
|
||||
if err != nil {
|
||||
return adm, fmt.Errorf("initializing daemon: %w", err)
|
||||
return fmt.Errorf("initializing daemon: %w", err)
|
||||
}
|
||||
|
||||
select {
|
||||
case <-readyCh:
|
||||
case <-ctx.Done():
|
||||
return adm, ctx.Err()
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
adm.Nebula.CACredentials = nebulaCACreds
|
||||
|
||||
return adm, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *daemon) JoinNetwork(
|
||||
@ -674,7 +668,6 @@ func makeCACreds(
|
||||
|
||||
func (d *daemon) CreateHost(
|
||||
ctx context.Context,
|
||||
caSigningPrivateKey nebula.SigningPrivateKey,
|
||||
hostName nebula.HostName,
|
||||
ip netip.Addr,
|
||||
) (
|
||||
@ -685,14 +678,17 @@ func (d *daemon) CreateHost(
|
||||
) (
|
||||
JoiningBootstrap, error,
|
||||
) {
|
||||
var (
|
||||
joiningBootstrap JoiningBootstrap
|
||||
err error
|
||||
caSigningPrivateKey, err := getNebulaCASigningPrivateKey(
|
||||
ctx, d.secretsStore,
|
||||
)
|
||||
if err != nil {
|
||||
return JoiningBootstrap{}, fmt.Errorf("getting CA signing key: %w", err)
|
||||
}
|
||||
|
||||
var joiningBootstrap JoiningBootstrap
|
||||
joiningBootstrap.Bootstrap, err = bootstrap.New(
|
||||
makeCACreds(currBootstrap, caSigningPrivateKey),
|
||||
currBootstrap.AdminCreationParams,
|
||||
currBootstrap.NetworkCreationParams,
|
||||
hostName,
|
||||
ip,
|
||||
)
|
||||
@ -722,7 +718,6 @@ func (d *daemon) CreateHost(
|
||||
|
||||
func (d *daemon) CreateNebulaCertificate(
|
||||
ctx context.Context,
|
||||
caSigningPrivateKey nebula.SigningPrivateKey,
|
||||
hostName nebula.HostName,
|
||||
hostPubKey nebula.EncryptingPublicKey,
|
||||
) (
|
||||
@ -738,6 +733,13 @@ func (d *daemon) CreateNebulaCertificate(
|
||||
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)
|
||||
|
||||
return nebula.NewHostCert(caCreds, hostPubKey, hostName, host.IP())
|
||||
|
@ -4,7 +4,6 @@ import (
|
||||
"cmp"
|
||||
"context"
|
||||
"fmt"
|
||||
"isle/admin"
|
||||
"isle/bootstrap"
|
||||
"isle/nebula"
|
||||
"net/netip"
|
||||
@ -47,9 +46,9 @@ type CreateNetworkRequest struct {
|
||||
func (r *RPC) CreateNetwork(
|
||||
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,
|
||||
)
|
||||
}
|
||||
@ -130,7 +129,6 @@ func (r *RPC) RemoveHost(ctx context.Context, req RemoveHostRequest) (struct{},
|
||||
//
|
||||
// All fields are required.
|
||||
type CreateHostRequest struct {
|
||||
CASigningPrivateKey nebula.SigningPrivateKey // TODO load from secrets storage
|
||||
HostName nebula.HostName
|
||||
IP netip.Addr
|
||||
}
|
||||
@ -148,7 +146,7 @@ func (r *RPC) CreateHost(
|
||||
CreateHostResult, error,
|
||||
) {
|
||||
joiningBootstrap, err := r.daemon.CreateHost(
|
||||
ctx, req.CASigningPrivateKey, req.HostName, req.IP,
|
||||
ctx, req.HostName, req.IP,
|
||||
)
|
||||
if err != nil {
|
||||
return CreateHostResult{}, err
|
||||
@ -162,7 +160,6 @@ func (r *RPC) CreateHost(
|
||||
//
|
||||
// All fields are required.
|
||||
type CreateNebulaCertificateRequest struct {
|
||||
CASigningPrivateKey nebula.SigningPrivateKey // TODO load from secrets storage
|
||||
HostName nebula.HostName
|
||||
HostEncryptingPublicKey nebula.EncryptingPublicKey
|
||||
}
|
||||
@ -181,7 +178,7 @@ func (r *RPC) CreateNebulaCertificate(
|
||||
CreateNebulaCertificateResult, error,
|
||||
) {
|
||||
cert, err := r.daemon.CreateNebulaCertificate(
|
||||
ctx, req.CASigningPrivateKey, req.HostName, req.HostEncryptingPublicKey,
|
||||
ctx, req.HostName, req.HostEncryptingPublicKey,
|
||||
)
|
||||
if err != nil {
|
||||
return CreateNebulaCertificateResult{}, err
|
||||
|
@ -3,13 +3,26 @@ package daemon
|
||||
import (
|
||||
"fmt"
|
||||
"isle/garage"
|
||||
"isle/nebula"
|
||||
"isle/secrets"
|
||||
)
|
||||
|
||||
const (
|
||||
secretsNSNebula = "nebula"
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
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.Hosts.primus.PublicCredentials')" \
|
||||
|
@ -6,14 +6,12 @@ cat pubkey
|
||||
|
||||
(
|
||||
isle nebula create-cert \
|
||||
--admin-path admin.json \
|
||||
--hostname non-esiste \
|
||||
--public-key-path pubkey \
|
||||
2>&1 || true \
|
||||
) | grep '\[6\] Host not found'
|
||||
|
||||
isle nebula create-cert \
|
||||
--admin-path admin.json \
|
||||
--hostname primus \
|
||||
--public-key-path pubkey \
|
||||
| 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 c/meta/isle/rpc_port)" = "3920" ]
|
||||
|
||||
[ "$(jq -r <admin.json '.CreationParams.ID')" != "" ]
|
||||
[ "$(jq -r <admin.json '.CreationParams.Name')" = "testing" ]
|
||||
[ "$(jq -r <admin.json '.CreationParams.Domain')" = "shared.test" ]
|
||||
[ "$(jq -r <"$BOOTSTRAP_FILE" '.NetworkCreationParams.ID')" != "" ]
|
||||
[ "$(jq -r <"$BOOTSTRAP_FILE" '.NetworkCreationParams.Name')" = "testing" ]
|
||||
[ "$(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" ]
|
||||
|
@ -63,12 +63,10 @@ EOF
|
||||
--domain shared.test \
|
||||
--hostname primus \
|
||||
--ip-net "$ipNet" \
|
||||
--name "testing" \
|
||||
> admin.json
|
||||
--name "testing"
|
||||
|
||||
echo "Creating secondus bootstrap"
|
||||
isle hosts create \
|
||||
--admin-path admin.json \
|
||||
--hostname secondus \
|
||||
--ip "$secondus_ip" \
|
||||
> "$secondus_bootstrap"
|
||||
|
Loading…
Reference in New Issue
Block a user