2022-10-16 14:39:05 +00:00
|
|
|
// Package admin deals with the parsing and creation of admin.tgz files.
|
|
|
|
package admin
|
|
|
|
|
|
|
|
import (
|
|
|
|
"cryptic-net/garage"
|
|
|
|
"cryptic-net/nebula"
|
|
|
|
"cryptic-net/tarutil"
|
|
|
|
"cryptic-net/yamlutil"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io/fs"
|
|
|
|
|
|
|
|
"gopkg.in/yaml.v3"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
2022-10-16 15:05:05 +00:00
|
|
|
creationParamsPath = "admin/creation-params.yml"
|
|
|
|
|
2022-10-16 14:39:05 +00:00
|
|
|
nebulaCertsCACertPath = "nebula/certs/ca.crt"
|
|
|
|
nebulaCertsCAKeyPath = "nebula/certs/ca.key"
|
|
|
|
|
|
|
|
garageGlobalBucketKeyYmlPath = "garage/cryptic-net-global-bucket-key.yml"
|
|
|
|
garageAdminBucketKeyYmlPath = "garage/cryptic-net-admin-bucket-key.yml"
|
|
|
|
garageRPCSecretPath = "garage/rpc-secret.txt"
|
|
|
|
)
|
|
|
|
|
2022-10-16 15:05:05 +00:00
|
|
|
// 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 {
|
2022-10-16 20:17:26 +00:00
|
|
|
ID string `yaml:"id"`
|
|
|
|
Domain string `yaml:"domain"`
|
2022-10-16 15:05:05 +00:00
|
|
|
}
|
|
|
|
|
2022-10-16 14:39:05 +00:00
|
|
|
// Admin is used for accessing all information contained within an admin.tgz.
|
|
|
|
type Admin struct {
|
2022-10-16 15:05:05 +00:00
|
|
|
CreationParams CreationParams
|
|
|
|
|
2022-10-16 14:39:05 +00:00
|
|
|
NebulaCACert nebula.CACert
|
|
|
|
|
|
|
|
GarageRPCSecret string
|
|
|
|
GarageGlobalBucketS3APICredentials garage.S3APICredentials
|
|
|
|
GarageAdminBucketS3APICredentials garage.S3APICredentials
|
|
|
|
}
|
|
|
|
|
|
|
|
// FromFS loads an Admin instance from the given fs.FS, which presumably
|
|
|
|
// represents the file structure of an admin.tgz file.
|
|
|
|
func FromFS(adminFS fs.FS) (Admin, error) {
|
|
|
|
|
|
|
|
var a Admin
|
|
|
|
|
|
|
|
filesToLoadAsYAML := []struct {
|
|
|
|
into interface{}
|
|
|
|
path string
|
|
|
|
}{
|
2022-10-16 15:05:05 +00:00
|
|
|
{&a.CreationParams, creationParamsPath},
|
2022-10-16 14:39:05 +00:00
|
|
|
{&a.GarageGlobalBucketS3APICredentials, garageGlobalBucketKeyYmlPath},
|
|
|
|
{&a.GarageAdminBucketS3APICredentials, garageAdminBucketKeyYmlPath},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, f := range filesToLoadAsYAML {
|
|
|
|
if err := yamlutil.LoadYamlFSFile(f.into, adminFS, f.path); err != nil {
|
|
|
|
return Admin{}, fmt.Errorf("loading %q from fs: %w", f.path, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
filesToLoadAsString := []struct {
|
|
|
|
into *string
|
|
|
|
path string
|
|
|
|
}{
|
|
|
|
{&a.NebulaCACert.CACert, nebulaCertsCACertPath},
|
|
|
|
{&a.NebulaCACert.CAKey, nebulaCertsCAKeyPath},
|
|
|
|
{&a.GarageRPCSecret, garageRPCSecretPath},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, f := range filesToLoadAsString {
|
|
|
|
body, err := fs.ReadFile(adminFS, f.path)
|
|
|
|
if err != nil {
|
|
|
|
return Admin{}, fmt.Errorf("loading %q from fs: %w", f.path, err)
|
|
|
|
}
|
|
|
|
*f.into = string(body)
|
|
|
|
}
|
|
|
|
|
|
|
|
return a, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// FromReader reads an admin.tgz file from the given io.Reader.
|
|
|
|
func FromReader(r io.Reader) (Admin, error) {
|
|
|
|
|
|
|
|
fs, err := tarutil.FSFromReader(r)
|
|
|
|
if err != nil {
|
|
|
|
return Admin{}, fmt.Errorf("reading admin.tgz: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return FromFS(fs)
|
|
|
|
}
|
|
|
|
|
|
|
|
// WriteTo writes the Admin as a new admin.tgz to the given io.Writer.
|
|
|
|
func (a Admin) WriteTo(into io.Writer) error {
|
|
|
|
|
|
|
|
w := tarutil.NewTGZWriter(into)
|
|
|
|
|
|
|
|
filesToWriteAsYAML := []struct {
|
|
|
|
value interface{}
|
|
|
|
path string
|
|
|
|
}{
|
2022-10-16 15:05:05 +00:00
|
|
|
{a.CreationParams, creationParamsPath},
|
2022-10-16 14:39:05 +00:00
|
|
|
{a.GarageGlobalBucketS3APICredentials, garageGlobalBucketKeyYmlPath},
|
|
|
|
{a.GarageAdminBucketS3APICredentials, garageAdminBucketKeyYmlPath},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, f := range filesToWriteAsYAML {
|
|
|
|
|
|
|
|
b, err := yaml.Marshal(f.value)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("yaml encoding data for %q: %w", f.path, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
w.WriteFileBytes(f.path, b)
|
|
|
|
}
|
|
|
|
|
|
|
|
filesToWriteAsString := []struct {
|
|
|
|
value string
|
|
|
|
path string
|
|
|
|
}{
|
|
|
|
{a.NebulaCACert.CACert, nebulaCertsCACertPath},
|
|
|
|
{a.NebulaCACert.CAKey, nebulaCertsCAKeyPath},
|
|
|
|
{a.GarageRPCSecret, garageRPCSecretPath},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, f := range filesToWriteAsString {
|
|
|
|
w.WriteFileBytes(f.path, []byte(f.value))
|
|
|
|
}
|
|
|
|
|
|
|
|
return w.Close()
|
|
|
|
}
|