122 lines
2.7 KiB
Go
122 lines
2.7 KiB
Go
// Copyright © 2022 Roberto Hidalgo <joao@un.rob.mx>
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
opClient "git.rob.mx/nidito/joao/pkg/op-client"
|
|
op "github.com/1Password/connect-sdk-go/onepassword"
|
|
"github.com/sirupsen/logrus"
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
const warnChecksumMismatch = `1Password item %s changed and checksum was not updated.
|
|
Expected: %s
|
|
found : %s`
|
|
|
|
func Load(ref string, preferRemote bool) (*Config, error) {
|
|
if preferRemote {
|
|
name := ref
|
|
vault := ""
|
|
|
|
if argIsYAMLFile(ref) {
|
|
path, err := filepath.Abs(ref)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not find asbolute path to file %s: %w", ref, err)
|
|
}
|
|
name, vault, err = VaultAndNameFrom(path, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
parts := strings.SplitN(ref, "/", 2)
|
|
if len(parts) > 1 {
|
|
vault = parts[0]
|
|
name = parts[1]
|
|
}
|
|
}
|
|
|
|
item, err := opClient.Get(vault, name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return FromOP(item)
|
|
}
|
|
|
|
if !argIsYAMLFile(ref) {
|
|
return nil, fmt.Errorf("could not load %s from local as it's not a path", ref)
|
|
}
|
|
|
|
path, err := filepath.Abs(ref)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not find asbolute path to file %s: %w", ref, err)
|
|
}
|
|
cfg, err := FromFile(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not load file %s: %w", path, err)
|
|
}
|
|
return cfg, nil
|
|
}
|
|
|
|
// FromFile reads a path and returns a config.
|
|
func FromFile(path string) (*Config, error) {
|
|
buf, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not read file %s", path)
|
|
}
|
|
|
|
if len(buf) == 0 {
|
|
buf = []byte("{}")
|
|
}
|
|
|
|
name, vault, err := VaultAndNameFrom(path, buf)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
logrus.Debugf("Found name: %s and vault: %s", name, vault)
|
|
|
|
cfg, err := FromYAML(buf)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cfg.Name = name
|
|
cfg.Vault = vault
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
// FromYAML reads yaml bytes and returns a config.
|
|
func FromYAML(data []byte) (*Config, error) {
|
|
cfg := &Config{
|
|
Tree: NewEntry("root", yaml.MappingNode),
|
|
}
|
|
|
|
err := yaml.Unmarshal(data, &cfg.Tree)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not parse %w", err)
|
|
}
|
|
cfg.Tree.SetPath([]string{}, ".")
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
// FromOP reads a config from an op item and returns a config.
|
|
func FromOP(item *op.Item) (*Config, error) {
|
|
cfg := &Config{
|
|
Vault: item.Vault.ID,
|
|
Name: item.Title,
|
|
Tree: NewEntry("root", yaml.MappingNode),
|
|
}
|
|
|
|
if cs := opClient.Checksum(item.Fields); cs != item.GetValue("password") {
|
|
logrus.Warnf(warnChecksumMismatch, fmt.Sprintf("%s/%s", item.Vault.ID, item.Title), cs, item.GetValue("password"))
|
|
}
|
|
err := cfg.Tree.FromOP(item.Fields)
|
|
return cfg, err
|
|
}
|