Set secret/config uid:gid to match container's USER

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
Nicolas De Loof 2025-10-15 11:10:27 +02:00 committed by Nicolas De loof
parent 157617480a
commit ee75be342b
4 changed files with 79 additions and 2 deletions

View file

@ -133,12 +133,17 @@ func (s *composeService) prepareRun(ctx context.Context, project *types.Project,
return "", err
}
err = s.injectSecrets(ctx, project, service, created.ID)
ctr, err := s.apiClient().ContainerInspect(ctx, created.ID)
if err != nil {
return "", err
}
err = s.injectSecrets(ctx, project, service, ctr.ID)
if err != nil {
return created.ID, err
}
err = s.injectConfigs(ctx, project, service, created.ID)
err = s.injectConfigs(ctx, project, service, ctr.ID)
return created.ID, err
}

View file

@ -22,6 +22,7 @@ import (
"context"
"fmt"
"strconv"
"strings"
"time"
"github.com/compose-spec/compose-go/v2/types"
@ -29,6 +30,7 @@ import (
)
func (s *composeService) injectSecrets(ctx context.Context, project *types.Project, service types.ServiceConfig, id string) error {
var ctrConfig *container.Config
for _, config := range service.Secrets {
file := project.Secrets[config.Source]
if file.Environment == "" {
@ -53,6 +55,25 @@ func (s *composeService) injectSecrets(ctx context.Context, project *types.Proje
}
content = env
}
if config.UID == "" && config.GID == "" {
if ctrConfig == nil {
ctr, err := s.apiClient().ContainerInspect(ctx, id)
if err != nil {
return err
}
ctrConfig = ctr.Config
}
parts := strings.Split(ctrConfig.User, ":")
if len(parts) > 0 {
config.UID = parts[0]
}
if len(parts) > 1 {
config.GID = parts[1]
}
}
b, err := createTar(content, types.FileReferenceConfig(config))
if err != nil {
return err
@ -69,6 +90,7 @@ func (s *composeService) injectSecrets(ctx context.Context, project *types.Proje
}
func (s *composeService) injectConfigs(ctx context.Context, project *types.Project, service types.ServiceConfig, id string) error {
var ctrConfig *container.Config
for _, config := range service.Configs {
file := project.Configs[config.Source]
content := file.Content
@ -91,6 +113,24 @@ func (s *composeService) injectConfigs(ctx context.Context, project *types.Proje
config.Target = "/" + config.Source
}
if config.UID == "" && config.GID == "" {
if ctrConfig == nil {
ctr, err := s.apiClient().ContainerInspect(ctx, id)
if err != nil {
return err
}
ctrConfig = ctr.Config
}
parts := strings.Split(ctrConfig.User, ":")
if len(parts) > 0 {
config.UID = parts[0]
}
if len(parts) > 1 {
config.GID = parts[1]
}
}
b, err := createTar(content, types.FileReferenceConfig(config))
if err != nil {
return err

View file

@ -14,6 +14,23 @@ services:
mode: 0440
command: cat /run/secrets/bar
bar:
image: alpine
user: "1005"
secrets:
- source: secret
target: bar
command: cat /run/secrets/bar
zot:
image: alpine
user: "1005:1005"
secrets:
- source: secret
target: bar
command: cat /run/secrets/bar
secrets:
secret:
environment: SECRET

View file

@ -40,6 +40,21 @@ func TestSecretFromEnv(t *testing.T) {
})
res.Assert(t, icmd.Expected{Out: "-r--r----- 1 1005 1005"})
})
t.Run("secret uid from user", func(t *testing.T) {
res := icmd.RunCmd(c.NewDockerComposeCmd(t, "-f", "./fixtures/env-secret/compose.yaml", "run", "bar", "ls", "-al", "/var/run/secrets/bar"),
func(cmd *icmd.Cmd) {
cmd.Env = append(cmd.Env, "SECRET=BAR")
})
res.Assert(t, icmd.Expected{Out: "-r--r--r-- 1 1005 root"})
})
t.Run("secret uid:gid from user", func(t *testing.T) {
res := icmd.RunCmd(c.NewDockerComposeCmd(t, "-f", "./fixtures/env-secret/compose.yaml", "run", "zot", "ls", "-al", "/var/run/secrets/bar"),
func(cmd *icmd.Cmd) {
cmd.Env = append(cmd.Env, "SECRET=BAR")
})
res.Assert(t, icmd.Expected{Out: "-r--r--r-- 1 1005 1005"})
})
}
func TestSecretFromInclude(t *testing.T) {