fix: harden thothctl diagnostics
This commit is contained in:
@@ -8,12 +8,15 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
const installationFileName = "thothii-installation.yaml"
|
||||
|
||||
const maxEnvironmentFileBytes = 1 << 20
|
||||
|
||||
type descriptor struct {
|
||||
Profile string `yaml:"profile"`
|
||||
ProjectDirectory string `yaml:"projectDirectory"`
|
||||
@@ -116,6 +119,62 @@ func (i Installation) ComposeArgs(command ...string) []string {
|
||||
return append(args, command...)
|
||||
}
|
||||
|
||||
// SecretFiles returns only existing, absolute regular files declared in the installation env file
|
||||
// through *_FILE or *_SOURCE variables. Missing paths are allowed because /run/secrets paths are
|
||||
// container-local declarations, not host files thothctl can read.
|
||||
func (i Installation) SecretFiles() ([]string, error) {
|
||||
info, err := os.Stat(i.EnvFile)
|
||||
if err != nil || info.Size() > maxEnvironmentFileBytes {
|
||||
return nil, errors.New("installation secret declarations could not be read")
|
||||
}
|
||||
contents, err := os.ReadFile(i.EnvFile)
|
||||
if err != nil || len(contents) > maxEnvironmentFileBytes {
|
||||
return nil, errors.New("installation secret declarations could not be read")
|
||||
}
|
||||
|
||||
files := make([]string, 0)
|
||||
seen := make(map[string]struct{})
|
||||
for _, line := range strings.Split(string(contents), "\n") {
|
||||
key, value, ok := environmentAssignment(line)
|
||||
if !ok || (!strings.HasSuffix(key, "_FILE") && !strings.HasSuffix(key, "_SOURCE")) || !filepath.IsAbs(value) {
|
||||
continue
|
||||
}
|
||||
fileInfo, err := os.Lstat(value)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
continue
|
||||
}
|
||||
if err != nil || !fileInfo.Mode().IsRegular() {
|
||||
return nil, errors.New("installation secret declarations could not be read")
|
||||
}
|
||||
if _, exists := seen[value]; !exists {
|
||||
files = append(files, value)
|
||||
seen[value] = struct{}{}
|
||||
}
|
||||
}
|
||||
return files, nil
|
||||
}
|
||||
|
||||
func environmentAssignment(line string) (string, string, bool) {
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" || strings.HasPrefix(line, "#") {
|
||||
return "", "", false
|
||||
}
|
||||
line = strings.TrimPrefix(line, "export ")
|
||||
key, value, found := strings.Cut(line, "=")
|
||||
if !found {
|
||||
return "", "", false
|
||||
}
|
||||
key = strings.TrimSpace(key)
|
||||
if key == "" {
|
||||
return "", "", false
|
||||
}
|
||||
value = strings.TrimSpace(value)
|
||||
if len(value) >= 2 && ((value[0] == '"' && value[len(value)-1] == '"') || (value[0] == '\'' && value[len(value)-1] == '\'')) {
|
||||
value = value[1 : len(value)-1]
|
||||
}
|
||||
return strings.ToUpper(key), value, true
|
||||
}
|
||||
|
||||
func ensureOnlyOneDocument(decoder *yaml.Decoder) error {
|
||||
var extra any
|
||||
err := decoder.Decode(&extra)
|
||||
|
||||
Reference in New Issue
Block a user