Skip to content

Commit

Permalink
feat(server): introduce server command
Browse files Browse the repository at this point in the history
  • Loading branch information
FalcoSuessgott committed Nov 18, 2023
1 parent 5701f97 commit a6ed0f6
Show file tree
Hide file tree
Showing 7 changed files with 231 additions and 9 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ on:
paths:
- '**.go'
branches:
- master
- '*'
- '!master'
pull_request_target:

jobs:
Expand Down
4 changes: 4 additions & 0 deletions Dockerfile.goreleaser
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
FROM alpine:3.17
COPY vkv /usr/bin/vkv

# required for vkv server
EXPOSE 8080

ENTRYPOINT ["/usr/bin/vkv"]
3 changes: 1 addition & 2 deletions cmd/export/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ func NewExportCmd(writer io.Writer, vaultClient *vault.Vault) *cobra.Command {
)

// prepare map

m, err := o.buildMap(vaultClient)
if err != nil {
return err
Expand All @@ -106,7 +105,7 @@ func NewExportCmd(writer io.Writer, vaultClient *vault.Vault) *cobra.Command {
// Input
cmd.Flags().StringVarP(&o.Path, "path", "p", o.Path, "KVv2 Engine path (env: VKV_EXPORT_PATH)")
cmd.Flags().StringVarP(&o.EnginePath, "engine-path", "e", o.EnginePath, "engine path in case your KV-engine contains special characters such as \"/\", the path value will then be appended if specified (\"<engine-path>/<path>\") (env: VKV_EXPORT_ENGINE_PATH)")
cmd.Flags().BoolVar(&o.SkipErrors, "skip-errors", o.SkipErrors, "dont exit on errors (permission denied, deleted secrets)")
cmd.Flags().BoolVar(&o.SkipErrors, "skip-errors", o.SkipErrors, "dont 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)")
Expand Down
2 changes: 2 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
imp "github.com/FalcoSuessgott/vkv/cmd/imp"
"github.com/FalcoSuessgott/vkv/cmd/list"
"github.com/FalcoSuessgott/vkv/cmd/manpage"
"github.com/FalcoSuessgott/vkv/cmd/server"
"github.com/FalcoSuessgott/vkv/cmd/snapshot"
"github.com/FalcoSuessgott/vkv/cmd/version"
"github.com/spf13/cobra"
Expand All @@ -33,6 +34,7 @@ func NewRootCmd(v string, writer io.Writer) *cobra.Command {
snapshot.NewSnapshotCmd(writer, nil),
version.NewVersionCmd(v),
imp.NewImportCmd(writer, nil),
server.NewServerCmd(writer, nil),
manpage.NewManCmd().Cmd,
)

Expand Down
141 changes: 141 additions & 0 deletions cmd/server/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package server

import (
"bytes"
"io"
"log"
"path"
"fmt"

printer "github.com/FalcoSuessgott/vkv/pkg/printer/secret"
"github.com/FalcoSuessgott/vkv/pkg/utils"
"github.com/FalcoSuessgott/vkv/pkg/vault"
"github.com/caarlos0/env/v6"
"github.com/gin-gonic/gin"
"github.com/spf13/cobra"
)

const envVarExportPrefix = "VKV_SERVER_"

type serverOptions struct {
Port string `env:"PORT" envDefault:"8080"`
Path string `env:"PATH"`
EnginePath string `env:"ENGINE_PATH"`
SkipErrors bool `env:"SKIP_ERRORS" envDefault:"false"`
}

// NewServerCmd export subcommand.
//nolint:lll
func NewServerCmd(writer io.Writer, vaultClient *vault.Vault) *cobra.Command {
var err error

o := &serverOptions{}

if err := o.parseEnvs(); err != nil {
log.Fatal(err)
}

cmd := &cobra.Command{
Use: "server",
Short: "expose a http server that returns the read secrets from Vault, useful during CI",
SilenceUsage: true,
SilenceErrors: true,
RunE: func(cmd *cobra.Command, args []string) error {
// vault auth
if vaultClient == nil {
if vaultClient, err = vault.NewDefaultClient(); err != nil {
return err
}
}

b := bytes.NewBufferString("")

// prepare printer
printer := printer.NewPrinter(
printer.ShowValues(true),
printer.ToFormat(printer.Export),
printer.WithVaultClient(vaultClient),
printer.WithWriter(b),
)

// prepare map
m, err := o.buildMap(vaultClient)
if err != nil {
return err
}

// print secrets
enginePath, _ := utils.HandleEnginePath(o.EnginePath, o.Path)

if err := printer.Out(enginePath, m); err != nil {
return err
}

return o.serve(b.Bytes())
},
}

cmd.Flags().SortFlags = false

// Input
cmd.Flags().StringVarP(&o.Port, "port", "P", o.Port, "HTTP Server Port (env: VKV_SERVER_PATH)")
cmd.Flags().StringVarP(&o.Path, "path", "p", o.Path, "KVv2 Engine path (env: VKV_SERVER_PATH)")
cmd.Flags().StringVarP(&o.EnginePath, "engine-path", "e", o.EnginePath, "engine path in case your KV-engine contains special characters such as \"/\", the path value will then be appended if specified (\"<engine-path>/<path>\") (env: VKV_SERVER_ENGINE_PATH)")
cmd.Flags().BoolVar(&o.SkipErrors, "skip-errors", o.SkipErrors, "dont exit on errors (permission denied, deleted secrets) (env: VKV_SERVER_SKIP_ERRORS)")

return cmd
}

func (o *serverOptions) buildMap(v *vault.Vault) (map[string]interface{}, error) {
var isSecretPath bool

rootPath, subPath := utils.HandleEnginePath(o.EnginePath, o.Path)

// read recursive all secrets
s, err := v.ListRecursive(rootPath, subPath, o.SkipErrors)
if err != nil {
return nil, err
}

// check if path is a directory or secret path
if _, isSecret := v.ReadSecrets(rootPath, subPath); isSecret == nil {
isSecretPath = true
}

path := path.Join(rootPath, subPath)
if o.EnginePath != "" {
path = subPath
}

// prepare the output map
pathMap := utils.PathMap(path, utils.ToMapStringInterface(s), isSecretPath)

if o.EnginePath != "" {
return map[string]interface{}{
o.EnginePath: pathMap,
}, nil
}

return pathMap, nil
}

func (o *serverOptions) parseEnvs() error {
if err := env.Parse(o, env.Options{
Prefix: envVarExportPrefix,
}); err != nil {
return err
}

return nil
}

func (o *serverOptions) serve(secrets []byte) error {
gin.SetMode(gin.ReleaseMode)
r := gin.Default()

r.GET("/export", func(c *gin.Context) {
c.Data(200, "text/plain", secrets)
})

return r.Run(fmt.Sprintf(":%s", o.Port))
}
30 changes: 24 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,15 @@ require (
github.com/breml/errchkjson v0.3.6 // indirect
github.com/butuzov/ireturn v0.2.1 // indirect
github.com/butuzov/mirror v1.1.0 // indirect
github.com/bytedance/sonic v1.10.2 // indirect
github.com/catenacyber/perfsprint v0.2.0 // indirect
github.com/ccojocar/zxcvbn-go v1.0.1 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/charithe/durationcheck v0.0.10 // indirect
github.com/chavacava/garif v0.1.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/containerd/containerd v1.7.7 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/cpuguy83/dockercfg v0.3.1 // indirect
Expand All @@ -68,10 +71,16 @@ require (
github.com/firefart/nonamedreturns v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/fzipp/gocyclo v0.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/ghostiam/protogetter v0.2.3 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.9.1 // indirect
github.com/go-critic/go-critic v0.9.0 // indirect
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.16.0 // indirect
github.com/go-toolsmith/astcast v1.1.0 // indirect
github.com/go-toolsmith/astcopy v1.1.0 // indirect
github.com/go-toolsmith/astequal v1.1.0 // indirect
Expand All @@ -81,6 +90,7 @@ require (
github.com/go-toolsmith/typep v1.1.0 // indirect
github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/gofrs/flock v0.8.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
Expand Down Expand Up @@ -113,16 +123,19 @@ require (
github.com/jgautheron/goconst v1.6.0 // indirect
github.com/jingyugao/rowserrcheck v1.1.1 // indirect
github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/julz/importas v0.1.0 // indirect
github.com/kisielk/errcheck v1.6.3 // indirect
github.com/kisielk/gotool v1.0.0 // indirect
github.com/kkHAIKE/contextcheck v1.1.4 // indirect
github.com/klauspost/compress v1.17.0 // indirect
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
github.com/kulti/thelper v0.6.3 // indirect
github.com/kunwardeep/paralleltest v1.0.8 // indirect
github.com/kyoh86/exportloopref v0.1.11 // indirect
github.com/ldez/gomoddirectives v0.2.3 // indirect
github.com/ldez/tagliatelle v0.5.0 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/leonklingele/grouper v1.1.1 // indirect
github.com/lufeee/execinquery v1.2.1 // indirect
github.com/lufia/plan9stats v0.0.0-20230326075908-cb1d2100619a // indirect
Expand All @@ -133,7 +146,7 @@ require (
github.com/maratori/testpackage v1.1.1 // indirect
github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mbilski/exhaustivestruct v1.2.0 // indirect
Expand All @@ -142,6 +155,8 @@ require (
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/patternmatcher v0.6.0 // indirect
github.com/moby/sys/sequential v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/moricho/tparallel v0.3.1 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/muesli/mango v0.2.0 // indirect
Expand All @@ -153,7 +168,7 @@ require (
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc5 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/polyfloyd/go-errorlint v1.4.5 // indirect
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
Expand Down Expand Up @@ -201,6 +216,8 @@ require (
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/tomarrell/wrapcheck/v2 v2.8.1 // indirect
github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect
github.com/ultraware/funlen v0.1.0 // indirect
github.com/ultraware/whitespace v0.0.5 // indirect
github.com/uudashr/gocognit v1.1.2 // indirect
Expand All @@ -214,12 +231,13 @@ require (
go.tmz.dev/musttag v0.7.2 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/goleak v1.1.12 // indirect
golang.org/x/arch v0.6.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833 // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/sync v0.4.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/sys v0.14.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.14.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
google.golang.org/grpc v1.58.2 // indirect
Expand Down Expand Up @@ -254,7 +272,7 @@ require (
github.com/hashicorp/go-hclog v1.5.0 // indirect
github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
github.com/olekukonko/tablewriter v0.0.5
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/crypto v0.15.0 // indirect
golang.org/x/net v0.18.0 // indirect
golang.org/x/time v0.3.0 // indirect
)
Loading

0 comments on commit a6ed0f6

Please sign in to comment.