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 }