|
|
|
@ -1,29 +1,14 @@ |
|
|
|
|
// Package admin deals with the parsing and creation of admin.tgz files.
|
|
|
|
|
// Package admin deals with the parsing and creation of admin.yml 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 ( |
|
|
|
|
creationParamsPath = "admin/creation-params.yml" |
|
|
|
|
|
|
|
|
|
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" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// 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 { |
|
|
|
@ -31,105 +16,28 @@ type CreationParams struct { |
|
|
|
|
Domain string `yaml:"domain"` |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Admin is used for accessing all information contained within an admin.tgz.
|
|
|
|
|
// Admin is used for accessing all information contained within an admin.yml.
|
|
|
|
|
type Admin struct { |
|
|
|
|
CreationParams CreationParams |
|
|
|
|
|
|
|
|
|
NebulaCACredentials nebula.CACredentials |
|
|
|
|
|
|
|
|
|
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.CreationParams, creationParamsPath}, |
|
|
|
|
{&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) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
CreationParams CreationParams `yaml:"creation_params"` |
|
|
|
|
|
|
|
|
|
filesToLoadAsString := []struct { |
|
|
|
|
into *string |
|
|
|
|
path string |
|
|
|
|
}{ |
|
|
|
|
{&a.NebulaCACredentials.CACertPEM, nebulaCertsCACertPath}, |
|
|
|
|
{&a.NebulaCACredentials.CAKeyPEM, nebulaCertsCAKeyPath}, |
|
|
|
|
{&a.GarageRPCSecret, garageRPCSecretPath}, |
|
|
|
|
} |
|
|
|
|
Nebula struct { |
|
|
|
|
CACredentials nebula.CACredentials `yaml:"ca_credentials"` |
|
|
|
|
} `yaml:"nebula"` |
|
|
|
|
|
|
|
|
|
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 |
|
|
|
|
Garage struct { |
|
|
|
|
RPCSecret string `yaml:"rpc_secret"` |
|
|
|
|
GlobalBucketS3APICredentials garage.S3APICredentials `yaml:"global_bucket_s3_api_credentials"` |
|
|
|
|
} `yaml:"garage"` |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// FromReader reads an admin.tgz file from the given io.Reader.
|
|
|
|
|
// FromReader reads an admin.yml 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) |
|
|
|
|
var a Admin |
|
|
|
|
err := yaml.NewDecoder(r).Decode(&a) |
|
|
|
|
return a, err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// WriteTo writes the Admin as a new admin.tgz to the given io.Writer.
|
|
|
|
|
// WriteTo writes the Admin as an admin.yml to the given io.Writer.
|
|
|
|
|
func (a Admin) WriteTo(into io.Writer) error { |
|
|
|
|
|
|
|
|
|
w := tarutil.NewTGZWriter(into) |
|
|
|
|
|
|
|
|
|
filesToWriteAsYAML := []struct { |
|
|
|
|
value interface{} |
|
|
|
|
path string |
|
|
|
|
}{ |
|
|
|
|
{a.CreationParams, creationParamsPath}, |
|
|
|
|
{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.NebulaCACredentials.CACertPEM, nebulaCertsCACertPath}, |
|
|
|
|
{a.NebulaCACredentials.CAKeyPEM, nebulaCertsCAKeyPath}, |
|
|
|
|
{a.GarageRPCSecret, garageRPCSecretPath}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for _, f := range filesToWriteAsString { |
|
|
|
|
w.WriteFileBytes(f.path, []byte(f.value)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return w.Close() |
|
|
|
|
return yaml.NewEncoder(into).Encode(a) |
|
|
|
|
} |
|
|
|
|