diff --git a/client/client_test.go b/client/client_test.go index a61e9dfcfcf5..cd2efb246671 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -36,6 +36,7 @@ func TestClientIntegration(t *testing.T) { testBuildHTTPSource, testBuildPushAndValidate, testResolveAndHosts, + testUser, }) } @@ -200,6 +201,59 @@ func testResolveAndHosts(t *testing.T, sb integration.Sandbox) { } +func testUser(t *testing.T, sb integration.Sandbox) { + requiresLinux(t) + t.Parallel() + c, err := New(sb.Address()) + require.NoError(t, err) + defer c.Close() + + st := llb.Image("busybox:latest").Run(llb.Shlex(`sh -c "mkdir -m 0777 /wd"`)) + + run := func(user, cmd string) { + st = st.Run(llb.Shlex(cmd), llb.Dir("/wd"), llb.User(user)) + } + + run("daemon", `sh -c "id -nu > user"`) + run("daemon:daemon", `sh -c "id -ng > group"`) + run("daemon:nogroup", `sh -c "id -ng > nogroup"`) + run("1:1", `sh -c "id -g > userone"`) + + st = st.Run(llb.Shlex("cp -a /wd/. /out/")) + out := st.AddMount("/out", llb.Scratch()) + + def, err := out.Marshal() + require.NoError(t, err) + + destDir, err := ioutil.TempDir("", "buildkit") + require.NoError(t, err) + defer os.RemoveAll(destDir) + + err = c.Solve(context.TODO(), def, SolveOpt{ + Exporter: ExporterLocal, + ExporterAttrs: map[string]string{ + "output": destDir, + }, + }, nil) + require.NoError(t, err) + + dt, err := ioutil.ReadFile(filepath.Join(destDir, "user")) + require.NoError(t, err) + require.Contains(t, string(dt), "daemon") + + dt, err = ioutil.ReadFile(filepath.Join(destDir, "group")) + require.NoError(t, err) + require.Contains(t, string(dt), "daemon") + + dt, err = ioutil.ReadFile(filepath.Join(destDir, "nogroup")) + require.NoError(t, err) + require.Contains(t, string(dt), "nogroup") + + dt, err = ioutil.ReadFile(filepath.Join(destDir, "userone")) + require.NoError(t, err) + require.Contains(t, string(dt), "1") +} + func testBuildPushAndValidate(t *testing.T, sb integration.Sandbox) { requiresLinux(t) t.Parallel() diff --git a/client/llb/exec.go b/client/llb/exec.go index 7496488403fc..6ca048e3f20d 100644 --- a/client/llb/exec.go +++ b/client/llb/exec.go @@ -12,6 +12,7 @@ type Meta struct { Args []string Env EnvList Cwd string + User string } func NewExecOp(root Output, meta Meta, readOnly bool, md OpMetadata) *ExecOp { @@ -110,6 +111,7 @@ func (e *ExecOp) Marshal() ([]byte, *OpMetadata, error) { Args: e.meta.Args, Env: e.meta.Env.ToArray(), Cwd: e.meta.Cwd, + User: e.meta.User, }, } @@ -271,6 +273,12 @@ func AddEnvf(key, value string, v ...interface{}) RunOption { }) } +func User(str string) RunOption { + return runOptionFunc(func(ei *ExecInfo) { + ei.State = ei.State.User(str) + }) +} + func Dir(str string) RunOption { return Dirf(str) } diff --git a/client/llb/meta.go b/client/llb/meta.go index 34fb6d8fed78..3f8f8be30718 100644 --- a/client/llb/meta.go +++ b/client/llb/meta.go @@ -12,6 +12,7 @@ var ( keyArgs = contextKeyT("llb.exec.args") keyDir = contextKeyT("llb.exec.dir") keyEnv = contextKeyT("llb.exec.env") + keyUser = contextKeyT("llb.exec.user") ) func addEnv(key, value string) StateOption { @@ -42,6 +43,12 @@ func dirf(str string, v ...interface{}) StateOption { } } +func user(str string) StateOption { + return func(s State) State { + return s.WithValue(keyUser, str) + } +} + func reset(s_ State) StateOption { return func(s State) State { s = NewState(s.Output()) @@ -74,6 +81,14 @@ func getArgs(s State) []string { return nil } +func getUser(s State) string { + v := s.Value(keyUser) + if v != nil { + return v.(string) + } + return "" +} + func args(args ...string) StateOption { return func(s State) State { return s.WithValue(keyArgs, args) diff --git a/client/llb/state.go b/client/llb/state.go index 1fdb00602c1a..64a2a7f476ac 100644 --- a/client/llb/state.go +++ b/client/llb/state.go @@ -129,6 +129,7 @@ func (s State) Run(ro ...RunOption) ExecState { Args: getArgs(ei.State), Cwd: getDir(ei.State), Env: getEnv(ei.State), + User: getUser(ei.State), } exec := NewExecOp(s.Output(), meta, ei.ReadonlyRootFS, ei.Metadata()) @@ -173,6 +174,10 @@ func (s State) Reset(s2 State) State { return reset(s2)(s) } +func (s State) User(v string) State { + return user(v)(s) +} + func (s State) With(so ...StateOption) State { for _, o := range so { s = o(s) diff --git a/executor/containerdexecutor/executor.go b/executor/containerdexecutor/executor.go index aaa1c0919328..fd1550c46290 100644 --- a/executor/containerdexecutor/executor.go +++ b/executor/containerdexecutor/executor.go @@ -7,10 +7,12 @@ import ( "github.com/containerd/containerd" "github.com/containerd/containerd/cio" + containerdoci "github.com/containerd/containerd/oci" "github.com/moby/buildkit/cache" "github.com/moby/buildkit/executor" "github.com/moby/buildkit/executor/oci" "github.com/moby/buildkit/identity" + "github.com/moby/buildkit/snapshot" "github.com/pkg/errors" "golang.org/x/net/context" ) @@ -40,16 +42,31 @@ func (w containerdExecutor) Exec(ctx context.Context, meta executor.Meta, root c return err } - spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile) + rootMounts, err := root.Mount(ctx, false) if err != nil { return err } - defer cleanup() - rootMounts, err := root.Mount(ctx, false) + uid, gid, err := oci.ParseUser(meta.User) + if err != nil { + lm := snapshot.LocalMounter(rootMounts) + rootfsPath, err := lm.Mount() + if err != nil { + return err + } + uid, gid, err = oci.GetUser(ctx, rootfsPath, meta.User) + if err != nil { + lm.Unmount() + return err + } + lm.Unmount() + } + + spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, containerdoci.WithUIDGID(uid, gid)) if err != nil { return err } + defer cleanup() container, err := w.client.NewContainer(ctx, id, containerd.WithSpec(spec), diff --git a/executor/oci/spec_unix.go b/executor/oci/spec_unix.go index 7d03f4ceebd8..028e88892ea2 100644 --- a/executor/oci/spec_unix.go +++ b/executor/oci/spec_unix.go @@ -21,7 +21,7 @@ import ( // Ideally we don't have to import whole containerd just for the default spec // GenerateSpec generates spec using containerd functionality. -func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id string, resolvConf, hostsFile string) (*specs.Spec, func(), error) { +func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mount, id, resolvConf, hostsFile string, opts ...oci.SpecOpts) (*specs.Spec, func(), error) { c := &containers.Container{ ID: id, } @@ -29,13 +29,16 @@ func GenerateSpec(ctx context.Context, meta executor.Meta, mounts []executor.Mou if !ok { ctx = namespaces.WithNamespace(ctx, "buildkit") } - // Note that containerd.GenerateSpec is namespaced so as to make - // specs.Linux.CgroupsPath namespaced - s, err := oci.GenerateSpec(ctx, nil, c, + + opts = append(opts, oci.WithHostNamespace(specs.NetworkNamespace), withROBind(resolvConf, "/etc/resolv.conf"), withROBind(hostsFile, "/etc/hosts"), ) + + // Note that containerd.GenerateSpec is namespaced so as to make + // specs.Linux.CgroupsPath namespaced + s, err := oci.GenerateSpec(ctx, nil, c, opts...) if err != nil { return nil, nil, err } diff --git a/executor/oci/user.go b/executor/oci/user.go new file mode 100644 index 000000000000..998aba97e3be --- /dev/null +++ b/executor/oci/user.go @@ -0,0 +1,86 @@ +package oci + +import ( + "context" + "os" + "strconv" + "strings" + + "github.com/containerd/containerd/fs" + "github.com/opencontainers/runc/libcontainer/user" +) + +func GetUser(ctx context.Context, root, username string) (uint32, uint32, error) { + // fast path from uid/gid + if uid, gid, err := ParseUser(username); err == nil { + return uid, gid, nil + } + + passwdPath, err := user.GetPasswdPath() + if err != nil { + return 0, 0, err + } + groupPath, err := user.GetGroupPath() + if err != nil { + return 0, 0, err + } + passwdFile, err := openUserFile(root, passwdPath) + if err == nil { + defer passwdFile.Close() + } + groupFile, err := openUserFile(root, groupPath) + if err == nil { + defer groupFile.Close() + } + + execUser, err := user.GetExecUser(username, nil, passwdFile, groupFile) + if err != nil { + return 0, 0, err + } + + return uint32(execUser.Uid), uint32(execUser.Gid), nil +} + +func ParseUser(str string) (uid uint32, gid uint32, err error) { + if str == "" { + return 0, 0, nil + } + parts := strings.SplitN(str, ":", 2) + for i, v := range parts { + switch i { + case 0: + uid, err = parseUID(v) + if err != nil { + return 0, 0, err + } + if len(parts) == 1 { + gid = uid + } + case 1: + gid, err = parseUID(v) + if err != nil { + return 0, 0, err + } + } + } + return +} + +func openUserFile(root, p string) (*os.File, error) { + p, err := fs.RootPath(root, p) + if err != nil { + return nil, err + } + return os.Open(p) +} + +func parseUID(str string) (uint32, error) { + if str == "root" { + return 0, nil + } + uid, err := strconv.ParseUint(str, 10, 32) + if err != nil { + return 0, err + } + return uint32(uid), nil +} diff --git a/executor/runcexecutor/executor.go b/executor/runcexecutor/executor.go index 0234464ae369..7e81e4ba7654 100644 --- a/executor/runcexecutor/executor.go +++ b/executor/runcexecutor/executor.go @@ -9,6 +9,7 @@ import ( "syscall" "github.com/containerd/containerd/mount" + containerdoci "github.com/containerd/containerd/oci" runc "github.com/containerd/go-runc" "github.com/docker/docker/pkg/symlink" "github.com/moby/buildkit/cache" @@ -82,21 +83,27 @@ func (w *runcExecutor) Exec(ctx context.Context, meta executor.Meta, root cache. if err := os.Mkdir(rootFSPath, 0700); err != nil { return err } + if err := mount.All(rootMount, rootFSPath); err != nil { + return err + } + defer mount.Unmount(rootFSPath, 0) + + uid, gid, err := oci.GetUser(ctx, rootFSPath, meta.User) + if err != nil { + return err + } + f, err := os.Create(filepath.Join(bundle, "config.json")) if err != nil { return err } defer f.Close() - spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile) + spec, cleanup, err := oci.GenerateSpec(ctx, meta, mounts, id, resolvConf, hostsFile, containerdoci.WithUIDGID(uid, gid)) if err != nil { return err } defer cleanup() - if err := mount.All(rootMount, rootFSPath); err != nil { - return err - } - defer mount.Unmount(rootFSPath, 0) spec.Root.Path = rootFSPath if _, ok := root.(cache.ImmutableRef); ok { // TODO: pass in with mount, not ref type spec.Root.Readonly = true diff --git a/frontend/dockerfile/dockerfile2llb/convert.go b/frontend/dockerfile/dockerfile2llb/convert.go index b61d04c90573..7ad152f5c968 100644 --- a/frontend/dockerfile/dockerfile2llb/convert.go +++ b/frontend/dockerfile/dockerfile2llb/convert.go @@ -477,6 +477,7 @@ func dispatchExpose(d *dispatchState, c *instructions.ExposeCommand, shlex *Shel return commitToHistory(&d.image, fmt.Sprintf("EXPOSE %v", ps), false, nil) } func dispatchUser(d *dispatchState, c *instructions.UserCommand, commit bool) error { + d.state = d.state.User(c.User) d.image.Config.User = c.User if commit { return commitToHistory(&d.image, fmt.Sprintf("USER %v", c.User), false, nil) diff --git a/frontend/dockerfile/dockerfile_test.go b/frontend/dockerfile/dockerfile_test.go index 562cc47d9f09..90a7f4dfe330 100644 --- a/frontend/dockerfile/dockerfile_test.go +++ b/frontend/dockerfile/dockerfile_test.go @@ -38,6 +38,7 @@ func TestIntegration(t *testing.T) { testDockerfileScratchConfig, testExportedHistory, testExposeExpansion, + testUser, }) } @@ -575,6 +576,101 @@ RUN ["ls"] require.Equal(t, true, ociimg.History[5].EmptyLayer) } +func testUser(t *testing.T, sb integration.Sandbox) { + t.Parallel() + + dockerfile := []byte(` +FROM busybox AS base +RUN mkdir -m 0777 /out +RUN id -un > /out/rootuser +USER daemon +RUN id -un > /out/daemonuser +FROM scratch +COPY --from=base /out / +USER nobody +`) + + dir, err := tmpdir( + fstest.CreateFile("Dockerfile", dockerfile, 0600), + ) + require.NoError(t, err) + defer os.RemoveAll(dir) + + c, err := client.New(sb.Address()) + require.NoError(t, err) + defer c.Close() + + destDir, err := ioutil.TempDir("", "buildkit") + require.NoError(t, err) + defer os.RemoveAll(destDir) + + err = c.Solve(context.TODO(), nil, client.SolveOpt{ + Frontend: "dockerfile.v0", + Exporter: client.ExporterLocal, + ExporterAttrs: map[string]string{ + "output": destDir, + }, + LocalDirs: map[string]string{ + localNameDockerfile: dir, + localNameContext: dir, + }, + }, nil) + require.NoError(t, err) + + dt, err := ioutil.ReadFile(filepath.Join(destDir, "rootuser")) + require.NoError(t, err) + require.Equal(t, string(dt), "root\n") + + dt, err = ioutil.ReadFile(filepath.Join(destDir, "daemonuser")) + require.NoError(t, err) + require.Equal(t, string(dt), "daemon\n") + + // test user in exported + target := "example.com/moby/dockerfileuser:test" + err = c.Solve(context.TODO(), nil, client.SolveOpt{ + Frontend: "dockerfile.v0", + Exporter: client.ExporterImage, + ExporterAttrs: map[string]string{ + "name": target, + }, + LocalDirs: map[string]string{ + localNameDockerfile: dir, + localNameContext: dir, + }, + }, nil) + require.NoError(t, err) + + var cdAddress string + if cd, ok := sb.(interface { + ContainerdAddress() string + }); !ok { + return + } else { + cdAddress = cd.ContainerdAddress() + } + + client, err := containerd.New(cdAddress) + require.NoError(t, err) + defer client.Close() + + ctx := namespaces.WithNamespace(context.Background(), "buildkit") + + img, err := client.ImageService().Get(ctx, target) + require.NoError(t, err) + + desc, err := img.Config(ctx, client.ContentStore(), platforms.Default()) + require.NoError(t, err) + + dt, err = content.ReadBlob(ctx, client.ContentStore(), desc.Digest) + require.NoError(t, err) + + var ociimg ocispec.Image + err = json.Unmarshal(dt, &ociimg) + require.NoError(t, err) + + require.Equal(t, "nobody", ociimg.Config.User) +} + func tmpdir(appliers ...fstest.Applier) (string, error) { tmpdir, err := ioutil.TempDir("", "buildkit-dockerfile") if err != nil { diff --git a/solver/exec.go b/solver/exec.go index 92992014e56c..35b518f39b56 100644 --- a/solver/exec.go +++ b/solver/exec.go @@ -109,6 +109,7 @@ func (e *execOp) Run(ctx context.Context, inputs []Reference) ([]Reference, erro Args: e.op.Meta.Args, Env: e.op.Meta.Env, Cwd: e.op.Meta.Cwd, + User: e.op.Meta.User, } stdout, stderr := logs.NewLogStreams(ctx) diff --git a/solver/pb/ops.pb.go b/solver/pb/ops.pb.go index 1de63115a3ec..b7fb57caac62 100644 --- a/solver/pb/ops.pb.go +++ b/solver/pb/ops.pb.go @@ -277,6 +277,7 @@ type Meta struct { Args []string `protobuf:"bytes,1,rep,name=args" json:"args,omitempty"` Env []string `protobuf:"bytes,2,rep,name=env" json:"env,omitempty"` Cwd string `protobuf:"bytes,3,opt,name=cwd,proto3" json:"cwd,omitempty"` + User string `protobuf:"bytes,4,opt,name=user,proto3" json:"user,omitempty"` } func (m *Meta) Reset() { *m = Meta{} } @@ -305,6 +306,13 @@ func (m *Meta) GetCwd() string { return "" } +func (m *Meta) GetUser() string { + if m != nil { + return m.User + } + return "" +} + type Mount struct { Input InputIndex `protobuf:"varint,1,opt,name=input,proto3,customtype=InputIndex" json:"input"` Selector string `protobuf:"bytes,2,opt,name=selector,proto3" json:"selector,omitempty"` @@ -753,6 +761,12 @@ func (m *Meta) MarshalTo(dAtA []byte) (int, error) { i = encodeVarintOps(dAtA, i, uint64(len(m.Cwd))) i += copy(dAtA[i:], m.Cwd) } + if len(m.User) > 0 { + dAtA[i] = 0x22 + i++ + i = encodeVarintOps(dAtA, i, uint64(len(m.User))) + i += copy(dAtA[i:], m.User) + } return i, nil } @@ -1270,6 +1284,10 @@ func (m *Meta) Size() (n int) { if l > 0 { n += 1 + l + sovOps(uint64(l)) } + l = len(m.User) + if l > 0 { + n += 1 + l + sovOps(uint64(l)) + } return n } @@ -1988,6 +2006,35 @@ func (m *Meta) Unmarshal(dAtA []byte) error { } m.Cwd = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field User", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowOps + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthOps + } + postIndex := iNdEx + intStringLen + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.User = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipOps(dAtA[iNdEx:]) @@ -3592,58 +3639,58 @@ var ( func init() { proto.RegisterFile("ops.proto", fileDescriptorOps) } var fileDescriptorOps = []byte{ - // 837 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xcd, 0x8e, 0xe3, 0x44, - 0x10, 0x1e, 0x3b, 0x3f, 0x9b, 0x94, 0x07, 0x14, 0x9a, 0x15, 0x44, 0xd1, 0x2a, 0x09, 0x06, 0xa1, - 0x00, 0x3b, 0x8e, 0x94, 0x95, 0xd0, 0x8a, 0xc3, 0x48, 0x93, 0x99, 0x95, 0x08, 0x68, 0x15, 0xa9, - 0x41, 0xe2, 0xb8, 0x72, 0xec, 0x4e, 0xd6, 0xda, 0xc4, 0xdd, 0xb2, 0xdb, 0x3b, 0x93, 0x0b, 0x07, - 0x9e, 0x00, 0x89, 0xb7, 0xe0, 0x1d, 0xe0, 0xbc, 0x47, 0xae, 0x70, 0x58, 0xd0, 0xf0, 0x0c, 0xdc, - 0x51, 0x55, 0x77, 0x62, 0xcf, 0x30, 0x48, 0x33, 0x82, 0x53, 0xba, 0xab, 0xaa, 0xbf, 0xaa, 0xfa, - 0xea, 0x2b, 0x07, 0xda, 0x52, 0xe5, 0x81, 0xca, 0xa4, 0x96, 0xcc, 0x55, 0x8b, 0xde, 0xd1, 0x2a, - 0xd1, 0xcf, 0x8b, 0x45, 0x10, 0xc9, 0xcd, 0x78, 0x25, 0x57, 0x72, 0x4c, 0xae, 0x45, 0xb1, 0xa4, - 0x1b, 0x5d, 0xe8, 0x64, 0x9e, 0xf8, 0x3f, 0x3b, 0xe0, 0xce, 0x15, 0x7b, 0x0f, 0x9a, 0x49, 0xaa, - 0x0a, 0x9d, 0x77, 0x9d, 0x61, 0x6d, 0xe4, 0x4d, 0xda, 0x81, 0x5a, 0x04, 0x33, 0xb4, 0x70, 0xeb, - 0x60, 0x43, 0xa8, 0x8b, 0x0b, 0x11, 0x75, 0xdd, 0xa1, 0x33, 0xf2, 0x26, 0x80, 0x01, 0x4f, 0x2e, - 0x44, 0x34, 0x57, 0x9f, 0x1f, 0x70, 0xf2, 0xb0, 0x0f, 0xa1, 0x99, 0xcb, 0x22, 0x8b, 0x44, 0xb7, - 0x46, 0x31, 0x87, 0x18, 0xf3, 0x15, 0x59, 0x28, 0xca, 0x7a, 0x11, 0x29, 0x92, 0x6a, 0xdb, 0xad, - 0x97, 0x48, 0xa7, 0x52, 0x6d, 0x0d, 0x12, 0x7a, 0xd8, 0xfb, 0xd0, 0x58, 0x14, 0xc9, 0x3a, 0xee, - 0x36, 0x28, 0xc4, 0xc3, 0x90, 0x29, 0x1a, 0x28, 0xc6, 0xf8, 0xa6, 0x75, 0x70, 0xa5, 0xf2, 0xbf, - 0x85, 0x06, 0xd5, 0xc9, 0xbe, 0x80, 0x66, 0x9c, 0xac, 0x44, 0xae, 0xbb, 0xce, 0xd0, 0x19, 0xb5, - 0xa7, 0x93, 0x57, 0xaf, 0x07, 0x07, 0xbf, 0xbd, 0x1e, 0x7c, 0x5c, 0x21, 0x44, 0x2a, 0x91, 0x46, - 0x32, 0xd5, 0x61, 0x92, 0x8a, 0x2c, 0x1f, 0xaf, 0xe4, 0x91, 0x79, 0x12, 0x9c, 0xd1, 0x0f, 0xb7, - 0x08, 0xec, 0x23, 0x68, 0x24, 0x69, 0x2c, 0x2e, 0xa8, 0xd9, 0xda, 0xf4, 0x6d, 0x0b, 0xe5, 0xcd, - 0x0b, 0xad, 0x0a, 0x3d, 0x43, 0x17, 0x37, 0x11, 0xfe, 0x0c, 0x9a, 0x86, 0x06, 0xf6, 0x00, 0xea, - 0x1b, 0xa1, 0x43, 0x4a, 0xef, 0x4d, 0x5a, 0x58, 0xf3, 0x53, 0xa1, 0x43, 0x4e, 0x56, 0x64, 0x78, - 0x23, 0x8b, 0x54, 0xe7, 0x5d, 0xb7, 0x64, 0xf8, 0x29, 0x5a, 0xb8, 0x75, 0xf8, 0xc7, 0x50, 0xc7, - 0x07, 0x8c, 0x41, 0x3d, 0xcc, 0x56, 0x66, 0x14, 0x6d, 0x4e, 0x67, 0xd6, 0x81, 0x9a, 0x48, 0x5f, - 0xd2, 0xdb, 0x36, 0xc7, 0x23, 0x5a, 0xa2, 0xf3, 0x98, 0xa8, 0x6e, 0x73, 0x3c, 0xfa, 0x3f, 0x3a, - 0xd0, 0x20, 0x44, 0x36, 0xc2, 0xfa, 0x55, 0x61, 0xa8, 0xa8, 0x4d, 0x99, 0xad, 0x1f, 0x88, 0xa9, - 0x7d, 0xf9, 0xc8, 0x5a, 0x0f, 0x5a, 0xb9, 0x58, 0x8b, 0x48, 0xcb, 0x8c, 0x9a, 0x6d, 0xf3, 0xfd, - 0x1d, 0xeb, 0x88, 0x91, 0x4f, 0x93, 0x82, 0xce, 0xec, 0x13, 0x68, 0x4a, 0x22, 0x81, 0xa6, 0xf7, - 0x2f, 0xd4, 0xd8, 0x10, 0x04, 0xcf, 0x44, 0x18, 0xcb, 0x74, 0xbd, 0xa5, 0x49, 0xb6, 0xf8, 0xfe, - 0xee, 0x1f, 0x43, 0xd3, 0x0c, 0x9d, 0x0d, 0xa1, 0x96, 0x67, 0x91, 0x15, 0xde, 0x9b, 0x3b, 0x35, - 0x18, 0xdd, 0x70, 0x74, 0xed, 0x0b, 0x71, 0xcb, 0x42, 0x7c, 0x0e, 0x50, 0x86, 0xfd, 0x3f, 0x0d, - 0xfb, 0x3f, 0x38, 0xd0, 0xda, 0xe9, 0x95, 0xf5, 0x01, 0x92, 0x58, 0xa4, 0x3a, 0x59, 0x26, 0x22, - 0x33, 0x9a, 0xe2, 0x15, 0x0b, 0x3b, 0x82, 0x46, 0xa8, 0x75, 0xb6, 0x9b, 0xe7, 0xbb, 0x55, 0xb1, - 0x07, 0x27, 0xe8, 0x79, 0x92, 0xea, 0x6c, 0xcb, 0x4d, 0x54, 0xef, 0x31, 0x40, 0x69, 0xc4, 0xe1, - 0xbd, 0x10, 0x5b, 0x8b, 0x8a, 0x47, 0x76, 0x1f, 0x1a, 0x2f, 0xc3, 0x75, 0x21, 0x6c, 0x51, 0xe6, - 0xf2, 0x99, 0xfb, 0xd8, 0xf1, 0x7f, 0x72, 0xe1, 0x9e, 0x15, 0x3f, 0x7b, 0x08, 0xf7, 0x48, 0xfc, - 0xb6, 0xa2, 0x9b, 0x3b, 0xdd, 0x85, 0xb0, 0xf1, 0x7e, 0xab, 0x2b, 0x35, 0x5a, 0x28, 0xb3, 0xdd, - 0xb6, 0xc6, 0x72, 0xc7, 0x6b, 0xb1, 0x58, 0xda, 0xf5, 0xa5, 0x51, 0x9c, 0x89, 0x65, 0x92, 0x26, - 0x3a, 0x91, 0x29, 0x47, 0x17, 0x7b, 0xb8, 0xeb, 0xba, 0x4e, 0x88, 0xef, 0x54, 0x11, 0xff, 0xd9, - 0xf4, 0x0c, 0xbc, 0x4a, 0x9a, 0x1b, 0xba, 0xfe, 0xa0, 0xda, 0xb5, 0x4d, 0x49, 0x70, 0xe6, 0xdb, - 0x53, 0xb2, 0xf0, 0x1f, 0xf8, 0xfb, 0x14, 0xa0, 0x84, 0xbc, 0xbd, 0x52, 0xfc, 0xbf, 0x1c, 0x80, - 0xb9, 0xc2, 0x8d, 0x8c, 0x43, 0x5a, 0xe0, 0xc3, 0x64, 0x95, 0xca, 0x4c, 0x3c, 0x8b, 0xc2, 0xe8, - 0xb9, 0xa0, 0xf7, 0x2d, 0xee, 0x19, 0xdb, 0x29, 0x9a, 0xd8, 0x09, 0x78, 0xb1, 0xc8, 0xa3, 0x2c, - 0x51, 0x48, 0x98, 0x25, 0x7d, 0x80, 0x3d, 0x95, 0x38, 0xc1, 0x59, 0x19, 0x61, 0xb8, 0xaa, 0xbe, - 0x61, 0x27, 0xf0, 0xd6, 0xb9, 0xcc, 0x5e, 0x88, 0xec, 0x59, 0x24, 0xd3, 0x5c, 0x67, 0x61, 0x92, - 0x6a, 0x3b, 0x8f, 0xfb, 0x08, 0xf4, 0x0d, 0x39, 0x4f, 0xf7, 0x3e, 0xde, 0x39, 0xbf, 0x66, 0xe9, - 0x1d, 0x43, 0xe7, 0x7a, 0x8e, 0x3b, 0xf1, 0xf5, 0x08, 0x3a, 0xd7, 0xb3, 0xb0, 0x01, 0x78, 0xb6, - 0x2c, 0xbd, 0x55, 0x62, 0xb7, 0x0d, 0xc6, 0xf4, 0xf5, 0x56, 0x09, 0xff, 0x57, 0x07, 0xa0, 0xd4, - 0x0a, 0xe6, 0x43, 0x21, 0xe1, 0x4e, 0x1f, 0x1a, 0xe1, 0xac, 0xa1, 0xb5, 0xb1, 0x14, 0x58, 0x62, - 0x1e, 0x5c, 0xd5, 0x57, 0xb0, 0x63, 0x88, 0x2a, 0x36, 0x9f, 0xef, 0xef, 0x7e, 0xbf, 0xd3, 0xe7, - 0x7b, 0x9f, 0xa1, 0xf7, 0x25, 0xbc, 0x71, 0x05, 0xee, 0x96, 0xd2, 0x2b, 0xc7, 0x54, 0x21, 0x64, - 0xda, 0x79, 0x75, 0xd9, 0x77, 0x7e, 0xb9, 0xec, 0x3b, 0x7f, 0x5c, 0xf6, 0x9d, 0xef, 0xff, 0xec, - 0x1f, 0x2c, 0x9a, 0xf4, 0xe7, 0xf9, 0xe8, 0xef, 0x00, 0x00, 0x00, 0xff, 0xff, 0x4c, 0x43, 0xb9, - 0x14, 0x7c, 0x07, 0x00, 0x00, + // 845 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x55, 0xcd, 0x8e, 0x1b, 0x45, + 0x10, 0xde, 0x19, 0xff, 0xc4, 0x53, 0xb3, 0x20, 0xd3, 0x44, 0x60, 0x59, 0x91, 0xd7, 0x0c, 0x08, + 0x2d, 0x90, 0x9d, 0x95, 0x36, 0x12, 0x8a, 0x38, 0x44, 0x5a, 0xef, 0x46, 0xc2, 0xa0, 0xc8, 0x52, + 0x83, 0xc4, 0x31, 0x1a, 0xcf, 0xb4, 0x9d, 0x51, 0xec, 0xe9, 0x56, 0x4f, 0x4f, 0x76, 0x7d, 0xe1, + 0xc0, 0x13, 0x20, 0xf1, 0x16, 0xbc, 0x03, 0x9c, 0x73, 0xe4, 0x0a, 0x87, 0x80, 0x96, 0x67, 0xe0, + 0x8e, 0xaa, 0xba, 0xed, 0x99, 0x2c, 0x41, 0xca, 0x0a, 0x4e, 0xae, 0xae, 0x9f, 0xaf, 0xaa, 0xbe, + 0xaa, 0x1a, 0x43, 0x20, 0x55, 0x19, 0x2b, 0x2d, 0x8d, 0x64, 0xbe, 0x9a, 0x0f, 0x8f, 0x96, 0xb9, + 0x79, 0x52, 0xcd, 0xe3, 0x54, 0xae, 0x8f, 0x97, 0x72, 0x29, 0x8f, 0xc9, 0x34, 0xaf, 0x16, 0xf4, + 0xa2, 0x07, 0x49, 0x36, 0x24, 0xfa, 0xd9, 0x03, 0x7f, 0xa6, 0xd8, 0x7b, 0xd0, 0xcd, 0x0b, 0x55, + 0x99, 0x72, 0xe0, 0x8d, 0x5b, 0x87, 0xe1, 0x49, 0x10, 0xab, 0x79, 0x3c, 0x45, 0x0d, 0x77, 0x06, + 0x36, 0x86, 0xb6, 0xb8, 0x14, 0xe9, 0xc0, 0x1f, 0x7b, 0x87, 0xe1, 0x09, 0xa0, 0xc3, 0xc3, 0x4b, + 0x91, 0xce, 0xd4, 0xe7, 0x7b, 0x9c, 0x2c, 0xec, 0x43, 0xe8, 0x96, 0xb2, 0xd2, 0xa9, 0x18, 0xb4, + 0xc8, 0x67, 0x1f, 0x7d, 0xbe, 0x22, 0x0d, 0x79, 0x39, 0x2b, 0x22, 0xa5, 0x52, 0x6d, 0x06, 0xed, + 0x1a, 0xe9, 0x4c, 0xaa, 0x8d, 0x45, 0x42, 0x0b, 0x7b, 0x1f, 0x3a, 0xf3, 0x2a, 0x5f, 0x65, 0x83, + 0x0e, 0xb9, 0x84, 0xe8, 0x32, 0x41, 0x05, 0xf9, 0x58, 0xdb, 0xa4, 0x0d, 0xbe, 0x54, 0xd1, 0xb7, + 0xd0, 0xa1, 0x3a, 0xd9, 0x17, 0xd0, 0xcd, 0xf2, 0xa5, 0x28, 0xcd, 0xc0, 0x1b, 0x7b, 0x87, 0xc1, + 0xe4, 0xe4, 0xf9, 0x8b, 0x83, 0xbd, 0xdf, 0x5e, 0x1c, 0x7c, 0xdc, 0x20, 0x44, 0x2a, 0x51, 0xa4, + 0xb2, 0x30, 0x49, 0x5e, 0x08, 0x5d, 0x1e, 0x2f, 0xe5, 0x91, 0x0d, 0x89, 0xcf, 0xe9, 0x87, 0x3b, + 0x04, 0xf6, 0x11, 0x74, 0xf2, 0x22, 0x13, 0x97, 0xd4, 0x6c, 0x6b, 0xf2, 0xb6, 0x83, 0x0a, 0x67, + 0x95, 0x51, 0x95, 0x99, 0xa2, 0x89, 0x5b, 0x8f, 0x68, 0x0a, 0x5d, 0x4b, 0x03, 0xbb, 0x03, 0xed, + 0xb5, 0x30, 0x09, 0xa5, 0x0f, 0x4f, 0x7a, 0x58, 0xf3, 0x23, 0x61, 0x12, 0x4e, 0x5a, 0x64, 0x78, + 0x2d, 0xab, 0xc2, 0x94, 0x03, 0xbf, 0x66, 0xf8, 0x11, 0x6a, 0xb8, 0x33, 0x44, 0x1c, 0xda, 0x18, + 0xc0, 0x18, 0xb4, 0x13, 0xbd, 0xb4, 0xa3, 0x08, 0x38, 0xc9, 0xac, 0x0f, 0x2d, 0x51, 0x3c, 0xa3, + 0xd8, 0x80, 0xa3, 0x88, 0x9a, 0xf4, 0x22, 0x23, 0xaa, 0x03, 0x8e, 0x22, 0xc6, 0x55, 0xa5, 0xd0, + 0xc4, 0x6b, 0xc0, 0x49, 0x8e, 0x7e, 0xf4, 0xa0, 0x43, 0x59, 0xd8, 0x21, 0xf6, 0xa4, 0x2a, 0x4b, + 0x4f, 0x6b, 0xc2, 0x5c, 0x4f, 0x40, 0xec, 0xed, 0x5a, 0x42, 0x26, 0x87, 0xd0, 0x2b, 0xc5, 0x4a, + 0xa4, 0x46, 0x6a, 0x22, 0x20, 0xe0, 0xbb, 0x37, 0xe6, 0xc8, 0x90, 0x63, 0x9b, 0x96, 0x64, 0xf6, + 0x09, 0x74, 0x25, 0x11, 0x43, 0x99, 0xff, 0x85, 0x2e, 0xe7, 0x82, 0xe0, 0x5a, 0x24, 0x99, 0x2c, + 0x56, 0x1b, 0x9a, 0x6e, 0x8f, 0xef, 0xde, 0xd1, 0x03, 0xe8, 0xda, 0x45, 0x60, 0x63, 0x68, 0x95, + 0x3a, 0x75, 0xcb, 0xf8, 0xe6, 0x76, 0x43, 0xec, 0x2e, 0x71, 0x34, 0xed, 0x0a, 0xf1, 0xeb, 0x42, + 0x22, 0x0e, 0x50, 0xbb, 0xfd, 0x3f, 0x0d, 0x47, 0x3f, 0x78, 0xd0, 0xdb, 0xee, 0x30, 0x1b, 0x01, + 0xe4, 0x99, 0x28, 0x4c, 0xbe, 0xc8, 0x85, 0xb6, 0x7b, 0xc6, 0x1b, 0x1a, 0x76, 0x04, 0x9d, 0xc4, + 0x18, 0xbd, 0x9d, 0xf1, 0xbb, 0xcd, 0x03, 0x88, 0x4f, 0xd1, 0xf2, 0xb0, 0x30, 0x7a, 0xc3, 0xad, + 0xd7, 0xf0, 0x3e, 0x40, 0xad, 0xc4, 0x81, 0x3e, 0x15, 0x1b, 0x87, 0x8a, 0x22, 0xbb, 0x0d, 0x9d, + 0x67, 0xc9, 0xaa, 0x12, 0xae, 0x28, 0xfb, 0xf8, 0xcc, 0xbf, 0xef, 0x45, 0x3f, 0xf9, 0x70, 0xcb, + 0x1d, 0x04, 0xbb, 0x0b, 0xb7, 0xe8, 0x20, 0x5c, 0x45, 0xaf, 0xee, 0x74, 0xeb, 0xc2, 0x8e, 0x77, + 0x97, 0xde, 0xa8, 0xd1, 0x41, 0xd9, 0x8b, 0x77, 0x35, 0xd6, 0x77, 0xdf, 0xca, 0xc4, 0xc2, 0x9d, + 0x34, 0x8d, 0xe2, 0x5c, 0x2c, 0xf2, 0x22, 0x37, 0xb9, 0x2c, 0x38, 0x9a, 0xd8, 0xdd, 0x6d, 0xd7, + 0x6d, 0x42, 0x7c, 0xa7, 0x89, 0xf8, 0xcf, 0xa6, 0xa7, 0x10, 0x36, 0xd2, 0xbc, 0xa2, 0xeb, 0x0f, + 0x9a, 0x5d, 0xbb, 0x94, 0x04, 0x67, 0xbf, 0x47, 0x35, 0x0b, 0xff, 0x81, 0xbf, 0x4f, 0x01, 0x6a, + 0xc8, 0xd7, 0xdf, 0x94, 0xe8, 0x2f, 0x0f, 0x60, 0xa6, 0xf0, 0x4a, 0xb3, 0x84, 0x8e, 0x7a, 0x3f, + 0x5f, 0x16, 0x52, 0x8b, 0xc7, 0x69, 0x92, 0x3e, 0x11, 0x14, 0xdf, 0xe3, 0xa1, 0xd5, 0x9d, 0xa1, + 0x8a, 0x9d, 0x42, 0x98, 0x89, 0x32, 0xd5, 0xb9, 0x42, 0xc2, 0x1c, 0xe9, 0x07, 0xd8, 0x53, 0x8d, + 0x13, 0x9f, 0xd7, 0x1e, 0x96, 0xab, 0x66, 0x0c, 0x3b, 0x85, 0xb7, 0x2e, 0xa4, 0x7e, 0x2a, 0xf4, + 0xe3, 0x54, 0x16, 0xa5, 0xd1, 0x49, 0x5e, 0x18, 0x37, 0x8f, 0xdb, 0x08, 0xf4, 0x0d, 0x19, 0xcf, + 0x76, 0x36, 0xde, 0xbf, 0xb8, 0xa6, 0x19, 0x3e, 0x80, 0xfe, 0xf5, 0x1c, 0x37, 0xe2, 0xeb, 0x1e, + 0xf4, 0xaf, 0x67, 0x61, 0x07, 0x10, 0xba, 0xb2, 0xcc, 0x46, 0x89, 0xed, 0x35, 0x58, 0xd5, 0xd7, + 0x1b, 0x25, 0xa2, 0x5f, 0x3d, 0x80, 0x7a, 0x57, 0x30, 0x1f, 0x2e, 0x12, 0xde, 0xf4, 0xbe, 0x5d, + 0x9c, 0x15, 0xf4, 0xd6, 0x8e, 0x02, 0x47, 0xcc, 0x9d, 0x97, 0xf7, 0x2b, 0xde, 0x32, 0x44, 0x15, + 0xdb, 0x4f, 0xfa, 0x77, 0xbf, 0xdf, 0xe8, 0x93, 0xbe, 0xcb, 0x30, 0xfc, 0x12, 0xde, 0x78, 0x09, + 0xee, 0x35, 0x57, 0xaf, 0x1e, 0x53, 0x83, 0x90, 0x49, 0xff, 0xf9, 0xd5, 0xc8, 0xfb, 0xe5, 0x6a, + 0xe4, 0xfd, 0x71, 0x35, 0xf2, 0xbe, 0xff, 0x73, 0xb4, 0x37, 0xef, 0xd2, 0x1f, 0xea, 0xbd, 0xbf, + 0x03, 0x00, 0x00, 0xff, 0xff, 0x26, 0xbe, 0xb0, 0x53, 0x90, 0x07, 0x00, 0x00, } diff --git a/solver/pb/ops.proto b/solver/pb/ops.proto index 3b2bc6bfc905..9c5f4296465a 100644 --- a/solver/pb/ops.proto +++ b/solver/pb/ops.proto @@ -30,6 +30,7 @@ message Meta { repeated string args = 1; repeated string env = 2; string cwd = 3; + string user = 4; } message Mount {