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.
103 lines
3.6 KiB
Go
103 lines
3.6 KiB
Go
package repo
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.kebcloud.no/keb/lazysecrets/internal/provider"
|
|
)
|
|
|
|
// hunter2, encrypted by Jasypt with the password "test-password".
|
|
const jasyptHunter2 = "ENC(5IQUKT4B7j38TnZJ+BlWqo/zSkKHTjl4XRJyaQEHgkCy4r00avLt4dWqFB74X0Zw)"
|
|
|
|
func TestJasyptPassword(t *testing.T) {
|
|
dir := t.TempDir()
|
|
value := func(name, body string) (string, error) {
|
|
file := filepath.Join(dir, name)
|
|
if err := os.WriteFile(file, []byte(body), 0o600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
key := "app.token"
|
|
if !IsSpring(name) {
|
|
key = "TOKEN"
|
|
}
|
|
v, err := (&Provider{}).Value(context.Background(), provider.Object{ID: file + "\x00" + key, Name: key})
|
|
return v.Reveal(), err
|
|
}
|
|
t.Setenv("JASYPT_ENCRYPTOR_PASSWORD", "")
|
|
t.Setenv("MY_PASSWORD", "")
|
|
spring := func(password string) string {
|
|
return "jasypt.encryptor.password: " + password + "\napp.token: " + jasyptHunter2 + "\n"
|
|
}
|
|
|
|
for _, c := range []struct{ name, file, body, env, want string }{
|
|
{"the file's own", "application.yml", spring("test-password"), "", "hunter2"},
|
|
{"a ${VAR}", "application.yml", spring("${MY_PASSWORD}"), "test-password", "hunter2"},
|
|
{"a ${VAR}'s default", "application.yml", spring("${MY_PASSWORD:test-password}"), "", "hunter2"},
|
|
{"properties", "application-local.properties", "jasypt.encryptor.password=test-password\napp.token=" + jasyptHunter2 + "\n", "", "hunter2"},
|
|
{"env file", ".env", "JASYPT_ENCRYPTOR_PASSWORD=test-password\nTOKEN=" + jasyptHunter2 + "\n", "", "hunter2"},
|
|
{"not jasypt", ".env", "TOKEN=hunter2\n", "", "hunter2"},
|
|
} {
|
|
t.Setenv("MY_PASSWORD", c.env)
|
|
if got, err := value(c.file, c.body); err != nil || got != c.want {
|
|
t.Errorf("%s: %q %v", c.name, got, err)
|
|
}
|
|
}
|
|
|
|
// $JASYPT_ENCRYPTOR_PASSWORD wins over the file's, as in Spring.
|
|
t.Setenv("JASYPT_ENCRYPTOR_PASSWORD", "test-password")
|
|
if got, err := value("application.yml", spring("wrong")); err != nil || got != "hunter2" {
|
|
t.Errorf("environment first: %q %v", got, err)
|
|
}
|
|
t.Setenv("JASYPT_ENCRYPTOR_PASSWORD", "wrong")
|
|
if _, err := value("application.yml", spring("test-password")); err == nil || !strings.Contains(err.Error(), "the password from $JASYPT_ENCRYPTOR_PASSWORD") {
|
|
t.Errorf("a wrong one says where it's from: %v", err)
|
|
}
|
|
|
|
t.Setenv("JASYPT_ENCRYPTOR_PASSWORD", "")
|
|
t.Setenv("MY_PASSWORD", "")
|
|
for body, want := range map[string]string{
|
|
spring("${MY_PASSWORD}"): "$MY_PASSWORD isn't set",
|
|
"app.token: " + jasyptHunter2: "set $JASYPT_ENCRYPTOR_PASSWORD, or jasypt.encryptor.password in application.yml",
|
|
} {
|
|
if _, err := value("application.yml", body); err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("no password: %v, want %q", err, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestJasyptEnvFile(t *testing.T) {
|
|
root := gitRepo(t, map[string]string{
|
|
"jasypt.env": "TOKEN=" + jasyptHunter2 + "\n",
|
|
"mixed.env": "TOKEN=" + jasyptHunter2 + "\nURL=https://example.com\n",
|
|
})
|
|
ctx := context.Background()
|
|
p := New(Settings{Dir: root})
|
|
srcs, _ := p.Sources(ctx)
|
|
cs, _ := p.Containers(ctx, srcs[0])
|
|
for _, c := range cs {
|
|
attrs, _ := p.Details(ctx, c)
|
|
got := map[string]provider.Attr{}
|
|
for _, a := range attrs {
|
|
got[a.Label] = a
|
|
}
|
|
switch c.Name {
|
|
case "jasypt.env":
|
|
if got["encryption"].Value != "jasypt: 1 of 1 values" || got["git"].Warn {
|
|
t.Errorf("all jasypt: %+v", got)
|
|
}
|
|
keys, _ := p.Objects(ctx, c, provider.TypeSecret)
|
|
if len(keys) != 1 || keys[0].Attrs[1].Value != "jasypt" || keys[0].Detail != "jasypt" {
|
|
t.Errorf("keys: %+v", keys)
|
|
}
|
|
case "mixed.env":
|
|
if got["encryption"].Value != "jasypt: 1 of 2 values" || !got["git"].Warn {
|
|
t.Errorf("mixed: %+v", got)
|
|
}
|
|
}
|
|
}
|
|
}
|