Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion internal/io/vault/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ func PrintVaultList(format string, vaultNames []string) {
for _, name := range vaultNames {
vault, err := vaultFromName(name)
if err != nil {
logger.Log().Fatalf("Vault error %s - %v", name, err)
logger.Log().Warnf("vault %s could not be opened - %v", name, err)
vault = unopenableVault(name, err)
}
vaults.Vaults = append(vaults.Vaults, vault)
}
Expand Down
15 changes: 11 additions & 4 deletions internal/io/vault/view.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,20 @@ type vaultEntity struct {
Name string `json:"name" yaml:"name"`
Path string `json:"path" yaml:"path"`
Type string `json:"type" yaml:"type"`
// Error is set when the vault could not be opened. It is listed anyway, so
// one unusable vault does not hide every other one.
Error string `json:"error,omitempty" yaml:"error,omitempty"`

Data map[string]interface{} `json:"data" yaml:"data"`
}

// unopenableVault is the placeholder for a vault whose config loads but whose
// provider will not open -- a missing key, a revoked identity, a config written
// by an older version.
func unopenableVault(name string, err error) *vaultEntity {
return &vaultEntity{Name: name, Type: "unknown", Error: err.Error(), Data: map[string]interface{}{}}
}

func (v *vaultEntity) YAML() (string, error) {
data, err := yaml.Marshal(v)
if err != nil {
Expand Down Expand Up @@ -115,10 +125,7 @@ func NewVaultListView(
for _, name := range vaultNames {
v, err := vaultFromName(name)
if err != nil || v == nil {
return views.NewErrorView(
fmt.Errorf("vault '%s' error: %w", name, err),
container.RenderState().Theme,
)
v = unopenableVault(name, err)
}
vaults = append(vaults, v)
}
Expand Down
19 changes: 12 additions & 7 deletions internal/vault/vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,7 @@ func NewExternalVault(providerConfigFile string) (*CreateResult, error) {
return nil, fmt.Errorf("invalid vault name %q in config: %w", cfg.ID, err)
}

// An external vault keeps a registry of the links it holds. A config authored
// elsewhere -- rendered from a preset, or written by hand -- has no business
// knowing where flow keeps vault state, so it arrives without a storage path
// and flow supplies the same location every other provider uses.
if cfg.External != nil && cfg.External.StoragePath == "" {
cfg.External.StoragePath = CacheDirectory(cfg.ID)
}
applyExternalDefaults(&cfg)

v, _, err := vault.New(cfg.ID, vault.WithExternalConfig(cfg.External))
if err != nil {
Expand Down Expand Up @@ -250,6 +244,8 @@ func VaultFromName(name string) (*VaultConfig, Vault, error) {
return nil, nil, fmt.Errorf("failed to load vault config: %w", err)
}

applyExternalDefaults(&cfg)

switch cfg.Type {
case vault.ProviderTypeAge:
provider, err := vault.NewAgeVault(&cfg)
Expand Down Expand Up @@ -360,3 +356,12 @@ func writeKeyToFile(key, filePath string) error {

return nil
}

// applyExternalDefaults fills in settings a config authored elsewhere cannot
// know. External vaults created before the link registry existed have no
// storage path, so this has to run when opening a vault as well as creating one.
func applyExternalDefaults(cfg *VaultConfig) {
if cfg.External != nil && cfg.External.StoragePath == "" {
cfg.External.StoragePath = CacheDirectory(cfg.ID)
}
}
Loading