diff --git a/solver/llbsolver/file/backend.go b/solver/llbsolver/file/backend.go index 974c2e04e8773..d4a0b24c7087c 100644 --- a/solver/llbsolver/file/backend.go +++ b/solver/llbsolver/file/backend.go @@ -10,6 +10,7 @@ import ( "github.com/containerd/continuity/fs" "github.com/docker/docker/pkg/idtools" + "github.com/moby/buildkit/executor" "github.com/moby/buildkit/snapshot" "github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes" "github.com/moby/buildkit/solver/pb" @@ -25,46 +26,6 @@ func timestampToTime(ts int64) *time.Time { return &tm } -func mapUserToChowner(user *copy.User, idmap *idtools.IdentityMapping) (copy.Chowner, error) { - if user == nil { - return func(old *copy.User) (*copy.User, error) { - if old == nil { - if idmap == nil { - return nil, nil - } - old = ©.User{} // root - // non-nil old is already mapped - if idmap != nil { - identity, err := idmap.ToHost(idtools.Identity{ - UID: old.UID, - GID: old.GID, - }) - if err != nil { - return nil, err - } - return ©.User{UID: identity.UID, GID: identity.GID}, nil - } - } - return old, nil - }, nil - } - u := *user - if idmap != nil { - identity, err := idmap.ToHost(idtools.Identity{ - UID: user.UID, - GID: user.GID, - }) - if err != nil { - return nil, err - } - u.UID = identity.UID - u.GID = identity.GID - } - return func(*copy.User) (*copy.User, error) { - return &u, nil - }, nil -} - func mkdir(ctx context.Context, d string, action pb.FileActionMkDir, user *copy.User, idmap *idtools.IdentityMapping) error { p, err := fs.RootPath(d, filepath.Join("/", action.Path)) if err != nil { @@ -258,6 +219,7 @@ func cleanPath(s string) string { } type Backend struct { + Executor executor.Executor } func (fb *Backend) Mkdir(ctx context.Context, m, user, group fileoptypes.Mount, action pb.FileActionMkDir) error { @@ -273,7 +235,7 @@ func (fb *Backend) Mkdir(ctx context.Context, m, user, group fileoptypes.Mount, } defer lm.Unmount() - u, err := readUser(action.Owner, user, group) + u, err := readUser(action.Owner, user, group, fb.Executor) if err != nil { return err } @@ -294,7 +256,7 @@ func (fb *Backend) Mkfile(ctx context.Context, m, user, group fileoptypes.Mount, } defer lm.Unmount() - u, err := readUser(action.Owner, user, group) + u, err := readUser(action.Owner, user, group, fb.Executor) if err != nil { return err } @@ -342,7 +304,7 @@ func (fb *Backend) Copy(ctx context.Context, m1, m2, user, group fileoptypes.Mou } defer lm2.Unmount() - u, err := readUser(action.Owner, user, group) + u, err := readUser(action.Owner, user, group, fb.Executor) if err != nil { return err } diff --git a/solver/llbsolver/file/backend_unix.go b/solver/llbsolver/file/backend_unix.go new file mode 100644 index 0000000000000..d01290f300ace --- /dev/null +++ b/solver/llbsolver/file/backend_unix.go @@ -0,0 +1,49 @@ +//go:build !windows +// +build !windows + +package file + +import ( + "github.com/docker/docker/pkg/idtools" + copy "github.com/tonistiigi/fsutil/copy" +) + +func mapUserToChowner(user *copy.User, idmap *idtools.IdentityMapping) (copy.Chowner, error) { + if user == nil { + return func(old *copy.User) (*copy.User, error) { + if old == nil { + if idmap == nil { + return nil, nil + } + old = ©.User{} // root + // non-nil old is already mapped + if idmap != nil { + identity, err := idmap.ToHost(idtools.Identity{ + UID: old.UID, + GID: old.GID, + }) + if err != nil { + return nil, err + } + return ©.User{UID: identity.UID, GID: identity.GID}, nil + } + } + return old, nil + }, nil + } + u := *user + if idmap != nil { + identity, err := idmap.ToHost(idtools.Identity{ + UID: user.UID, + GID: user.GID, + }) + if err != nil { + return nil, err + } + u.UID = identity.UID + u.GID = identity.GID + } + return func(*copy.User) (*copy.User, error) { + return &u, nil + }, nil +} diff --git a/solver/llbsolver/file/backend_windows.go b/solver/llbsolver/file/backend_windows.go new file mode 100644 index 0000000000000..03f3bbe7b3089 --- /dev/null +++ b/solver/llbsolver/file/backend_windows.go @@ -0,0 +1,22 @@ +package file + +import ( + "github.com/docker/docker/pkg/idtools" + copy "github.com/tonistiigi/fsutil/copy" +) + +func mapUserToChowner(user *copy.User, idmap *idtools.IdentityMapping) (copy.Chowner, error) { + if user == nil || user.SID == "" { + return func(old *copy.User) (*copy.User, error) { + if old == nil || old.SID == "" { + old = ©.User{ + SID: idtools.ContainerAdministratorSidString, + } + } + return old, nil + }, nil + } + return func(*copy.User) (*copy.User, error) { + return user, nil + }, nil +} diff --git a/solver/llbsolver/file/user_linux.go b/solver/llbsolver/file/user_linux.go index 1f17431f5c326..2871db9b0d1a9 100644 --- a/solver/llbsolver/file/user_linux.go +++ b/solver/llbsolver/file/user_linux.go @@ -13,7 +13,7 @@ import ( copy "github.com/tonistiigi/fsutil/copy" ) -func readUser(chopt *pb.ChownOpt, mu, mg fileoptypes.Mount) (*copy.User, error) { +func readUser(chopt *pb.ChownOpt, mu, mg fileoptypes.Mount, exec executor.Executor) (*copy.User, error) { if chopt == nil { return nil, nil } diff --git a/solver/llbsolver/file/user_nolinux.go b/solver/llbsolver/file/user_other.go similarity index 50% rename from solver/llbsolver/file/user_nolinux.go rename to solver/llbsolver/file/user_other.go index 80652fd4abe4b..1a81984a6afdd 100644 --- a/solver/llbsolver/file/user_nolinux.go +++ b/solver/llbsolver/file/user_other.go @@ -1,5 +1,5 @@ -//go:build !linux -// +build !linux +//go:build !linux && !windows +// +build !linux,!windows package file @@ -10,9 +10,9 @@ import ( copy "github.com/tonistiigi/fsutil/copy" ) -func readUser(chopt *pb.ChownOpt, mu, mg fileoptypes.Mount) (*copy.User, error) { +func readUser(chopt *pb.ChownOpt, mu, mg fileoptypes.Mount, exec executor.Executor) (*copy.User, error) { if chopt == nil { return nil, nil } - return nil, errors.New("only implemented in linux") + return nil, errors.New("only implemented in linux and windows") } diff --git a/solver/llbsolver/file/user_windows.go b/solver/llbsolver/file/user_windows.go new file mode 100644 index 0000000000000..06e160e7085da --- /dev/null +++ b/solver/llbsolver/file/user_windows.go @@ -0,0 +1,41 @@ +package file + +import ( + "context" + + "github.com/docker/docker/pkg/idtools" + "github.com/moby/buildkit/executor" + "github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes" + "github.com/moby/buildkit/solver/pb" + "github.com/moby/buildkit/util/windows" + "github.com/pkg/errors" + copy "github.com/tonistiigi/fsutil/copy" +) + +func readUser(chopt *pb.ChownOpt, mu, mg fileoptypes.Mount, exec executor.Executor) (*copy.User, error) { + if chopt == nil { + return nil, nil + } + + if chopt.User != nil { + switch u := chopt.User.User.(type) { + case *pb.UserOpt_ByName: + if mu == nil { + return nil, errors.Errorf("invalid missing user mount") + } + mmu, ok := mu.(*Mount) + if !ok { + return nil, errors.Errorf("invalid mount type %T", mu) + } + + ident, err := windows.ResolveUsernameToSID(context.Background(), exec, mmu.m, u.ByName.Name) + if err != nil { + return nil, err + } + return ©.User{SID: ident.SID}, nil + default: + return ©.User{SID: idtools.ContainerAdministratorSidString}, nil + } + } + return ©.User{SID: idtools.ContainerAdministratorSidString}, nil +} diff --git a/solver/llbsolver/ops/file.go b/solver/llbsolver/ops/file.go index 7bbb3276797cd..f3225e45e2c2c 100644 --- a/solver/llbsolver/ops/file.go +++ b/solver/llbsolver/ops/file.go @@ -46,7 +46,7 @@ func NewFileOp(v solver.Vertex, op *pb.Op_File, cm cache.Manager, parallelism *s md: cm, numInputs: len(v.Inputs()), w: w, - solver: NewFileOpSolver(w, &file.Backend{}, file.NewRefManager(cm, v.Name())), + solver: NewFileOpSolver(w, &file.Backend{Executor: w.Executor()}, file.NewRefManager(cm, v.Name())), parallelism: parallelism, }, nil }