compose.yaml, docker-compose.yml and their variants tracked by git are
listed under Repos, their services' environment variables as secrets,
named service.VAR.
- environment as a map or a list, and <<: *anchors shared between
services; the secret patterns pick the keys, the rest hidden, with
compose.secretPatterns for compose files' own.
- ${VAR}, $VAR, ${VAR:?…} and variables without a value are marked as
references; docker-compose.example.yml and the like are hidden.
- Jasypt values decrypt with the service's JASYPT_ENCRYPTOR_PASSWORD.
- A blue Docker icon, themeable with composeColor.
67 lines
2.3 KiB
Go
67 lines
2.3 KiB
Go
package repo
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"git.kebcloud.no/keb/lazysecrets/internal/jasypt"
|
|
"git.kebcloud.no/keb/lazysecrets/internal/provider"
|
|
)
|
|
|
|
// jasyptEnv is where Spring looks for the password first, before the
|
|
// config's jasypt.encryptor.password, and so does lazysecrets.
|
|
const jasyptEnv = "JASYPT_ENCRYPTOR_PASSWORD"
|
|
|
|
// jasyptValue decrypts v when it's a Jasypt value, ENC(...), from a plain
|
|
// file; other values are as they are.
|
|
func jasyptValue(file, name string, v provider.SecretValue) (provider.SecretValue, error) {
|
|
s := v.Reveal()
|
|
if !jasypt.Is(s) {
|
|
return v, nil
|
|
}
|
|
password, from, err := jasyptPassword(file, name)
|
|
if err != nil {
|
|
return provider.SecretValue{}, err
|
|
}
|
|
plain, err := jasypt.Decrypt(s, password)
|
|
if errors.Is(err, jasypt.ErrDecrypt) {
|
|
return provider.SecretValue{}, fmt.Errorf("jasypt: with the password from %s: %w", from, err)
|
|
}
|
|
if err != nil {
|
|
return provider.SecretValue{}, fmt.Errorf("jasypt: %w", err)
|
|
}
|
|
return provider.NewSecretValue([]byte(plain)), nil
|
|
}
|
|
|
|
// jasyptPassword is the password for the Jasypt value of the key named
|
|
// name, and where it's from: $JASYPT_ENCRYPTOR_PASSWORD, else the file's
|
|
// own setting (jasypt.encryptor.password in a Spring file; the service's
|
|
// JASYPT_ENCRYPTOR_PASSWORD in a compose file, the file's in an env file),
|
|
// with a ${VAR} in it read from the environment.
|
|
func jasyptPassword(file, name string) (password, from string, err error) {
|
|
if v := os.Getenv(jasyptEnv); v != "" {
|
|
return v, "$" + jasyptEnv, nil
|
|
}
|
|
setting, read, placeholder := jasyptEnv, plainValue, composePlaceholder // env files interpolate like compose
|
|
if t, ok := configTypeOf(file); ok {
|
|
setting, read, placeholder = t.jasyptSetting(name), t.value, t.placeholder
|
|
}
|
|
v, err := read(file, setting)
|
|
if err != nil {
|
|
return "", "", fmt.Errorf("jasypt: no password: set $%s, or %s in %s", jasyptEnv, setting, filepath.Base(file))
|
|
}
|
|
from = setting + " in " + filepath.Base(file)
|
|
env, def, hasDef, ok := placeholder(v.Reveal())
|
|
switch {
|
|
case !ok:
|
|
return v.Reveal(), from, nil
|
|
case os.Getenv(env) != "":
|
|
return os.Getenv(env), "$" + env + " (" + from + ")", nil
|
|
case hasDef:
|
|
return def, "the default in " + from, nil
|
|
}
|
|
return "", "", fmt.Errorf("jasypt: no password: %s is %s, and $%s isn't set", from, v.Reveal(), env)
|
|
}
|