package config import ( "bytes" "fmt" "os" "gopkg.in/yaml.v3" ) // Load reads and decodes the file at path. A missing file is not an error: // it returns a zero-valued *File so the tool remains usable purely from // flags/env (see the package doc). Unknown YAML keys are a hard error so // typos in a hand-edited config surface immediately instead of being // silently ignored. func Load(path string) (*File, error) { data, err := os.ReadFile(path) if err != nil { if os.IsNotExist(err) { return &File{Version: SchemaVersion}, nil } return nil, fmt.Errorf("reading config %q: %w", path, err) } var f File dec := yaml.NewDecoder(bytes.NewReader(data)) dec.KnownFields(true) if err := dec.Decode(&f); err != nil { return nil, fmt.Errorf("parsing config %q: %w", path, err) } if f.Version == 0 { f.Version = SchemaVersion } if f.Version != SchemaVersion { return nil, fmt.Errorf("config %q has version %d, vault-tui supports version %d", path, f.Version, SchemaVersion) } for name, p := range f.Profiles { if p != nil && p.Token.Value != "" { fmt.Fprintf(os.Stderr, "warning: profile %q sets token.value directly in the config file; prefer VAULT_TOKEN or token.file\n", name) } } return &f, nil } // Save writes f to path as YAML, creating parent directories as needed. // The file is written with 0600 permissions since profiles may carry // TLS key paths and (discouraged but supported) inline token values. func Save(path string, f *File) error { if err := os.MkdirAll(dirOf(path), 0o700); err != nil { return fmt.Errorf("creating config directory: %w", err) } var buf bytes.Buffer enc := yaml.NewEncoder(&buf) enc.SetIndent(2) if err := enc.Encode(f); err != nil { return fmt.Errorf("encoding config: %w", err) } if err := enc.Close(); err != nil { return err } return os.WriteFile(path, buf.Bytes(), 0o600) } func dirOf(path string) string { for i := len(path) - 1; i >= 0; i-- { if path[i] == '/' { return path[:i] } } return "." } // Exists reports whether a config file is present at path. func Exists(path string) bool { _, err := os.Stat(path) return err == nil }