1
0
mirror of https://github.com/lxc/distrobuilder.git synced 2026-02-05 06:45:19 +01:00

Add user/group ID mapping from passwd and group files

Introduce functionality to parse `/etc/passwd` and `/etc/group` files to map symbolic user/group names to numeric IDs. This ensures consistency in file definitions by replacing symbolic references with their corresponding numeric IDs in the global configuration. An environment override for logger colors was also added.

Signed-off-by: Arthur <git@arthur.pro>
This commit is contained in:
Arthur
2025-03-01 15:49:18 +00:00
parent bfae9cc45e
commit 196667c0c2
3 changed files with 83 additions and 1 deletions

View File

@@ -265,11 +265,35 @@ func (c *cmdIncus) run(cmd *cobra.Command, args []string, overlayDir string) err
imageTargets |= shared.ImageTargetContainer
}
for _, file := range c.global.definition.Files {
// Maps symbolic user/group names to their numeric IDs using information from passwd and group files.
userMap, groupMap, err := parsePasswdAndGroupFiles(overlayDir)
if err != nil {
c.global.logger.WithField("overlay", overlayDir).Warn("Could not parse passwd/group file: %w", err)
}
for i, file := range c.global.definition.Files {
if !shared.ApplyFilter(&file, c.global.definition.Image.Release, c.global.definition.Image.ArchitectureMapped, c.global.definition.Image.Variant, c.global.definition.Targets.Type, imageTargets) {
continue
}
if file.UID != "" && !isNumeric(file.UID) {
uid, exists := userMap[file.UID]
if exists {
c.global.definition.Files[i].UID = uid
} else {
c.global.logger.WithField("generator", file.Generator).Warnf("Could not find UID for user %q", file.UID)
}
}
if file.UID != "" && !isNumeric(file.GID) {
gid, exists := groupMap[file.GID]
if exists {
c.global.definition.Files[i].GID = gid
} else {
c.global.logger.WithField("generator", file.Generator).Warnf("Could not find GID for group %q", file.GID)
}
}
generator, err := generators.Load(file.Generator, c.global.logger, c.global.flagCacheDir, overlayDir, file, *c.global.definition)
if err != nil {
return fmt.Errorf("Failed to load generator %q: %w", file.Generator, err)

56
distrobuilder/passwd.go Normal file
View File

@@ -0,0 +1,56 @@
package main
import (
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
)
// parsePasswdAndGroupFiles reads passwd and group files from the given root directory
// and returns mappings of names to IDs for both users and groups.
func parsePasswdAndGroupFiles(rootDir string) (map[string]string, map[string]string, error) {
userMap, err := parsePasswdFile(filepath.Join(rootDir, "/etc/passwd"))
if err != nil {
return nil, nil, fmt.Errorf("parsing passwd file: %w", err)
}
groupMap, err := parsePasswdFile(filepath.Join(rootDir, "/etc/group"))
if err != nil {
return nil, nil, fmt.Errorf("parsing group file: %w", err)
}
return userMap, groupMap, nil
}
// parsePasswdFile reads a passwd-format file and returns a map of names to IDs.
func parsePasswdFile(path string) (map[string]string, error) {
idMap := make(map[string]string)
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("reading file %s: %w", path, err)
}
for _, line := range strings.Split(string(data), "\n") {
if line == "" {
continue
}
fields := strings.Split(line, ":")
if len(fields) < 3 {
continue
}
idMap[fields[0]] = fields[2]
}
return idMap, nil
}
// isNumeric is a helper function to check if a string is numeric.
func isNumeric(s string) bool {
_, err := strconv.Atoi(s)
return err == nil
}

View File

@@ -17,6 +17,8 @@ func GetLogger(debug bool) (*logrus.Logger, error) {
PadLevelText: true,
}
formatter.EnvironmentOverrideColors = true
logger.Formatter = &formatter
if debug {