// Package garage contains helper functions and types which are useful for // setting up garage configs, processes, and deployments. package garage import ( "encoding/hex" "errors" "fmt" "io/fs" "os" "path/filepath" ) const ( // Region is the region which garage is configured with. Region = "garage" // GlobalBucket is the name of the global garage bucket which is // accessible to all hosts in the network. GlobalBucket = "cryptic-net-global" // ReplicationFactor indicates the replication factor set on the garage // cluster. We currently only support a factor of 3. ReplicationFactor = 3 ) func nodeKeyPath(metaDirPath string) string { return filepath.Join(metaDirPath, "node_key") } func nodeKeyPubPath(metaDirPath string) string { return filepath.Join(metaDirPath, "node_key.pub") } // LoadAllocID returns the peer ID (ie the public key) of the node at the given // meta directory. func LoadAllocID(metaDirPath string) (string, error) { nodeKeyPubPath := nodeKeyPubPath(metaDirPath) pubKey, err := os.ReadFile(nodeKeyPubPath) if err != nil { return "", fmt.Errorf("reading %q: %w", nodeKeyPubPath, err) } return hex.EncodeToString(pubKey), nil } // InitAlloc initializes the meta directory and keys for a particular // allocation, if it hasn't been done so already. It returns the peer ID (ie the // public key) in any case. func InitAlloc(metaDirPath string) (string, error) { var err error exists := func(path string) bool { if err != nil { return false } else if _, err = os.Stat(path); errors.Is(err, fs.ErrNotExist) { return false } else if err != nil { err = fmt.Errorf("checking if %q exists: %w", path, err) return false } return true } nodeKeyPath := nodeKeyPath(metaDirPath) nodeKeyPubPath := nodeKeyPubPath(metaDirPath) nodeKeyPathExists := exists(nodeKeyPath) nodeKeyPubPathExists := exists(nodeKeyPubPath) if err != nil { return "", err } else if nodeKeyPubPathExists != nodeKeyPathExists { return "", fmt.Errorf("%q or %q exist without the other existing", nodeKeyPath, nodeKeyPubPath) } else if nodeKeyPathExists { return LoadAllocID(metaDirPath) } // node key hasn't been written, write it if err := os.MkdirAll(metaDirPath, 0750); err != nil { return "", fmt.Errorf("making directory %q: %w", metaDirPath, err) } pubKey, privKey := GeneratePeerKey() if err := os.WriteFile(nodeKeyPath, privKey, 0400); err != nil { return "", fmt.Errorf("writing private key to %q: %w", nodeKeyPath, err) } else if err := os.WriteFile(nodeKeyPubPath, pubKey, 0440); err != nil { return "", fmt.Errorf("writing public key to %q: %w", nodeKeyPubPath, err) } return "", nil }