Skip to content

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
FalcoSuessgott committed Jul 28, 2024
1 parent 9efd5df commit 4efdb0b
Show file tree
Hide file tree
Showing 21 changed files with 483 additions and 361 deletions.
2 changes: 1 addition & 1 deletion assets/export.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
{{- range $key, $value := $secrets }}
export {{ list $path $key | join "/" | replace "/" "_" | upper | trimPrefix "SECRET_" }}={{ $value | squote -}}
{{ end -}}
{{- end }}
{{- end }}
92 changes: 20 additions & 72 deletions cmd/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,25 @@ import (
prt "github.com/FalcoSuessgott/vkv/pkg/printer"
"github.com/FalcoSuessgott/vkv/pkg/utils"
"github.com/FalcoSuessgott/vkv/pkg/vault"
"github.com/k0kubun/pp/v3"
"github.com/spf13/cobra"
)

var fOpts = []vault.Option{}

// exportOptions holds all available commandline options.
type exportOptions struct {
Path string `env:"PATH"`
EnginePath string `env:"ENGINE_PATH"`

OnlyKeys bool `env:"ONLY_KEYS"`
OnlyPaths bool `env:"ONLY_PATHS"`
ShowValues bool `env:"SHOW_VALUES"`
WithHyperLink bool `env:"WITH_HYPERLINK" envDefault:"true"`
MaxValueLength int `env:"MAX_VALUE_LENGTH" envDefault:"12"`
ShowDiff bool `env:"SHOW_DIFF" envDefault:"true"`

SkipErrors bool `env:"SKIP_ERRORS" envDefault:"false"`

PrintLegend bool `env:"PRINT_LEGEND" envDefault:"true"`
ShowValues bool `env:"SHOW_VALUES"`

AllVersions bool

TemplateFile string `env:"TEMPLATE_FILE"`
TemplateString string `env:"TEMPLATE_STRING"`

FormatString string `env:"FORMAT" envDefault:"default"`
FormatString string `env:"FORMAT" envDefault:"default"`
FormatOptions []vault.Option
}

