123 lines
2.9 KiB
Go
123 lines
2.9 KiB
Go
|
// 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 (
|
||
|
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"
|
||
|
)
|
||
|
|
||
|
// Admin is used for accessing all information contained within an admin.tgz.
|
||
|
type Admin struct {
|
||
|
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
|
||
|
}{
|
||
|
{&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
|
||
|
}{
|
||
|
{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()
|
||
|
}
|