From af85595e957c9f3dfb7d80487f5202a806feb0f3 Mon Sep 17 00:00:00 2001 From: Ernest Micklei Date: Sat, 27 Jan 2024 11:53:25 +0100 Subject: [PATCH 1/2] add analyse command to find weak secrets --- README.md | 6 ++++- cmd/kiya/cmd_analyse.go | 53 +++++++++++++++++++++++++++++++++++++++++ cmd/kiya/main.go | 5 +++- go.mod | 1 + go.sum | 2 ++ 5 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 cmd/kiya/cmd_analyse.go diff --git a/README.md b/README.md index 8c17600..dbc8a90 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ Use the backend `ssm` if you are storing keys in AWS Parameter Store as part of "backend": "akv", "vaultUrl": "https://.vault.azure.net" }, - "ag5": { + "teamF5-on-ssm": { "backend": "ssm", "location": "eu-central-1" } @@ -195,7 +195,11 @@ For accessing OS environment values: kiya teamF1 move bitbucket.org/johndoe teamF2 +### Analyse all secrets by checking their strength (entropy) +```shell +kiya teamF2 analyse +``` ## Backup diff --git a/cmd/kiya/cmd_analyse.go b/cmd/kiya/cmd_analyse.go new file mode 100644 index 0000000..583975d --- /dev/null +++ b/cmd/kiya/cmd_analyse.go @@ -0,0 +1,53 @@ +package main + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/kramphub/kiya/backend" + + passwordvalidator "github.com/wagslane/go-password-validator" +) + +// commandAnalyse perform an analysis of the profile +func commandAnalyse(ctx context.Context, b backend.Backend, target *backend.Profile) { + fmt.Printf("loading all secrets in profile [%s]...\n", target.Label) + + when := time.Now() + kv, err := getAllItems(ctx, b, *target, "") + if err != nil { + log.Printf("error: failed to get all items, %s", err.Error()) + return + } + fmt.Printf("loaded all secrets [%d] in %v\n", len(kv), time.Since(when)) + + fmt.Println("detecting weak secrets with entroopy < 50 ...") + when = time.Now() + count := 0 + for k, v := range kv { + entropy := passwordvalidator.GetEntropy(string(v)) + if entropy < 50 { + count++ + fmt.Printf("WARNING: ") + } + fmt.Printf("kiya %s copy %s (entropy:%.2f length:%d)\n", target.Label, k, entropy, len(v)) + } + fmt.Printf("detected weak secrets [%d] in %v\n", count, time.Since(when)) +} + +// getAllItems returns all keys and values in store. +func getAllItems(ctx context.Context, b backend.Backend, target backend.Profile, filter string) (map[string][]byte, error) { + items := make(map[string][]byte) + keys := commandList(ctx, b, &target, filter) + for _, key := range keys { + buf, err := b.Get(ctx, &target, key.Name) + if err != nil { + fmt.Printf("error: get key '%s' failed, %s", key.Name, err.Error()) + continue + } + items[key.Name] = buf + } + return items, nil +} diff --git a/cmd/kiya/main.go b/cmd/kiya/main.go index 21be2e1..0aff695 100644 --- a/cmd/kiya/main.go +++ b/cmd/kiya/main.go @@ -40,7 +40,7 @@ func main() { } kiya.LoadConfiguration(*oConfigFilename) if len(flag.Args()) < 2 { - fmt.Println("kiya [flags] [profile] [get|put|delete|list|template|copy|paste|move|generate] [|parent/key] [|value] [|template-filename] [|secret-length]") + fmt.Println("kiya [flags] [profile] [get|put|delete|list|template|copy|paste|move|generate|analyse] [|parent/key] [|value] [|template-filename] [|secret-length]") fmt.Println(" if value, template-filename or secret length is needed, but missing, it is read from stdin") flag.PrintDefaults() os.Exit(0) @@ -337,6 +337,9 @@ func main() { } fmt.Println("Public key copied to clipboard") + case "analyse": + commandAnalyse(ctx, b, &target) + default: keys := commandList(ctx, b, &target, flag.Arg(1)) writeTable(keys, &target, flag.Arg(1)) diff --git a/go.mod b/go.mod index 41340ae..6900090 100644 --- a/go.mod +++ b/go.mod @@ -55,6 +55,7 @@ require ( github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect + github.com/wagslane/go-password-validator v0.3.0 // indirect go.opencensus.io v0.24.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect diff --git a/go.sum b/go.sum index a3acac4..626a86f 100644 --- a/go.sum +++ b/go.sum @@ -129,6 +129,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/wagslane/go-password-validator v0.3.0 h1:vfxOPzGHkz5S146HDpavl0cw1DSVP061Ry2PX0/ON6I= +github.com/wagslane/go-password-validator v0.3.0/go.mod h1:TI1XJ6T5fRdRnHqHt14pvy1tNVnrwe7m3/f1f2fDphQ= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= From faf4b52d4c898f1a61b706dcf4626f0c2c8b96ce Mon Sep 17 00:00:00 2001 From: Ernest Micklei Date: Sat, 27 Jan 2024 13:51:19 +0100 Subject: [PATCH 2/2] only output warnings --- cmd/kiya/cmd_analyse.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/kiya/cmd_analyse.go b/cmd/kiya/cmd_analyse.go index 583975d..768e7ef 100644 --- a/cmd/kiya/cmd_analyse.go +++ b/cmd/kiya/cmd_analyse.go @@ -30,9 +30,8 @@ func commandAnalyse(ctx context.Context, b backend.Backend, target *backend.Prof entropy := passwordvalidator.GetEntropy(string(v)) if entropy < 50 { count++ - fmt.Printf("WARNING: ") + fmt.Printf("WARNING: kiya %s copy %s (entropy:%.2f length:%d)\n", target.Label, k, entropy, len(v)) } - fmt.Printf("kiya %s copy %s (entropy:%.2f length:%d)\n", target.Label, k, entropy, len(v)) } fmt.Printf("detected weak secrets [%d] in %v\n", count, time.Since(when)) }