// NewExportCmd export subcommand.
Expand All @@ -56,34 +49,18 @@ func NewExportCmd() *cobra.Command {
RunE: func(cmd *cobra.Command, args []string) error {
rootPath, subPath := utils.HandleEnginePath(o.EnginePath, o.Path)

// TODO flag for all versions
kv, err := vaultClient.NewKVSecrets(rootPath, subPath, o.SkipErrors, true)
kv, err := vaultClient.NewKVSecrets(rootPath, subPath, o.SkipErrors, o.AllVersions)
if err != nil {
return err
}

opts := prt.DefaultPrinterOptions()
opts.Format = o.FormatString

pp.Println(kv.Secrets)
pp.Println("")

formatOptions := vault.NewFormatOptions(fOpts...)

fmt.Printf("%#v\n", formatOptions)

if err := prt.Print(kv.PrinterFuncs(formatOptions), opts); err != nil {
if err := prt.Print(kv.PrinterFuncs(vault.NewFormatOptions(o.FormatOptions...)), opts); err != nil {
return err
}

if o.FormatString == "default" && o.PrintLegend {
fmt.Printf("[ ] = no changes\n%s = added\n%s = changed\n%s = removed\n",
utils.ColorGreen("[+]"),
utils.ColorYellow("[~]"),
utils.ColorRed("[-]"),
)
}

return nil
},
}
Expand All @@ -96,21 +73,12 @@ func NewExportCmd() *cobra.Command {
cmd.Flags().BoolVar(&o.SkipErrors, "skip-errors", o.SkipErrors, "don't exit on errors (permission denied, deleted secrets) (env: VKV_EXPORT_SKIP_ERRORS)")

// Modify
cmd.Flags().BoolVar(&o.OnlyKeys, "only-keys", o.OnlyKeys, "show only keys (env: VKV_EXPORT_ONLY_KEYS)")
cmd.Flags().BoolVar(&o.OnlyPaths, "only-paths", o.OnlyPaths, "show only paths (env: VKV_EXPORT_ONLY_PATHS)")
cmd.Flags().BoolVar(&o.ShowValues, "show-values", o.ShowValues, "don't mask values (env: VKV_EXPORT_SHOW_VALUES)")
cmd.Flags().BoolVar(&o.WithHyperLink, "with-hyperlink", o.WithHyperLink, "don't link to the Vault UI (env: VKV_EXPORT_WITH_HYPERLINK)")
cmd.Flags().BoolVar(&o.ShowDiff, "show-diff", o.WithHyperLink, "when enabled highlights the diff for each secret version (env: VKV_EXPORT_SHOW_DIFF)")

cmd.Flags().IntVar(&o.MaxValueLength, "max-value-length", o.MaxValueLength, "maximum char length of values. Set to \"-1\" for disabling "+
"(env: VKV_EXPORT_MAX_VALUE_LENGTH)")

// Template
cmd.Flags().StringVar(&o.TemplateFile, "template-file", o.TemplateFile, "path to a file containing Go-template syntax to render the KV entries (env: VKV_EXPORT_TEMPLATE_FILE)")
cmd.Flags().StringVar(&o.TemplateString, "template-string", o.TemplateString, "template string containing Go-template syntax to render KV entries (env: VKV_EXPORT_TEMPLATE_STRING)")

cmd.Flags().BoolVarP(&o.PrintLegend, "legend", "l", o.PrintLegend, "wether to print a legend (env: VKV_EXPORT_PRINT_LEGEND)")

// Output format
cmd.Flags().StringVarP(&o.FormatString, "format", "f", o.FormatString, "one of the allowed output formats env: VKV_EXPORT_FORMAT)")

Expand All @@ -120,52 +88,30 @@ func NewExportCmd() *cobra.Command {
// nolint: cyclop, goconst
func (o *exportOptions) validateFlags(cmd *cobra.Command, args []string) error {
switch {
case (o.OnlyKeys && o.ShowValues), (o.OnlyPaths && o.ShowValues), (o.OnlyKeys && o.OnlyPaths):
return errInvalidFlagCombination
case o.EnginePath == "" && o.Path == "":
return errors.New("no KV-paths given. Either --engine-path / -e or --path / -p needs to be specified")
case o.EnginePath != "" && o.Path != "":
return errors.New("cannot specify both engine-path and path")
}

switch strings.ToLower(o.FormatString) {
case "yaml", "yml":
o.OnlyKeys = false
o.OnlyPaths = false
o.MaxValueLength = -1
// for certain output formats we dont mask secrets
case "yaml", "yml", "json", "export", "policy":
o.ShowValues = true
case "json":
o.OnlyKeys = false
o.OnlyPaths = false
o.MaxValueLength = -1
o.ShowValues = true
case "export":
o.OnlyKeys = false
o.OnlyPaths = false
o.ShowValues = true
o.MaxValueLength = -1
case "markdown":
case "default":
if o.ShowDiff {
fOpts = append(fOpts, vault.ShowDiff())
}

if o.OnlyKeys {
fOpts = append(fOpts, vault.OnlyKeys())
// for some we make it configurable
case "markdown", "default":
if !o.ShowValues {
o.FormatOptions = append(o.FormatOptions, vault.MaskSecrets())
}

case "full":
o.AllVersions = true
if !o.ShowValues {
fOpts = append(fOpts, vault.MaskSecrets())
o.FormatOptions = append(o.FormatOptions, vault.MaskSecrets())
}

case "policy":
o.OnlyKeys = false
o.OnlyPaths = false
o.ShowValues = true
o.FormatOptions = append(o.FormatOptions, vault.ShowDiff())
case "template", "tmpl":
o.OnlyKeys = false
o.OnlyPaths = false
o.MaxValueLength = -1
o.ShowValues = true

if o.TemplateFile != "" && o.TemplateString != "" {
return fmt.Errorf("%w: %s", errInvalidFlagCombination, "cannot specify both --template-file and --template-string")
Expand All @@ -174,6 +120,8 @@ func (o *exportOptions) validateFlags(cmd *cobra.Command, args []string) error {
if o.TemplateFile == "" && o.TemplateString == "" {
return fmt.Errorf("%w: %s", errInvalidFlagCombination, "either --template-file or --template-string is required")
}

o.FormatOptions = append(o.FormatOptions, vault.WithTemplate(o.TemplateString, o.TemplateFile))
default:
return prt.ErrInvalidPrinterFormat
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/render/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ import (
)

// String renders byte array input with the given data.
func Apply(tmpl []byte, input interface{}) (bytes.Buffer, error) {
func Apply(tmpl []byte, input interface{}) ([]byte, error) {
var buf bytes.Buffer

tpl, err := template.New("template").
Option("missingkey=error").
Funcs(sprig.FuncMap()).
Parse(string(tmpl))
if err != nil {
return buf, err
return nil, err
}

if err := tpl.Execute(&buf, input); err != nil {
return buf, err
return nil, err
}

return buf, nil
return buf.Bytes(), nil
}
2 changes: 1 addition & 1 deletion pkg/render/render_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestRenderTemplate(t *testing.T) {
})

require.NoError(t, err)
assert.Equal(t, "This is a test template which replaces certain values!", result.String())
assert.Equal(t, "This is a test template which replaces certain values!", string(result))
}

func TestRenderInvalidString(t *testing.T) {
Expand Down
83 changes: 52 additions & 31 deletions pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"path"
"path/filepath"
"sort"
"strconv"
"strings"
"time"

Expand All @@ -23,12 +24,17 @@ const (
// Delimiter / delimiter for splitting a path.
Delimiter = "/"

NoColorEnv = "NO_COLOR"
MaxValueLengthEnv = "MAX_VALUE_LENGTH"
NoColorEnv = "NO_COLOR"
NoHyperlinksEnv = "NO_HYPERLINKS"

Reset = "\033[0m"
Red = "\033[31m"
Green = "\033[32m"
Yellow = "\033[33m"

has = "✔"
hasNot = "✖"
)

// Keys type for receiving all keys of a map.
Expand All @@ -38,29 +44,58 @@ func NormalizePath(path string) string {
return filepath.Clean(path) + Delimiter
}

var (
ColorRed = func(text string) string {
if _, ok := os.LookupEnv(NoColorEnv); !ok {
return fmt.Sprintf("%s%s%s", Red, text, Reset)
}
func ColorRed(text string) string {
if _, ok := os.LookupEnv(NoColorEnv); !ok {
return fmt.Sprintf("%s%s%s", Red, text, Reset)
}

return text
}

return text
func ColorYellow(text string) string {
if _, ok := os.LookupEnv(NoColorEnv); !ok {
return fmt.Sprintf("%s%s%s", Yellow, text, Reset)
}
ColorYellow = func(text string) string {
if _, ok := os.LookupEnv(NoColorEnv); !ok {
return fmt.Sprintf("%s%s%s", Yellow, text, Reset)
}

return text
return text
}

func ColorGreen(text string) string {
if _, ok := os.LookupEnv(NoColorEnv); !ok {
return fmt.Sprintf("%s%s%s", Green, text, Reset)
}
ColorGreen = func(text string) string {
if _, ok := os.LookupEnv(NoColorEnv); !ok {
return fmt.Sprintf("%s%s%s", Green, text, Reset)

return text
}

func MaskString(s interface{}) string {
length := 12

if v, ok := os.LookupEnv(MaxValueLengthEnv); ok {
i, err := strconv.Atoi(v)
if err != nil {
log.Printf("invalid value for %s - using default value %d\n", MaxValueLengthEnv, length)
}

return text
length = i
}

n := fmt.Sprintf("%s", s)

if len(n) > length && length != -1 {
return strings.Repeat("*", length)
}
)

return strings.Repeat("*", len(n))
}

func ResolveCap(v bool) string {
if v {
return ColorGreen(has)
}

return ColorRed(hasNot)
}

// FlattenMap flattens a nested map into a single map with its.
func FlattenMap(a, b map[string]interface{}, key string) {
Expand All @@ -82,10 +117,6 @@ func UnflattenMap[T any](path string, v []*T, ignoreElements ...string) map[stri

parts := strings.Split(path, Delimiter)

// if path == "" {
// return
// }

path = NormalizePath(path)

// if element is to be ignored
Expand Down Expand Up @@ -318,13 +349,3 @@ func ParseEnvs(prefix string, i interface{}) error {
func TimeAgo(t time.Time) string {
return timeago.Parse(t)
}

func MaskString(s interface{}, length int) string {
n := fmt.Sprintf("%s", s)

if len(n) > length && length != -1 {
return strings.Repeat("*", length)
}

return strings.Repeat("*", len(n))
}
Loading

0 comments on commit 4efdb0b

Please sign in to comment.