ENC(...) values are decrypted on reveal, copy or get with
jasypt-spring-boot's default algorithm (3.0+, PBEWITHHMACSHA512ANDAES_256).
- The password is, as in Spring, $JASYPT_ENCRYPTOR_PASSWORD, else the
file's own jasypt.encryptor.password (JASYPT_ENCRYPTOR_PASSWORD in a
.env), with ${VAR} and ${VAR:default} read from the environment.
- Errors say which password was used, or which one is missing.
- Secrets show a detail after their name: jasypt, or reference for a
Spring ${VAR}; also in Go to and Favourites.
- A .env whose values are all Jasypt isn't marked as plain text in git.
95 lines
2.9 KiB
Go
95 lines
2.9 KiB
Go
package repo
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"git.kebcloud.no/keb/lazysecrets/internal/provider"
|
|
)
|
|
|
|
// Details are how a file is encrypted and for whom, and what git knows of
|
|
// it: a plain .env file that git tracks, or could, is marked.
|
|
func (p *Provider) Details(ctx context.Context, c provider.Container) ([]provider.Attr, error) {
|
|
r, ok := p.repo(c.Source.ID)
|
|
if !ok {
|
|
return nil, provider.ErrUnsupported
|
|
}
|
|
rel, err := filepath.Rel(r.root, c.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var out []provider.Attr
|
|
meta, isSops := readMeta(c.ID)
|
|
// A plain file's values are at risk in git, unless they're all Jasypt;
|
|
// a Spring file's only when one of its secrets is in plain text.
|
|
plain := !isSops
|
|
if !isSops && IsSpring(c.ID) {
|
|
out, plain = p.springDetails(c)
|
|
} else if isSops {
|
|
out = append(out, provider.Attr{Label: "encryption", Value: "sops · " + strings.Join(meta.methods, ", ")})
|
|
for i, k := range meta.recipients {
|
|
label := ""
|
|
if i == 0 {
|
|
label = "keys"
|
|
}
|
|
out = append(out, provider.Attr{Label: label, Value: k})
|
|
}
|
|
if !meta.modified.IsZero() {
|
|
out = append(out, provider.Attr{Label: "encrypted", Value: meta.modified.Local().Format("2006-01-02 15:04")})
|
|
}
|
|
} else {
|
|
out, plain = envDetails(c.ID)
|
|
}
|
|
|
|
git := func(args ...string) (string, bool) {
|
|
b, err := exec.CommandContext(ctx, "git", append([]string{"-C", r.root}, args...)...).Output()
|
|
return strings.TrimSpace(string(b)), err == nil
|
|
}
|
|
switch _, tracked := git("ls-files", "--error-unmatch", "--", rel); {
|
|
case tracked && plain:
|
|
out = append(out, provider.Attr{Label: "git", Value: "tracked: its values are in the repo's history", Warn: true})
|
|
case tracked:
|
|
out = append(out, provider.Attr{Label: "git", Value: "tracked"})
|
|
default:
|
|
if _, ignored := git("check-ignore", "-q", "--", rel); ignored {
|
|
out = append(out, provider.Attr{Label: "git", Value: "ignored"})
|
|
} else {
|
|
out = append(out, provider.Attr{Label: "git", Value: "untracked and not ignored: easy to commit by mistake", Warn: plain})
|
|
}
|
|
return out, nil
|
|
}
|
|
if last, ok := git("log", "-1", "--format=%h · %ar", "--", rel); ok && last != "" {
|
|
out = append(out, provider.Attr{Label: "last commit", Value: last})
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
// envDetails says how a plain env file's values are encrypted, and whether
|
|
// any is in plain text.
|
|
func envDetails(file string) (attrs []provider.Attr, plain bool) {
|
|
b, err := os.ReadFile(file)
|
|
if err != nil {
|
|
return []provider.Attr{{Label: "encryption", Value: err.Error(), Warn: true}}, true
|
|
}
|
|
keys, _ := parseKeys(file, b)
|
|
n := 0
|
|
for _, k := range keys {
|
|
if k.jasypt {
|
|
n++
|
|
}
|
|
}
|
|
return []provider.Attr{{Label: "encryption", Value: jasyptShare(n, len(keys))}}, n < len(keys)
|
|
}
|
|
|
|
// jasyptShare is how many of a plain file's values are Jasypt's.
|
|
func jasyptShare(n, of int) string {
|
|
if n == 0 {
|
|
return "none: plain text"
|
|
}
|
|
return fmt.Sprintf("jasypt: %d of %d values", n, of)
|
|
}
|