isle/go/bootstrap/hosts.go

93 lines
2.4 KiB
Go

package bootstrap
import (
"bytes"
"isle/nebula"
"fmt"
"net"
"strings"
"gopkg.in/yaml.v3"
)
// NebulaHost describes the nebula configuration of a Host which is relevant for
// other hosts to know.
type NebulaHost struct {
SignedPublicCredentials string `yaml:"signed_public_credentials"`
PublicAddr string `yaml:"public_addr,omitempty"`
}
// NewNebulaHostSignedPublicCredentials constructs the SignedPublicCredentials
// field of the NebulaHost struct, using the CACredentials to sign the
// HostPublicCredentials.
func NewNebulaHostSignedPublicCredentials(
caCreds nebula.CACredentials,
hostPublicCreds nebula.HostPublicCredentials,
) (
string, error,
) {
hostPublicCredsB, err := yaml.Marshal(hostPublicCreds)
if err != nil {
return "", fmt.Errorf("yaml marshaling host's public credentials: %w", err)
}
buf := new(bytes.Buffer)
err = nebula.SignAndWrap(buf, caCreds.SigningPrivateKeyPEM, hostPublicCredsB)
if err != nil {
return "", fmt.Errorf("signing host's public credentials: %w", err)
}
return buf.String(), nil
}
// GarageHost describes a single garage instance in the GarageHost.
type GarageHostInstance struct {
ID string `yaml:"id"`
RPCPort int `yaml:"rpc_port"`
S3APIPort int `yaml:"s3_api_port"`
}
// GarageHost describes the garage configuration of a Host which is relevant for
// other hosts to know.
type GarageHost struct {
Instances []GarageHostInstance `yaml:"instances"`
}
// Host consolidates all information about a single host from the bootstrap
// file.
type Host struct {
Name string `yaml:"name"`
Nebula NebulaHost `yaml:"nebula"`
Garage GarageHost `yaml:"garage,omitempty"`
}
// IP returns the IP address encoded in the Host's nebula certificate, or panics
// if there is an error.
//
// This assumes that the Host and its data has already been verified against the
// CA signing key.
func (h Host) IP() net.IP {
hostPublicCredsB, _, err := nebula.Unwrap(
strings.NewReader(h.Nebula.SignedPublicCredentials),
)
if err != nil {
panic(fmt.Errorf("unwrapping host's signed public credentials: %w", err))
}
var hostPublicCreds nebula.HostPublicCredentials
if err := yaml.Unmarshal(hostPublicCredsB, &hostPublicCreds); err != nil {
panic(fmt.Errorf("yaml unmarshaling host's public credentials: %w", err))
}
ip, err := nebula.IPFromHostCertPEM(hostPublicCreds.CertPEM)
if err != nil {
panic(fmt.Errorf("could not parse IP out of cert for host %q: %w", h.Name, err))
}
return ip
}