Добавлены новые возможности для работы с файловыми логами Docker-сервисов: - Эндпоинты для получения списка логов и хвоста лог-файла. - Очистка лог-файлов с возможностью выбора режима (truncate или delete) и запись в аудит очистки. - Обновлена документация и конфигурация для поддержки новых функций. Co-authored-by: Cursor <[email protected]>
70 lines
1.5 KiB
Go
70 lines
1.5 KiB
Go
package runtimelogs
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
var filenamePattern = regexp.MustCompile(`^[a-z0-9][a-z0-9_.-]*\.log$`)
|
|
|
|
// ValidateFilename checks basename allowlist for runtime log files.
|
|
func ValidateFilename(filename string) error {
|
|
name := strings.TrimSpace(filename)
|
|
if name == "" || len(name) > 128 {
|
|
return ErrInvalidFilename
|
|
}
|
|
if name != filepath.Base(name) {
|
|
return ErrInvalidFilename
|
|
}
|
|
if strings.Contains(name, "..") {
|
|
return ErrInvalidFilename
|
|
}
|
|
if !filenamePattern.MatchString(name) {
|
|
return ErrInvalidFilename
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ResolveLogPath maps a validated basename to an absolute path under root.
|
|
func ResolveLogPath(root, filename string) (string, error) {
|
|
if err := ValidateFilename(filename); err != nil {
|
|
return "", err
|
|
}
|
|
rootAbs, err := filepath.Abs(root)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
rootAbs = filepath.Clean(rootAbs)
|
|
candidate := filepath.Join(rootAbs, filename)
|
|
resolved, err := filepath.EvalSymlinks(candidate)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
resolved = filepath.Clean(candidate)
|
|
} else {
|
|
return "", err
|
|
}
|
|
}
|
|
resolved = filepath.Clean(resolved)
|
|
if !pathUnderRoot(resolved, rootAbs) {
|
|
return "", ErrInvalidFilename
|
|
}
|
|
if st, err := os.Lstat(resolved); err == nil {
|
|
if st.IsDir() {
|
|
return "", ErrNotAFile
|
|
}
|
|
}
|
|
return resolved, nil
|
|
}
|
|
|
|
func pathUnderRoot(path, root string) bool {
|
|
path = filepath.Clean(path)
|
|
root = filepath.Clean(root)
|
|
if path == root {
|
|
return false
|
|
}
|
|
sep := string(os.PathSeparator)
|
|
return strings.HasPrefix(path+sep, root+sep)
|
|
}
|